PHPackages                             cable8mm/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. cable8mm/toc

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

cable8mm/toc
============

The TOC is an opinionated table of contents generator.

v1.3.1(1mo ago)06MITPHPPHP ^8.2CI passing

Since Apr 26Pushed 1mo ago1 watchersCompare

[ Source](https://github.com/cable8mm/toc)[ Packagist](https://packagist.org/packages/cable8mm/toc)[ Docs](https://github.com/cable8mm/toc)[ RSS](/packages/cable8mm-toc/feed)WikiDiscussions main Synced 2w ago

READMEChangelog (7)Dependencies (4)Versions (8)Used By (0)

TOC - Table of Contents Parser for Markdown
===========================================

[](#toc---table-of-contents-parser-for-markdown)

[![code-style](https://github.com/cable8mm/toc/actions/workflows/code-style.yml/badge.svg)](https://github.com/cable8mm/toc/actions/workflows/code-style.yml)[![run-tests](https://github.com/cable8mm/toc/actions/workflows/run-tests.yml/badge.svg)](https://github.com/cable8mm/toc/actions/workflows/run-tests.yml)[![Packagist Version](https://camo.githubusercontent.com/f8a7f9e1fe622e43c96d139a3d45e752fce4a17de3ea7c2d88b86fe59466958d/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6361626c65386d6d2f746f63)](https://packagist.org/packages/cable8mm/toc)[![Packagist Downloads](https://camo.githubusercontent.com/0b687b7b3bad56394c9e71531ac43cc54dfc85fd7c00dc44c72bb6003dac8b95/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6361626c65386d6d2f746f63)](https://packagist.org/packages/cable8mm/toc/stats)[![Packagist Dependency Version](https://camo.githubusercontent.com/f2c689322c81b562ba6f598b90dc480521d2ea2c3f86992ff86d4056207a2efc/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f646570656e64656e63792d762f6361626c65386d6d2f746f632f706870)](https://packagist.org/packages/cable8mm/toc)[![Packagist Stars](https://camo.githubusercontent.com/51d81e374d3b48cd9abf94d4a69735d62d5a78bb5eb97fc5082608a3928f55bd/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f73746172732f6361626c65386d6d2f746f63)](https://github.com/cable8mm/toc/stargazers)[![Packagist License](https://camo.githubusercontent.com/6fb75475c387dc8c3ec3c7dcbfb43a092219891a5de7e20a9a8414ef65a8e43c/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f6361626c65386d6d2f746f63)](https://github.com/cable8mm/toc/blob/main/LICENSE)

**TOC** parses Markdown documents and extracts table of contents (navigation) structures. It supports multiple documentation formats including Laravel, Samsung Tizen, Naver Clova AI, and Rhymix.

Originally built for the [document2](https://github.com/cable8mm/document2) project.

---

Installation
------------

[](#installation)

```
composer require cable8mm/toc
```

---

Quick Start
-----------

[](#quick-start)

Parse a Markdown TOC and iterate over its items:

```
use Cable8mm\Toc\Toc;

$markdown = '
- ## Prologue
    - [Release Notes](/docs/{{version}}/releases)
    - [Upgrade Guide](/docs/{{version}}/upgrade)
    - [Contribution Guide](/docs/{{version}}/contributions)
- ## Getting Started
    - [Installation](/docs/{{version}}/installation)
    - [Configuration](/docs/{{version}}/configuration)
';

$lines = Toc::of($markdown)->getLines();

foreach ($lines as $line) {
    echo $line->getTitle().PHP_EOL;      // "Prologue", "Release Notes", ...
    echo $line->getLink().PHP_EOL;       // null, "/docs/{{version}}/releases", ...
    echo $line->getType()->name.PHP_EOL; // "section", "page", ...
    echo $line->getDepth().PHP_EOL;      // 1, 2, ...
}
```

---

Supported Document Styles
-------------------------

[](#supported-document-styles)

### Laravel Style (`- ## Section`, indented `- [Page](link)`)

[](#laravel-style----section-indented---pagelink)

```
- ## Prologue
  - [Release Notes](/docs/{{version}}/releases)
  - [Upgrade Guide](/docs/{{version}}/upgrade)
```

### Samsung Tizen Style (`# Section`, `## [Page](link)`)

[](#samsung-tizen-style--section--pagelink)

```
# What is Tizen?

## Versions

## [Overview](/platform/what-is-tizen/overview.md)

### [TV](/platform/what-is-tizen/profiles/tv.md)
```

### Naver Clova AI Style (`# Section`, `* [Page](link)` with 2-space indent)

[](#naver-clova-ai-style--section--pagelink-with-2-space-indent)

```
# Summary

## Clova Face Recognition

- [CFR API란?](/CFR/API_Guide.md#Overview)
  - [유명인 얼굴 인식 API](/CFR/API_Guide.md#CelebrityAPI)
```

### Rhymix Style (`### Section`, `- [Page](link)`)

[](#rhymix-style--section---pagelink)

```
### 개요

- [설치 환경](./ko/introduction/requirements.md)
- [라이믹스 설치](./ko/introduction/install.md)
```

---

API Reference
-------------

[](#api-reference)

### `Toc` — Main parser class

[](#toc--main-parser-class)

MethodDescriptionReturns`Toc::of(string $markdown)`Create and parse markdown in one call (factory)`Toc``new Toc(string $markdown)`Create instance (call `->of()` to parse)`Toc``getLines()`Get all parsed line items`Item[]``getLine(int $n)`Get the nth line item (0-based)`Item``getSectionTitle(string $pageTitle)`Find the section title containing a page`?string``toArray()`Get grouped sections with their pages`array``addConverters(ConverterInterface[])`Add custom preprocessors`static`**Example — find which section a page belongs to:**

```
$toc = Toc::of($markdown);
echo $toc->getSectionTitle('Release Notes'); // "Prologue"
echo $toc->getSectionTitle('Installation');  // "Getting Started"
```

**Example — grouped navigation structure:**

```
$sections = Toc::of($markdown)->toArray();

foreach ($sections as $section) {
    echo $section['section']->getTitle().PHP_EOL; // Section heading
    foreach ($section['pages'] as $page) {
        echo '  - '.$page->getTitle().PHP_EOL;    // Page under this section
    }
}
```

### `Item` — A single TOC line

[](#item--a-single-toc-line)

MethodDescriptionReturns`getTitle()`Extract the display title`string``getLink()`Extract the URL (if it's a link)`?string``getType()`Whether it's a `section` or `page``ItemEnum``getDepth()`Nesting level (1-based)`int``toHtml()`Render as `` HTML tag`string`**Example — render as HTML:**

```
$lines = Toc::of($markdown)->getLines();

foreach ($lines as $line) {
    echo $line->toHtml().PHP_EOL;
    // Prologue
    // Release Notes
}
```

### `ItemEnum` — Item type enum

[](#itemenum--item-type-enum)

CaseMeaning`ItemEnum::section`A section heading (no link)`ItemEnum::page`A page entry (has a link)---

Advanced Usage
--------------

[](#advanced-usage)

### Custom depth calculation

[](#custom-depth-calculation)

Different documentation styles use different indent patterns. Pass style-specific parameters to `getDepth()`:

```
// Tizen style — uses '#' headings with '#' symbol
Item::of('## Versions')->getDepth(indent: '#', symbol: '#', initialHCount: 1, depth: 1);
// => 2

// Naver Clova style — uses '*' symbol with 2-space indent
Item::of('* [CFR API란?](/CFR/API_Guide.md#Overview)')
    ->getDepth(indent: '  ', symbol: '*', initialHCount: 1, depth: 2);
// => 3

// Rhymix style — starts from h3
Item::of('- [설치 환경](./ko/introduction/requirements.md)')
    ->getDepth(symbol: '-', initialHCount: 3, depth: 1);
// => 2
```

### Custom converters

[](#custom-converters)

Add preprocessors to clean or transform markdown before parsing:

```
use Cable8mm\Toc\Converters\CleanJustTopHConverter;

$toc = new Toc($markdown);
$toc->addConverters([
    new CleanJustTopHConverter, // Removes standalone top-level # headings
]);

// Now parse
$reflection = new ReflectionMethod(Toc::class, 'normalize');
$reflection->setAccessible(true);
$reflection->invoke($toc);
```

You can also implement your own converter by implementing `ConverterInterface`:

```
use Cable8mm\Toc\Contracts\ConverterInterface;
use Cable8mm\Toc\Types\MarkdownString;

class MyConverter implements ConverterInterface
{
    public function do(MarkdownString $markdown): MarkdownString
    {
        // Transform $markdown, then return a new MarkdownString
        $cleaned = some_transformation((string) $markdown);
        return new MarkdownString($cleaned);
    }
}
```

---

Testing
-------

[](#testing)

```
composer test
```

---

Code Style
----------

[](#code-style)

```
composer lint    # Auto-fix PSR-12 issues
composer inspect # Check PSR-12 compliance
```

---

License
-------

[](#license)

The MIT License (MIT). See [LICENSE](LICENSE).

###  Health Score

43

—

FairBetter than 89% of packages

Maintenance93

Actively maintained with recent releases

Popularity4

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity59

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% 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 ~134 days

Recently: every ~201 days

Total

7

Last Release

35d ago

PHP version history (2 changes)v1.0.0PHP ^8.1

v1.3.1PHP ^8.2

### Community

Maintainers

![](https://www.gravatar.com/avatar/c910c874a0263a18f9f976273054cd45faa3ffbcba7891992f4ab52d0656dd93?d=identicon)[Sam Lee](/maintainers/Sam%20Lee)

---

Top Contributors

[![cable8mm](https://avatars.githubusercontent.com/u/2672043?v=4)](https://github.com/cable8mm "cable8mm (15 commits)")

---

Tags

document2

###  Code Quality

TestsPest

Code StyleLaravel Pint

### Embed Badge

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

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

PHPackages © 2026

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