|
| 1 | +import re |
1 | 2 | from naturalsize import replStrPassage |
2 | 3 |
|
3 | 4 | from .defaults import HELLO_WORLD as DEFAULT |
4 | 5 | from .commons import * |
5 | 6 | from .exceptions import InvalidIncludePhraseFiletypeError, StaticResourceUsageOutsideHeadError |
6 | 7 | from .beta import BETA |
| 8 | +from .patterns import * |
7 | 9 |
|
8 | 10 | class PyHTML: |
9 | 11 | def __init__(self, html: str = DEFAULT): |
10 | 12 | self.html = html |
11 | 13 |
|
12 | | - def decode(self): |
| 14 | + def _replace_eval_phrase(self): |
13 | 15 | """ |
14 | | - Decodes the HTML content. |
| 16 | + Scans the HTML for the evalPyHTML phrase and replaces it with the appropriate start and end phrases. |
15 | 17 | """ |
16 | | - self.html = self.html.strip() |
17 | | - |
18 | | - # common html beginning phrase |
19 | | - if self.html.startswith("<{{evalPyHTML}}>"): |
20 | | - self.html = START_REPLACE + self.html[16:] |
| 18 | + if self.html.startswith(EVAL_PYHTML): |
| 19 | + self.html = START_REPLACE + self.html[len(EVAL_PYHTML):] |
| 20 | + if self.html.endswith(EVAL_PYHTML): |
| 21 | + self.html = self.html[:-len(EVAL_PYHTML)] + END_REPLACE |
21 | 22 |
|
22 | | - # common html ending phrase |
23 | | - if self.html.endswith("<{{evalPyHTML}}>"): |
24 | | - self.html = self.html[:-16] + END_REPLACE |
25 | | - |
26 | | - # PyWSGIRef's styling |
27 | | - idx = self.html.find("<{{evalPyHTML-modernStyling: true}}>") |
| 23 | + def _replace_modern_styling(self): |
| 24 | + """ |
| 25 | + Scans the HTML for the modern styling phrase and replaces it with the appropriate CSS. |
| 26 | + """ |
| 27 | + idx = self.html.find(MODERN_STYLING_PHRASE) |
28 | 28 | if idx != -1: |
29 | | - if idx > self.html.find("</head>"): |
| 29 | + head_idx = self.html.find("</head>") |
| 30 | + if idx > head_idx: |
30 | 31 | raise StaticResourceUsageOutsideHeadError() |
31 | | - self.html = replStrPassage(idx, idx+35, self.html, MODERN_STYLING) |
32 | | - |
| 32 | + self.html = replStrPassage(idx, idx+len(MODERN_STYLING_PHRASE), self.html, MODERN_STYLING) |
| 33 | + |
| 34 | + def _replace_includes(self): |
| 35 | + """ |
| 36 | + Scans the HTML for include phrases and replaces them with the appropriate resources. |
| 37 | + """ |
| 38 | + for match in re.finditer(INCLUDE_PATTERN, self.html): |
| 39 | + idx, idxEnd = match.span() |
| 40 | + head_idx = self.html.find("</head>") |
| 41 | + if idx > head_idx: |
| 42 | + raise StaticResourceUsageOutsideHeadError() |
| 43 | + resources = match.group(1).split(",") |
| 44 | + setIn = "" |
| 45 | + for i in resources: |
| 46 | + i = i.strip() |
| 47 | + if i.endswith(".css"): |
| 48 | + setIn += f"\t\t<link rel='stylesheet' href='{i}'/>\n" |
| 49 | + elif i.endswith(".js"): |
| 50 | + setIn += f"\t\t<script src='{i}'></script>\n" |
| 51 | + elif i.endswith(".json"): |
| 52 | + setIn += f"\t\t<link rel='manifest' href='{i}'/>\n" |
| 53 | + elif i.endswith("favicon.ico"): |
| 54 | + setIn += f"\t\t<link rel='icon' href='{i}'/>\n" |
| 55 | + else: |
| 56 | + raise InvalidIncludePhraseFiletypeError() |
| 57 | + self.html = self.html[:idx] + setIn + self.html[idxEnd:] |
| 58 | + |
| 59 | + def _replace_script_blocks(self): |
| 60 | + """ |
| 61 | + Sucht nach evalPyHTML-script Phrasen und ersetzt sie durch <script>-Blöcke. |
| 62 | + Nur im BETA-Modus aktiv. |
| 63 | + """ |
| 64 | + for match in re.finditer(SCRIPT_PATTERN, self.html, re.DOTALL): |
| 65 | + idx, idxEnd = match.span() |
| 66 | + script_content = match.group(1).strip() |
| 67 | + replacement = f"<script>{script_content}</script>" |
| 68 | + self.html = self.html[:idx] + replacement + self.html[idxEnd:] |
| 69 | + |
| 70 | + def _replace_style_blocks(self): |
| 71 | + """ |
| 72 | + Sucht nach evalPyHTML-style Phrasen und ersetzt sie durch <style>-Blöcke. |
| 73 | + Nur im BETA-Modus aktiv. |
| 74 | + """ |
| 75 | + for match in re.finditer(STYLE_PATTERN, self.html, re.DOTALL): |
| 76 | + idx, idxEnd = match.span() |
| 77 | + style_content = match.group(1).strip() |
| 78 | + replacement = f"<style>{style_content}</style>" |
| 79 | + self.html = self.html[:idx] + replacement + self.html[idxEnd:] |
| 80 | + |
| 81 | + def decode(self): |
| 82 | + """ |
| 83 | + Decodes the HTML content by replacing specific phrases and applying modern styling. |
| 84 | + """ |
| 85 | + self.html = self.html.strip() |
| 86 | + self._replace_eval_phrase() |
| 87 | + self._replace_modern_styling() |
33 | 88 | if BETA.value: |
34 | | - # static ressources |
35 | | - idx = self.html.find("<{{evalPyHTML-include: ") |
36 | | - if idx != -1: |
37 | | - idxEnd = self.html.find(" :include-}}>", idx) |
38 | | - if idxEnd > self.html.find("</head>"): |
39 | | - raise StaticResourceUsageOutsideHeadError() |
40 | | - setIn = "" |
41 | | - for i in self.html[idx:idxEnd].split(":")[1].strip().split(","): |
42 | | - if i.endswith(".css"): |
43 | | - setIn += "\t\t<link rel='stylesheet' href='{}'/>\n".format(i) |
44 | | - elif i.endswith(".js"): |
45 | | - setIn += "\t\t<script src='{}'></script>\n".format(i) |
46 | | - elif i.endswith(".json"): |
47 | | - setIn += "\t\t<link rel='manifest' href='{}'/>\n".format(i) |
48 | | - else: |
49 | | - raise InvalidIncludePhraseFiletypeError() |
50 | | - self.html = replStrPassage(idx, idxEnd+12, self.html, setIn) |
| 89 | + self._replace_includes() |
| 90 | + self._replace_script_blocks() |
| 91 | + self._replace_style_blocks() |
51 | 92 |
|
52 | 93 | def decoded(self) -> str: |
53 | 94 | """ |
|
0 commit comments