import re import os import shlex import textwrap from mkdocs.plugins import BasePlugin from codeinclude.resolver import select RE_START = r"""(?x) ^ (?P\s*) (?P\s*) $ """ RE_END = r"""(?x) ^ (?P\s*) (?P\s*) $ """ RE_SNIPPET = r"""(?x) ^ (?P\s*) \[(?P[^\]]*)\]\((?P<filename>[^)]+)\) ([\t ]+(?P<params>.*))? (?P<ignored_trailing_space>\s*) $ """ def get_substitute(page, title, filename, lines, block, inside_block): page_parent_dir = os.path.dirname(page.file.abs_src_path) import_path = os.path.join(page_parent_dir, filename) # Always use UTF-8, as it is the recommended default for source file encodings. with open(import_path, encoding='UTF-8') as f: content = f.read() selected_content = select( content, lines=lines, block=block, inside_block=inside_block ) dedented = textwrap.dedent(selected_content) return '\n```java tab="' + title + '"\n' + dedented + "\n```\n\n" class CodeIncludePlugin(BasePlugin): def on_page_markdown(self, markdown, page, config, site_navigation=None, **kwargs): "Provide a hook for defining functions from an external module" active = False results = "" for line in markdown.splitlines(): boundary = False # detect end if active and re.match(RE_END, line): active = False boundary = True # handle each line of a codeinclude zone if active: snippet_match = re.match(RE_SNIPPET, line) if snippet_match: title = snippet_match.group("title") filename = snippet_match.group("filename") indent = snippet_match.group("leading_space") raw_params = snippet_match.group("params") if raw_params: params = dict(token.split(":") for token in shlex.split(raw_params)) lines = params.get("lines", "") block = params.get("block", "") inside_block = params.get("inside_block", "") else: lines = "" block = "" inside_block = "" code_block = get_substitute( page, title, filename, lines, block, inside_block ) # re-indent code_block = re.sub("^", indent, code_block, flags=re.MULTILINE) results += code_block # detect start if re.match(RE_START, line): active = True boundary = True # outside a codeinclude zone and ignoring the boundaries if not active and not boundary: results += line + "\n" return results