技术控

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

[其他] TOC的生成

[复制链接]
我怀念的 发表于 2016-10-4 22:17:18
173 1
TOC是什么

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

  由于原始文档的格式(markdown,html,asciidoc)比较多,但是用于最后展示的还是    html,所以为了方便统一的处理,先将文档都选染成html  
      

TOC的生成

TOC的生成
  
  
       
  •       使用        ParseDown渲染markdown      
       
  •       使用        Crawler解析html      
       
  •       提取        h{n},结构化        h{n},并设置html中的        id属性      
       
  •       展示树形 TOC
      
  预览

      

TOC的生成

TOC的生成
  
  实现

  安装依赖包
  1. composer require erusev/parsedown-extra
  2. composer require symfony/dom-crawler
  3. composer require symfony/css-selector
复制代码
代码实现
  1. public function getTocAttribute() {
  2.     if ($this->headerNodes) {
  3.         return $this->headerNodes;
  4.     }
  5.     $crawler = new Crawler();
  6.     $crawler->addHtmlContent($this->html, 'utf-8');
  7.     $this->headerNodes = $crawler->filter('h1,h2,h3,h4,h5,h6')->each(function (Crawler $node, $i) {
  8.         $attrId = 'header_' . $i;
  9.         $node->getNode(0)->setAttribute('id', $attrId);
  10.         return [
  11.             'target' => '#' . $attrId,
  12.             'level' => intval(substr($node->nodeName(), 1)),
  13.             'text' => $node->text(),
  14.         ];
  15.     });
  16.     $this->tocedHtml = $crawler->html();
  17.     return $this->headerNodes;
  18. }
复制代码
树形结构化
  1. class MenuItem {
  2.     public $level;
  3.     public $text;
  4.     public $target;
  5.     public $children = [];
  6.     public function __construct($target, $level, $text) {
  7.         $this->target = $target;
  8.         $this->level = $level;
  9.         $this->text = $text;
  10.     }
  11. }
  12. $rootMenu = new MenuItem(-1, 0, '__root__');
  13. foreach ($wiki->toc as $hn) {
  14.     $menuItem = new MenuItem($hn['target'], $hn['level'], $hn['text']);
  15.     // 每个菜单都从根目录开始寻找
  16.     $lastMenu = $rootMenu;
  17.     while (true) {
  18.         $nestMenu = end($lastMenu->children);
  19.         // 如果比上个层级还大,就挂载到他后面
  20.         if (!$nestMenu && $hn['level'] > $lastMenu->level) {
  21.             $lastMenu->children[] = $menuItem;
  22.             break;
  23.         }
  24.         // 如果循环下来发现没有匹配的层级,则放进根目录
  25.         if ($hn['level'] < $nestMenu->level) {
  26.             $rootMenu->children[] = $menuItem;
  27.             break;
  28.         }
  29.         // 如果和上个层级一样,就赛到上层的children
  30.         if ($nestMenu->level >= $hn['level']) {
  31.             $lastMenu->children[] = $menuItem;
  32.             break;
  33.         }
  34.         $lastMenu = $nestMenu;
  35.     }
  36. }
复制代码
渲染输出
  1. function tree($menu) {
  2.     $html = '<ul>';
  3.     $html .= '<li><a href="' . $menu->target . '">' . $menu->text . '</a>';
  4.     if ($menu->children) {
  5.         foreach ($menu->children as $subMenu) {
  6.             $html .= tree($subMenu);
  7.         }
  8.     }
  9.     $html .= '</li></ul>';
  10.     return $html;
  11. }
  12. echo '<div class="wiki-index"><div class="wiki-index-header">文章目录</div><div class="wiki-index-body">';
  13. foreach ($rootMenu->children as $menu) {
  14.     echo tree($menu);
  15. }
  16. echo '</div></div>';
复制代码
刘文博 发表于 2016-10-7 02:41:37
来,来,干了这杯翔!
回复 支持 反对

使用道具 举报

我要投稿

推荐阅读


回页顶回复上一篇下一篇回列表
手机版/c.CoLaBug.com ( 粤ICP备05003221号 | 粤公网安备 44010402000842号 )

© 2001-2017 Comsenz Inc.

返回顶部 返回列表