Merge pull request 'V1' (#1) from V1 into main

Reviewed-on: crossdark/CrossDown#1
This commit is contained in:
跨越晨昏 2024-10-14 20:08:08 +08:00
commit f8488570e1
11 changed files with 890 additions and 200 deletions

336
CrossDown/Core.py Normal file
View File

@ -0,0 +1,336 @@
from markdown.extensions import Extension, extra, admonition, meta, sane_lists, toc, wikilinks, codehilite
from pygments.formatters import HtmlFormatter
from markdown.treeprocessors import Treeprocessor
from markdown.inlinepatterns import Pattern as Pattern_
from markdown.preprocessors import Preprocessor
from markdown.inlinepatterns import InlineProcessor
from markdown.blockprocessors import BlockProcessor
from markdown import Markdown
from typing import *
import re
import xml
import emoji
try: # 检测当前平台是否支持扩展语法
from .Extra import *
EXTRA_ABLE = True
except ModuleNotFoundError: # 不支持扩展语法
EXTRA_ABLE = False
class HighlightHtmlFormatter(HtmlFormatter):
def __init__(self, lang_str='', **options):
super().__init__(**options)
# lang_str has the value {lang_prefix}{lang}
# specified by the CodeHilite's options
self.lang_str = lang_str.split('-')[-1]
def _wrap_code(self, source):
yield 0, f'<code class="{self.lang_str}">'
yield from source
yield 0, '</code>'
Extensions = {
'基本扩展': extra.ExtraExtension(fenced_code={'lang_prefix': ''}),
'警告扩展': admonition.AdmonitionExtension(),
'元数据': meta.MetaExtension(),
'能列表': sane_lists.SaneListExtension(),
'目录': toc.TocExtension(),
'内部链接': wikilinks.WikiLinkExtension(),
'代码高亮': codehilite.CodeHiliteExtension(guess_lang=False, pygments_formatter=HighlightHtmlFormatter),
}
class Simple(InlineProcessor):
"""
可通过简单的正则表达式和HTML标签实现的样式
"""
def __init__(self, pattern: str, tag: str):
"""
初始化
:param pattern: 正则表达式
:param tag: html标签
"""
super().__init__(pattern)
self.tag = tag
def handleMatch(self, match, match_line):
tag = xml.etree.ElementTree.Element(self.tag) # 创建标签
tag.text = match.group(1) # 获取匹配到的文本并设置为标签的内容
return tag, match.start(), match.end()
class Nest(InlineProcessor):
"""
需要嵌套HTML标签实现的样式
"""
def __init__(self, pattern: str, outer_tag: str, inner_tag: str):
"""
初始化
:param pattern: 正则表达式
:param outer_tag: 外层html标签
:param inner_tag: 内层html标签
"""
super().__init__(pattern)
self.outer_tag = outer_tag
self.inner_tag = inner_tag
def handleMatch(self, match, match_line):
outer_tag = xml.etree.ElementTree.Element(self.outer_tag) # 创建外层标签
inner_tag = xml.etree.ElementTree.SubElement(outer_tag, self.inner_tag) # 创建内层标签
outer_tag.text = match.group(1) # 设置外层标签文本
inner_tag.text = match.group(2) # 设置内层标签文本
return outer_tag, match.start(), match.end()
class ID(InlineProcessor):
"""
需要对HTML标签设置ID实现的样式
"""
def __init__(self, pattern: str, tag: str, property_: str, value: Union[str, bool] = None):
"""
初始化
:param pattern: 正则表达式
:param tag: html标签
:param property_: html标签属性名称
:param value: html标签属性的值 不设置时为第二个匹配组,设置为整数时则为指定的匹配组,设置为字符串则为原始字符串
"""
super().__init__(pattern)
self.tag = tag
self.property = property_
self.value = value
def handleMatch(self, match, match_line):
tag = xml.etree.ElementTree.Element(self.tag) # 创建标签
tag.text = match.group(1) # 设置标签内容
tag.set(self.property, match.group(2) if self.value is None else self.value) # 设置标签属性,属性的值默认为第二个匹配组
return tag, match.start(), match.end()
class Emoji(InlineProcessor):
"""
需要对HTML标签设置ID实现的样式
"""
def __init__(self, pattern: str):
"""
初始化
:param pattern: 正则表达式
"""
super().__init__(pattern)
def handleMatch(self, match, match_line):
return emoji.emojize(match.group(0)), match.start(), match.end()
class Syllabus(BlockProcessor):
# 定义提纲的正则表达式
syllabus_re = r'(\d+(\.\d+)*)\s+(.*)'
def test(self, parent, block):
# 检查当前块是否匹配我们的正则表达式
return re.match(self.syllabus_re, block)
def run(self, parent, blocks):
syllabus = re.match(self.syllabus_re, blocks[0]) # 匹配提纲的号和内容
header = xml.etree.ElementTree.SubElement(parent, f'h{len(syllabus.group(1).split("."))}') # 按照提纲号等级创建标题
header.set('id', syllabus.group(1)) # 设置提纲ID
header.text = syllabus.group(1) + ' ' + syllabus.group(3) # 设置提纲内容
blocks[0] = ''
return False
class BoxBlock(BlockProcessor):
def __init__(self, parser, re_start, re_end, style):
super().__init__(parser)
self.re_start = re_start # start line, e.g., ` !!!!
self.re_end = re_end # last non-blank line, e.g, '!!!\n \n\n'
self.style = style
def test(self, parent, block):
return re.match(self.re_start, block)
def run(self, parent, blocks):
original_block = blocks[0]
blocks[0] = re.sub(self.re_start, '', blocks[0])
# Find block with ending fence
for block_num, block in enumerate(blocks):
if re.search(self.re_end, block):
# remove fence
blocks[block_num] = re.sub(self.re_end, '', block)
# render fenced area inside a new div
e = xml.etree.ElementTree.SubElement(parent, 'div')
e.set('style', self.style)
self.parser.parseBlocks(e, blocks[0:block_num + 1])
# remove used blocks
for i in range(0, block_num + 1):
blocks.pop(0)
return True # or could have had no return statement
# No closing marker! Restore and do nothing
blocks[0] = original_block
return False # equivalent to our test() routine returning False
class _Anchor(InlineProcessor):
def handleMatch(self, match, match_line):
tag = xml.etree.ElementTree.Element('span') # 创建标签
tag.text = match.group(1)
tag.set('id', match.group(1)) # 设置id
return tag, match.start(), match.end()
class LinkLine(InlineProcessor):
def handleMatch(self, match, match_line):
tag = xml.etree.ElementTree.Element('a') # 创建标签
tag.set('href', '#' + match.group(1)) # 设置id
tag.text = match.group(1)
return tag, match.start(), match.end()
class CodeLine(Treeprocessor):
def __init__(self, variable: Dict):
super().__init__()
self.variable = variable
def run(self, root):
for elem in root.iter('p'): # 在所有段落中查找单行代码
if elem.findall('code'): # 找到单行代码
for code in elem:
if re.match(r'\$[^$]*\$', code.text): # 渲染Latex
if isinstance(elem.text, str): # 这个段落还有其它内容
elem.text += fr'\({code.text[1:-1]}\){code.tail}' # 插入latex
else:
elem.text = fr'\({code.text[1:-1]}\)' # latex是段落中唯一的内容
elem.remove(code)
elif re.match(r'¥[^$]*¥', code.text): # 是数学函数(单行)
if EXTRA_ABLE: # 支持扩展语法
expression, range_ = re.findall(r'¥([^$]*)¥(€[^$]*€)?', code.text)[0] # 分离表达式与范围(如果有)
x_r = (-10, 10)
y_r = (-20, 20)
if range_ != '': # 定义了范围
ranges = range_[1:-1].split('|')
if len(ranges) in (1, 2): # 定义的范围正确
x_r = tuple(int(i) for i in ranges[0].split(','))
if len(ranges) == 2: # 定义了y范围
y_r = tuple(int(i) for i in ranges[1].split(','))
code.tag = 'img'
code.set('src', f"""data:image/png;base64,{(function_drawing(
function=lambda x: eval(expression.split('=')[1]), x_range=x_r, y_range=y_r
))}""") # 绘制函数图像
code.set('alt', 'Base64 函数图片')
else: # 不支持扩展语法
code.tag = 'span'
code.set('class', 'block')
code.text = '该平台不支持扩展语法'
elif re.match(r'\{[^$]*}', code.text): # 是强调
code.tag = 'span'
code.set('class', 'block')
key = code.text[1:-1] # 去掉两边的{}
if key in self.variable:
code.text = self.variable[key]
else:
code.text = key
class CodeBlock(Treeprocessor):
def run(self, root):
for code in root.findall('p'):
# 在这里处理 <pre> 标签
# 例如,你可以添加属性或修改内容
print(f'{code.text} | {code.tag}')
class Basic(Extension): # TODO InlineProcessor 不能渲染一行中两个以上的元素(内置的扩展斜体和粗体的优先级好像是一样的)
"""
渲染基本样式
"""
def extendMarkdown(self, md):
md.registerExtension(self) # 注册扩展
md.inlinePatterns.register(Simple(r'~~(.*?)~~', tag='s'), 'strikethrough', 1) # ~~删除线~~
md.inlinePatterns.register(Simple(r'~(.*?)~', tag='u'), 'underline', 2) # ~下划线~
md.inlinePatterns.register(Simple(r'==(.*?)==', tag='mark'), 'high_light', 3) # ==高亮==
md.inlinePatterns.register(Nest(
r'\[(.*?)]\^\((.*?)\)', outer_tag='ruby', inner_tag='rt'), 'up', 4
) # [在文本的正上方添加一行小文本]^(主要用于标拼音)
md.inlinePatterns.register(ID(
r'\[(.*?)]-\((.*?)\)', tag='span', property_='title'), 'hide', 5
) # [在指定的文本里面隐藏一段文本]-(只有鼠标放在上面才会显示隐藏文本)
md.inlinePatterns.register(Emoji(r':(.+?):'), 'emoji', 6) # 将emoji短代码转换为emoji字符
md.parser.blockprocessors.register(Syllabus(md.parser), 'syllabus', 11) # 渲染提纲
class Box(Extension):
"""
渲染外框
"""
def extendMarkdown(self, md):
md.registerExtension(self) # 注册扩展
# 红框警告
md.inlinePatterns.register(ID(
r'!{3}(.+?)!{3}', tag='div', property_='style', value='display: inline-block; border: 1px solid red;'
), 'warning_in_line', 20) # 行内
md.parser.blockprocessors.register(BoxBlock(
md.parser, r'^ *!{3} *\n', r'\n *!{3}\s*$', 'display: inline-block; border: 1px solid red;'
), 'warning_box', 175) # 块
# 黄框提醒
md.inlinePatterns.register(ID(
r'!-!(.+?)!-!', tag='div', property_='style', value='display: inline-block; border: 1px solid yellow;'
), 'reminding_in_line', 21) # 行内
md.parser.blockprocessors.register(BoxBlock(
md.parser, r'^ *!-! *\n', r'\n *!-!\s*$', 'display: inline-block; border: 1px solid yellow;'
), 'reminding_box', 176) # 块
# 绿框安心
md.inlinePatterns.register(ID(
r',{3}(.+?),{3}', tag='div', property_='style', value='display: inline-block; border: 1px solid green;'
), 'reminding_in_line', 22) # 行内
md.parser.blockprocessors.register(BoxBlock(
md.parser, r'^ *,{3} *\n', r'\n *,{3}\s*$', 'display: inline-block; border: 1px solid green;'
), 'reminding_box', 177) # 块
# 蓝框怀疑
md.inlinePatterns.register(ID(
r',-,(.+?),{2}', tag='div', property_='style', value='display: inline-block; border: 1px solid blue;'
), 'reminding_in_line', 23) # 行内
md.parser.blockprocessors.register(BoxBlock(
md.parser, r'^ *,-, *\n', r'\n *,-,\s*$', 'display: inline-block; border: 1px solid blue;'
), 'reminding_box', 178) # 块
class Anchor(Extension):
def extendMarkdown(self, md: Markdown):
md.registerExtension(self) # 注册扩展
md.inlinePatterns.register(_Anchor(r'\{#([^{}#]+)}'), 'anchor', 0) # 定义锚点
md.inlinePatterns.register(LinkLine(r'\{([^{}#]+)}'), 'line_link', 0) # 添加页内链接
class Code(Extension):
def __init__(self, variable: Dict):
super().__init__()
self.variable = variable
def extendMarkdown(self, md: Markdown):
md.registerExtension(self) # 注册扩展
md.treeprocessors.register(CodeLine(variable=self.variable), 'code_line', 0) # 渲染单行代码块
# md.treeprocessors.register(CodeBlock(), 'code_block', 1) # 渲染多行代码块
def main(text: str, variable: Dict) -> Tuple[str, Dict[str, List[str]]]:
md = Markdown(extensions=[Basic(), Box(), Anchor()] + list(Extensions.values()) + [Code(variable=variable)])
return md.convert(text), md.Meta

View File

@ -1,4 +0,0 @@
from markdown.extensions import Extension
from markdown.treeprocessors import Treeprocessor
from markdown.inlinepatterns import Pattern
from markdown import Markdown

43
CrossDown/Extra.py Normal file
View File

@ -0,0 +1,43 @@
import matplotlib.pyplot as plt
import numpy as np
import base64
from io import BytesIO
EXTRA = [
]
def function_drawing(function, x_range=(-10, 10), y_range=(-20, 20), dpi=100):
# 创建一个图像和坐标轴对象
fig, ax = plt.subplots()
# 生成x值
x = np.linspace(x_range[0], x_range[1], 400)
# 计算y值
y = function(x)
# 绘制图像
ax.plot(x, y)
# 设置坐标轴范围
ax.set_xlim(x_range)
ax.set_ylim(y_range)
# 隐藏坐标轴
ax.axis('on')
# 将图像保存到BytesIO对象
buf = BytesIO()
fig.savefig(buf, format='png', dpi=dpi)
# 获取图像数据的Base64编码
data = base64.b64encode(buf.getbuffer()).decode("ascii")
# 关闭图像和坐标轴对象
plt.close(fig)
# 返回Base64编码的字符串
return data

View File

@ -0,0 +1,60 @@
from typing import *
from .Core import main
__all__ = [
'main', # 主函数
'indent', # 添加空格
'HEAD', #
'BODY', #
]
__version__ = '0.11.2'
__author__ = 'CrossDark'
__email__ = 'liuhanbo333@icloud.com'
__source__ = 'https://crossdark.net/'
__license__ = """MIT"""
HEAD = (
'<script type="text/javascript" async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/MathJax.js?config=TeX-MML-AM_CHTML"></script>',
'<link href="https://cdn.jsdelivr.net/npm/prismjs/themes/prism.css" rel="stylesheet" />',
'<script src="https://cdn.jsdelivr.net/npm/prismjs/prism.js"></script>',
'<script src="https://cdn.jsdelivr.net/npm/prismjs/components/prism-yaml.min.js"></script>',
# mermaid
'<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>',
'<script>',
' mermaid.initialize({startOnLoad:true});',
'</script>',
# Highlight.js
# '<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.3.1/styles/default.min.css">',
# '<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.3.1/highlight.min.js"></script>',
# '<script>hljs.highlightAll();</script>',
'<link rel="stylesheet" href="../Static/styles.css">',
'<style>',
' .block {',
' background-color: grey; /* 灰色背景 */',
' color: white; /* 白色文字 */',
'}',
'</style>'
)
BODY = (
'',
)
def indent(input_: Union[str, List, Tuple], indent_spaces: int = 4) -> str:
"""
给字符串中的每一行前面加上缩进
:param input_: 原始字符串可以包含多行
:param indent_spaces: 每行前面要添加的空格数默认为4
:return: 带缩进的新字符串
"""
# 使用字符串的splitlines()方法分割原始字符串为行列表,如果是可迭代对象则直接遍历
# 遍历行列表,给每行前面加上相应的缩进,并重新组合成字符串
return "\n".join(
f"{' ' * indent_spaces}{line}" for line in (lambda x: x.splitlines() if isinstance(x, str) else x)(input_))

View File

@ -6,7 +6,6 @@ import markdown
try: # 检测当前平台是否支持扩展语法
import CrossMore
EXTRA_ABLE = True
except ModuleNotFoundError:
EXTRA_ABLE = False

File diff suppressed because one or more lines are too long

188
README.md
View File

@ -1,13 +1,13 @@
Title: CrossDown示例
Summary: 够简洁的了
Authors: CrossDark
Date: __date__
base_url: http://crossdark.net:3000/crossdark/CrossDown
[TOC]
---
title: "Markdown文档标题"
author: "作者姓名"
date: "2024-09-26"
---
# CrossDown
自制的markdown添加了一些自定义的语法
自制的markdown,添加了一些自定义的语法
效果请见[README.html](https://github.com/CrossDark/CrossDown/blob/main/README.html)
1 基本语法
@ -67,33 +67,39 @@ ___
[变量]: https://crossdark.com
2 变量
2 缩写
2.1 定义
{变量名} = 值
*[缩写]: 长的文本
2.2 赋值
{变量名} {锚点名}
直接在文本中使用 缩写 即可
提纲的编号已经自动配置为了锚点,可直接使用{2}
3 锚点
2.3 添加锚点
3.1 定义
{#锚点名}
3 代码块
3.2 页内链接
3.1 `单行`
{锚点名}
3.1.1 LaTex
4 代码块
`$CO_2$`
4.1 `单行`
`$H_2O$`
4.1.1 LaTex
3.1.2 函数
这是`$CO_2$`二氧化碳
这是`$H_2O$`水
`$\lg\left(\frac{目标生物的理智值}{稳定折磨型工具人的理智值}\right)$`
4.1.2 函数
`¥y=x*2+1¥` // 不定义范围
@ -101,11 +107,17 @@ ___
`¥y=x**3¥€-50,50|-100,100€` // 定义了y范围
3.2 多行
4.1.3 强调
3.2.1 YAML
`{强调文本}`
`
`{强调变量}`
4.2 多行
4.2.1 YAML
```yaml
A:
1. a
2. b
@ -114,25 +126,32 @@ B:
- a
- b
- c
`
```
3.2.2 Python
4.2.2 Python
`python
print('CrossDown')
`
```python
def main():
print('CrossDown')
```
3.2.3 Mermaid
4.2.3 Mermaid
`mermaid
graph LR
A-->B
A-->C
B-->D
C-->D
`
```mermaid
graph TD
A[开始]-->B[流程]
B-->C{判断}
C-->|结果1|D[结束1]
C-->|结果2|E[结束2]
```
4 转义
4.2.4 shell
```shell
cd ../..
```
5 转义
\\
@ -140,7 +159,7 @@ graph LR
\*
5 引用
6 引用
> 一级引用
>> 二级引用
@ -151,68 +170,129 @@ graph LR
>
> 引文内添加*斜体***粗体**~下划线~~~删除线~~==高亮==
6 提纲
7 提纲
6.1 提纲号
7.1 提纲号
以数字和点组成,通过空格与提纲名分隔,例如:
6.1.1 提纲号示例
7.1.1 提纲号示例
点不能出现在开头或结尾,例如
.6.1.2 错误示范
.7.1.2 错误示范
6.1.3. 错误示范
7.1.3. 错误示范
不能出现两个及以上连续的点,例如:
6..1...4 错误示范
7..1...4 错误示范
提纲号会被自动配置为锚点,可直接使用{6}{6.1}
提纲号会被自动配置为锚点,可直接使用{7}{7.1}
7 注释
8 注释
7.1 强注释
8.1 强注释
|=
无论如何都会被移除
`放在代码块里也没用`
=|
7.2 弱注释
8.2 弱注释
<!-- 这是注释 -->
只有在 // 后面才会被移除
`// 代码中的注释弱不会被移除`
8 列表
9 列表
9.1 有序列表
8.1 有序列表
1. a
2. b
3. c
4. d
8.2 无序列表
9.2 无序列表
- A
- B
- C
- D
9 表格
10 表格
| 表头1 | 表头2 | 表头3 |
|:----:|:----:|:----:|
| 单元格1 | 单元格2 | 单元格3 |
| 单元格4 | 单元格5 | 单元格6 |
10 警告
11 警告
!!! 这是一条警告
!!! warning "警告标题"
警告内容
11 Emoji
12 Emoji
:person_biking:
:grinning_face_with_big_eyes:
这是一个笑脸:grinning_face_with_big_eyes:图案
13 脚注
13.1 使用
这是一个[^脚注]
13.2 定义
[^脚注]: 一段长的文本用于说明
13.3 放置
通过一下代码可以将文章中所有的脚注定义集中于一处
///Footnotes Go Here///
否则所有定义将被集中在文章末尾
14 外框
14.1 警告
这是一个!!!警告!!!……
!!!
这是一条警告
!!!
14.2 提醒
这是一个!-!提醒!-!……
!-!
这是一条提醒
!-!
14.3 安心
这是一个,,,安心,,,……
,,,
这是一条安心
,,,
14.4 怀疑
这是一个,-,怀疑,-,……
,-,
这是一条怀疑
,-,
15 内部链接
[[Bracketed]]

75
Static/styles.css Normal file
View File

@ -0,0 +1,75 @@
pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.codehilite .hll { background-color: #ffffcc }
.codehilite { background: #f8f8f8; }
.codehilite .c { color: #3D7B7B; font-style: italic } /* Comment */
.codehilite .err { border: 1px solid #FF0000 } /* Error */
.codehilite .k { color: #008000; font-weight: bold } /* Keyword */
.codehilite .o { color: #666666 } /* Operator */
.codehilite .ch { color: #3D7B7B; font-style: italic } /* Comment.Hashbang */
.codehilite .cm { color: #3D7B7B; font-style: italic } /* Comment.Multiline */
.codehilite .cp { color: #9C6500 } /* Comment.Preproc */
.codehilite .cpf { color: #3D7B7B; font-style: italic } /* Comment.PreprocFile */
.codehilite .c1 { color: #3D7B7B; font-style: italic } /* Comment.Single */
.codehilite .cs { color: #3D7B7B; font-style: italic } /* Comment.Special */
.codehilite .gd { color: #A00000 } /* Generic.Deleted */
.codehilite .ge { font-style: italic } /* Generic.Emph */
.codehilite .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.codehilite .gr { color: #E40000 } /* Generic.Error */
.codehilite .gh { color: #000080; font-weight: bold } /* Generic.Heading */
.codehilite .gi { color: #008400 } /* Generic.Inserted */
.codehilite .go { color: #717171 } /* Generic.Output */
.codehilite .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
.codehilite .gs { font-weight: bold } /* Generic.Strong */
.codehilite .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
.codehilite .gt { color: #0044DD } /* Generic.Traceback */
.codehilite .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
.codehilite .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
.codehilite .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
.codehilite .kp { color: #008000 } /* Keyword.Pseudo */
.codehilite .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
.codehilite .kt { color: #B00040 } /* Keyword.Type */
.codehilite .m { color: #666666 } /* Literal.Number */
.codehilite .s { color: #BA2121 } /* Literal.String */
.codehilite .na { color: #687822 } /* Name.Attribute */
.codehilite .nb { color: #008000 } /* Name.Builtin */
.codehilite .nc { color: #0000FF; font-weight: bold } /* Name.Class */
.codehilite .no { color: #880000 } /* Name.Constant */
.codehilite .nd { color: #AA22FF } /* Name.Decorator */
.codehilite .ni { color: #717171; font-weight: bold } /* Name.Entity */
.codehilite .ne { color: #CB3F38; font-weight: bold } /* Name.Exception */
.codehilite .nf { color: #0000FF } /* Name.Function */
.codehilite .nl { color: #767600 } /* Name.Label */
.codehilite .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
.codehilite .nt { color: #008000; font-weight: bold } /* Name.Tag */
.codehilite .nv { color: #19177C } /* Name.Variable */
.codehilite .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
.codehilite .w { color: #bbbbbb } /* Text.Whitespace */
.codehilite .mb { color: #666666 } /* Literal.Number.Bin */
.codehilite .mf { color: #666666 } /* Literal.Number.Float */
.codehilite .mh { color: #666666 } /* Literal.Number.Hex */
.codehilite .mi { color: #666666 } /* Literal.Number.Integer */
.codehilite .mo { color: #666666 } /* Literal.Number.Oct */
.codehilite .sa { color: #BA2121 } /* Literal.String.Affix */
.codehilite .sb { color: #BA2121 } /* Literal.String.Backtick */
.codehilite .sc { color: #BA2121 } /* Literal.String.Char */
.codehilite .dl { color: #BA2121 } /* Literal.String.Delimiter */
.codehilite .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
.codehilite .s2 { color: #BA2121 } /* Literal.String.Double */
.codehilite .se { color: #AA5D1F; font-weight: bold } /* Literal.String.Escape */
.codehilite .sh { color: #BA2121 } /* Literal.String.Heredoc */
.codehilite .si { color: #A45A77; font-weight: bold } /* Literal.String.Interpol */
.codehilite .sx { color: #008000 } /* Literal.String.Other */
.codehilite .sr { color: #A45A77 } /* Literal.String.Regex */
.codehilite .s1 { color: #BA2121 } /* Literal.String.Single */
.codehilite .ss { color: #19177C } /* Literal.String.Symbol */
.codehilite .bp { color: #008000 } /* Name.Builtin.Pseudo */
.codehilite .fm { color: #0000FF } /* Name.Function.Magic */
.codehilite .vc { color: #19177C } /* Name.Variable.Class */
.codehilite .vg { color: #19177C } /* Name.Variable.Global */
.codehilite .vi { color: #19177C } /* Name.Variable.Instance */
.codehilite .vm { color: #19177C } /* Name.Variable.Magic */
.codehilite .il { color: #666666 } /* Literal.Number.Integer.Long */

View File

@ -1,3 +1,4 @@
Markdown>=3.7
matplotlib>=3.9.2
numpy>=2.1.1
pygments>=2.18.0

35
run.py Normal file
View File

@ -0,0 +1,35 @@
import time
from CrossDown import *
if __name__ == '__main__':
# 开始计时
start_time = time.perf_counter_ns()
# 主程序
with open('README.md', encoding='utf-8') as test:
cd, meta = main(test.read(), variable={
'a': 'b',
'强调变量': '强调值'
})
print(meta)
with open('README.html', 'w', encoding='utf-8') as html:
html.write(f"""<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>UTF-8编码示例</title>
{indent(HEAD)}
<!-- 可以在这里添加其他元数据和CSS链接 -->
</head>
<body>
{indent(BODY)}
{indent(cd, 4)}
</body>
</html>
""")
# 停止计时
end_time = time.perf_counter_ns()
# 输出用时
print("运行时间: {:.9f}".format((end_time - start_time) / 1e9))

View File

@ -5,17 +5,14 @@ with open("README.md", "r") as fh:
setuptools.setup(
name="CrossDown",
version="0.11.2",
version="1.0.1",
author="CrossDark",
author_email="liuhanbo333@icloud.com",
description="CrossDark's MarkDown",
long_description=long_description,
long_description_content_type="text/markdown",
url="https://github.com/CrossDark/CrossDown",
py_modules=[
'CrossDown',
'CrossMore',
],
packages=setuptools.find_packages(),
install_requires=[
'markdown',
'matplotlib',