Exemplo n.º 1
0
def main(idir, odir):

    for path, name in findall_files(idir, 'zip', '.css'):
        lk.logax(name)
        ifile, ofile = path, f'{odir}/{name}'
        rdata = read_file(ifile)
        wdata = rdata.replace('.highlight', '.codehilite')
        write_file(wdata, ofile)
def compose_html(
    title: str,
    md: str,
    css=f'{_STYLES_DIR}/github-markdown.css',
    syntax_highlight=f'{_STYLES_DIR}/syntax_highlight/richleland-pygments'
    f'-css/default.css'):
    """ Convert markdown to pure html, then rendered by github-markdown-css.
    
    Args:
        title: Suggest passing filename (without suffix) or the first line of
            `md` as title.
        md: The markdown text.
        css: For now (2020-11-26) we only support Github flavored markdown theme
            (see https://github.com/sindresorhus/github-markdown-css), in
            theoretically, any class-less markdown stylesheets can also be
            available (thus Typora themes not meet the requirements.)
        syntax_highlight: You can download syntax highlight css from
            http://richleland.github.io/pygments-css/, and put it in 'assets/
            syntax_highlight' folder.
        
    References:
        https://github.com/trentm/python-markdown2
        https://github.com/sindresorhus/github-markdown-css
    """
    import markdown2
    import textwrap
    #   https://google.github.io/styleguide/pyguide.html#310-strings

    # 1/3: Templates
    html = textwrap.dedent('''\
        <!doctype html>
        <html>
            {__head__}
            {__body__}
        </html>
    ''')
    head = textwrap.dedent('''\
        <head>
            <meta charset='UTF-8'>
            <meta name='viewport' content='width=device-width initial-scale=1'>
            {__title__}
            {__style__}
        </head>
    ''')
    title = f'<title>{title}</title>'
    style = textwrap.dedent('''\
        <style>
            /* GitHub theme uses 980px width and 45px padding, and 15px padding
               for mobile. */
               
            .markdown-body {{
                box-sizing: border-box;
                min-width: 200px;
                max-width: 980px;
                margin: 0 auto;
                padding: 45px;
            }}
            
            @media (max-width: 767px) {{
                .markdown-body {{
                    padding: 15px;
                }}
            }}
            
            {__main_style__}
            {__syntax_highlight__}
        </style>
    ''')
    body = textwrap.dedent('''\
        <body>
            <div id='write' class='markdown-body'>
                {__content__}
            </div>
        </body>
    ''')
    content = markdown2.markdown(
        md,
        extras=[
            # https://github.com/trentm/python-markdown2/wiki/Extras
            'code-friendly',
            'cuddled-lists',
            'fenced-code-blocks',
            'header-ids',
            'numbering',
            'strike',
            'tables',
            'task_list',
            'toc',
        ])
    content = re.sub(  # Remove 'disabled' from checkbox elements.
        r'<(input type="checkbox" class="task-list-item-checkbox"(?: checked)?)'
        r' disabled>', r'<\1>', content)

    # 2/3: Interpolates
    body = body.format(__content__=content)
    style = style.format(__main_style__=read_file(css),
                         __syntax_highlight__=read_file(syntax_highlight))
    head = head.format(__title__=title, __style__=style)
    html = html.format(__head__=head, __body__=body)

    # 3/3: Return full html
    return html
Exemplo n.º 3
0
def main(pyml_file: str):
    compile_pyml_code(read_file(pyml_file))
Exemplo n.º 4
0
def main(file_i: str, file_o):
    """
    Args:
        file_i: "~/blueprint/resources/no1_all_qml_modules.html". 该文件被我事先
            从 "{YourQtProgram}/Docs/Qt-{version}/qtdoc/modules-qml.html" 拷贝过
            来.
        file_o: '~/blueprint/resources/no2_all_qml_modules.json'
            "~/resources/all_qml_modules.json"
                格式: {
                    'module_group': {raw_module_group: formatted_name, ...},
                        raw_module_group: see `Notes:no1`
                        formatted_name: see `Notes:no3`
                    'module': {raw_module: formatted_name, ...}
                        raw_module: see `Notes:no2`
                }
                示例: {
                    'module_group': {
                        'qtquick': 'QtQuick',
                        'qtquickcontrols': 'QtQuickControls',
                        ...
                    },
                    'module': {
                        'qtquick-windows': 'QtQuick.Windows',
                        ...
                    },
                }
            Notes:
                1. `raw_module_group` 的键是没有空格或连接符的, 只有纯小写字母和
                    数字组成
                2. `raw_module` 的键是由纯小写字母和连接符组成 (例如 'qtquick
                    -windows')
                3. `formatted_name` 是由首字母大写的单词和点号组成 (例如
                    'QtQuick.Windows')
                    1. 但是有一个特例: 'QtQuick.labs.xxx' 从 'lab' 开始全部都是
                        小写(例如 'Qt.labs.folderlistmodel')
                4. 该生成文件可被直接用于 `no2_all_qml_types.py.py:_correct
                    _module_lettercase`
    """
    file_i = file_i.replace('\\', '/')
    soup = BeautifulSoup(read_and_write.read_file(file_i), 'html.parser')
    container = soup.find('table', 'annotated')

    writer = {
        'module_group': {},  # value: {raw_module_group: formatted_name, ...}
        'module': {},  # value: {raw_module: formatted_name, ...}
    }

    extra_words = ['Qt', 'Quick', 'Qml', 'Win', 'Labs']

    for e in container.find_all('td', 'tblName'):
        """ <td class="tblName">
                <p>
                    <a href="../qtcharts/qtcharts-qmlmodule.html">
                                ^--1---^ ^--2---^
                        Qt Charts QML Types
                        ^---3---^
                    </a>
                </p>
            </td>
            
            -> 1. module_group: 'qtcharts'
               2. module: 'qtcharts'
               3. name: 'Qt Charts'
        """
        link = e.a['href'].split('/')
        # -> ['..', 'qtquickcontrols1', 'qtquick-controls-qmlmodule.html']

        module_group_raw = link[1]  # type: str
        # -> 'qtquickcontrols1'
        module_raw = link[2].replace('-qmlmodule.html', '')  # type: str
        # -> 'qtquick-controls'
        """ 针对 QtQuick Controls 的处理
        
        背景: Qt 对 QtQuick.Controls 的命名关系有点乱, 如下所示:
            QtQuick.Controls v1:
                module_group = 'qtquickcontrols1'
                module = 'qtquick-controls'
            QtQuick.Controls v2:
                module_group = 'qtquickcontrols'
                module = 'qtquick-controls2'
        我将 v1 舍弃, 只处理 v2, 并将 v2 的命名改为:
                module_group = 'qtquickcontrols'
                module = 'qtquick-controls' (注意去掉了尾部的数字 2)
        
        为什么这样做:
            以 Button 为例, v1 的 Button 继承于 FocusScope, v2 的 Button 继承于
            AbstractButton. 我的设计的前提是只使用 'qtquickcontrols' 和
            'qtquick-controls', 那么在这种情况下, 二者就只能保留其中一个模组. 因
            此我保留了 v2, 后续解析和分析继承关系也都基于 v2 继续.
        """
        if module_group_raw == 'qtquickcontrols1':
            continue
        if module_raw == 'qtquick-controls2':
            module_raw = 'qtquick-controls'

        mini_lexicon = (e.a.text.replace(' QML Types', '').replace(
            'Qt Quick',
            'QtQuick').replace('Qt3DAnimation',
                               'Animation').replace('Web', 'Web ').title()
                        )  # type: str
        """ 解释一下上面的 mini_lexicon 的处理逻辑.
            
            mini_lexicon 为 module_group 和 module 提供一个小型词典, 该词典可用
            于帮助调整 module_group 和 module 的大小写格式.
            例如:
                调整前:
                    module_group: 'qtcharts'
                    module: 'qtcharts'
                调整后:
                    module_group: 'QtCharts'
                    module: 'QtCharts'
            mini_lexicon 来源于 `e.a.text`, 在考虑到实际情况中, 有许多细节需要重
            新调整, 所以我们才要对 mini_lexicon 进行诸多处理, 才能为
            module_group 和 module 所用:
                1. `replace(' QML Types', '')`: 把不必要的词尾去掉
                2. `replace('Qt Quick', 'QtQuick')`: 遵循模块的写法规范
                3. `replace('Qt3DAnimation', 'Animation')`: 针对 'Qt 3D
                    Qt3DAnimation' 的处理. 这个貌似是官方的写法有点问题, 所以我
                    把 'Qt3DAnimation' 改成了 'Animation'
                4. `replace('Web', 'Web ')`: 为了将 'WebEngine' 拆分成
                    'Web Engine', 需要 `mini_lexicon` 提供这两个独立的单词
                5. `title()`: 将首字母大写, 非首字母小写. 例如:
                    1. 'Qt NFS' -> 'Qt Nfc'
                    2. 'Qt QML' -> 'Qt Qml'
                    
            此外还有一些其他问题:
                1. module_group = 'qtwinextras' 的 `e.a.text` 是
                    'Qt Windows Extras', 该问题不属于 mini_lexicon 的处理范畴.
                    我使用 `extra_words` 变量解决这个问题, 见 extra_words 的定义
        """

        words = [x.title() for x in mini_lexicon.split(' ') if len(x) > 1]
        # -> ['QtQuick', 'Controls']
        module_group_fmt = _correct_module_lettercase(module_group_raw,
                                                      extra_words + words)
        module_fmt = _correct_module_lettercase(module_raw,
                                                extra_words + words)

        writer['module_group'][module_group_raw] = module_group_fmt
        writer['module'][module_raw] = module_fmt

    read_and_write.dumps(writer, file_o)
Exemplo n.º 5
0
def main(file_i, file_o):
    """
    
    Args:
        file_i: '~/blueprint/resources/no2_all_qml_types.html'. 该文件被我事先从
            "{YourQtProgram}/Docs/Qt-{version}/qtdoc/qmltypes.html" 拷贝过来.
        file_o: 生成文件. "~/blueprint/resources/no3_all_qml_types.json"
            {module_group: {module: {type_name: path}, ...}, ...}
            #   {模组: {模块: {类型: 路径}}}
            e.g. {
                'qtquick': {
                    'qtquick': {
                        'Rectangle': 'qtquick/qml-qtquick-rectangle.html',
                        'Text': 'qtquick/qml-qtquick-text.html',
                        ...
                    },
                    'qtquick-window': {
                        'Window': 'qtquick/qml-qtquick-window-window.html',
                        ...
                    },
                    ...
                },
                ...
            }
    
    思路:
        1. 我们安装了 Qt 主程序以后, 在软件安装目录下的 'Docs/Qt-{version}' 中有
           它的 API 文档
        2. 其中 "~/Docs/Qt-{version}/qtdoc/qmltypes.html" 列出了全部的 qml types
        3. 我们对 "qmltypes.html" 用 BeautifulSoup 解析, 从中获取每个 qml types
           和它的链接, 最终我们将得到这些信息: 模组, 模块, 类型, 路径等
        4. 将这些信息保存到本项目下的 "~/resources/qmltypes.json" 文件中
    """
    soup = BeautifulSoup(read_and_write.read_file(file_i), 'html.parser')

    # https://www.itranslater.com/qa/details/2325827141935563776
    data = defaultdict(lambda: defaultdict(dict))
    #   {module_group: {module: {type_name: filename, ...}, ...}, ...}

    container = soup.find('div', 'flowListDiv')
    for e in container.find_all('dd'):
        link = e.a['href']  # type: str
        #   e.g. "../qtdatavisualization/qml-qtdatavisualization-
        #         abstract3dseries.html"

        match = re.search(r'\.\./(\w+)/([-\w]+)\.html', link)
        #                  |     ^-1-^ ^--2---^      |
        #                  ^-------- group(0) -------^
        #   match.group(0): '../qtdatavisualization/qml-qtdatavisualization
        #       -abstract3dseries.html'
        #   match.group(1): 'qtdatavisualization'
        #   match.group(2): 'qml-qtdatavisualization-abstract3dseries'
        assert match, e

        module_group = match.group(1)
        module = match.group(2)
        # see `blueprint/qml_modules_indexing/no1_all_qml_modules.py:comments
        # :针对 QtQuick Controls 的处理`
        if module_group == 'qtquickcontrols1':
            continue
        if 'qtquick-controls2' in module:
            #   e.g. 'qml-qtquick-controls2-label'
            module = module.replace('controls2', 'controls')

        path = match.group(0).lstrip('../')
        #   -> 'qtdatavisualization/qml-qtdatavisualization-abstract3dseries
        #   .html'
        module_group = _correct_module_lettercase(module_group)
        #   'qtdatavisualization' -> 'QtDataVisualization'
        module = _correct_module_lettercase('-'.join(module.split('-')[1:-1]))
        #   eg1: 'qml-qtdatavisualization-abstract3dseries' -> ['qml',
        #   'qtdatavisualization', 'abstract3dseries'] -> [
        #   'qtdatavisualization'] -> 'qtdatavisualization'
        #   -> 'QtDataVisualization'
        #   eg2: 'qml-qt3d-input-abstractactioninput' -> ['qml', 'qt3d',
        #   'input', 'abstractactioninput'] -> ['qt3d', 'input',
        #   'abstractactioninput'] -> 'qt3d-input' -> 'Qt3D.Input'
        #   注: 为什么要舍去末尾的元素? 因为末尾的那个是 `type_name`, 不是
        #   `module`. 接下来我们会抽取 `type_name`.
        type_name = e.text.split(':', 1)[0]
        #   注意我们不使用 `correct_module_lettercase(match.group(2).split('-')
        #   [-1])`, 是因为 `correct_module_lettercase` 的词库范围比较小, 仅对
        #   `module_group` 和 `module` 做了覆盖, 不能保证对 `type_name` 的处理正
        #   确; 而 `soup` 是可以比较轻松地通过 tag 提取到它的, 所以通过 html 元
        #   素获取.
        #   e.g. 'RadioButton: QtQuickControls' -> 'RadioButton'

        lk.loga(module_group, module, type_name)
        data[module_group][module][type_name] = path

    read_and_write.dumps(data, file_o)