ParsedownUtils.php 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. <?php
  2. declare(strict_types=1);
  3. namespace app\utils;
  4. use \Parsedown;
  5. /**
  6. * markdown 解析
  7. */
  8. class ParsedownUtils extends Parsedown
  9. {
  10. protected $isTocEnabled = false;
  11. protected $rawTocList = [];
  12. protected $findTocSyntaxRule = '#^<p> *\[TOC\]\s*</p>$#m';
  13. public function setTocEnabled($isTocEnable)
  14. {
  15. $this->isTocEnabled = $isTocEnable;
  16. return $this;
  17. }
  18. public function setTocSyntaxRule($findTocSyntaxRule)
  19. {
  20. $this->findTocSyntaxRule = $findTocSyntaxRule;
  21. return $this;
  22. }
  23. public function text($text)
  24. {
  25. $content = parent::text($text);
  26. if (!$this->isTocEnabled || empty($this->rawTocList) || !preg_match($this->findTocSyntaxRule, $content)) {
  27. return ["toc"=>"","content"=>$content];
  28. }
  29. $content = preg_replace($this->findTocSyntaxRule, "", $content);
  30. return ["toc"=>$this->buildToc(), "content"=>$content];
  31. }
  32. protected function buildToc()
  33. {
  34. $tocMarkdownContent = '';
  35. $topHeadLevel = min(array_column($this->rawTocList, 'level'));
  36. foreach ($this->rawTocList as $id => $tocItem) {
  37. $tocMarkdownContent .= sprintf('%s- [%s](#%s)' . PHP_EOL, str_repeat(' ', $tocItem['level'] - $topHeadLevel), $this->line($tocItem['text']), $tocItem['id']);
  38. }
  39. return parent::text($tocMarkdownContent);
  40. }
  41. protected function blockHeader($line)
  42. {
  43. $block = parent::blockHeader($line);
  44. $text = $block['element']['handler']['argument'];
  45. $no = 0;
  46. foreach ($this->rawTocList as $key => $value) {
  47. if ($text == $value['text']) {
  48. $no = $value['no'] + 1;
  49. }
  50. }
  51. $id = urlencode($this->line($text));
  52. if ($no != 0) {
  53. $id .= '-' . $no;
  54. }
  55. $block['element']['attributes'] = [
  56. 'id' => $id,
  57. ];
  58. $this->rawTocList[] = [
  59. 'id' => $id,
  60. 'text' => $text,
  61. 'level' => str_replace('h', '', $block['element']['name']),
  62. 'no'=> $no,
  63. ];
  64. return $block;
  65. }
  66. }