Coverage for phml\compiler\steps\markup.py: 100%
40 statements
« prev ^ index » next coverage.py v6.5.0, created at 2023-04-06 14:03 -0500
« prev ^ index » next coverage.py v6.5.0, created at 2023-04-06 14:03 -0500
1from pathlib import Path
2from typing import Any
4from phml.components import ComponentManager
5from phml.embedded import exec_embedded
6from phml.nodes import Element, Parent
8from .base import comp_step
10try: # pragma: no cover
11 from markdown import Markdown as PyMarkdown
13 MARKDOWN = PyMarkdown
14except ImportError: # pragma: no cover
15 error = Exception(
16 "You do not have the package 'markdown' installed. Install it to be able to use <Markdown /> tags",
17 )
19 class Markdown:
20 def __init__(self, *args, **kwargs) -> None:
21 raise error
23 def registerExtensions(self, *args, **kwargs):
24 raise error
26 def reset(self, *args, **kwargs):
27 raise error
29 MARKDOWN = Markdown
32@comp_step
33def step_compile_markdown(
34 node: Parent, components: ComponentManager, context: dict[str, Any]
35):
36 """Step to compile markdown. This step only works when you have `markdown` installed."""
37 from phml.core import HypertextManager
39 md_tags = [
40 child
41 for child in node
42 if isinstance(child, Element) and child.tag == "Markdown"
43 ]
45 if len(md_tags) > 0:
46 markdown = MARKDOWN(extensions=["codehilite", "tables", "fenced_code"])
47 for md in md_tags:
48 extras = str(md.get(":extras", None) or md.pop("extras", None) or "")
49 configs = md.pop(":configs", None)
50 if configs is not None:
51 configs = exec_embedded(
52 str(configs),
53 "<Markdown :configs='<dict>'",
54 **context,
55 )
56 if extras is not None:
57 if ":extras" in md:
58 extras = exec_embedded(
59 str(md.pop(":extras")),
60 "<Markdown :extras='<list|str>'",
61 **context,
62 )
63 if isinstance(extras, str):
64 extras = extras.split(" ")
65 elif isinstance(extras, list):
66 markdown.registerExtensions(
67 extensions=extras, configs=configs or {}
68 )
69 else:
70 raise TypeError(
71 "Expected ':extras' attribute to be a space seperated list as a str or a python list of str",
72 )
74 src = md.pop(":src", None) or md.pop("src", None)
75 if src is None or not isinstance(src, str):
76 raise ValueError(
77 "<Markdown /> element must have a 'src' or ':src' attribute that is a string",
78 )
80 path = Path(src).resolve()
81 if not path.is_file():
82 raise FileNotFoundError(f"No markdown file at path '{path}'")
84 with path.open("r", encoding="utf-8") as md_file:
85 content = str(markdown.reset().convert(md_file.read()))
87 # TODO:
88 # PERF: Sanatize the markdown
89 phml = HypertextManager()
90 phml.components = components
91 ast = phml.parse(content).ast
93 if len(ast) > 0 and md.parent is not None:
94 idx = md.parent.index(md)
95 md.parent.remove(md)
96 md.parent.insert(
97 idx,
98 Element("article", attributes=md.attributes, children=ast.children),
99 )