PHPackages                             boomdevs/toc - 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. [Utility &amp; Helpers](/categories/utility)
4. /
5. boomdevs/toc

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

boomdevs/toc
============

Simple Table-of-Contents Generator for PHP. Generates TOCs based off H1...H6 tags

v3.0.3(4y ago)05MITPHPPHP ^7.2|^8.0

Since Feb 2Pushed 4y agoCompare

[ Source](https://github.com/EnamulHaq/toc)[ Packagist](https://packagist.org/packages/boomdevs/toc)[ Docs](https://github.com/EnamulHaq/toc)[ RSS](/packages/boomdevs-toc/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (1)Dependencies (8)Versions (16)Used By (0)

PHP TOC Generator
=================

[](#php-toc-generator)

Generates a Table of Contents from *H1...H6* Tags in HTML Content

[![Latest Version on Packagist](https://camo.githubusercontent.com/3958275c217e1def6eb7263cccfe65debdc9a1a92238d2cb1a7cd7ab1b22e405/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f626f6f6d646576732f746f632e737667)](https://packagist.org/packages/boomdevs/toc)[![Software License](https://camo.githubusercontent.com/074b89bca64d3edc93a1db6c7e3b1636b874540ba91d66367c0e5e354c56d0ea/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d627269676874677265656e2e737667)](LICENSE.md)[![Github Build](https://github.com/boomdevs/toc/workflows/Github%20Build/badge.svg)](https://github.com/boomdevs/toc/actions?query=workflow%3A%22Github+Build%22)[![Code coverage](https://github.com/boomdevs/toc/raw/master/coverage.svg)](coverage.svg)[![PHPStan Level 8](https://camo.githubusercontent.com/0729e562e10fac943b16dbb271b4af26488f779a33fc82cc3eef1e37a432c0b4/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048505374616e2d6c6576656c253230352d627269676874677265656e2e737667)](https://phpstan.org/)[![Total Downloads](https://camo.githubusercontent.com/3ab45e2293d805953c15fc8a71a6714cbbbe3a6d13e7859a1af1ac425ba300e9/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f626f6f6d646576732f746f632e737667)](https://packagist.org/packages/boomdevs/toc)

**NOTE: This library now requires PHP 7.2 or newer; to retain PHP5-7.1 support, use the following composer directive:**`composer require boomdevs/toc ~2.0.0`

This package provides a simple, framework-agnostic library to build a Table-of-Contents from HTML markup. It does so by evaluating your *H1...H6* tags. It can also automatically add appropriate *id* anchor attributes to header tags so that in-page links work.

Features:

- Generates HTML menus and [KnpMenu Item](https://github.com/KnpLabs/KnpMenu) Menus
- Adds anchor ID attributes to *H1*...*H6* tags in your content where they do not already exist
- You can specify which *H1*...*H6* heading tag levels to include in the TOC
- Includes a Twig Extension for generating TOCs and compatible markup directly in your templates
- Uses the flexible [KnpMenu Library](https://github.com/KnpLabs/KnpMenu) to generate menus
- [PSR-12](https://www.php-fig.org/psr/psr-12/) compliant
- Composer-compatible
- Unit-tested (95% coverage)

In the spirit of [KISS philosophy](http://en.wikipedia.org/wiki/KISS_principle), this library makes a few assumptions:

1. The hierarchy of your content is defined solely by the header (*H1*...*H6*) tags. All other tags are ignored when generating the TOC.
2. The link titles in the Table of Contents match either the `title` attribute of the header tag, or if there is no `title`, the (slugified) plaintext body of the header tag.

Installation Options
--------------------

[](#installation-options)

Install via [Composer](http://getcomposer.org/) by including the following in your `composer.json` file:

```
{
    "require": {
        "boomdevs/toc": "^3.0",
    }
}

```

Or, drop the `src` folder into your application and use a [PSR-4 autoloader](http://www.php-fig.org/psr/psr-4/) to include the files.

Usage
-----

[](#usage)

This package contains two main classes:

1. `TOC\MarkupFixer`: Adds `id` anchor attributes to any *H1*...*H6* tags that do not already have any (you can specify which header tag levels to use at runtime)
2. `TOC\TocGenerator`: Generates a Table of Contents from HTML markup

Basic Example:

```
$myHtmlContent = fix($myHtmlContent) . "";

// This generates the Table of Contents in HTML
$htmlOut .= "" . $tocGenerator->getHtmlMenu($myHtmlContent) . "";

echo $htmlOut;
```

This produces the following output:

```

    This is a header tag with no anchor id
    Lorum ipsum doler sit amet
    This is a header tag with an anchor id
    Stuff here
    This is a header tag with an anchor id

                    This is a header tag with an anchor id

                            This is a header tag with an anchor id

```

Twig Integration
----------------

[](#twig-integration)

This library includes a [Twig](http://twig.sensiolabs.org) extension that enables you to load TOC lists and add anchors to markup from your Twig templates.

In order to enable Twig integration, you must register the `TocTwigExtension` with your Twig environment:

```
use Twig\Environment;
use Twig\Loader\FilesystemLoader;

$myTwig = new Environment(new FilesystemLoader());
$myTwig->addExtension(new TOC\TocTwigExtension());
```

Specifically, the extension adds a Twig function for generating Table of Contents HTML:

```
{# Generates HTML markup for given htmlContent #}
{{ toc(htmlContent) }}
```

It also provides a function and a filter for ensuring that your content includes anchors for all HTML header tags. They both do the same thing, so choose which one suits your needs best:

```
{# Adds anchor links (id tags) for given htmlContent #}
{{ add_anchors(htmlContent) }}

{# You can also use it as a filter #}

    {{ htmlContent | add_anchors }}

```

Your HTML content may be hard-coded in your Twig Template. An easy way to accommodate this is to make sure the content is surrounded by `{% block %}...{% endblock %}` tags, and then just pass in that block to the *toc* function.

For example:

```
{% extends 'base.html.twig' %}
{% block page_content %}

   {{ toc(add_anchors(block('my_writeup'))) }}

   {{ add_anchors(block('my_writeup')) }}

{% endblock %}

{% block my_writeup %}
Hi There
Lorum ipsum baz biz etecetra
This is some content
More content here.  Blah blah
{% endblock %}
```

Specifying Heading Levels to Include
------------------------------------

[](#specifying-heading-levels-to-include)

You can choose to include only specific *h1...h6* heading levels in your TOC. To do this, pass two additional arguments to the `TocGenerator::getHtmlMenu()` method: `$topLevel` and `$depth`. For example:

```
$tocGenerator = new TOC\TocGenerator();
$someHtmlContent = 'TestLorum ipsumTest2Lorum ipsum';

// Get TOC using h2, h3, h4
$tocGenerator->getHtmlMenu($someHtmlContent, 2, 3);

// Get TOC using h1, h2
$tocGenerator->getHtmlMenu($someHtmlContent, 1, 2);

// Get TOC using h4, h5, h6
$tocGenerator->getHtmlMenu($someHtmlContent, 4, 3);
```

Most other methods in the package handle these arguments as well:

```
$tocGenerator = new TOC\TocGenerator();
$markupFixer = new TOC\MarkupFixer();
$someHtmlContent = 'TestLorum ipsumTest2Lorum ipsum';

// Get KnpMenu using h1, h2, h3
$tocGenerator->getMenu($someHtmlContent, 1, 3);

// Fix markup for h3, h4 tags only
$markupFixer->fix($someHtmlContent, 3, 2);
```

Twig functions and filters accept these arguments as well:

```
{# Generate TOC using h2, h3 tags #}
{{ toc(my_content, 2, 3) }}

{# Add anchors to h4, h5, h6 tags #}
{{ my_content | add_anchors(4, 3) }}
```

Customizing Menu Output
-----------------------

[](#customizing-menu-output)

You can customize the rendering of lists that the `TocGenerator` class outputs. By default, `TocGenerator` uses the [KnpMenu ListRenderer](https://github.com/KnpLabs/KnpMenu/blob/master/src/Knp/Menu/Renderer/ListRenderer.php)class to output the HTML.

You can pass your own instance of the `ListRenderer` class to `TocGenerator::getHtmlMenu()`. Or, you can pass in your own renderer (implements [`Knp\Menu\Renderer\RendererInterface`](https://github.com/KnpLabs/KnpMenu/blob/master/src/Knp/Menu/Renderer/RendererInterface.php)).

For example, you may wish to use different CSS classes for your list items:

```
$someHtmlContent = 'TestLorum ipsumTest2Lorum ipsum';

$options = [
    'currentAsLink' => false,
    'currentClass'  => 'curr_page',
    'ancestorClass' => 'curr_ancestor',
    'branch_class'  => 'branch'
];

$renderer = new Knp\Menu\Renderer\ListRenderer(new Knp\Menu\Matcher\Matcher(), $options);

// Render the list
$tocGenerator = new TOC\TocGenerator();
$listHtml = $tocGenerator->getHtmlMenu($someHtmlContent, 1, 6, $renderer);
```

#### Customizing with Twig

[](#customizing-with-twig)

The KnpMenu library offers more robust integration with the [Twig Templating System](http://twig.sensiolabs.org/)than is offered by default with this library. You can take advantage of it by using the [TwigRenderer](https://github.com/KnpLabs/KnpMenu/blob/master/doc/02-Twig-Integration.markdown#using-the-twigrenderer)that is bundled with KnpMenu:

```
use Knp\Menu\Matcher\Matcher;
use Knp\Menu\Renderer\TwigRenderer;
use Twig\Environment;
use Twig\Loader\FilesystemLoader;

$someHtmlContent = 'TestLorum ipsumTest2Lorum ipsum';

$twigLoader = new FilesystemLoader(array(
    __DIR__.'/vendor/KnpMenu/src/Knp/Menu/Resources/views',
    // ...paths to your own Twig templates that render KnpMenus...
));

$twig = new Environment($twigLoader);
$itemMatcher = new Matcher();
$menuRenderer = new TwigRenderer($twig, 'knp_menu.html.twig', $itemMatcher);

$tocGenerator = new TOC\TocGenerator();

// Output the Menu using the template
echo $menuRenderer->render($tocGenerator->getMenu($someHtmlContent));
```

Ordered vs Unordered Lists
--------------------------

[](#ordered-vs-unordered-lists)

The KnpMenu library produces unordered lists (`ul`) by default. This library contains a custom renderer for ordered lists, whether you're using Twig or not:

```
$someHtmlContent = 'TestLorum ipsumTest2Lorum ipsum';

// Ordered List
$orderedRenderedList = (new TOC\TocGenerator())->getOrderedHtmlMenu($someHtmlContent);
```

Twig Usage:

```
{# Generate ordered TOC #}
{{ toc_ordered(my_content) }}

{# The same options can be used for ordered lists as unordered lists #}
{{ toc_ordered(my_content, 2, 3) }}
```

###  Health Score

31

—

LowBetter than 68% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity4

Limited adoption so far

Community12

Small or concentrated contributor base

Maturity76

Established project with proven stability

 Bus Factor1

Top contributor holds 94.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 ~178 days

Recently: every ~118 days

Total

15

Last Release

1623d ago

Major Versions

v1.2 → v2.02018-11-09

v2.x-dev → v3.02020-08-20

PHP version history (4 changes)v1.0PHP &gt;=5.4

v2.1PHP ^7.1

v3.0.1PHP ^7.1|^8.0

v3.0.2PHP ^7.2|^8.0

### Community

Maintainers

![](https://www.gravatar.com/avatar/50ec5111a440fddda26385f4d059a7602f59443b47537308aa86f9b61357a958?d=identicon)[EnamulHaq](/maintainers/EnamulHaq)

---

Top Contributors

[![caseyamcl](https://avatars.githubusercontent.com/u/53035?v=4)](https://github.com/caseyamcl "caseyamcl (112 commits)")[![Schlaefer](https://avatars.githubusercontent.com/u/143224?v=4)](https://github.com/Schlaefer "Schlaefer (2 commits)")[![EnamulHaq](https://avatars.githubusercontent.com/u/35990207?v=4)](https://github.com/EnamulHaq "EnamulHaq (1 commits)")[![NicoHood](https://avatars.githubusercontent.com/u/6888294?v=4)](https://github.com/NicoHood "NicoHood (1 commits)")[![peter279k](https://avatars.githubusercontent.com/u/9021747?v=4)](https://github.com/peter279k "peter279k (1 commits)")[![yaquawa](https://avatars.githubusercontent.com/u/13927101?v=4)](https://github.com/yaquawa "yaquawa (1 commits)")

---

Tags

TOCtable-of-contents

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP\_CodeSniffer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/boomdevs-toc/health.svg)

```
[![Health](https://phpackages.com/badges/boomdevs-toc/health.svg)](https://phpackages.com/packages/boomdevs-toc)
```

###  Alternatives

[caseyamcl/toc

Simple Table-of-Contents Generator for PHP. Generates TOCs based off H1...H6 tags

92344.9k5](/packages/caseyamcl-toc)[j0k3r/php-readability

Automatic article extraction from HTML

186808.8k6](/packages/j0k3r-php-readability)

PHPackages © 2026

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