caseyamcl / toc
PHP 简单目录生成器。基于 H1...H6 标签生成目录
Requires
- php: ^7.2|^8.0
- ext-dom: *
- cocur/slugify: ^3.0|^4.0
- knplabs/knp-menu: ^3.2
- masterminds/html5: ^2.1
Requires (Dev)
- jaschilz/php-coverage-badger: ^2.0
- phpstan/phpstan: ^1.4
- phpunit/phpunit: ^7.5|^8.0|^9.0
- squizlabs/php_codesniffer: ^3.5
- twig/twig: ^2.4|^3.0
README
从 HTML 内容中的 H1...H6 标签生成目录
注意:此库现在需要 PHP 7.2 或更高版本;为了保留 PHP5-7.1 支持,请使用以下 composer 指令: composer require caseyamcl/toc ~2.0.0
此包提供了一个简单、无框架依赖的库,用于从 HTML 标记构建目录。它是通过评估您的 H1...H6 标签来实现的。它还可以自动为标题标签添加适当的 id 锚点属性,以便页内链接可以正常工作。
特性
- 生成 HTML 菜单和 KnpMenu Item 菜单
- 为您的内容中的 H1...H6 标签添加锚点 ID 属性,如果它们尚未存在
- 您可以指定要在目录中包含哪些 H1...H6 标题标签级别
- 包含一个 Twig 扩展,可以直接在模板中生成目录和兼容的标记
- 使用灵活的 KnpMenu 库 生成菜单
- 符合 PSR-12 规范
- 兼容 Composer
- 单元测试(95% 覆盖率)
遵循 KISS 原则,此库做了一些假设
- 您的内容层次结构完全由标题(H1...H6)标签定义。在生成目录时忽略所有其他标签。
- 目录中的链接标题与标题标签的
title
属性匹配,或者如果没有title
,则匹配标题标签的(缩略化)纯文本内容。
安装选项
通过在您的 composer.json
文件中包含以下内容通过 Composer 安装:
{
"require": {
"caseyamcl/toc": "^3.0",
}
}
或者,将 src
文件夹放入您的应用程序中,并使用 PSR-4 自动加载器 包含文件。
使用方法
此包包含两个主要类
TOC\MarkupFixer
:为任何尚未有锚点属性的 H1...H6 标签添加锚点属性(您可以在运行时指定要使用的标题标签级别)TOC\TocGenerator
:从 HTML 标记生成目录
基本示例
$myHtmlContent = <<<END <h1>This is a header tag with no anchor id</h1> <p>Lorum ipsum doler sit amet</p> <h2 id='foo'>This is a header tag with an anchor id</h2> <p>Stuff here</p> <h3 id='bar'>This is a header tag with an anchor id</h3> END; $markupFixer = new TOC\MarkupFixer(); $tocGenerator = new TOC\TocGenerator(); // This ensures that all header tags have `id` attributes so they can be used as anchor links $htmlOut = "<div class='content'>" . $markupFixer->fix($myHtmlContent) . "</div>"; // This generates the Table of Contents in HTML $htmlOut .= "<div class='toc'>" . $tocGenerator->getHtmlMenu($htmlOut) . "</div>"; echo $htmlOut;
这将产生以下输出
<div class='content'> <h1 id="this-is-a-header-tag-with-no-anchor-id">This is a header tag with no anchor id</h1> <p>Lorum ipsum doler sit amet</p> <h2 id="foo">This is a header tag with an anchor id</h2> <p>Stuff here</p> <h3 id="bar">This is a header tag with an anchor id</h3> </div> <div class='toc'> <ul> <li class="first last"> <span></span> <ul class="menu_level_1"> <li class="first last"> <a href="#foo">This is a header tag with an anchor id</a> <ul class="menu_level_2"> <li class="first last"> <a href="#bar">This is a header tag with an anchor id</a> </li> </ul> </li> </ul> </li> </ul> </div>
Twig 集成
此库包含一个 Twig 扩展,允许您从 Twig 模板加载 TOC 列表并为标记添加锚点。
为了启用 Twig 集成,您必须将 TocTwigExtension
注册到您的 Twig 环境中
use Twig\Environment; use Twig\Loader\FilesystemLoader; $myTwig = new Environment(new FilesystemLoader()); $myTwig->addExtension(new TOC\TocTwigExtension());
具体来说,此扩展添加了一个用于生成目录 HTML 的 Twig 函数
{# Generates HTML markup for given htmlContent #} <ul>{{ toc(htmlContent) }}</ul>
它还提供了一个函数和一个过滤器,以确保您的所有内容都包含所有 HTML 标题标签的锚点。它们都做同样的事情,因此请根据您的需求选择最适合您的选项
{# Adds anchor links (id tags) for given htmlContent #} {{ add_anchors(htmlContent) }} {# You can also use it as a filter #} <div class='my_content'> {{ htmlContent | add_anchors }} </div>
您的 HTML 内容可能已在 Twig 模板中硬编码。为了适应这种情况,请确保内容被 {% block %}...{% endblock %}
标签包围,然后只需将那个块传递给 toc 函数。
例如
{% extends 'base.html.twig' %} {% block page_content %} <div class='page_sidebar'> {{ toc(add_anchors(block('my_writeup'))) }} </div> <div class='page_content'> {{ add_anchors(block('my_writeup')) }} </div> {% endblock %} {% block my_writeup %} <h1>Hi There</h1> <p>Lorum ipsum baz biz etecetra</p> <h2>This is some content</h2> <p>More content here. Blah blah</p> {% endblock %}
指定要包含的标题级别
您可以选择只包括TOC中的特定h1...h6标题级别。为此,请向TocGenerator::getHtmlMenu()
方法传递两个额外的参数:$topLevel
和$depth
。例如
$tocGenerator = new TOC\TocGenerator(); $someHtmlContent = '<div><h1>Test</h1><p>Lorum ipsum</p><h2>Test2</h2><p>Lorum ipsum</p></div>'; // 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);
该包中的大多数其他方法也处理这些参数
$tocGenerator = new TOC\TocGenerator(); $markupFixer = new TOC\MarkupFixer(); $someHtmlContent = '<div><h1>Test</h1><p>Lorum ipsum</p><h2>Test2</h2><p>Lorum ipsum</p></div>'; // Get KnpMenu using h1, h2, h3 $tocGenerator->getMenu($someHtmlContent, 1, 3); // Fix markup for h3, h4 tags only $markupFixer->fix($someHtmlContent, 3, 2);
Twig函数和过滤器也接受这些参数
{# Generate TOC using h2, h3 tags #} {{ toc(my_content, 2, 3) }} {# Add anchors to h4, h5, h6 tags #} {{ my_content | add_anchors(4, 3) }}
自定义菜单输出
您可以为TocGenerator
类输出的列表进行自定义渲染。默认情况下,TocGenerator
使用KnpMenu ListRenderer类来输出HTML。
您可以将自己的ListRenderer
类实例传递给TocGenerator::getHtmlMenu()
。或者,您也可以传递自己的渲染器(实现Knp\Menu\Renderer\RendererInterface
)。
例如,您可能希望为列表项使用不同的CSS类
$someHtmlContent = '<div><h1>Test</h1><p>Lorum ipsum</p><h2>Test2</h2><p>Lorum ipsum</p></div>'; $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);
使用Twig进行自定义
KnpMenu库比该库默认提供的更全面地集成了Twig模板系统。您可以通过使用KnpMenu捆绑的TwigRenderer来利用它。
use Knp\Menu\Matcher\Matcher; use Knp\Menu\Renderer\TwigRenderer; use Twig\Environment; use Twig\Loader\FilesystemLoader; $someHtmlContent = '<div><h1>Test</h1><p>Lorum ipsum</p><h2>Test2</h2><p>Lorum ipsum</p></div>'; $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));
有序列表与无序列表
KnpMenu库默认生成无序列表(ul
)。此库包含一个用于有序列表的自定义渲染器,无论您是否使用Twig
$someHtmlContent = '<div><h1>Test</h1><p>Lorum ipsum</p><h2>Test2</h2><p>Lorum ipsum</p></div>'; // Ordered List $orderedRenderedList = (new TOC\TocGenerator())->getOrderedHtmlMenu($someHtmlContent);
Twig使用方法
{# 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) }}