1.5提纲头疼中

This commit is contained in:
跨越晨昏 2024-10-05 18:25:00 +08:00
parent 900d999b7a
commit 54c2584b0f
2 changed files with 179 additions and 114 deletions

View File

@ -1,13 +1,14 @@
import xml
import emoji
from markdown.extensions import Extension from markdown.extensions import Extension
from markdown.treeprocessors import Treeprocessor from markdown.treeprocessors import Treeprocessor
from markdown.inlinepatterns import Pattern as Pattern_ from markdown.inlinepatterns import Pattern as Pattern_
from markdown.preprocessors import Preprocessor from markdown.preprocessors import Preprocessor
from markdown.inlinepatterns import InlineProcessor from markdown.inlinepatterns import InlineProcessor
from markdown.blockprocessors import BlockProcessor
from markdown import Markdown from markdown import Markdown
from typing import * from typing import *
import re import re
import xml
import emoji
Extensions = { Extensions = {
"Extra": "markdown.extensions.extra", "Extra": "markdown.extensions.extra",
@ -120,6 +121,56 @@ class Emoji(InlineProcessor):
return emoji.emojize(match.group(0)), match.start(), match.end() return emoji.emojize(match.group(0)), match.start(), match.end()
class Syllabus_(InlineProcessor):
"""
需要对HTML标签设置ID实现的样式
"""
def __init__(self, pattern: str):
"""
初始化
:param pattern: 正则表达式
"""
super().__init__(pattern)
def handleMatch(self, match, match_line):
tag = xml.etree.ElementTree.Element(f'h{len(match.group(1).split("."))}') # 创建标签
tag.text = match.group(1) + ' ' + match.group(3) # 设置标签内容
tag.set('id', match.group(1)) # 设置标签属性
return tag, match.start(), match.end()
class Syllabus(BlockProcessor):
# 定义提纲的正则表达式
ALERT_RE = r'(\d+(\.\d+)*)\s+(.*)'
def test(self, parent, block):
# 检查当前块是否匹配我们的正则表达式
return bool(self.ALERT_RE.match(block))
def run(self, parent, blocks):
# 处理匹配的块
block = blocks.pop(0)
m = self.ALERT_RE.search(block)
if m:
before = block[:m.start()] # 匹配之前的文本
after = block[m.end():] # 匹配之后的文本
if before:
# 如果匹配之前有文本,则创建一个新的段落来包含它
p = etree.SubElement(parent, 'p')
p.text = before.strip()
# 创建包含警告内容的 div 元素
div = etree.SubElement(parent, 'div', {'class': 'alert'})
div.text = m.group(1).strip()
# 如果匹配之后还有文本,则将其重新添加到块列表中以便后续处理
if after.strip():
blocks.insert(0, after)
else:
# 如果没有匹配,则保留原始块以便后续处理器处理
return False
class Basic(Extension): class Basic(Extension):
""" """
渲染基本样式 渲染基本样式
@ -136,92 +187,10 @@ class Basic(Extension):
md.inlinePatterns.register(ID( md.inlinePatterns.register(ID(
r'\[(.*?)]-\((.*?)\)', tag='span', property_='title'), 'hide', 0 r'\[(.*?)]-\((.*?)\)', tag='span', property_='title'), 'hide', 0
) # [在指定的文本里面隐藏一段文本]-(只有鼠标放在上面才会显示隐藏文本) ) # [在指定的文本里面隐藏一段文本]-(只有鼠标放在上面才会显示隐藏文本)
md.inlinePatterns.register(Emoji( md.inlinePatterns.register(Emoji(r':(.+?):'), 'emoji', 0) # 将emoji短代码转换为emoji字符
r':(.+?):'), 'emoji', 0 md.inlinePatterns.register(Syllabus(r'(\d+(\.\d+)*)\s+(.*)'), 'syllabus', 0) # 渲染提纲
) # 将emoji短代码转换为emoji字符
class Syllabus(Preprocessor):
def run(self, lines: List[str]) -> List[str]:
return [
(lambda match, origen:
re.sub(f'^({match.groups()[0]})', # 按照提纲等级添加#和锚点
fr'{"#" * len(match.groups()[0].split("."))} \1', origen)
if match is not None else origen) # 对于不是提纲的行,直接返回原始字符
((lambda x: re.match(r'^([\d.]+) ', x) # 判断是否是提纲
if not any((x.startswith('.'), # 以.开头
re.search('\. ', x) is not None, # 存在.+空格
re.search('\.{2,}', x), # 存在连续的.
))
else None)(line), line) # 排除.在提纲号开头或结尾的情况
for line in lines # 分割并遍历文本的每一行
]
class Value(Preprocessor):
def run(self, lines: List[str]) -> List[str]:
values = {
key: value.strip() # 去除值两侧的空白字符
for line in lines
for match in [re.match(r'\{([^{}#]+)} ?= ?(.+?)(?=\n|$)', line)]
if match
for key, value in [match.groups()]
} # 识别变量定义
anchors = re.findall(r'\{#([^{}#]+)}', '\n'.join(lines)) # 识别锚点定义
text = '\n'.join(lines) # 先合并成一行
for item in anchors:
text = re.sub(r'\{#(' + item + ')}', r'<span id="\1"></span>', text) # 添加锚点
text = re.sub(r'\{' + item + '}', fr'<a href="#{item}">{item}</a>', text) # 添加页内链接
for k, v in values.items():
text = re.sub(r'\{' + k + '} ?= ?(.+?)(?=\n|$)', '', text) # 移除变量的定义
text = re.sub(r'\{' + k + '}', fr'{v}', text) # 给变量赋值
return text.split('\n') # 再分割为列表
class Tag(Treeprocessor):
def run(self, root):
"""
通过修改AST来给标题添加锚点
"""
for header in root.iter():
if header.tag in ('h1', 'h2', 'h3', 'h4', 'h5', 'h6'): # 查找标题
header.set('id', header.text.split(' ')[0]) # 给标题添加锚点
elif header.tag == 'ul': # 是无序列表
for i in header: # 遍历列表内容
try:
i[0].set('href', '#' + i[0].text.split(' ')[0]) # 是目录,更改链接为标准格式
except IndexError:
pass # 是普通的无序列表
class Basic_(Extension):
"""
基本扩展
"""
def extendMarkdown(self, md):
md.registerExtension(self) # 注册扩展
md.preprocessors.register(Syllabus(md), 'syllabus', 0)
class More(Extension):
"""
高级扩展
"""
def extendMarkdown(self, md):
md.preprocessors.register(Value(md), 'values', 0)
class Decorate(Extension):
"""
修饰扩展,最后处理
"""
def extendMarkdown(self, md):
md.treeprocessors.register(Tag(md), 'header', 0)
def main(text: str) -> Tuple[str, Dict[str, List[str]]]: def main(text: str) -> Tuple[str, Dict[str, List[str]]]:
md = Markdown(extensions=[Basic(), Basic_(), More()] + list(Extensions.values()) + [Decorate()], safe_mode=False) md = Markdown(extensions=[Basic()] + list(Extensions.values()), safe_mode=False)
return md.convert(text), md.Meta return md.convert(text), md.Meta

View File

@ -29,17 +29,17 @@
</script> </script>
<div class="toc"> <div class="toc">
<ul> <ul>
<li><a href="#CrossDown">CrossDown</a></li> <li><a href="#crossdown">CrossDown</a></li>
<li><a href="#1">1 基本语法</a><ul> <li><a href="#1">1 基本语法</a><ul>
<li><a href="#1.1">1.1 标题</a></li> <li><a href="#1.1">1.1 标题</a></li>
</ul> </ul>
</li> </li>
<li><a href="#一级标题">一级标题</a><ul> <li><a href="#_1">一级标题</a><ul>
<li><a href="#二级标题">二级标题</a><ul> <li><a href="#_2">二级标题</a><ul>
<li><a href="#三级标题">三级标题</a><ul> <li><a href="#_3">三级标题</a><ul>
<li><a href="#四级标题">四级标题</a><ul> <li><a href="#_4">四级标题</a><ul>
<li><a href="#五级标题">五级标题</a><ul> <li><a href="#_5">五级标题</a><ul>
<li><a href="#六级标题">六级标题</a></li> <li><a href="#_6">六级标题</a></li>
</ul> </ul>
</li> </li>
</ul> </ul>
@ -94,10 +94,12 @@
<li><a href="#7">7 提纲</a><ul> <li><a href="#7">7 提纲</a><ul>
<li><a href="#7.1">7.1 提纲号</a><ul> <li><a href="#7.1">7.1 提纲号</a><ul>
<li><a href="#7.1.1">7.1.1 提纲号示例</a></li> <li><a href="#7.1.1">7.1.1 提纲号示例</a></li>
<li><a href="#7.1.2">7.1.2 错误示范</a></li>
</ul> </ul>
</li> </li>
</ul> </ul>
</li> </li>
<li><a href="#4">4 错误示范</a></li>
<li><a href="#8">8 注释</a><ul> <li><a href="#8">8 注释</a><ul>
<li><a href="#8.1">8.1 强注释</a></li> <li><a href="#8.1">8.1 强注释</a></li>
<li><a href="#8.2">8.2 弱注释</a></li> <li><a href="#8.2">8.2 弱注释</a></li>
@ -105,7 +107,7 @@
</li> </li>
<li><a href="#9">9 列表</a><ul> <li><a href="#9">9 列表</a><ul>
<li><a href="#9.1">9.1 有序列表</a></li> <li><a href="#9.1">9.1 有序列表</a></li>
<li><a href="#9.2">9.2 无序列表</a></li> <li><a href="#9.2">9.2 无序列表klzzwxhklzzwxhklzzwxh:00800077- Cklzzwxh:0078- D</a></li>
</ul> </ul>
</li> </li>
<li><a href="#10">10 表格</a></li> <li><a href="#10">10 表格</a></li>
@ -120,58 +122,112 @@
<li><a href="#14">14 扩展</a></li> <li><a href="#14">14 扩展</a></li>
</ul> </ul>
</div> </div>
<h1 id="CrossDown">CrossDown</h1> <h1 id="crossdown">CrossDown</h1>
<p>自制的markdown,添加了一些自定义的语法klzzwxh:0001效果请见klzzwxh:0000</p> <p>自制的markdown,添加了一些自定义的语法klzzwxh:0001效果请见klzzwxh:0000</p>
<p>
<h1 id="1">1 基本语法</h1> <h1 id="1">1 基本语法</h1>
</p>
<p>
<h2 id="1.1">1.1 标题</h2> <h2 id="1.1">1.1 标题</h2>
<h1 id="一级标题">一级标题</h1> </p>
<h2 id="二级标题">二级标题</h2> <h1 id="_1">一级标题</h1>
<h3 id="三级标题">三级标题</h3> <h2 id="_2">二级标题</h2>
<h4 id="四级标题">四级标题</h4> <h3 id="_3">三级标题</h3>
<h5 id="五级标题">五级标题</h5> <h4 id="_4">四级标题</h4>
<h6 id="六级标题">六级标题</h6> <h5 id="_5">五级标题</h5>
<h6 id="_6">六级标题</h6>
<p>
<h2 id="1.2">1.2 样式</h2> <h2 id="1.2">1.2 样式</h2>
</p>
<p>
<h3 id="1.2.1">1.2.1 <em>斜体</em></h3> <h3 id="1.2.1">1.2.1 <em>斜体</em></h3>
</p>
<p>
<h3 id="1.2.2">1.2.2 <strong>粗体</strong></h3> <h3 id="1.2.2">1.2.2 <strong>粗体</strong></h3>
</p>
<p>
<h3 id="1.2.3">1.2.3 <strong><em>粗斜体</em></strong></h3> <h3 id="1.2.3">1.2.3 <strong><em>粗斜体</em></strong></h3>
</p>
<p>
<h3 id="1.2.4">1.2.4 <u>下划线</u></h3> <h3 id="1.2.4">1.2.4 <u>下划线</u></h3>
</p>
<p>
<h3 id="1.2.5">1.2.5 <s>删除线</s></h3> <h3 id="1.2.5">1.2.5 <s>删除线</s></h3>
</p>
<p>
<h3 id="1.2.6">1.2.6 <mark>高亮</mark></h3> <h3 id="1.2.6">1.2.6 <mark>高亮</mark></h3>
</p>
<p>
<h3 id="1.2.7">1.2.7 <ruby>在文本的正上方添加一行小文本<rt>主要用于标拼音</rt></ruby></h3> <h3 id="1.2.7">1.2.7 <ruby>在文本的正上方添加一行小文本<rt>主要用于标拼音</rt></ruby></h3>
</p>
<p>
<h3 id="1.2.8">1.2.8 <span title="只有鼠标放在上面才会显示隐藏文本">在指定的文本里面隐藏一段文本</span></h3> <h3 id="1.2.8">1.2.8 <span title="只有鼠标放在上面才会显示隐藏文本">在指定的文本里面隐藏一段文本</span></h3>
</p>
<p>
<h3 id="1.2.9">1.2.9 分割线</h3> <h3 id="1.2.9">1.2.9 分割线</h3>
</p>
<hr /> <hr />
<hr /> <hr />
<hr /> <hr />
<p>
<h2 id="1.3">1.3 链接</h2> <h2 id="1.3">1.3 链接</h2>
</p>
<p>
<h3 id="1.3.1">1.3.1 普通链接</h3> <h3 id="1.3.1">1.3.1 普通链接</h3>
</p>
<p><a href="链接地址">链接文本</a></p> <p><a href="链接地址">链接文本</a></p>
<p><a href="https://crossdark.com">CrossDark</a></p> <p><a href="https://crossdark.com">CrossDark</a></p>
<p><a href="https://crossdark.net/">https://crossdark.net/</a></p> <p><a href="https://crossdark.net/">https://crossdark.net/</a></p>
<p>
<h3 id="1.3.2">1.3.2 图片</h3> <h3 id="1.3.2">1.3.2 图片</h3>
</p>
<p><img alt="链接图片" src="链接地址" /></p> <p><img alt="链接图片" src="链接地址" /></p>
<p><img alt="sea" src="https://crossdark.com/wp-content/uploads/2024/05/1715259682-sea.jpg" /></p> <p><img alt="sea" src="https://crossdark.com/wp-content/uploads/2024/05/1715259682-sea.jpg" /></p>
<p>
<h3 id="1.3.3">1.3.3 变量链接</h3> <h3 id="1.3.3">1.3.3 变量链接</h3>
</p>
<p><a href="https://crossdark.com">链接文本</a></p> <p><a href="https://crossdark.com">链接文本</a></p>
<p>
<h1 id="2">2 <abbr title="长的文本">缩写</abbr></h1> <h1 id="2">2 <abbr title="长的文本">缩写</abbr></h1>
</p>
<p>
<h2 id="2.1">2.1 定义</h2> <h2 id="2.1">2.1 定义</h2>
</p>
<p>
<h2 id="2.2">2.2 赋值</h2> <h2 id="2.2">2.2 赋值</h2>
</p>
<p>直接在文本中使用 <abbr title="长的文本">缩写</abbr> 即可</p> <p>直接在文本中使用 <abbr title="长的文本">缩写</abbr> 即可</p>
<p>
<h1 id="3">3 锚点</h1> <h1 id="3">3 锚点</h1>
<p>klzzwxh:0017klzzwxh:0018</p> </p>
<p>{#锚点名}</p>
<p>
<h1 id="4">4 代码块</h1> <h1 id="4">4 代码块</h1>
</p>
<p>
<h2 id="4.1">4.1 <code>单行</code></h2> <h2 id="4.1">4.1 <code>单行</code></h2>
</p>
<p>
<h3 id="4.1.1">4.1.1 LaTex</h3> <h3 id="4.1.1">4.1.1 LaTex</h3>
</p>
<p><code>$CO_2$</code></p> <p><code>$CO_2$</code></p>
<p><code>$H_2O$</code></p> <p><code>$H_2O$</code></p>
<p>
<h3 id="4.1.2">4.1.2 函数</h3> <h3 id="4.1.2">4.1.2 函数</h3>
</p>
<p><code>¥y=x*2+1¥</code> // 不定义范围</p> <p><code>¥y=x*2+1¥</code> // 不定义范围</p>
<p><code>¥y=x**2¥€-50,50€</code> // 定义了x范围</p> <p><code>¥y=x**2¥€-50,50€</code> // 定义了x范围</p>
<p><code>¥y=x**3¥€-50,50|-100,100€</code> // 定义了y范围</p> <p><code>¥y=x**3¥€-50,50|-100,100€</code> // 定义了y范围</p>
<p>
<h3 id="4.1.3">4.1.3 强调</h3> <h3 id="4.1.3">4.1.3 强调</h3>
</p>
<p><code>{强调文本}</code></p> <p><code>{强调文本}</code></p>
<p>
<h2 id="4.2">4.2 多行</h2> <h2 id="4.2">4.2 多行</h2>
</p>
<p>
<h3 id="4.2.1">4.2.1 YAML</h3> <h3 id="4.2.1">4.2.1 YAML</h3>
</p>
<div class="codehilite"><pre><span></span><code><span class="nt">A</span><span class="p">:</span> <div class="codehilite"><pre><span></span><code><span class="nt">A</span><span class="p">:</span>
<span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">1. a</span> <span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">1. a</span>
<span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">2. b</span> <span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">2. b</span>
@ -182,11 +238,15 @@
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">c</span> <span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">c</span>
</code></pre></div> </code></pre></div>
<p>
<h3 id="4.2.2">4.2.2 Python</h3> <h3 id="4.2.2">4.2.2 Python</h3>
</p>
<div class="codehilite"><pre><span></span><code><span class="nb">print</span><span class="p">(</span><span class="s1">&#39;CrossDown&#39;</span><span class="p">)</span> <div class="codehilite"><pre><span></span><code><span class="nb">print</span><span class="p">(</span><span class="s1">&#39;CrossDown&#39;</span><span class="p">)</span>
</code></pre></div> </code></pre></div>
<p>
<h3 id="4.2.3">4.2.3 Mermaid</h3> <h3 id="4.2.3">4.2.3 Mermaid</h3>
</p>
<div class="codehilite"><pre><span></span><code><span class="nf">graph</span><span class="w"> </span><span class="n">LR</span> <div class="codehilite"><pre><span></span><code><span class="nf">graph</span><span class="w"> </span><span class="n">LR</span>
<span class="w"> </span><span class="n">A</span><span class="o">--&gt;</span><span class="n">B</span> <span class="w"> </span><span class="n">A</span><span class="o">--&gt;</span><span class="n">B</span>
<span class="w"> </span><span class="n">A</span><span class="o">--&gt;</span><span class="n">C</span> <span class="w"> </span><span class="n">A</span><span class="o">--&gt;</span><span class="n">C</span>
@ -194,11 +254,15 @@
<span class="w"> </span><span class="n">C</span><span class="o">--&gt;</span><span class="n">D</span> <span class="w"> </span><span class="n">C</span><span class="o">--&gt;</span><span class="n">D</span>
</code></pre></div> </code></pre></div>
<p>
<h1 id="5">5 转义</h1> <h1 id="5">5 转义</h1>
</p>
<p>\ </p> <p>\ </p>
<p>\a </p> <p>\a </p>
<p>*</p> <p>*</p>
<p>
<h1 id="6">6 引用</h1> <h1 id="6">6 引用</h1>
</p>
<blockquote> <blockquote>
<p>一级引用</p> <p>一级引用</p>
<blockquote> <blockquote>
@ -216,42 +280,58 @@
</blockquote> </blockquote>
</blockquote> </blockquote>
</blockquote> </blockquote>
<p>引文内添加klzzwxhklzzwxhklzzwxh:00450042klzzwxh:0043</p> <p>引文内添加klzzwxhklzzwxhklzzwxh:00990096klzzwxh:0097</p>
</blockquote> </blockquote>
<p>
<h1 id="7">7 提纲</h1> <h1 id="7">7 提纲</h1>
</p>
<p>
<h2 id="7.1">7.1 提纲号</h2> <h2 id="7.1">7.1 提纲号</h2>
</p>
<p>以数字和点组成,通过空格与提纲名分隔,例如:</p> <p>以数字和点组成,通过空格与提纲名分隔,例如:</p>
<p>
<h3 id="7.1.1">7.1.1 提纲号示例</h3> <h3 id="7.1.1">7.1.1 提纲号示例</h3>
</p>
<p>点不能出现在开头或结尾,例如</p> <p>点不能出现在开头或结尾,例如</p>
<p>.7.1.2 错误示范</p> <p>.<h3 id="7.1.2">7.1.2 错误示范</h3>
</p>
<p>7.1.3. 错误示范</p> <p>7.1.3. 错误示范</p>
<p>不能出现两个及以上连续的点,例如:</p> <p>不能出现两个及以上连续的点,例如:</p>
<p>7..1&hellip;4 错误示范</p> <p>7..1&hellip;<h1 id="4">4 错误示范</h1>
</p>
<p>提纲号会被自动配置为锚点,可直接使用{7}76.1}</p> <p>提纲号会被自动配置为锚点,可直接使用{7}76.1}</p>
<p>
<h1 id="8">8 注释</h1> <h1 id="8">8 注释</h1>
</p>
<p>
<h2 id="8.1">8.1 强注释</h2> <h2 id="8.1">8.1 强注释</h2>
<p>|=klzzwxhklzzwxhklzzwxh:00340029klzzwxh:0032=|</p> </p>
<p>|=klzzwxhklzzwxhklzzwxh:00690064klzzwxh:0067=|</p>
<p>
<h2 id="8.2">8.2 弱注释</h2> <h2 id="8.2">8.2 弱注释</h2>
</p>
<!-- 这是注释 --> <!-- 这是注释 -->
<p>只有在 // 后面才会被移除</p> <p>只有在 // 后面才会被移除</p>
<p><code>// 代码中的注释弱不会被移除</code></p> <p><code>// 代码中的注释弱不会被移除</code></p>
<p>
<h1 id="9">9 列表</h1> <h1 id="9">9 列表</h1>
</p>
<p>
<h2 id="9.1">9.1 有序列表</h2> <h2 id="9.1">9.1 有序列表</h2>
</p>
<ol> <ol>
<li>a</li> <li>a</li>
<li>b</li> <li>b</li>
<li>c</li> <li>c</li>
<li>d</li> <li>d</li>
</ol> </ol>
<h2 id="9.2">9.2 无序列表</h2> <p>
<ul> <h2 id="9.2">9.2 无序列表klzzwxhklzzwxhklzzwxh:00800077- Cklzzwxh:0078- D</h2>
<li>A</li> </p>
<li>B</li> <p>
<li>C</li>
<li>D</li>
</ul>
<h1 id="10">10 表格</h1> <h1 id="10">10 表格</h1>
</p>
<table> <table>
<thead> <thead>
<tr> <tr>
@ -273,19 +353,32 @@
</tr> </tr>
</tbody> </tbody>
</table> </table>
<p>
<h1 id="11">11 警告</h1> <h1 id="11">11 警告</h1>
</p>
<div class="admonition warning"> <div class="admonition warning">
<p class="admonition-title">警告标题</p> <p class="admonition-title">警告标题</p>
<p>警告内容</p> <p>警告内容</p>
</div> </div>
<p>
<h1 id="12">12 Emoji</h1> <h1 id="12">12 Emoji</h1>
</p>
<p>🚴</p> <p>🚴</p>
<p>这是一个笑脸😃图案</p> <p>这是一个笑脸😃图案</p>
<p>
<h1 id="13">13 脚注</h1> <h1 id="13">13 脚注</h1>
</p>
<p>
<h2 id="13.1">13.1 使用</h2> <h2 id="13.1">13.1 使用</h2>
</p>
<p>这是一个<sup id="fnref:脚注"><a class="footnote-ref" href="#fn:脚注">1</a></sup></p> <p>这是一个<sup id="fnref:脚注"><a class="footnote-ref" href="#fn:脚注">1</a></sup></p>
<p>
<h2 id="13.2">13.2 定义</h2> <h2 id="13.2">13.2 定义</h2>
</p>
<p>
<h2 id="13.3">13.3 放置</h2> <h2 id="13.3">13.3 放置</h2>
</p>
<p>通过一下代码可以将文章中所有的脚注定义集中于一处</p>
<div class="footnote"> <div class="footnote">
<hr /> <hr />
<ol> <ol>
@ -294,6 +387,9 @@
</li> </li>
</ol> </ol>
</div> </div>
<p>否则所有定义将被集中在文章末尾</p>
<p>
<h1 id="14">14 扩展</h1> <h1 id="14">14 扩展</h1>
</p>
</body> </body>
</html> </html>