math.py 4.0 KB
Newer Older
F
feilong 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
import os
import re

from .tree import load_json, dump_json


def load_md(p):
    with open(p, 'r', encoding='utf-8') as f:
        return f.read()


def dump_md(p, str):
    with open(p, 'w', encoding='utf-8') as f:
        return f.write(str)


class MathWalker:
    def __init__(self, root) -> None:
        self.root = root

    def walk(self):
        for base, dirs, files in os.walk(self.root):
            config_path = os.path.join(base, 'config.json')
            if os.path.exists(config_path):
                config = load_json(config_path)
                if config.get('export') is not None:
                    self.parse_math(base, config)

    def parse_math(self, base, config):
        for export in config['export']:
            export_path = os.path.join(base, export)
            export_obj = load_json(export_path)
            source_path = os.path.join(base, export_obj['source'])
            md = load_md(source_path)
            new_md = []
            math_ctx = {
                "enter": False,
                "chars": []
            }

            count = len(md)
            i = 0
            has_enter_math = False
            while i < count:
                c = md[i]
                if c == '$':
                    if math_ctx['enter']:
                        j = 0
                        chars = math_ctx['chars']
                        length = len(chars)
                        while j < length:
                            cc = chars[j]
                            if cc == '_':
                                next_c = chars[j+1]
                                if next_c == '{':
                                    subs = []
                                    cursor = 2
                                    next_c = chars[j+cursor]
                                    while next_c != '}':
                                        subs.append(next_c)
                                        cursor += 1
                                        next_c = chars[j+cursor]

                                    sub = ''.join(subs)
                                    new_md.append(f'<sub>{sub}</sub>')
                                    j += cursor
                                else:
                                    new_md.append(f'<sub>{next_c}</sub>')
                                    j += 1
                            elif cc == '^':
                                next_c = chars[j+1]
                                if next_c == '{':
                                    subs = []
                                    cursor = 2
                                    next_c = chars[j+cursor]
                                    while next_c != '}':
                                        subs.append(next_c)
                                        cursor += 1
                                        next_c = chars[j+cursor]

                                    sub = ''.join(subs)
                                    new_md.append(f'<sup>{sub}</sup>')
                                    j += cursor
                                else:
                                    new_md.append(f'<sup>{next_c}</sup>')
                                    j += 1
                            else:
                                new_md.append(cc)
                            j += 1

                        math_ctx['enter'] = False
                    else:
                        math_ctx['enter'] = True
                        has_enter_math = True
                else:
                    if math_ctx['enter']:
                        math_ctx['chars'].append(c)
                    else:
                        new_md.append(c)
                i += 1

            source_new_relative = export_obj['source']+".md"
            source_path_new = os.path.join(base, source_new_relative)
            if has_enter_math:
                dump_md(source_path_new, ''.join(new_md))
                export_obj['source'] = source_new_relative
                dump_json(export_path, export_obj, True, True)