forked from CrossDark/CrossDown
Merge pull request 'V1' (#1) from V1 into main
Reviewed-on: crossdark/CrossDown#1
This commit is contained in:
commit
f8488570e1
336
CrossDown/Core.py
Normal file
336
CrossDown/Core.py
Normal 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
|
@ -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
43
CrossDown/Extra.py
Normal 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
|
@ -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_))
|
@ -6,7 +6,6 @@ import markdown
|
||||
|
||||
try: # 检测当前平台是否支持扩展语法
|
||||
import CrossMore
|
||||
|
||||
EXTRA_ABLE = True
|
||||
except ModuleNotFoundError:
|
||||
EXTRA_ABLE = False
|
338
README.html
338
README.html
File diff suppressed because one or more lines are too long
188
README.md
188
README.md
@ -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
75
Static/styles.css
Normal 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 */
|
@ -1,3 +1,4 @@
|
||||
Markdown>=3.7
|
||||
matplotlib>=3.9.2
|
||||
numpy>=2.1.1
|
||||
numpy>=2.1.1
|
||||
pygments>=2.18.0
|
35
run.py
Normal file
35
run.py
Normal 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))
|
7
setup.py
7
setup.py
@ -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',
|
||||
|
Loading…
Reference in New Issue
Block a user