| import os |
| from typing import TYPE_CHECKING, Any, Dict, List, Match, Union |
|
|
| from ._base import BaseDirective, DirectivePlugin |
|
|
| if TYPE_CHECKING: |
| from ..block_parser import BlockParser |
| from ..core import BaseRenderer, BlockState |
| from ..markdown import Markdown |
|
|
|
|
| class Include(DirectivePlugin): |
| def parse( |
| self, block: "BlockParser", m: Match[str], state: "BlockState" |
| ) -> Union[Dict[str, Any], List[Dict[str, Any]]]: |
| source_file = state.env.get("__file__") |
| if not source_file: |
| return {"type": "block_error", "raw": "Missing source file"} |
|
|
| encoding = "utf-8" |
| options = self.parse_options(m) |
| if options: |
| attrs = dict(options) |
| if "encoding" in attrs: |
| encoding = attrs["encoding"] |
| else: |
| attrs = {} |
|
|
| relpath = self.parse_title(m) |
| dest = os.path.join(os.path.dirname(source_file), relpath) |
| dest = os.path.normpath(dest) |
|
|
| if dest == source_file: |
| return { |
| "type": "block_error", |
| "raw": "Could not include self: " + relpath, |
| } |
|
|
| if not os.path.isfile(dest): |
| return { |
| "type": "block_error", |
| "raw": "Could not find file: " + relpath, |
| } |
|
|
| with open(dest, "rb") as f: |
| content = f.read().decode(encoding) |
|
|
| ext = os.path.splitext(relpath)[1] |
| if ext in {".md", ".markdown", ".mkd"}: |
| new_state = block.state_cls() |
| new_state.env["__file__"] = dest |
| new_state.process(content) |
| block.parse(new_state) |
| return new_state.tokens |
|
|
| elif ext in {".html", ".xhtml", ".htm"}: |
| return {"type": "block_html", "raw": content} |
|
|
| attrs["filepath"] = dest |
| return { |
| "type": "include", |
| "raw": content, |
| "attrs": attrs, |
| } |
|
|
| def __call__(self, directive: BaseDirective, md: "Markdown") -> None: |
| directive.register("include", self.parse) |
| if md.renderer and md.renderer.NAME == "html": |
| md.renderer.register("include", render_html_include) |
|
|
|
|
| def render_html_include(renderer: "BaseRenderer", text: str, **attrs: Any) -> str: |
| return '<pre class="directive-include">\n' + text + "</pre>\n" |
|
|