技术控

    今日:59| 主题:49211
收藏本版 (1)
最新软件应用技术尽在掌握

[其他] TOC的生成

[复制链接]
我怀念的 发表于 2016-10-4 22:17:18
106 1

立即注册CoLaBug.com会员,免费获得投稿人的专业资料,享用更多功能,玩转个人品牌!

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
TOC是什么

  TOC 即 Table of Content,就是将文档中的    h1-h6抽取出来,并结构化的展示;可以通过链接直接跳转到相应的内容 (这里我使用锚点)  
  这个本身是没什么好写的,但是涉及到树形的结构化处理,要考虑到怪异的层级问题。
  方案

  由于原始文档的格式(markdown,html,asciidoc)比较多,但是用于最后展示的还是    html,所以为了方便统一的处理,先将文档都选染成html  
      
TOC的生成-1 (function,require,public,return)
  
  
       
  •       使用        ParseDown渲染markdown      
       
  •       使用        Crawler解析html      
       
  •       提取        h{n},结构化        h{n},并设置html中的        id属性      
       
  •       展示树形 TOC
      
  预览

TOC的生成-2 (function,require,public,return)
  
  实现

  安装依赖包
  [code]composer require erusev/parsedown-extra
composer require symfony/dom-crawler
composer require symfony/css-selector[/code]  代码实现
  [code]public function getTocAttribute() {
    if ($this->headerNodes) {
        return $this->headerNodes;
    }
    $crawler = new Crawler();
    $crawler->addHtmlContent($this->html, 'utf-8');
    $this->headerNodes = $crawler->filter('h1,h2,h3,h4,h5,h6')->each(function (Crawler $node, $i) {
        $attrId = 'header_' . $i;
        $node->getNode(0)->setAttribute('id', $attrId);
        return [
            'target' => '#' . $attrId,
            'level' => intval(substr($node->nodeName(), 1)),
            'text' => $node->text(),
        ];
    });
    $this->tocedHtml = $crawler->html();
    return $this->headerNodes;
}[/code]  树形结构化
  [code]class MenuItem {
    public $level;
    public $text;
    public $target;
    public $children = [];
    public function __construct($target, $level, $text) {
        $this->target = $target;
        $this->level = $level;
        $this->text = $text;
    }
}
$rootMenu = new MenuItem(-1, 0, '__root__');
foreach ($wiki->toc as $hn) {
    $menuItem = new MenuItem($hn['target'], $hn['level'], $hn['text']);
    // 每个菜单都从根目录开始寻找
    $lastMenu = $rootMenu;
    while (true) {
        $nestMenu = end($lastMenu->children);
        // 如果比上个层级还大,就挂载到他后面
        if (!$nestMenu && $hn['level'] > $lastMenu->level) {
            $lastMenu->children[] = $menuItem;
            break;
        }
        // 如果循环下来发现没有匹配的层级,则放进根目录
        if ($hn['level'] < $nestMenu->level) {
            $rootMenu->children[] = $menuItem;
            break;
        }
        // 如果和上个层级一样,就赛到上层的children
        if ($nestMenu->level >= $hn['level']) {
            $lastMenu->children[] = $menuItem;
            break;
        }
        $lastMenu = $nestMenu;
    }
}[/code]  渲染输出
  [code]function tree($menu) {
    $html = '
    ';
        $html .= '
  • ' . $menu->text . '';
        if ($menu->children) {
            foreach ($menu->children as $subMenu) {
                $html .= tree($subMenu);
            }
        }
        $html .= '
';
    return $html;
}
echo '
文章目录
';
foreach ($rootMenu->children as $menu) {
    echo tree($menu);
}
echo '
';[/code]
友荐云推荐




上一篇:How does public key cryptography work? – Gary explains
下一篇:Material Animations 1:Content Transitions
酷辣虫提示酷辣虫禁止发表任何与中华人民共和国法律有抵触的内容!所有内容由用户发布,并不代表酷辣虫的观点,酷辣虫无法对用户发布内容真实性提供任何的保证,请自行验证并承担风险与后果。如您有版权、违规等问题,请通过"联系我们"或"违规举报"告知我们处理。

刘文博 发表于 2016-10-7 02:41:37
来,来,干了这杯翔!
回复 支持 反对

使用道具 举报

*滑动验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

我要投稿

推荐阅读

扫码访问 @iTTTTT瑞翔 的微博
回页顶回复上一篇下一篇回列表手机版
手机版/CoLaBug.com ( 粤ICP备05003221号 | 文网文[2010]257号 )|网站地图 酷辣虫

© 2001-2016 Comsenz Inc. Design: Dean. DiscuzFans.

返回顶部 返回列表