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

1from pathlib import Path 

2from typing import Any 

3 

4from phml.components import ComponentManager 

5from phml.embedded import exec_embedded 

6from phml.nodes import Element, Parent 

7 

8from .base import comp_step 

9 

10try: # pragma: no cover 

11 from markdown import Markdown as PyMarkdown 

12 

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 ) 

18 

19 class Markdown: 

20 def __init__(self, *args, **kwargs) -> None: 

21 raise error 

22 

23 def registerExtensions(self, *args, **kwargs): 

24 raise error 

25 

26 def reset(self, *args, **kwargs): 

27 raise error 

28 

29 MARKDOWN = Markdown 

30 

31 

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 

38 

39 md_tags = [ 

40 child 

41 for child in node 

42 if isinstance(child, Element) and child.tag == "Markdown" 

43 ] 

44 

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 ) 

73 

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 ) 

79 

80 path = Path(src).resolve() 

81 if not path.is_file(): 

82 raise FileNotFoundError(f"No markdown file at path '{path}'") 

83 

84 with path.open("r", encoding="utf-8") as md_file: 

85 content = str(markdown.reset().convert(md_file.read())) 

86 

87 # TODO: 

88 # PERF: Sanatize the markdown 

89 phml = HypertextManager() 

90 phml.components = components 

91 ast = phml.parse(content).ast 

92 

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 )