PHP 简单目录生成器。基于 H1...H6 标签生成目录

v3.1 2022-03-16 15:46 UTC

This package is auto-updated.

Last update: 2024-08-29 14:11:42 UTC


README

从 HTML 内容中的 H1...H6 标签生成目录

Latest Version on Packagist Software License Github Build Code coverage PHPStan Level 8 Total Downloads

注意:此库现在需要 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 原则,此库做了一些假设

  1. 您的内容层次结构完全由标题(H1...H6)标签定义。在生成目录时忽略所有其他标签。
  2. 目录中的链接标题与标题标签的 title 属性匹配,或者如果没有 title,则匹配标题标签的(缩略化)纯文本内容。

安装选项

通过在您的 composer.json 文件中包含以下内容通过 Composer 安装:

{
    "require": {
        "caseyamcl/toc": "^3.0",
    }
}

或者,将 src 文件夹放入您的应用程序中,并使用 PSR-4 自动加载器 包含文件。

使用方法

此包包含两个主要类

  1. TOC\MarkupFixer:为任何尚未有锚点属性的 H1...H6 标签添加锚点属性(您可以在运行时指定要使用的标题标签级别)
  2. 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) }}