74 أسطر
2.3 KiB
Python
74 أسطر
2.3 KiB
Python
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"
|