diff --git a/CrossDown_.py b/CrossDown_.py deleted file mode 100644 index a161f34..0000000 --- a/CrossDown_.py +++ /dev/null @@ -1,344 +0,0 @@ -import time -from typing import * -import re -import emoji -import markdown - -try: # 检测当前平台是否支持扩展语法 - import CrossMore - EXTRA_ABLE = True -except ModuleNotFoundError: - EXTRA_ABLE = False - -__all__ = [ - 'main', # 主函数 - 'indent', # 添加空格 - 'body', # 主题函数 - 'Style', # 风格 - 'Value', # 变量 - 'CodeBlock', # 代码块 - 'Syllabus', # 提纲 - 'Basic', # 基础 - 'HEAD', - 'BODY', -] -__version__ = '0.11.2' -__author__ = 'CrossDark' -__email__ = 'liuhanbo333@icloud.com' -__source__ = 'https://crossdark.net/' -__license__ = """MIT""" - -HEAD = ( - '', - '', - '', - '', - '', - '' -) - -BODY = ( - '', - '', -) - - -class Style: - """ - 渲染字体样式 - """ - - def __init__(self, text: str): - """ - 初始化 - :param text: cd文本 - """ - self.text = text - - def underline(self): - """ - ~下划线~ - :return: - """ - self.text = re.sub(r'~([^~\n]+)~', r'\1', self.text) - - def strikethrough(self): - """ - ~~删除线~~ - :return: - """ - self.text = re.sub(r'~~([^~\n]+)~~', r'\1', self.text) - - def highlight(self): - """ - ==高亮== - :return: - """ - self.text = re.sub(r'==([^=\n]+)==', r'\1', self.text) - - def up(self): - """ - [在文本的正上方添加一行小文本]^(主要用于标拼音) - :return: - """ - self.text = re.sub(r'\[(.*?)]\^\((.*?)\)', r'\1\2', self.text) - - def hide(self): - """ - [在指定的文本里面隐藏一段文本]-(只有鼠标放在上面才会显示隐藏文本) - :return: - """ - self.text = re.sub(r'\[(.*?)]-\((.*?)\)', r'\1', self.text) - - def __call__(self, *args, **kwargs) -> str: - """ - 一键运行 - :param args: - :param kwargs: - :return: 处理后的文本 - """ - self.strikethrough() - self.underline() - self.highlight() - self.up() - self.hide() - return self.text - - -class Value: - """ - 定义: {变量名} = 值 - 赋值: {变量或锚点名} - 锚点: {#锚点名} - """ - - def __init__(self, text: str): - self.text = text - self.values = { - key: value for key, value in re.findall(r'\{([^{}#]+)} ?= ?(.+?)(?=\n|$)', text) - } # 从text中提取所有变量并转换成字典 - self.anchor = re.findall(r'\{#([^{}#]+)}', text) - - def __call__(self, *args, **kwargs) -> Tuple[str, Dict[str, str]]: - """ - 将所有变量赋值并移除变量定义 - :param args: - :param kwargs: - :return: 赋值后的正文 - """ - text = self.text - for item in self.anchor: - text = re.sub(r'\{#(' + item + ')}', r'', text) # 添加锚点 - text = re.sub(r'\{' + item + '}', fr'{item}', text) # 添加页内链接 - for k, v in self.values.items(): - text = re.sub(r'\{' + k + '} ?= ?(.+?)(?=\n|$)', '', text) # 移除变量的定义 - text = re.sub(r'\{' + k + '}', fr'{v}', text) # 给变量赋值 - return text, self.values - - -class CodeBlock: - def __init__(self, text: str): - """ - 找出`代码块`并移除代码标识 - :param text: 输入的文本 - """ - self.codes = [i for i in re.findall(r'`([^`]*)`', text) if i != ''] # 找出代码快 - self.text = re.sub(r'``', '', text) # 移除代码标识` - - def __call__(self, *args, **kwargs) -> str: - """ - 临时移除代码块 - :param args: - :param kwargs: - :return: 不含代码的文本 - """ - for index, item in enumerate(self.codes): # 替换代码块为-@@-(ID)-@@- - self.text = re.sub(fr'`{re.escape(item)}`', f'\0\1{index}\1\0', self.text) # 同时转译特殊字符 - return self.text - - def rendering(self, values: Dict[str, str]): - """ - 渲染代码 - :param values: 变量字典 - :return: - """ - for index, code in enumerate(self.codes): - if re.match(r'\{[^$]*}', code): # 是变量 - # 给变量赋值 - key = re.findall(r'\{([^}]+)}', code)[0] # 查找变量名 - code = re.sub(r'\{' + key + '}', fr'{values[key]}', code) - self.codes[index] = code # 给变量赋值 - if re.search(r'\n', code): # 是多行代码 - head = re.findall(r'(.*?)\n', code)[0] - if head in ('', 'yaml'): - self.codes[index] = f'
{code}
' - elif head in ('shell', 'python'): - self.codes[ - index] = f'
{re.sub(f"({head})", "", code)}
' - elif head in ('mermaid',): - self.codes[index] = f'
{re.sub(f"({head})", "", code)}
' - elif re.match(r'\$[^$]*\$', code): # 是LaTex代码(单行) - self.codes[index] = re.sub(fr'\$([^$]*)\$', r'

\(\1\)

', code) - elif re.match(r'¥[^$]*¥', code): # 是数学函数(单行) - if EXTRA_ABLE: - expression, range_ = re.findall(r'¥([^$]*)¥(€[^$]*€)?', code)[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(',')) - self.codes[index] = CrossMore.function_drawing( # 绘制函数图像 - function=lambda x: eval(expression.split('=')[1]), x_range=x_r, y_range=y_r - ) - - else: - self.codes[index] = '该平台不支持扩展语法' - else: # 是突出块 - self.codes[index] = f'{code}' - - def restore(self, new_text: str) -> str: - """ - 将渲染好的代码重新放回处理好的正文 - :param new_text: 处理好的正文 - :return: 加上代码的文章 - """ - for index, item in enumerate(self.codes): - new_text = re.sub(f'\0\1{index}\1\0', f'{item}', new_text, flags=re.DOTALL) - return new_text - - -class Syllabus: - """ - 1. 找到提纲 - 2 找到符合若干个‘数字+点+数字’且首尾都是数字的行 - 每个提纲编号全文只能出现一次 - """ - - def __init__(self, text: str): - self.text = text - - def __call__(self, *args, **kwargs) -> str: - return '\n'.join([ - (lambda match, origen: - re.sub(f'^({match.groups()[0]})', # 按照提纲等级添加#和锚点 - fr'{"#" * len(match.groups()[0].split("."))} \1{{#' + match.groups()[0] + '}', 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 self.text.splitlines() # 分割并遍历文本的每一行 - ]) - - -class Basic: - def __init__(self, text: str): - self.text: str = text - - @staticmethod - def strong_annotation(text: str) -> str: - """ - 移除|=强注释=| - :param text: 原始文本 - :return: 移除强注释后的文本 - """ - return re.sub('\|=[\s\S]*=\|', '', text, re.DOTALL) - - @staticmethod - def week_annotation(text: str) -> str: - """ - 移除 // 弱注释 - :param text: 原始文本 - :return: 移除弱注释后的文本 - """ - return re.sub('// .*?\n', '\n', text) - - -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_)) - - -def body(text: str) -> Tuple[str, Dict[str, str]]: - """ - 渲染正文部分 - :param text: 输入正文 - :return: 输出渲染后的正文 - """ - text = Basic.week_annotation(text) # 移除弱注释 - text = Syllabus(text)() # 渲染提纲 - text, values = Value(text)() # 提取变量并赋值到文本中 - text = Style(text)() # 渲染字体样式 - text = markdown.markdown(text, extensions=[ - 'markdown.extensions.extra', # 扩展语法 - 'markdown.extensions.codehilite', # 语法高亮拓展 - 'markdown.extensions.toc', # 自动生成目录 - 'markdown.extensions.admonition', # 警告扩展 - 'markdown.extensions.meta', # 元数据 - ]) # 渲染标准markdown - text = emoji.emojize(text) # 渲染Emoji - return text, values - - -def main(origen: str): - # 预处理 - origen = Basic.strong_annotation(origen) # 移除强注释 - code_block = CodeBlock(origen) # 获取代码内容 - text = code_block() # 暂时移除代码 - # 处理正文 - text, values = body(text) - # 后处理 - code_block.rendering(values) # 渲染代码 - return code_block.restore(text) # 放回代码 - - -if __name__ == '__main__': - # 开始计时 - start_time = time.perf_counter_ns() - # 主程序 - with open('README.md', encoding='utf-8') as test: - cd = main(test.read()) - with open('README.html', 'w', encoding='utf-8') as html: - html.write(f""" - - - - - UTF-8编码示例 -{indent(HEAD)} - - - -{indent(BODY)} -{indent(cd, 4)} - - -""") - # 停止计时 - end_time = time.perf_counter_ns() - # 输出用时 - print("运行时间: {:.9f} 秒".format((end_time - start_time) / 1e9))