simplibs-extractor-html 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- simplibs/extractor_html/__init__.py +82 -0
- simplibs/extractor_html/actions/ApplyToHtmlBlocks.py +29 -0
- simplibs/extractor_html/actions/CleanupHtmlWhitespace.py +22 -0
- simplibs/extractor_html/actions/CompactHtml.py +22 -0
- simplibs/extractor_html/actions/HtmlOutline.py +23 -0
- simplibs/extractor_html/actions/RemoveTemplateImports.py +22 -0
- simplibs/extractor_html/actions/StripHtmlComments.py +23 -0
- simplibs/extractor_html/actions/StripTemplateComments.py +27 -0
- simplibs/extractor_html/actions/TemplateOutline.py +23 -0
- simplibs/extractor_html/actions/__init__.py +57 -0
- simplibs/extractor_html/annotations/TemplateEngine.py +26 -0
- simplibs/extractor_html/annotations/__init__.py +14 -0
- simplibs/extractor_html/constants/HTML_ANY_TAG_PATTERN.py +16 -0
- simplibs/extractor_html/constants/HTML_BLOCK_LANGUAGE_BY_TYPE.py +41 -0
- simplibs/extractor_html/constants/HTML_COMMENT_END_PATTERN.py +19 -0
- simplibs/extractor_html/constants/HTML_CONDITIONAL_PATTERN.py +23 -0
- simplibs/extractor_html/constants/HTML_DEPENDENCY_DIR_NAMES.py +18 -0
- simplibs/extractor_html/constants/HTML_EXTRA_LANGUAGE_BY_SUFFIX.py +31 -0
- simplibs/extractor_html/constants/HTML_HEADING_ELEMENTS.py +15 -0
- simplibs/extractor_html/constants/HTML_ID_ATTRIBUTE_PATTERN.py +21 -0
- simplibs/extractor_html/constants/HTML_IMPLIED_END.py +34 -0
- simplibs/extractor_html/constants/HTML_LICENSE_START.py +14 -0
- simplibs/extractor_html/constants/HTML_LICENSE_TAGS.py +14 -0
- simplibs/extractor_html/constants/HTML_OUTLINE_ELEMENTS.py +32 -0
- simplibs/extractor_html/constants/HTML_OUTLINE_TEXT_LIMIT.py +15 -0
- simplibs/extractor_html/constants/HTML_OUTPUT_DIR_NAMES.py +43 -0
- simplibs/extractor_html/constants/HTML_PLAIN_SUFFIXES.py +18 -0
- simplibs/extractor_html/constants/HTML_RAW_TEXT_END_PATTERNS.py +28 -0
- simplibs/extractor_html/constants/HTML_SUFFIXES.py +22 -0
- simplibs/extractor_html/constants/HTML_TAG_NAME_PATTERN.py +16 -0
- simplibs/extractor_html/constants/HTML_TEMPLATE_BLOCKS.py +38 -0
- simplibs/extractor_html/constants/HTML_TEMPLATE_IMPORT_TAGS.py +29 -0
- simplibs/extractor_html/constants/HTML_TEMPLATE_OUTLINE_TAGS.py +35 -0
- simplibs/extractor_html/constants/HTML_TEMPLATE_SUFFIXES.py +19 -0
- simplibs/extractor_html/constants/HTML_TEMPLATE_TAG_NAME_PATTERN.py +16 -0
- simplibs/extractor_html/constants/HTML_TEMPLATE_TOKEN_PATTERN.py +16 -0
- simplibs/extractor_html/constants/HTML_TEXT_ELEMENTS.py +16 -0
- simplibs/extractor_html/constants/HTML_TOKEN_PATTERN.py +26 -0
- simplibs/extractor_html/constants/HTML_TYPE_ATTRIBUTE_PATTERN.py +21 -0
- simplibs/extractor_html/constants/HTML_VOID_ELEMENTS.py +21 -0
- simplibs/extractor_html/constants/HTML_WRAPPED_STEM_ENDING.py +14 -0
- simplibs/extractor_html/constants/HTML_WRAPPED_SUFFIXES.py +15 -0
- simplibs/extractor_html/constants/__init__.py +77 -0
- simplibs/extractor_html/file_rules/__init__.py +56 -0
- simplibs/extractor_html/file_rules/atomic/DEPENDENCY_DIRS.py +17 -0
- simplibs/extractor_html/file_rules/atomic/DOT_NAME.py +19 -0
- simplibs/extractor_html/file_rules/atomic/OUTPUT_DIRS.py +17 -0
- simplibs/extractor_html/file_rules/atomic/VCS_DIRS.py +21 -0
- simplibs/extractor_html/file_rules/atomic/WRAPPED_HTML.py +22 -0
- simplibs/extractor_html/file_rules/atomic/__init__.py +26 -0
- simplibs/extractor_html/file_rules/html/HTML_BASE.py +22 -0
- simplibs/extractor_html/file_rules/html/HTML_FILES.py +24 -0
- simplibs/extractor_html/file_rules/html/HTML_PLAIN_BASE.py +24 -0
- simplibs/extractor_html/file_rules/html/HTML_STRICT_EXCLUDE.py +21 -0
- simplibs/extractor_html/file_rules/html/__init__.py +20 -0
- simplibs/extractor_html/logic/__init__.py +44 -0
- simplibs/extractor_html/logic/_helpers/HtmlBlock.py +31 -0
- simplibs/extractor_html/logic/_helpers/HtmlOutlineBuilder.py +189 -0
- simplibs/extractor_html/logic/_helpers/HtmlScan.py +50 -0
- simplibs/extractor_html/logic/_helpers/HtmlTag.py +32 -0
- simplibs/extractor_html/logic/_helpers/Ranges.py +48 -0
- simplibs/extractor_html/logic/_helpers/TemplateScan.py +43 -0
- simplibs/extractor_html/logic/_helpers/TemplateTag.py +33 -0
- simplibs/extractor_html/logic/_helpers/__init__.py +68 -0
- simplibs/extractor_html/logic/_helpers/blank_spans.py +40 -0
- simplibs/extractor_html/logic/_helpers/build_html_outline.py +38 -0
- simplibs/extractor_html/logic/_helpers/build_template_outline.py +75 -0
- simplibs/extractor_html/logic/_helpers/find_blanks_start.py +29 -0
- simplibs/extractor_html/logic/_helpers/find_block_language.py +35 -0
- simplibs/extractor_html/logic/_helpers/find_comments.py +60 -0
- simplibs/extractor_html/logic/_helpers/find_protected_spans.py +48 -0
- simplibs/extractor_html/logic/_helpers/find_template_import_spans.py +37 -0
- simplibs/extractor_html/logic/_helpers/fit_removal_span.py +40 -0
- simplibs/extractor_html/logic/_helpers/is_license_comment.py +26 -0
- simplibs/extractor_html/logic/_helpers/line_of.py +23 -0
- simplibs/extractor_html/logic/_helpers/raise_block_result_invalid.py +38 -0
- simplibs/extractor_html/logic/_helpers/replace_spans.py +42 -0
- simplibs/extractor_html/logic/_helpers/scan_checked.py +45 -0
- simplibs/extractor_html/logic/_helpers/scan_html.py +208 -0
- simplibs/extractor_html/logic/_helpers/scan_templates.py +128 -0
- simplibs/extractor_html/logic/_helpers/scan_templates_checked.py +39 -0
- simplibs/extractor_html/logic/_helpers/skip_html_comment.py +41 -0
- simplibs/extractor_html/logic/_helpers/skip_html_tag.py +46 -0
- simplibs/extractor_html/logic/_helpers/tidy_lines.py +86 -0
- simplibs/extractor_html/logic/_helpers/warn_problems.py +32 -0
- simplibs/extractor_html/logic/apply_to_html_blocks.py +103 -0
- simplibs/extractor_html/logic/cleanup_html_whitespace.py +54 -0
- simplibs/extractor_html/logic/compact_html.py +44 -0
- simplibs/extractor_html/logic/html_comment_spans.py +54 -0
- simplibs/extractor_html/logic/html_outline.py +66 -0
- simplibs/extractor_html/logic/strip_html_comments.py +63 -0
- simplibs/extractor_html/logic/templates/__init__.py +25 -0
- simplibs/extractor_html/logic/templates/remove_template_imports.py +51 -0
- simplibs/extractor_html/logic/templates/strip_template_comments.py +60 -0
- simplibs/extractor_html/logic/templates/template_comment_spans.py +49 -0
- simplibs/extractor_html/logic/templates/template_outline.py +62 -0
- simplibs/extractor_html/plugin/__init__.py +14 -0
- simplibs/extractor_html/plugin/register_all.py +60 -0
- simplibs/extractor_html/presets/__init__.py +43 -0
- simplibs/extractor_html/presets/html_clean_steps.py +54 -0
- simplibs/extractor_html/presets/html_no_imports_steps.py +50 -0
- simplibs/extractor_html/presets/html_outline_steps.py +28 -0
- simplibs/extractor_html/presets/template_structure_steps.py +27 -0
- simplibs/extractor_html/profiles/DJANGO_CLEAN.py +36 -0
- simplibs/extractor_html/profiles/DJANGO_NO_IMPORTS.py +32 -0
- simplibs/extractor_html/profiles/DJANGO_OUTLINE.py +32 -0
- simplibs/extractor_html/profiles/DJANGO_STRUCTURE.py +32 -0
- simplibs/extractor_html/profiles/HTML_CODE_CLEAN.py +32 -0
- simplibs/extractor_html/profiles/HTML_CODE_NO_IMPORTS.py +30 -0
- simplibs/extractor_html/profiles/HTML_DATA_ALL.py +26 -0
- simplibs/extractor_html/profiles/HTML_OUTLINE.py +31 -0
- simplibs/extractor_html/profiles/HTML_PROFILES.py +42 -0
- simplibs/extractor_html/profiles/HTML_SRC_CLEAN.py +31 -0
- simplibs/extractor_html/profiles/JINJA_CLEAN.py +35 -0
- simplibs/extractor_html/profiles/JINJA_NO_IMPORTS.py +32 -0
- simplibs/extractor_html/profiles/JINJA_OUTLINE.py +30 -0
- simplibs/extractor_html/profiles/JINJA_STRUCTURE.py +31 -0
- simplibs/extractor_html/profiles/__init__.py +86 -0
- simplibs/extractor_html/profiles/steps_for_engine.py +39 -0
- simplibs/extractor_html/profiles/steps_for_pages.py +36 -0
- simplibs/extractor_html/py.typed +1 -0
- simplibs_extractor_html-0.1.0.dist-info/METADATA +504 -0
- simplibs_extractor_html-0.1.0.dist-info/RECORD +127 -0
- simplibs_extractor_html-0.1.0.dist-info/WHEEL +5 -0
- simplibs_extractor_html-0.1.0.dist-info/entry_points.txt +2 -0
- simplibs_extractor_html-0.1.0.dist-info/licenses/LICENSE +21 -0
- simplibs_extractor_html-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
from .annotations import TemplateEngine
|
|
2
|
+
from .logic import (
|
|
3
|
+
apply_to_html_blocks,
|
|
4
|
+
cleanup_html_whitespace,
|
|
5
|
+
compact_html,
|
|
6
|
+
html_comment_spans,
|
|
7
|
+
html_outline,
|
|
8
|
+
remove_template_imports,
|
|
9
|
+
strip_html_comments,
|
|
10
|
+
strip_template_comments,
|
|
11
|
+
template_comment_spans,
|
|
12
|
+
template_outline,
|
|
13
|
+
)
|
|
14
|
+
from .plugin import register_all
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
__all__ = [
|
|
18
|
+
# annotations
|
|
19
|
+
"TemplateEngine",
|
|
20
|
+
# steps for pages
|
|
21
|
+
"apply_to_html_blocks",
|
|
22
|
+
"cleanup_html_whitespace",
|
|
23
|
+
"compact_html",
|
|
24
|
+
"html_comment_spans",
|
|
25
|
+
"html_outline",
|
|
26
|
+
"strip_html_comments",
|
|
27
|
+
# steps for templates
|
|
28
|
+
"remove_template_imports",
|
|
29
|
+
"strip_template_comments",
|
|
30
|
+
"template_comment_spans",
|
|
31
|
+
"template_outline",
|
|
32
|
+
# add-on of the extractor
|
|
33
|
+
"register_all",
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
_DESIGN_NOTES = """
|
|
38
|
+
# simplibs-extractor-html — Package Root
|
|
39
|
+
|
|
40
|
+
## Purpose
|
|
41
|
+
The add-on that teaches `simplibs-extractor` about pages (HTML) and about the
|
|
42
|
+
templates of Django and Jinja: file rules for such projects, the steps that
|
|
43
|
+
clean the source (comments, imports, whitespace, the code inside the page) or
|
|
44
|
+
reduce it to an overview, and thirteen ready profiles. Install it and the
|
|
45
|
+
profiles are there:
|
|
46
|
+
|
|
47
|
+
simplibs-extractor html django-clean my_project
|
|
48
|
+
|
|
49
|
+
## What the Root Exports
|
|
50
|
+
The steps as plain functions (`str -> str`, except the spans), the annotation
|
|
51
|
+
of their `engine` parameter, and `register_all` (the target of the entry point
|
|
52
|
+
`simplibs.extractor.plugins`):
|
|
53
|
+
|
|
54
|
+
from simplibs.extractor_html import strip_html_comments, html_outline, TemplateEngine
|
|
55
|
+
|
|
56
|
+
## What the Root Deliberately Does NOT Export
|
|
57
|
+
Four domain folders with their own `__all__`, imported through their domain:
|
|
58
|
+
|
|
59
|
+
from simplibs.extractor_html.actions import StripHtmlComments
|
|
60
|
+
from simplibs.extractor_html.file_rules import HTML_BASE
|
|
61
|
+
from simplibs.extractor_html.presets import html_clean_steps
|
|
62
|
+
from simplibs.extractor_html.profiles import DJANGO_CLEAN
|
|
63
|
+
|
|
64
|
+
and the internals: `_helpers/` inside `logic`.
|
|
65
|
+
|
|
66
|
+
## Spans
|
|
67
|
+
The steps find ranges of characters as `simplibs.text.Span`. The type is not
|
|
68
|
+
defined here, it is taken from `simplibs-text`.
|
|
69
|
+
|
|
70
|
+
## The Other Add-Ons
|
|
71
|
+
The presets that clean the code inside a page use `simplibs-extractor-javascript`
|
|
72
|
+
and `simplibs-extractor-css`. The steps themselves (`apply_to_html_blocks`) take
|
|
73
|
+
the steps for the code as parameters and know nothing of either.
|
|
74
|
+
|
|
75
|
+
## Layering
|
|
76
|
+
`constants` ← `annotations` ← `file_rules` ← `logic` ← `actions` ← `presets` ← `profiles` ← `plugin`.
|
|
77
|
+
Each layer imports only from the layers on its left; the root imports from the ones it exports.
|
|
78
|
+
|
|
79
|
+
## `__all__`
|
|
80
|
+
Defined here and in the domain folders (`actions`, `file_rules`, `presets`,
|
|
81
|
+
`profiles`) only; the layers inside them use plain imports.
|
|
82
|
+
"""
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from simplibs.actions import create_action
|
|
2
|
+
# Outers
|
|
3
|
+
from ..logic import apply_to_html_blocks
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
ApplyToHtmlBlocks = create_action(
|
|
7
|
+
apply_to_html_blocks,
|
|
8
|
+
main_param="text",
|
|
9
|
+
class_name="ApplyToHtmlBlocks",
|
|
10
|
+
)
|
|
11
|
+
"""Action wrapping `apply_to_html_blocks` — runs the given steps on the code inside `script` and `style` of the page flowing in."""
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
_DESIGN_NOTES = """
|
|
15
|
+
# ApplyToHtmlBlocks — Action Over `apply_to_html_blocks`
|
|
16
|
+
|
|
17
|
+
## Purpose
|
|
18
|
+
The step that gives the code inside a page to the steps of its own language:
|
|
19
|
+
`ApplyToHtmlBlocks(script=JS_CLEAN, style=CSS_PLAIN_CLEAN)`.
|
|
20
|
+
|
|
21
|
+
## Shape
|
|
22
|
+
Main input: `text`. Options: `script` and `style` (each a step, an action or a
|
|
23
|
+
whole pipeline that turns the text of a block into the new text, or `None`) and
|
|
24
|
+
`engine`. Text in, text out.
|
|
25
|
+
|
|
26
|
+
## Steps Inside an Action
|
|
27
|
+
An action is callable, so it is a step for this one: the pipelines of the other
|
|
28
|
+
add-ons are passed as they are.
|
|
29
|
+
"""
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from simplibs.actions import create_action
|
|
2
|
+
# Outers
|
|
3
|
+
from ..logic import cleanup_html_whitespace
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
CleanupHtmlWhitespace = create_action(
|
|
7
|
+
cleanup_html_whitespace,
|
|
8
|
+
main_param="text",
|
|
9
|
+
class_name="CleanupHtmlWhitespace",
|
|
10
|
+
)
|
|
11
|
+
"""Action wrapping `cleanup_html_whitespace` — tidies the whitespace of the page flowing in and spares `pre` and the like."""
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
_DESIGN_NOTES = """
|
|
15
|
+
# CleanupHtmlWhitespace — Action Over `cleanup_html_whitespace`
|
|
16
|
+
|
|
17
|
+
## Purpose
|
|
18
|
+
The gentle tidying as a link of a pipeline: `CleanupHtmlWhitespace(engine="jinja")`.
|
|
19
|
+
|
|
20
|
+
## Shape
|
|
21
|
+
Main input: `text`. Option: `engine`. Text in, text out.
|
|
22
|
+
"""
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from simplibs.actions import create_action
|
|
2
|
+
# Outers
|
|
3
|
+
from ..logic import compact_html
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
CompactHtml = create_action(
|
|
7
|
+
compact_html,
|
|
8
|
+
main_param="text",
|
|
9
|
+
class_name="CompactHtml",
|
|
10
|
+
)
|
|
11
|
+
"""Action wrapping `compact_html` — drops the blank lines of the page flowing in and spares `pre` and the like."""
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
_DESIGN_NOTES = """
|
|
15
|
+
# CompactHtml — Action Over `compact_html`
|
|
16
|
+
|
|
17
|
+
## Purpose
|
|
18
|
+
The thorough tidying as a link of a pipeline: `CompactHtml(engine="django")`.
|
|
19
|
+
|
|
20
|
+
## Shape
|
|
21
|
+
Main input: `text`. Option: `engine`. Text in, text out.
|
|
22
|
+
"""
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from simplibs.actions import create_action
|
|
2
|
+
# Outers
|
|
3
|
+
from ..logic import html_outline
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
HtmlOutline = create_action(
|
|
7
|
+
html_outline,
|
|
8
|
+
main_param="text",
|
|
9
|
+
class_name="HtmlOutline",
|
|
10
|
+
)
|
|
11
|
+
"""Action wrapping `html_outline` — turns the page flowing in into the list of its landmarks, headings and ids."""
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
_DESIGN_NOTES = """
|
|
15
|
+
# HtmlOutline — Action Over `html_outline`
|
|
16
|
+
|
|
17
|
+
## Purpose
|
|
18
|
+
The overview step as a link of a pipeline: `HtmlOutline(engine="django", max_depth=3)`.
|
|
19
|
+
|
|
20
|
+
## Shape
|
|
21
|
+
Main input: `text`. Options: `engine` and `max_depth`. Text in, text out (one
|
|
22
|
+
element per line, indented by depth).
|
|
23
|
+
"""
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from simplibs.actions import create_action
|
|
2
|
+
# Outers
|
|
3
|
+
from ..logic import remove_template_imports
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
RemoveTemplateImports = create_action(
|
|
7
|
+
remove_template_imports,
|
|
8
|
+
main_param="text",
|
|
9
|
+
class_name="RemoveTemplateImports",
|
|
10
|
+
)
|
|
11
|
+
"""Action wrapping `remove_template_imports` — takes `{% load %}`, `{% import %}` and `{% from %}` out of the template flowing in."""
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
_DESIGN_NOTES = """
|
|
15
|
+
# RemoveTemplateImports — Action Over `remove_template_imports`
|
|
16
|
+
|
|
17
|
+
## Purpose
|
|
18
|
+
The import step as a link of a pipeline: `RemoveTemplateImports(engine="jinja")`.
|
|
19
|
+
|
|
20
|
+
## Shape
|
|
21
|
+
Main input: `text`. Option: `engine`, required. Text in, text out.
|
|
22
|
+
"""
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from simplibs.actions import create_action
|
|
2
|
+
# Outers
|
|
3
|
+
from ..logic import strip_html_comments
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
StripHtmlComments = create_action(
|
|
7
|
+
strip_html_comments,
|
|
8
|
+
main_param="text",
|
|
9
|
+
class_name="StripHtmlComments",
|
|
10
|
+
)
|
|
11
|
+
"""Action wrapping `strip_html_comments` — takes the HTML comments out of the page flowing in."""
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
_DESIGN_NOTES = """
|
|
15
|
+
# StripHtmlComments — Action Over `strip_html_comments`
|
|
16
|
+
|
|
17
|
+
## Purpose
|
|
18
|
+
The comment step as a link of a pipeline: `StripHtmlComments(engine="django", keep_license=True)`.
|
|
19
|
+
|
|
20
|
+
## Shape
|
|
21
|
+
Main input: `text`. Options: `engine` (`"django"`, `"jinja"` or `None`),
|
|
22
|
+
`keep_conditional` and `keep_license`. Text in, text out.
|
|
23
|
+
"""
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from simplibs.actions import create_action
|
|
2
|
+
# Outers
|
|
3
|
+
from ..logic import strip_template_comments
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
StripTemplateComments = create_action(
|
|
7
|
+
strip_template_comments,
|
|
8
|
+
main_param="text",
|
|
9
|
+
class_name="StripTemplateComments",
|
|
10
|
+
)
|
|
11
|
+
"""Action wrapping `strip_template_comments` — takes `{# ... #}` and `{% comment %}` out of the template flowing in."""
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
_DESIGN_NOTES = """
|
|
15
|
+
# StripTemplateComments — Action Over `strip_template_comments`
|
|
16
|
+
|
|
17
|
+
## Purpose
|
|
18
|
+
The template comment step as a link of a pipeline: `StripTemplateComments(engine="django")`.
|
|
19
|
+
|
|
20
|
+
## Shape
|
|
21
|
+
Main input: `text`. Option: `engine`, **required** (`"django"` or `"jinja"`):
|
|
22
|
+
building the action without it is a `TypeError`. Text in, text out.
|
|
23
|
+
|
|
24
|
+
## One Action, Not Two
|
|
25
|
+
Django and Jinja differ only in the option, so there is no class for each of
|
|
26
|
+
them; the profiles build the two pipelines from the same action.
|
|
27
|
+
"""
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from simplibs.actions import create_action
|
|
2
|
+
# Outers
|
|
3
|
+
from ..logic import template_outline
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
TemplateOutline = create_action(
|
|
7
|
+
template_outline,
|
|
8
|
+
main_param="text",
|
|
9
|
+
class_name="TemplateOutline",
|
|
10
|
+
)
|
|
11
|
+
"""Action wrapping `template_outline` — turns the template flowing in into the list of its `extends`, `include` and blocks."""
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
_DESIGN_NOTES = """
|
|
15
|
+
# TemplateOutline — Action Over `template_outline`
|
|
16
|
+
|
|
17
|
+
## Purpose
|
|
18
|
+
The skeleton step as a link of a pipeline: `TemplateOutline(engine="django", max_depth=2)`.
|
|
19
|
+
|
|
20
|
+
## Shape
|
|
21
|
+
Main input: `text`. Options: `engine` (required) and `max_depth`. Text in, text
|
|
22
|
+
out (one tag per line, indented by the depth of its blocks).
|
|
23
|
+
"""
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
from .ApplyToHtmlBlocks import ApplyToHtmlBlocks
|
|
2
|
+
from .CleanupHtmlWhitespace import CleanupHtmlWhitespace
|
|
3
|
+
from .CompactHtml import CompactHtml
|
|
4
|
+
from .HtmlOutline import HtmlOutline
|
|
5
|
+
from .RemoveTemplateImports import RemoveTemplateImports
|
|
6
|
+
from .StripHtmlComments import StripHtmlComments
|
|
7
|
+
from .StripTemplateComments import StripTemplateComments
|
|
8
|
+
from .TemplateOutline import TemplateOutline
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
"ApplyToHtmlBlocks",
|
|
13
|
+
"CleanupHtmlWhitespace",
|
|
14
|
+
"CompactHtml",
|
|
15
|
+
"HtmlOutline",
|
|
16
|
+
"RemoveTemplateImports",
|
|
17
|
+
"StripHtmlComments",
|
|
18
|
+
"StripTemplateComments",
|
|
19
|
+
"TemplateOutline",
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
_DESIGN_NOTES = """
|
|
24
|
+
# simplibs.extractor_html.actions — The Steps as Pipeline Actions
|
|
25
|
+
|
|
26
|
+
## Purpose
|
|
27
|
+
Every text step of `logic/` as an `Action` of `simplibs-actions`, so it can be
|
|
28
|
+
chained with `>>` and used as the `steps` of an extractor profile.
|
|
29
|
+
|
|
30
|
+
from simplibs.extractor_html.actions import StripHtmlComments, CompactHtml
|
|
31
|
+
steps = StripHtmlComments() >> CompactHtml()
|
|
32
|
+
|
|
33
|
+
## Domain Folder
|
|
34
|
+
`actions/` has its own `__all__` and is not re-exported from the package root:
|
|
35
|
+
a function and an action are different kinds of thing and stay visibly
|
|
36
|
+
different at the import line.
|
|
37
|
+
|
|
38
|
+
## Thin Wrappers
|
|
39
|
+
Each action is `create_action(function, main_param="text", ...)`.
|
|
40
|
+
|
|
41
|
+
## What Has No Action
|
|
42
|
+
`html_comment_spans` and `template_comment_spans` return spans, not a text:
|
|
43
|
+
they are not links of a pipeline that carries text.
|
|
44
|
+
|
|
45
|
+
## Internal Components Registry
|
|
46
|
+
|
|
47
|
+
| Component | Type | Description |
|
|
48
|
+
| :---------------------- | :----- | :------------------------------------------------ |
|
|
49
|
+
| `ApplyToHtmlBlocks` | Action | Over `apply_to_html_blocks`. |
|
|
50
|
+
| `CleanupHtmlWhitespace` | Action | Over `cleanup_html_whitespace`. |
|
|
51
|
+
| `CompactHtml` | Action | Over `compact_html`. |
|
|
52
|
+
| `HtmlOutline` | Action | Over `html_outline`. |
|
|
53
|
+
| `RemoveTemplateImports` | Action | Over `remove_template_imports`. |
|
|
54
|
+
| `StripHtmlComments` | Action | Over `strip_html_comments`. |
|
|
55
|
+
| `StripTemplateComments` | Action | Over `strip_template_comments`. |
|
|
56
|
+
| `TemplateOutline` | Action | Over `template_outline`. |
|
|
57
|
+
"""
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
from typing import Literal
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
TemplateEngine = Literal["django", "jinja"]
|
|
5
|
+
"""The template language a page is written in: `"django"` or `"jinja"` (Nunjucks counts as Jinja)."""
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
_DESIGN_NOTES = """
|
|
9
|
+
# TemplateEngine — Which Rules the Curly Braces Follow
|
|
10
|
+
|
|
11
|
+
## Purpose
|
|
12
|
+
Django and Jinja look alike and differ in details that matter to a scanner:
|
|
13
|
+
|
|
14
|
+
* Django keeps `{{ ... }}`, `{% ... %}` and `{# ... #}` on one line; Jinja lets
|
|
15
|
+
them run over several.
|
|
16
|
+
* Django has `{% comment %}...{% endcomment %}` and `{% verbatim %}`; Jinja has
|
|
17
|
+
`{% raw %}` and no comment tag.
|
|
18
|
+
|
|
19
|
+
## Why a `Literal`
|
|
20
|
+
A typo (`"jinja2"`, `"Django"`) fails at the signature, and an editor
|
|
21
|
+
completes both values. Nunjucks, which uses the same syntax as Jinja, is read
|
|
22
|
+
as `"jinja"`.
|
|
23
|
+
|
|
24
|
+
## No "none"
|
|
25
|
+
A page that is not a template needs no engine: the parameter is `None`.
|
|
26
|
+
"""
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from .TemplateEngine import TemplateEngine
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
_DESIGN_NOTES = """
|
|
5
|
+
# annotations — Types for the Signatures of simplibs-extractor-html
|
|
6
|
+
|
|
7
|
+
Plain imports, no `__all__` (the package root decides what is public).
|
|
8
|
+
|
|
9
|
+
## Internal Components Registry
|
|
10
|
+
|
|
11
|
+
| Component | Type | Description |
|
|
12
|
+
| :--------------- | :------ | :---------------------------------------------- |
|
|
13
|
+
| `TemplateEngine` | Literal | `"django"` or `"jinja"`. |
|
|
14
|
+
"""
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from typing import Final
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
HTML_ANY_TAG_PATTERN: Final[re.Pattern[str]] = re.compile(r"<[^>]*>")
|
|
6
|
+
"""Anything that looks like a tag: from `<` to the next `>`."""
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
_DESIGN_NOTES = """
|
|
10
|
+
# HTML_ANY_TAG_PATTERN — Text Without Its Markup
|
|
11
|
+
|
|
12
|
+
## Purpose
|
|
13
|
+
The text of a heading (`<h1>Hello <em>world</em></h1>`) is what remains when
|
|
14
|
+
the tags inside it are taken out. For this, the exact shape of a tag does not
|
|
15
|
+
matter.
|
|
16
|
+
"""
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
from typing import Final
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
HTML_BLOCK_LANGUAGE_BY_TYPE: Final[dict[str, dict[str, str]]] = {
|
|
5
|
+
"script": {
|
|
6
|
+
"": "javascript",
|
|
7
|
+
"module": "javascript",
|
|
8
|
+
"text/javascript": "javascript",
|
|
9
|
+
"application/javascript": "javascript",
|
|
10
|
+
"text/ecmascript": "javascript",
|
|
11
|
+
"application/ecmascript": "javascript",
|
|
12
|
+
"text/jsx": "javascript",
|
|
13
|
+
"text/babel": "javascript",
|
|
14
|
+
},
|
|
15
|
+
"style": {
|
|
16
|
+
"": "css",
|
|
17
|
+
"text/css": "css",
|
|
18
|
+
},
|
|
19
|
+
}
|
|
20
|
+
"""For `script` and `style`, which values of `type` mean that the content is code, and in what language."""
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
_DESIGN_NOTES = """
|
|
24
|
+
# HTML_BLOCK_LANGUAGE_BY_TYPE — Code or Something Else
|
|
25
|
+
|
|
26
|
+
## Purpose
|
|
27
|
+
A `script` may hold JavaScript, JSON, a template for a framework or a shader.
|
|
28
|
+
Only the first kind can be cleaned by the JavaScript steps, so the scanner
|
|
29
|
+
says what a block is, and the block step touches only code.
|
|
30
|
+
|
|
31
|
+
## The Empty Type
|
|
32
|
+
No `type` at all means JavaScript for a `script` and CSS for a `style`.
|
|
33
|
+
|
|
34
|
+
## `text/jsx` and `text/babel`
|
|
35
|
+
Pages that compile JSX in the browser put it there. The JavaScript add-on
|
|
36
|
+
reads JSX.
|
|
37
|
+
|
|
38
|
+
## What Is Not Here
|
|
39
|
+
`application/json`, `application/ld+json`, `importmap`, `text/template` and
|
|
40
|
+
anything unknown: such a block is data, and it stays as it is.
|
|
41
|
+
"""
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from typing import Final
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
HTML_COMMENT_END_PATTERN: Final[re.Pattern[str]] = re.compile(r"--!?>")
|
|
6
|
+
"""How a comment ends: `-->`, or `--!>`, which browsers accept as well."""
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
_DESIGN_NOTES = """
|
|
10
|
+
# HTML_COMMENT_END_PATTERN — The End of a Comment
|
|
11
|
+
|
|
12
|
+
## Purpose
|
|
13
|
+
A comment ends at `-->`. The HTML specification also closes it at `--!>`
|
|
14
|
+
(an error, but one every browser forgives), so the scanner does the same.
|
|
15
|
+
|
|
16
|
+
## The Shortest Comments
|
|
17
|
+
`<!-->` and `<!--->` end at once, by the same specification. The scanner
|
|
18
|
+
checks them before it looks for this pattern.
|
|
19
|
+
"""
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from typing import Final
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
HTML_CONDITIONAL_PATTERN: Final[re.Pattern[str]] = re.compile(
|
|
6
|
+
r"<!--\s*(?:\[if\b|<!\[endif\])",
|
|
7
|
+
re.IGNORECASE,
|
|
8
|
+
)
|
|
9
|
+
"""The beginning of an Internet Explorer conditional comment: `<!--[if IE]>` or `<!--<![endif]-->`."""
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
_DESIGN_NOTES = """
|
|
13
|
+
# HTML_CONDITIONAL_PATTERN — Comments That Are Not Comments
|
|
14
|
+
|
|
15
|
+
## Purpose
|
|
16
|
+
Old Internet Explorer read `<!--[if lt IE 9]> ... <![endif]-->` as code, and
|
|
17
|
+
every other browser as a comment. Such a comment holds real tags (a script
|
|
18
|
+
for IE), so by default the comment step keeps it.
|
|
19
|
+
|
|
20
|
+
## Both Forms
|
|
21
|
+
The "hidden" form begins `<!--[if`; the "revealed" form ends in
|
|
22
|
+
`<!--<![endif]-->`. Both begin like this.
|
|
23
|
+
"""
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from typing import Final
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
HTML_DEPENDENCY_DIR_NAMES: Final[tuple[str, ...]] = ("node_modules", "bower_components", "vendor")
|
|
5
|
+
"""Names of folders that hold pages written by other people."""
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
_DESIGN_NOTES = """
|
|
9
|
+
# HTML_DEPENDENCY_DIR_NAMES — Other People's Pages
|
|
10
|
+
|
|
11
|
+
## Purpose
|
|
12
|
+
The names behind `DEPENDENCY_DIRS`. Packages bring their own examples,
|
|
13
|
+
documentation and templates, and none of them is the project's source.
|
|
14
|
+
|
|
15
|
+
## Own List
|
|
16
|
+
Each add-on decides for its own language what counts as dependencies; the
|
|
17
|
+
library does not borrow the list of another add-on.
|
|
18
|
+
"""
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
from typing import Final
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
HTML_EXTRA_LANGUAGE_BY_SUFFIX: Final[dict[str, str]] = {
|
|
5
|
+
".htm": "html",
|
|
6
|
+
".xhtml": "html",
|
|
7
|
+
".jinja": "jinja2",
|
|
8
|
+
".jinja2": "jinja2",
|
|
9
|
+
".njk": "jinja2",
|
|
10
|
+
".j2": "jinja2",
|
|
11
|
+
}
|
|
12
|
+
"""The code-fence language of the suffixes the extractor does not know on its own."""
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
_DESIGN_NOTES = """
|
|
16
|
+
# HTML_EXTRA_LANGUAGE_BY_SUFFIX — Names for the Fence
|
|
17
|
+
|
|
18
|
+
## Purpose
|
|
19
|
+
The markdown output writes the language after the opening fence, so a viewer
|
|
20
|
+
can colour the code. The extractor knows `.html` itself; the other suffixes are
|
|
21
|
+
what this add-on brings, and `register_all` tells the extractor about them.
|
|
22
|
+
|
|
23
|
+
## `jinja2`
|
|
24
|
+
The name that the common highlighters know for the syntax of Jinja. Nunjucks
|
|
25
|
+
(`.njk`) is close enough to it to be coloured the same way, and the `.j2`
|
|
26
|
+
wrapper is named for the template language, as a suffix cannot tell which
|
|
27
|
+
language is inside.
|
|
28
|
+
|
|
29
|
+
## Only What Is Missing
|
|
30
|
+
`.html` is not listed: registering it again would change nothing.
|
|
31
|
+
"""
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from typing import Final
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
HTML_HEADING_ELEMENTS: Final[tuple[str, ...]] = ("h1", "h2", "h3", "h4", "h5", "h6")
|
|
5
|
+
"""The six heading elements."""
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
_DESIGN_NOTES = """
|
|
9
|
+
# HTML_HEADING_ELEMENTS — The Six Headings
|
|
10
|
+
|
|
11
|
+
## Purpose
|
|
12
|
+
A heading is closed implicitly by another heading that follows it:
|
|
13
|
+
`<h1>Title<h2>Sub</h2>` has two headings side by side, not one inside the
|
|
14
|
+
other. The outline needs to know which names are headings to follow that rule.
|
|
15
|
+
"""
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from typing import Final
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
HTML_ID_ATTRIBUTE_PATTERN: Final[re.Pattern[str]] = re.compile(
|
|
6
|
+
r"""\sid\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'>]+))""",
|
|
7
|
+
re.IGNORECASE,
|
|
8
|
+
)
|
|
9
|
+
"""The `id` attribute of a tag; its value is in one of the three groups (double quotes, single quotes, none)."""
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
_DESIGN_NOTES = """
|
|
13
|
+
# HTML_ID_ATTRIBUTE_PATTERN — What the Part Is Called
|
|
14
|
+
|
|
15
|
+
## Purpose
|
|
16
|
+
The outline lists every element that has an `id`.
|
|
17
|
+
|
|
18
|
+
## The Blank in Front
|
|
19
|
+
A blank must come before `id`, so `data-id="x"` and `aria-labelledby` are not
|
|
20
|
+
mistaken for it.
|
|
21
|
+
"""
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
from typing import Final
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
HTML_IMPLIED_END: Final[dict[str, tuple[tuple[str, ...], tuple[str, ...]]]] = {
|
|
5
|
+
"li": (("li",), ("ul", "ol", "menu")),
|
|
6
|
+
"dt": (("dt", "dd"), ("dl",)),
|
|
7
|
+
"dd": (("dt", "dd"), ("dl",)),
|
|
8
|
+
"td": (("td", "th"), ("tr", "table")),
|
|
9
|
+
"th": (("td", "th"), ("tr", "table")),
|
|
10
|
+
"tr": (("tr", "td", "th"), ("table", "thead", "tbody", "tfoot")),
|
|
11
|
+
"thead": (("thead", "tbody", "tfoot", "tr", "td", "th"), ("table",)),
|
|
12
|
+
"tbody": (("thead", "tbody", "tfoot", "tr", "td", "th"), ("table",)),
|
|
13
|
+
"tfoot": (("thead", "tbody", "tfoot", "tr", "td", "th"), ("table",)),
|
|
14
|
+
"option": (("option",), ("select", "optgroup", "datalist")),
|
|
15
|
+
}
|
|
16
|
+
"""For each element whose end tag may be left out: which open elements its start tag closes, and which ones stop the search."""
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
_DESIGN_NOTES = """
|
|
20
|
+
# HTML_IMPLIED_END — The End Tags a Page May Leave Out
|
|
21
|
+
|
|
22
|
+
## Purpose
|
|
23
|
+
`<ul><li>a<li>b</ul>` is valid: the second `<li>` ends the first. Without this
|
|
24
|
+
the outline would put `b` inside `a`.
|
|
25
|
+
|
|
26
|
+
## How to Read an Entry
|
|
27
|
+
`"li": (("li",), ("ul", "ol", "menu"))`: a new `li` closes an open `li`, but
|
|
28
|
+
the search stops at a `ul`, `ol` or `menu`, because an `li` inside a nested
|
|
29
|
+
list belongs to that list and not to the one outside.
|
|
30
|
+
|
|
31
|
+
## What Is Not Here
|
|
32
|
+
`p` is left out: what closes it depends on the element that follows, and it
|
|
33
|
+
rarely has a heading or an `id` inside.
|
|
34
|
+
"""
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from typing import Final
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
HTML_LICENSE_START: Final[str] = "<!--!"
|
|
5
|
+
"""How a comment that has to survive minification begins."""
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
_DESIGN_NOTES = """
|
|
9
|
+
# HTML_LICENSE_START — The Comment That Tools Keep
|
|
10
|
+
|
|
11
|
+
## Purpose
|
|
12
|
+
By the convention of minifiers, a comment starting `<!--!` is meant to stay:
|
|
13
|
+
a licence, a banner, a copyright line. With `keep_license` the step keeps it.
|
|
14
|
+
"""
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from typing import Final
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
HTML_LICENSE_TAGS: Final[tuple[str, ...]] = ("@license", "@preserve")
|
|
5
|
+
"""Words inside a comment that mark it as one to keep."""
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
_DESIGN_NOTES = """
|
|
9
|
+
# HTML_LICENSE_TAGS — The Other Way to Say "Keep This"
|
|
10
|
+
|
|
11
|
+
## Purpose
|
|
12
|
+
Besides the leading `!`, minifiers keep a comment that contains `@license` or
|
|
13
|
+
`@preserve`. The same two words keep it here.
|
|
14
|
+
"""
|