PHPackages                             baraja-core/table-of-content - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Parsing &amp; Serialization](/categories/parsing)
4. /
5. baraja-core/table-of-content

ActiveLibrary[Parsing &amp; Serialization](/categories/parsing)

baraja-core/table-of-content
============================

A tool for easily compiling Table of content from the article content.

v1.1.0(4y ago)1221PHPPHP ^8.0CI passing

Since Mar 27Pushed 4mo ago1 watchersCompare

[ Source](https://github.com/baraja-core/table-of-content)[ Packagist](https://packagist.org/packages/baraja-core/table-of-content)[ Docs](https://github.com/baraja-core/table-of-content)[ RSS](/packages/baraja-core-table-of-content/feed)WikiDiscussions master Synced yesterday

READMEChangelog (3)Dependencies (8)Versions (6)Used By (0)

Table of Content
================

[](#table-of-content)

A lightweight PHP library for automatically generating a Table of Contents from HTML article content. The library parses your HTML, extracts headings, creates anchor links, and provides structured data for building navigation.

🎯 Key Features
--------------

[](#-key-features)

- **Automatic heading extraction** - Parses `` tags and generates URL-friendly anchor IDs
- **Title and perex detection** - Automatically extracts the main title (``) and introductory paragraph
- **XSS-safe output** - All generated attributes are properly escaped to prevent security vulnerabilities
- **Immutable response object** - Returns a clean, typed `Response` entity with all extracted data
- **Zero configuration** - Works out of the box with sensible defaults
- **PHP 8.0+ support** - Uses modern PHP features including named arguments and constructor property promotion

🏗️ Architecture Overview
------------------------

[](#️-architecture-overview)

The library consists of two main components working together:

```
┌─────────────────────────────────────────────────────────────────┐
│                        HTML Input                               │
│  TitlePerex...Section 1...            │
└─────────────────────────────────┬───────────────────────────────┘
                                  │
                                  ▼
┌─────────────────────────────────────────────────────────────────┐
│                      ContentManager                             │
│  ┌───────────────────────────────────────────────────────────┐  │
│  │  • Parses  headings                                   │  │
│  │  • Generates webalized anchor IDs (slug format)           │  │
│  │  • Injects  anchors before each heading              │  │
│  │  • Extracts  title                                    │  │
│  │  • Extracts first  as perex                            │  │
│  └───────────────────────────────────────────────────────────┘  │
└─────────────────────────────────┬───────────────────────────────┘
                                  │
                                  ▼
┌─────────────────────────────────────────────────────────────────┐
│                         Response                                │
│  ┌───────────────────────────────────────────────────────────┐  │
│  │  • original: string    (unchanged input HTML)             │  │
│  │  • content: string     (HTML with injected anchors)       │  │
│  │  • pureContent: string (content without )             │  │
│  │  • title: ?string      (extracted from )              │  │
│  │  • perex: ?string      (extracted from first )         │  │
│  │  • items: array        (id => title mapping)              │  │
│  └───────────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────────┘

```

🔧 Components
------------

[](#-components)

### ContentManager

[](#contentmanager)

The main service class responsible for parsing HTML content. It provides a single public method:

- **`parse(string $html): Response`** - Accepts raw HTML and returns a structured `Response` object

**Processing steps:**

1. Scans for all `` tags in the content
2. For each heading, generates a URL-friendly ID using `Nette\Utils\Strings::webalize()`
3. Injects an anchor `` element before each heading for smooth scroll navigation
4. Extracts the page title from the first `` tag
5. Extracts the perex (lead paragraph) from the first `` tag
6. Returns all data wrapped in an immutable `Response` object

### Response

[](#response)

An immutable data transfer object implementing `Stringable`. When cast to string, it returns the processed content with anchors.

**Available methods:**

MethodReturn TypeDescription`getOriginal()``string`Returns the original unmodified HTML input`getContent()``string`Returns HTML with injected anchor elements`getPureContent()``string`Returns content without the `` title tag`getTitle()``?string`Returns the extracted title or `null``getPerex()``?string`Returns the extracted perex or `null``getItems()``array`Returns anchor ID to heading title mapping📦 Installation
--------------

[](#-installation)

It's best to use [Composer](https://getcomposer.org) for installation, and you can also find the package on [Packagist](https://packagist.org/packages/baraja-core/table-of-content) and [GitHub](https://github.com/baraja-core/table-of-content).

To install, simply use the command:

```
$ composer require baraja-core/table-of-content
```

You can use the package manually by creating an instance of the internal classes, or register a DIC extension to link the services directly to the Nette Framework.

### Requirements

[](#requirements)

- PHP 8.0 or higher
- `nette/utils` ^3.0

🚀 Basic Usage
-------------

[](#-basic-usage)

### Simple Example

[](#simple-example)

```
use Baraja\TableOfContent\ContentManager;

$manager = new ContentManager();

$html = '
PHP Online Course for Beginners
PHP is a server-side scripting language designed for modern web applications.
How to Start?
First, you need to install PHP on your computer...
Basic Software
You will need a code editor and a local server...
License
This course is released under MIT license.
';

$response = $manager->parse($html);
```

### Accessing Parsed Data

[](#accessing-parsed-data)

```
// Get the title extracted from
$title = $response->getTitle();
// Result: "PHP Online Course for Beginners"

// Get the perex extracted from the first
$perex = $response->getPerex();
// Result: "PHP is a server-side scripting language designed for modern web applications."

// Get all table of content items (ID => Title)
$items = $response->getItems();
// Result:
// [
//     'how-to-start' => 'How to Start?',
//     'basic-software' => 'Basic Software',
//     'licence' => 'License',
// ]

// Get modified content with anchor elements
$content = $response->getContent();

// Get content without the  tag (useful for separate title rendering)
$pureContent = $response->getPureContent();

// Get the original unmodified HTML
$original = $response->getOriginal();
```

### Rendering the Table of Contents

[](#rendering-the-table-of-contents)

```
$items = $response->getItems();

echo '';
echo 'Contents:';
echo '';
foreach ($items as $id => $title) {
    echo sprintf('%s', $id, htmlspecialchars($title));
}
echo '';
echo '';
```

### Using Response as String

[](#using-response-as-string)

The `Response` object implements `Stringable`, so you can use it directly where a string is expected:

```
$response = $manager->parse($html);

// Both of these are equivalent:
echo $response;
echo $response->getContent();
```

📸 Visual Examples
-----------------

[](#-visual-examples)

### Response Entity Structure

[](#response-entity-structure)

The following image shows the structure of the `Response` object after parsing:

[![Response entity](doc/response-entity.png)](doc/response-entity.png)

### Rendered Table of Contents

[](#rendered-table-of-contents)

Example of how a rendered table of contents looks in a real application:

[![Rendered content](doc/rendered-content.png)](doc/rendered-content.png)

💡 How Anchor Generation Works
-----------------------------

[](#-how-anchor-generation-works)

When the parser encounters an `` heading like:

```
How to Start?
```

It transforms it to:

```
How to Start?
```

The anchor ID is generated using `Nette\Utils\Strings::webalize()` which:

- Converts text to lowercase
- Replaces spaces with hyphens
- Removes diacritics (accents)
- Strips special characters

This ensures clean, URL-friendly anchor IDs that work reliably across all browsers.

🔒 Security
----------

[](#-security)

The library implements proper XSS protection:

- All generated `id` attributes are escaped using `htmlspecialchars()` with `ENT_QUOTES | ENT_HTML5 | ENT_SUBSTITUTE` flags
- Protection against innerHTML mXSS vulnerability ([nette/nette#1496](https://github.com/nette/nette/issues/1496)) is included
- Original content is preserved without modification in `getOriginal()`

⚙️ Integration with Nette Framework
-----------------------------------

[](#️-integration-with-nette-framework)

For Nette Framework users, you can register the service in your configuration:

```
services:
    - Baraja\TableOfContent\ContentManager
```

Then inject it into your presenters or services:

```
public function __construct(
    private ContentManager $contentManager,
) {
}
```

🎨 Styling Recommendations
-------------------------

[](#-styling-recommendations)

For smooth scroll behavior to anchors, add this CSS:

```
html {
    scroll-behavior: smooth;
}

.content-anchor {
    scroll-margin-top: 80px; /* Offset for fixed headers */
}
```

👤 Author
--------

[](#-author)

**Jan Barasek**

- Website:
- GitHub: [@baraja-core](https://github.com/baraja-core)

📄 License
---------

[](#-license)

`baraja-core/table-of-content` is licensed under the MIT license. See the [LICENSE](https://github.com/baraja-core/table-of-content/blob/master/LICENSE) file for more details.

###  Health Score

37

—

LowBetter than 83% of packages

Maintenance52

Moderate activity, may be stable

Popularity13

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity61

Established project with proven stability

 Bus Factor1

Top contributor holds 92.9% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~179 days

Total

3

Last Release

1514d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/3382204?v=4)[baraja](/maintainers/baraja)[@baraja](https://github.com/baraja)

---

Top Contributors

[![janbarasek](https://avatars.githubusercontent.com/u/4738758?v=4)](https://github.com/janbarasek "janbarasek (13 commits)")[![ImgBotApp](https://avatars.githubusercontent.com/u/31427850?v=4)](https://github.com/ImgBotApp "ImgBotApp (1 commits)")

---

Tags

articlecontententityfastgeneratorparserspeed

###  Code Quality

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/baraja-core-table-of-content/health.svg)

```
[![Health](https://phpackages.com/badges/baraja-core-table-of-content/health.svg)](https://phpackages.com/packages/baraja-core-table-of-content)
```

###  Alternatives

[mtdowling/jmespath.php

Declaratively specify how to extract elements from a JSON document

2.0k472.8M135](/packages/mtdowling-jmespathphp)[opis/closure

A library that can be used to serialize closures (anonymous functions) and arbitrary data.

2.6k230.0M284](/packages/opis-closure)[masterminds/html5

An HTML5 parser and serializer.

1.8k242.8M229](/packages/masterminds-html5)[sabberworm/php-css-parser

Parser for CSS Files written in PHP

1.8k191.2M65](/packages/sabberworm-php-css-parser)[jms/metadata

Class/method/property metadata management in PHP

1.8k152.8M88](/packages/jms-metadata)[jms/serializer-bundle

Allows you to easily serialize, and deserialize data of any complexity

1.8k89.3M627](/packages/jms-serializer-bundle)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
