|
@@ -0,0 +1,88 @@
|
|
|
+<?php
|
|
|
+
|
|
|
+declare(strict_types=1);
|
|
|
+
|
|
|
+namespace app\common\utils;
|
|
|
+
|
|
|
+use \Parsedown;
|
|
|
+
|
|
|
+/**
|
|
|
+ * markdown 解析
|
|
|
+ */
|
|
|
+class ParsedownUtils extends Parsedown
|
|
|
+{
|
|
|
+ protected $isTocEnabled = false;
|
|
|
+
|
|
|
+ protected $rawTocList = [];
|
|
|
+
|
|
|
+ protected $findTocSyntaxRule = '#^<p> *\[TOC\]\s*</p>$#m';
|
|
|
+
|
|
|
+ public function setTocEnabled($isTocEnable)
|
|
|
+ {
|
|
|
+ $this->isTocEnabled = $isTocEnable;
|
|
|
+
|
|
|
+ return $this;
|
|
|
+ }
|
|
|
+
|
|
|
+ public function setTocSyntaxRule($findTocSyntaxRule)
|
|
|
+ {
|
|
|
+ $this->findTocSyntaxRule = $findTocSyntaxRule;
|
|
|
+
|
|
|
+ return $this;
|
|
|
+ }
|
|
|
+
|
|
|
+ public function text($text)
|
|
|
+ {
|
|
|
+ $content = parent::text($text);
|
|
|
+
|
|
|
+ if (!$this->isTocEnabled || empty($this->rawTocList) || !preg_match($this->findTocSyntaxRule, $content)) {
|
|
|
+ return ["toc"=>"","content"=>$content];
|
|
|
+ }
|
|
|
+
|
|
|
+ $content = preg_replace($this->findTocSyntaxRule, "", $content);
|
|
|
+ return ["toc"=>$this->buildToc(), "content"=>$content];
|
|
|
+ }
|
|
|
+
|
|
|
+ protected function buildToc()
|
|
|
+ {
|
|
|
+ $tocMarkdownContent = '';
|
|
|
+ $topHeadLevel = min(array_column($this->rawTocList, 'level'));
|
|
|
+
|
|
|
+ foreach ($this->rawTocList as $id => $tocItem) {
|
|
|
+ $tocMarkdownContent .= sprintf('%s- [%s](#%s)' . PHP_EOL, str_repeat(' ', $tocItem['level'] - $topHeadLevel), $this->line($tocItem['text']), $tocItem['id']);
|
|
|
+ }
|
|
|
+
|
|
|
+ return parent::text($tocMarkdownContent);
|
|
|
+ }
|
|
|
+
|
|
|
+ protected function blockHeader($line)
|
|
|
+ {
|
|
|
+ $block = parent::blockHeader($line);
|
|
|
+ $text = $block['element']['handler']['argument'];
|
|
|
+ $no = 0;
|
|
|
+ foreach ($this->rawTocList as $key => $value) {
|
|
|
+ if ($text == $value['text']) {
|
|
|
+ $no = $value['no'] + 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ $id = urlencode($this->line($text));
|
|
|
+
|
|
|
+ if ($no != 0) {
|
|
|
+ $id .= '-' . $no;
|
|
|
+ }
|
|
|
+
|
|
|
+ $block['element']['attributes'] = [
|
|
|
+ 'id' => $id,
|
|
|
+ ];
|
|
|
+
|
|
|
+ $this->rawTocList[] = [
|
|
|
+ 'id' => $id,
|
|
|
+ 'text' => $text,
|
|
|
+ 'level' => str_replace('h', '', $block['element']['name']),
|
|
|
+ 'no'=> $no,
|
|
|
+ ];
|
|
|
+
|
|
|
+ return $block;
|
|
|
+ }
|
|
|
+}
|