Coverage for phml\compiler\steps\markup.py: 98%

48 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2023-04-12 14:26 -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 

7from phml.utilities import sanatize 

8 

9from .base import scoped_step 

10 

11try: # pragma: no cover 

12 from markdown import Markdown as PyMarkdown 

13 

14 MARKDOWN = PyMarkdown 

15except ImportError: # pragma: no cover 

16 error = Exception( 

17 "You do not have the package 'markdown' installed. Install it to be able to use <Markdown /> tags", 

18 ) 

19 

20 class Markdown: 

21 def __init__(self, *_a, **_k) -> None: 

22 raise error 

23 

24 def registerExtensions(self, *_a, **_k): 

25 raise error 

26 

27 def reset(self, *_a, **_k): 

28 raise error 

29 

30 MARKDOWN = Markdown 

31 

32 

33@scoped_step 

34def step_compile_markdown( 

35 node: Parent, components: ComponentManager, context: dict[str, Any] 

36): 

37 """Step to compile markdown. This step only works when you have `markdown` installed.""" 

38 from phml.core import HypertextManager 

39 

40 md_tags = [ 

41 child 

42 for child in node 

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

44 ] 

45 

46 if len(md_tags) > 0: 

47 markdown = MARKDOWN(extensions=["codehilite", "tables", "fenced_code"]) 

48 for md in md_tags: 

49 extras = str(md.get(":extras", None) or md.pop("extras", None) or "") 

50 configs = md.pop(":configs", None) 

51 if configs is not None: 

52 configs = exec_embedded( 

53 str(configs), 

54 "<Markdown :configs='<dict>'", 

55 **context, 

56 ) 

57 if extras is not None: 

58 if ":extras" in md: 

59 extras = exec_embedded( 

60 str(md.pop(":extras")), 

61 "<Markdown :extras='<list|str>'", 

62 **context, 

63 ) 

64 if isinstance(extras, str): 

65 extras = extras.split(" ") 

66 elif isinstance(extras, list): 

67 markdown.registerExtensions( 

68 extensions=extras, configs=configs or {} 

69 ) 

70 else: 

71 raise TypeError( 

72 "Expected ':extras' attribute to be a space seperated list as a str or a python list of str", 

73 ) 

74 

75 src = md.pop(":src", None) or md.pop("src", None) 

76 if src is None or not isinstance(src, str): 

77 raise ValueError( 

78 "<Markdown /> element must have a 'src' or ':src' attribute that is a string", 

79 ) 

80 

81 if context.get("_phml_path_", None) is not None: 

82 path = Path(context["_phml_path_"]) 

83 if path.suffix not in ["", None]: 

84 path = path.parent / Path(src) 

85 else: 

86 path = path / Path(src) 

87 else: 

88 path = Path.cwd() / Path(src) 

89 

90 if not path.is_file(): 

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

92 

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

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

95 

96 phml = HypertextManager() 

97 phml.components = components 

98 ast = phml.parse(content).ast 

99 

100 if len(ast) > 0 and md.parent is not None: 

101 wrapper = Element( 

102 "article", attributes=md.attributes, children=ast.children 

103 ) 

104 sanatize(wrapper) 

105 

106 idx = md.parent.index(md) 

107 

108 md.parent.remove(md) 

109 md.parent.insert(idx, wrapper)