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.
Files changed (127) hide show
  1. simplibs/extractor_html/__init__.py +82 -0
  2. simplibs/extractor_html/actions/ApplyToHtmlBlocks.py +29 -0
  3. simplibs/extractor_html/actions/CleanupHtmlWhitespace.py +22 -0
  4. simplibs/extractor_html/actions/CompactHtml.py +22 -0
  5. simplibs/extractor_html/actions/HtmlOutline.py +23 -0
  6. simplibs/extractor_html/actions/RemoveTemplateImports.py +22 -0
  7. simplibs/extractor_html/actions/StripHtmlComments.py +23 -0
  8. simplibs/extractor_html/actions/StripTemplateComments.py +27 -0
  9. simplibs/extractor_html/actions/TemplateOutline.py +23 -0
  10. simplibs/extractor_html/actions/__init__.py +57 -0
  11. simplibs/extractor_html/annotations/TemplateEngine.py +26 -0
  12. simplibs/extractor_html/annotations/__init__.py +14 -0
  13. simplibs/extractor_html/constants/HTML_ANY_TAG_PATTERN.py +16 -0
  14. simplibs/extractor_html/constants/HTML_BLOCK_LANGUAGE_BY_TYPE.py +41 -0
  15. simplibs/extractor_html/constants/HTML_COMMENT_END_PATTERN.py +19 -0
  16. simplibs/extractor_html/constants/HTML_CONDITIONAL_PATTERN.py +23 -0
  17. simplibs/extractor_html/constants/HTML_DEPENDENCY_DIR_NAMES.py +18 -0
  18. simplibs/extractor_html/constants/HTML_EXTRA_LANGUAGE_BY_SUFFIX.py +31 -0
  19. simplibs/extractor_html/constants/HTML_HEADING_ELEMENTS.py +15 -0
  20. simplibs/extractor_html/constants/HTML_ID_ATTRIBUTE_PATTERN.py +21 -0
  21. simplibs/extractor_html/constants/HTML_IMPLIED_END.py +34 -0
  22. simplibs/extractor_html/constants/HTML_LICENSE_START.py +14 -0
  23. simplibs/extractor_html/constants/HTML_LICENSE_TAGS.py +14 -0
  24. simplibs/extractor_html/constants/HTML_OUTLINE_ELEMENTS.py +32 -0
  25. simplibs/extractor_html/constants/HTML_OUTLINE_TEXT_LIMIT.py +15 -0
  26. simplibs/extractor_html/constants/HTML_OUTPUT_DIR_NAMES.py +43 -0
  27. simplibs/extractor_html/constants/HTML_PLAIN_SUFFIXES.py +18 -0
  28. simplibs/extractor_html/constants/HTML_RAW_TEXT_END_PATTERNS.py +28 -0
  29. simplibs/extractor_html/constants/HTML_SUFFIXES.py +22 -0
  30. simplibs/extractor_html/constants/HTML_TAG_NAME_PATTERN.py +16 -0
  31. simplibs/extractor_html/constants/HTML_TEMPLATE_BLOCKS.py +38 -0
  32. simplibs/extractor_html/constants/HTML_TEMPLATE_IMPORT_TAGS.py +29 -0
  33. simplibs/extractor_html/constants/HTML_TEMPLATE_OUTLINE_TAGS.py +35 -0
  34. simplibs/extractor_html/constants/HTML_TEMPLATE_SUFFIXES.py +19 -0
  35. simplibs/extractor_html/constants/HTML_TEMPLATE_TAG_NAME_PATTERN.py +16 -0
  36. simplibs/extractor_html/constants/HTML_TEMPLATE_TOKEN_PATTERN.py +16 -0
  37. simplibs/extractor_html/constants/HTML_TEXT_ELEMENTS.py +16 -0
  38. simplibs/extractor_html/constants/HTML_TOKEN_PATTERN.py +26 -0
  39. simplibs/extractor_html/constants/HTML_TYPE_ATTRIBUTE_PATTERN.py +21 -0
  40. simplibs/extractor_html/constants/HTML_VOID_ELEMENTS.py +21 -0
  41. simplibs/extractor_html/constants/HTML_WRAPPED_STEM_ENDING.py +14 -0
  42. simplibs/extractor_html/constants/HTML_WRAPPED_SUFFIXES.py +15 -0
  43. simplibs/extractor_html/constants/__init__.py +77 -0
  44. simplibs/extractor_html/file_rules/__init__.py +56 -0
  45. simplibs/extractor_html/file_rules/atomic/DEPENDENCY_DIRS.py +17 -0
  46. simplibs/extractor_html/file_rules/atomic/DOT_NAME.py +19 -0
  47. simplibs/extractor_html/file_rules/atomic/OUTPUT_DIRS.py +17 -0
  48. simplibs/extractor_html/file_rules/atomic/VCS_DIRS.py +21 -0
  49. simplibs/extractor_html/file_rules/atomic/WRAPPED_HTML.py +22 -0
  50. simplibs/extractor_html/file_rules/atomic/__init__.py +26 -0
  51. simplibs/extractor_html/file_rules/html/HTML_BASE.py +22 -0
  52. simplibs/extractor_html/file_rules/html/HTML_FILES.py +24 -0
  53. simplibs/extractor_html/file_rules/html/HTML_PLAIN_BASE.py +24 -0
  54. simplibs/extractor_html/file_rules/html/HTML_STRICT_EXCLUDE.py +21 -0
  55. simplibs/extractor_html/file_rules/html/__init__.py +20 -0
  56. simplibs/extractor_html/logic/__init__.py +44 -0
  57. simplibs/extractor_html/logic/_helpers/HtmlBlock.py +31 -0
  58. simplibs/extractor_html/logic/_helpers/HtmlOutlineBuilder.py +189 -0
  59. simplibs/extractor_html/logic/_helpers/HtmlScan.py +50 -0
  60. simplibs/extractor_html/logic/_helpers/HtmlTag.py +32 -0
  61. simplibs/extractor_html/logic/_helpers/Ranges.py +48 -0
  62. simplibs/extractor_html/logic/_helpers/TemplateScan.py +43 -0
  63. simplibs/extractor_html/logic/_helpers/TemplateTag.py +33 -0
  64. simplibs/extractor_html/logic/_helpers/__init__.py +68 -0
  65. simplibs/extractor_html/logic/_helpers/blank_spans.py +40 -0
  66. simplibs/extractor_html/logic/_helpers/build_html_outline.py +38 -0
  67. simplibs/extractor_html/logic/_helpers/build_template_outline.py +75 -0
  68. simplibs/extractor_html/logic/_helpers/find_blanks_start.py +29 -0
  69. simplibs/extractor_html/logic/_helpers/find_block_language.py +35 -0
  70. simplibs/extractor_html/logic/_helpers/find_comments.py +60 -0
  71. simplibs/extractor_html/logic/_helpers/find_protected_spans.py +48 -0
  72. simplibs/extractor_html/logic/_helpers/find_template_import_spans.py +37 -0
  73. simplibs/extractor_html/logic/_helpers/fit_removal_span.py +40 -0
  74. simplibs/extractor_html/logic/_helpers/is_license_comment.py +26 -0
  75. simplibs/extractor_html/logic/_helpers/line_of.py +23 -0
  76. simplibs/extractor_html/logic/_helpers/raise_block_result_invalid.py +38 -0
  77. simplibs/extractor_html/logic/_helpers/replace_spans.py +42 -0
  78. simplibs/extractor_html/logic/_helpers/scan_checked.py +45 -0
  79. simplibs/extractor_html/logic/_helpers/scan_html.py +208 -0
  80. simplibs/extractor_html/logic/_helpers/scan_templates.py +128 -0
  81. simplibs/extractor_html/logic/_helpers/scan_templates_checked.py +39 -0
  82. simplibs/extractor_html/logic/_helpers/skip_html_comment.py +41 -0
  83. simplibs/extractor_html/logic/_helpers/skip_html_tag.py +46 -0
  84. simplibs/extractor_html/logic/_helpers/tidy_lines.py +86 -0
  85. simplibs/extractor_html/logic/_helpers/warn_problems.py +32 -0
  86. simplibs/extractor_html/logic/apply_to_html_blocks.py +103 -0
  87. simplibs/extractor_html/logic/cleanup_html_whitespace.py +54 -0
  88. simplibs/extractor_html/logic/compact_html.py +44 -0
  89. simplibs/extractor_html/logic/html_comment_spans.py +54 -0
  90. simplibs/extractor_html/logic/html_outline.py +66 -0
  91. simplibs/extractor_html/logic/strip_html_comments.py +63 -0
  92. simplibs/extractor_html/logic/templates/__init__.py +25 -0
  93. simplibs/extractor_html/logic/templates/remove_template_imports.py +51 -0
  94. simplibs/extractor_html/logic/templates/strip_template_comments.py +60 -0
  95. simplibs/extractor_html/logic/templates/template_comment_spans.py +49 -0
  96. simplibs/extractor_html/logic/templates/template_outline.py +62 -0
  97. simplibs/extractor_html/plugin/__init__.py +14 -0
  98. simplibs/extractor_html/plugin/register_all.py +60 -0
  99. simplibs/extractor_html/presets/__init__.py +43 -0
  100. simplibs/extractor_html/presets/html_clean_steps.py +54 -0
  101. simplibs/extractor_html/presets/html_no_imports_steps.py +50 -0
  102. simplibs/extractor_html/presets/html_outline_steps.py +28 -0
  103. simplibs/extractor_html/presets/template_structure_steps.py +27 -0
  104. simplibs/extractor_html/profiles/DJANGO_CLEAN.py +36 -0
  105. simplibs/extractor_html/profiles/DJANGO_NO_IMPORTS.py +32 -0
  106. simplibs/extractor_html/profiles/DJANGO_OUTLINE.py +32 -0
  107. simplibs/extractor_html/profiles/DJANGO_STRUCTURE.py +32 -0
  108. simplibs/extractor_html/profiles/HTML_CODE_CLEAN.py +32 -0
  109. simplibs/extractor_html/profiles/HTML_CODE_NO_IMPORTS.py +30 -0
  110. simplibs/extractor_html/profiles/HTML_DATA_ALL.py +26 -0
  111. simplibs/extractor_html/profiles/HTML_OUTLINE.py +31 -0
  112. simplibs/extractor_html/profiles/HTML_PROFILES.py +42 -0
  113. simplibs/extractor_html/profiles/HTML_SRC_CLEAN.py +31 -0
  114. simplibs/extractor_html/profiles/JINJA_CLEAN.py +35 -0
  115. simplibs/extractor_html/profiles/JINJA_NO_IMPORTS.py +32 -0
  116. simplibs/extractor_html/profiles/JINJA_OUTLINE.py +30 -0
  117. simplibs/extractor_html/profiles/JINJA_STRUCTURE.py +31 -0
  118. simplibs/extractor_html/profiles/__init__.py +86 -0
  119. simplibs/extractor_html/profiles/steps_for_engine.py +39 -0
  120. simplibs/extractor_html/profiles/steps_for_pages.py +36 -0
  121. simplibs/extractor_html/py.typed +1 -0
  122. simplibs_extractor_html-0.1.0.dist-info/METADATA +504 -0
  123. simplibs_extractor_html-0.1.0.dist-info/RECORD +127 -0
  124. simplibs_extractor_html-0.1.0.dist-info/WHEEL +5 -0
  125. simplibs_extractor_html-0.1.0.dist-info/entry_points.txt +2 -0
  126. simplibs_extractor_html-0.1.0.dist-info/licenses/LICENSE +21 -0
  127. simplibs_extractor_html-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,32 @@
1
+ from typing import Final
2
+
3
+
4
+ HTML_OUTLINE_ELEMENTS: Final[tuple[str, ...]] = (
5
+ "header",
6
+ "nav",
7
+ "main",
8
+ "section",
9
+ "article",
10
+ "aside",
11
+ "footer",
12
+ "form",
13
+ "table",
14
+ "dialog",
15
+ "template",
16
+ )
17
+ """The elements that always appear in the outline of a page: the landmarks and the other big parts."""
18
+
19
+
20
+ _DESIGN_NOTES = """
21
+ # HTML_OUTLINE_ELEMENTS — The Parts a Page Is Made Of
22
+
23
+ ## Purpose
24
+ The outline of a page is not a copy of its tags: a `div` inside a `div` inside
25
+ a `div` says nothing. These are the elements whose name says what a part of the
26
+ page is.
27
+
28
+ ## The Others
29
+ Any element with an `id` is listed too (it is something that stylesheets,
30
+ scripts and links point to), and so are the headings and the title, with their
31
+ text.
32
+ """
@@ -0,0 +1,15 @@
1
+ from typing import Final
2
+
3
+
4
+ HTML_OUTLINE_TEXT_LIMIT: Final[int] = 80
5
+ """The longest text of a heading that appears in the outline, in characters."""
6
+
7
+
8
+ _DESIGN_NOTES = """
9
+ # HTML_OUTLINE_TEXT_LIMIT — A Heading Is Not a Paragraph
10
+
11
+ ## Purpose
12
+ A heading that has grown into a sentence would make a line of the outline
13
+ longer than the part of the page it names. A longer text is cut and marked
14
+ with an ellipsis.
15
+ """
@@ -0,0 +1,43 @@
1
+ from typing import Final
2
+
3
+
4
+ HTML_OUTPUT_DIR_NAMES: Final[tuple[str, ...]] = (
5
+ "build",
6
+ "dist",
7
+ "out",
8
+ ".next",
9
+ ".nuxt",
10
+ ".docusaurus",
11
+ "_build",
12
+ "_site",
13
+ "staticfiles",
14
+ "coverage",
15
+ "htmlcov",
16
+ "storybook-static",
17
+ )
18
+ """Names of folders that hold generated pages: build output, built documentation, reports."""
19
+
20
+
21
+ _DESIGN_NOTES = """
22
+ # HTML_OUTPUT_DIR_NAMES — Generated, Not Written
23
+
24
+ ## Purpose
25
+ The names behind `OUTPUT_DIRS`. These folders are full of pages that a tool
26
+ made.
27
+
28
+ ## What They Are
29
+ * `build`, `dist`, `out`, `.next`, `.nuxt`, `.docusaurus`: results of a build.
30
+ * `_build`: the output of Sphinx, with a page for every document.
31
+ * `_site`: the output of Jekyll and similar generators.
32
+ * `staticfiles`: what Django's `collectstatic` collects.
33
+ * `coverage`, `htmlcov`: test-coverage reports, one page for every source file.
34
+ * `storybook-static`: a built Storybook.
35
+
36
+ ## `public` Is Not Here
37
+ In a React project `public/index.html` is the page itself, the one the
38
+ bundler fills in, and it is source.
39
+
40
+ ## `.next`, `.nuxt`, `.docusaurus`
41
+ They start with a dot, but the base rule only leaves out dot FILES, so without
42
+ these names the pages inside would be read as source.
43
+ """
@@ -0,0 +1,18 @@
1
+ from typing import Final
2
+
3
+
4
+ HTML_PLAIN_SUFFIXES: Final[tuple[str, ...]] = (".html", ".htm", ".xhtml")
5
+ """The suffixes of HTML pages and of the templates that hide behind them (a Django template is a `.html` file)."""
6
+
7
+
8
+ _DESIGN_NOTES = """
9
+ # HTML_PLAIN_SUFFIXES — Pages, and Django Templates With Them
10
+
11
+ ## Purpose
12
+ The suffixes the file rules and the profiles take for HTML. A Django template
13
+ has the suffix `.html` like any page, so the suffix cannot tell them apart:
14
+ the steps that read a template must be safe on a plain page, and they are.
15
+
16
+ ## `.xhtml`
17
+ The same language in the syntax of XML; comments and tags are read the same way.
18
+ """
@@ -0,0 +1,28 @@
1
+ import re
2
+ from typing import Final
3
+
4
+
5
+ HTML_RAW_TEXT_END_PATTERNS: Final[dict[str, re.Pattern[str]]] = {
6
+ name: re.compile(rf"</{name}(?=[\s/>])", re.IGNORECASE)
7
+ for name in ("script", "style", "textarea", "title")
8
+ }
9
+ """For each element whose content is raw text, the pattern of its end tag."""
10
+
11
+
12
+ _DESIGN_NOTES = """
13
+ # HTML_RAW_TEXT_END_PATTERNS — Elements Whose Content Is Not Markup
14
+
15
+ ## Purpose
16
+ Inside `script` and `style` a `<` is just a character, and inside `textarea`
17
+ and `title` only the end tag counts. So there can be no comment in them, and
18
+ the scanner skips the content as a whole, to the end tag.
19
+
20
+ ## The Names Are the List
21
+ The keys are the elements this library knows to be raw. The end tag is
22
+ `</name` followed by a blank, a slash or `>`, so `</scripts>` does not end a
23
+ `script`.
24
+
25
+ ## Not Included
26
+ The legacy `xmp`, `iframe`, `noembed` and `noframes` are left out: they are
27
+ rare, and a page that uses them is not the kind this library is made for.
28
+ """
@@ -0,0 +1,22 @@
1
+ from typing import Final
2
+ # Inners
3
+ from .HTML_PLAIN_SUFFIXES import HTML_PLAIN_SUFFIXES
4
+ from .HTML_TEMPLATE_SUFFIXES import HTML_TEMPLATE_SUFFIXES
5
+ from .HTML_WRAPPED_SUFFIXES import HTML_WRAPPED_SUFFIXES
6
+
7
+
8
+ HTML_SUFFIXES: Final[tuple[str, ...]] = HTML_PLAIN_SUFFIXES + HTML_TEMPLATE_SUFFIXES + HTML_WRAPPED_SUFFIXES
9
+ """Every suffix of a file this library may read: pages, Jinja templates and the `.j2` wrapper."""
10
+
11
+
12
+ _DESIGN_NOTES = """
13
+ # HTML_SUFFIXES — The Whole List in One Place
14
+
15
+ ## Purpose
16
+ The profiles choose the steps of a file by its suffix, and they need the
17
+ list of every suffix they can meet. The file rules do not use it: `.j2` is
18
+ accepted there only together with a look at the stem.
19
+
20
+ ## Built From the Three Parts
21
+ A suffix added to any of them is known to the profiles at once.
22
+ """
@@ -0,0 +1,16 @@
1
+ import re
2
+ from typing import Final
3
+
4
+
5
+ HTML_TAG_NAME_PATTERN: Final[re.Pattern[str]] = re.compile(r"</?([A-Za-z][^\s/>]*)")
6
+ """The name of a tag, in the first group (`div` of `<div class="a">` and of `</div>`)."""
7
+
8
+
9
+ _DESIGN_NOTES = """
10
+ # HTML_TAG_NAME_PATTERN — Which Element Is It
11
+
12
+ ## Purpose
13
+ The scanner needs the name of a tag to treat `script`, `style`, `textarea`,
14
+ `title` and `pre` differently. The name is read up to the first blank, slash
15
+ or `>`, and compared in lower case.
16
+ """
@@ -0,0 +1,38 @@
1
+ import re
2
+ from typing import Final
3
+
4
+
5
+ HTML_TEMPLATE_BLOCKS: Final[dict[str, dict[str, tuple[str, re.Pattern[str]]]]] = {
6
+ "django": {
7
+ "comment": ("comment", re.compile(r"\{%[-+]?\s*endcomment\b.*?%\}", re.DOTALL)),
8
+ "verbatim": ("verbatim", re.compile(r"\{%[-+]?\s*endverbatim\b.*?%\}", re.DOTALL)),
9
+ },
10
+ "jinja": {
11
+ "raw": ("verbatim", re.compile(r"\{%[-+]?\s*endraw\b.*?%\}", re.DOTALL)),
12
+ },
13
+ }
14
+ """For each engine, the tags that open a block running to an end tag: its name, what the block is (`comment` or `verbatim`) and the pattern of the end tag."""
15
+
16
+
17
+ _DESIGN_NOTES = """
18
+ # HTML_TEMPLATE_BLOCKS — Tags That Swallow Everything Up to Their End
19
+
20
+ ## Purpose
21
+ A Django `{% comment %}` hides everything up to `{% endcomment %}`, and
22
+ `{% verbatim %}` or a Jinja `{% raw %}` makes everything up to its end plain
23
+ text. The scanner must treat such a stretch as one piece, whatever HTML it
24
+ contains.
25
+
26
+ ## What Each Block Is
27
+ * `comment`: removed by the template comment step, like `{# ... #}`.
28
+ * `verbatim`: left as it is, and hidden from the scanner of HTML (a `<!-- -->`
29
+ inside `{% verbatim %}` is text for the template engine).
30
+
31
+ ## The End Tag
32
+ `{%`, optional whitespace control (`-` or `+`), the name, anything up to `%}`.
33
+ A comment block may carry a note (`{% comment "why" %}`), and the end tag
34
+ may carry whitespace control (`{%- endcomment -%}`).
35
+
36
+ ## Why Jinja Has No Comment Block
37
+ Jinja has no such tag; its comments are `{# ... #}`, which may span lines.
38
+ """
@@ -0,0 +1,29 @@
1
+ from typing import Final
2
+
3
+
4
+ HTML_TEMPLATE_IMPORT_TAGS: Final[dict[str, tuple[str, ...]]] = {
5
+ "django": ("load",),
6
+ "jinja": ("import", "from"),
7
+ }
8
+ """For each engine, the names of the tags that bring other names into a template."""
9
+
10
+
11
+ _DESIGN_NOTES = """
12
+ # HTML_TEMPLATE_IMPORT_TAGS — What a Template Needs From Elsewhere
13
+
14
+ ## Purpose
15
+ The names behind `remove_template_imports`. Like the imports of a program,
16
+ these tags only say where the names that the rest of the template uses come
17
+ from, and a reader who wants the page itself can do without them.
18
+
19
+ ## Django
20
+ `{% load static %}` and `{% load i18n static %}` bring in tag libraries.
21
+
22
+ ## Jinja
23
+ `{% import 'forms.html' as forms %}` and `{% from 'forms.html' import field %}`
24
+ bring in macros.
25
+
26
+ ## What Is Not Here
27
+ `{% extends %}` and `{% include %}` are not imports: they build the page and
28
+ say what it is made of, so they stay.
29
+ """
@@ -0,0 +1,35 @@
1
+ from typing import Final
2
+
3
+
4
+ HTML_TEMPLATE_OUTLINE_TAGS: Final[dict[str, dict[str, tuple[str, ...]]]] = {
5
+ "django": {
6
+ "opens": ("block",),
7
+ "closes": ("endblock",),
8
+ "lines": ("extends", "include"),
9
+ },
10
+ "jinja": {
11
+ "opens": ("block", "macro"),
12
+ "closes": ("endblock", "endmacro"),
13
+ "lines": ("extends", "include"),
14
+ },
15
+ }
16
+ """For each engine, the template tags of the outline: those that open a level, those that close it, and those that stand alone on a line."""
17
+
18
+
19
+ _DESIGN_NOTES = """
20
+ # HTML_TEMPLATE_OUTLINE_TAGS — The Skeleton of a Template
21
+
22
+ ## Purpose
23
+ `{% extends %}` says what a template is built on, `{% block %}` what it fills
24
+ in or offers to be filled, `{% include %}` what it pulls in, and in Jinja
25
+ `{% macro %}` what it defines. Everything else (`if`, `for`, `with`) is the
26
+ flesh, not the skeleton.
27
+
28
+ ## Opens and Closes
29
+ `block` and `macro` open a level and `endblock` and `endmacro` close it. The
30
+ name that may follow `endblock` is not compared with the name of the block it
31
+ closes.
32
+
33
+ ## What Is Not Here
34
+ The imports are not part of the outline: they have a step of their own.
35
+ """
@@ -0,0 +1,19 @@
1
+ from typing import Final
2
+
3
+
4
+ HTML_TEMPLATE_SUFFIXES: Final[tuple[str, ...]] = (".jinja", ".jinja2", ".njk")
5
+ """The suffixes of HTML templates of the Jinja family (Jinja, Nunjucks)."""
6
+
7
+
8
+ _DESIGN_NOTES = """
9
+ # HTML_TEMPLATE_SUFFIXES — Templates That Say What They Are
10
+
11
+ ## Purpose
12
+ Templates with a suffix of their own: Jinja (`.jinja`, `.jinja2`) and
13
+ Nunjucks (`.njk`), which uses the same `{% %}` and `{# #}` syntax.
14
+
15
+ ## What Is Not Here
16
+ `.j2` is too general (Ansible keeps configuration files in it); it has its own
17
+ constant. `.twig`, `.liquid`, `.hbs`, `.ejs` and `.mustache` have comment
18
+ syntax of their own, which this library does not read.
19
+ """
@@ -0,0 +1,16 @@
1
+ import re
2
+ from typing import Final
3
+
4
+
5
+ HTML_TEMPLATE_TAG_NAME_PATTERN: Final[re.Pattern[str]] = re.compile(r"\{%[-+]?\s*(\w+)")
6
+ """The name of a template tag, in the first group (`block` of `{% block content %}`)."""
7
+
8
+
9
+ _DESIGN_NOTES = """
10
+ # HTML_TEMPLATE_TAG_NAME_PATTERN — Which Tag Is It
11
+
12
+ ## Purpose
13
+ `{% comment %}`, `{% verbatim %}` and `{% raw %}` change how the scanner reads
14
+ what follows; every other tag is only skipped. The name is read after the
15
+ optional whitespace control (`{%-`).
16
+ """
@@ -0,0 +1,16 @@
1
+ import re
2
+ from typing import Final
3
+
4
+
5
+ HTML_TEMPLATE_TOKEN_PATTERN: Final[re.Pattern[str]] = re.compile(r"\{#|\{%|\{\{")
6
+ """What the template scanner stops at: the opening of a template comment, tag or variable."""
7
+
8
+
9
+ _DESIGN_NOTES = """
10
+ # HTML_TEMPLATE_TOKEN_PATTERN — Where a Template Construct Begins
11
+
12
+ ## Purpose
13
+ The three openings Django and Jinja share: `{#` (comment), `{%` (tag) and
14
+ `{{` (variable). What closes each one is decided by the scanner, because it
15
+ depends on the engine.
16
+ """
@@ -0,0 +1,16 @@
1
+ from typing import Final
2
+ # Inners
3
+ from .HTML_HEADING_ELEMENTS import HTML_HEADING_ELEMENTS
4
+
5
+
6
+ HTML_TEXT_ELEMENTS: Final[tuple[str, ...]] = ("title", *HTML_HEADING_ELEMENTS)
7
+ """The elements that appear in the outline with their text: the title and the headings."""
8
+
9
+
10
+ _DESIGN_NOTES = """
11
+ # HTML_TEXT_ELEMENTS — What the Page Calls Its Parts
12
+
13
+ ## Purpose
14
+ A heading is the name the author gave to a part. For a reader who sees only the
15
+ outline, `h2 "Opening hours"` says more than any number of tags.
16
+ """
@@ -0,0 +1,26 @@
1
+ import re
2
+ from typing import Final
3
+
4
+
5
+ HTML_TOKEN_PATTERN: Final[re.Pattern[str]] = re.compile(
6
+ r"""<!--|<!\[CDATA\[|<![A-Za-z]|<\?|</[A-Za-z]|<[A-Za-z]""",
7
+ re.IGNORECASE,
8
+ )
9
+ """What the scanner stops at in a page: a comment, a CDATA section, a declaration, a processing instruction, an end tag or a start tag."""
10
+
11
+
12
+ _DESIGN_NOTES = """
13
+ # HTML_TOKEN_PATTERN — Where Something Interesting Begins
14
+
15
+ ## Purpose
16
+ The scanner does not look at every character. It asks this pattern for the
17
+ next place where markup may begin and jumps there. Text between is only text.
18
+
19
+ ## Why a `<` Alone Is Not a Stop
20
+ A `<` is markup only when a letter, `!`, `/` or `?` follows. `a < b` and
21
+ `1<2` are text, so a stray less-than sign is never read as the start of a tag.
22
+
23
+ ## The Order
24
+ `<!--` comes first, so a comment is never mistaken for a declaration, and the
25
+ CDATA opening comes before the general `<!` declaration.
26
+ """
@@ -0,0 +1,21 @@
1
+ import re
2
+ from typing import Final
3
+
4
+
5
+ HTML_TYPE_ATTRIBUTE_PATTERN: Final[re.Pattern[str]] = re.compile(
6
+ r"""\stype\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'>]+))""",
7
+ re.IGNORECASE,
8
+ )
9
+ """The `type` 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_TYPE_ATTRIBUTE_PATTERN — What Is in the Script
14
+
15
+ ## Purpose
16
+ `<script type="application/json">` is data, `<script type="module">` is code.
17
+ The value of `type` tells the two apart.
18
+
19
+ ## The Blank in Front
20
+ A blank must come before `type`, so `data-type="x"` is not mistaken for it.
21
+ """
@@ -0,0 +1,21 @@
1
+ from typing import Final
2
+
3
+
4
+ HTML_VOID_ELEMENTS: Final[frozenset[str]] = frozenset({
5
+ "area", "base", "br", "col", "embed", "hr", "img", "input",
6
+ "link", "meta", "param", "source", "track", "wbr",
7
+ })
8
+ """The elements that never have content and never have an end tag."""
9
+
10
+
11
+ _DESIGN_NOTES = """
12
+ # HTML_VOID_ELEMENTS — Elements That End Where They Begin
13
+
14
+ ## Purpose
15
+ `<br>`, `<img src="a.png">` and `<input>` have no end tag. The outline must
16
+ not wait for one, or every element after them would seem to be inside them.
17
+
18
+ ## Self-Closing Syntax
19
+ A tag written with `/>` is also a complete element, whatever its name; that is
20
+ decided by the tag itself, not by this list.
21
+ """
@@ -0,0 +1,14 @@
1
+ from typing import Final
2
+
3
+
4
+ HTML_WRAPPED_STEM_ENDING: Final[str] = ".html"
5
+ """What the stem of a wrapped file ends with when it is a page (`index.html` of `index.html.j2`)."""
6
+
7
+
8
+ _DESIGN_NOTES = """
9
+ # HTML_WRAPPED_STEM_ENDING — What Is Inside the Wrapper
10
+
11
+ ## Purpose
12
+ Used by `WRAPPED_HTML`. Only `.html` is accepted: it is by far the common
13
+ name of a Jinja page, and every other ending would be a guess.
14
+ """
@@ -0,0 +1,15 @@
1
+ from typing import Final
2
+
3
+
4
+ HTML_WRAPPED_SUFFIXES: Final[tuple[str, ...]] = (".j2",)
5
+ """The suffixes that only wrap the real one (`index.html.j2`); a file is HTML only if what is inside the wrapper is."""
6
+
7
+
8
+ _DESIGN_NOTES = """
9
+ # HTML_WRAPPED_SUFFIXES — The Suffix That Needs a Look Behind
10
+
11
+ ## Purpose
12
+ `.j2` is added to the name of a file that is a Jinja template: `index.html.j2`
13
+ is a page, `nginx.conf.j2` is a configuration. The suffix alone says nothing,
14
+ so the file rules also look at the stem (`HTML_WRAPPED_STEM_ENDING`).
15
+ """
@@ -0,0 +1,77 @@
1
+ from .HTML_ANY_TAG_PATTERN import HTML_ANY_TAG_PATTERN
2
+ from .HTML_BLOCK_LANGUAGE_BY_TYPE import HTML_BLOCK_LANGUAGE_BY_TYPE
3
+ from .HTML_COMMENT_END_PATTERN import HTML_COMMENT_END_PATTERN
4
+ from .HTML_CONDITIONAL_PATTERN import HTML_CONDITIONAL_PATTERN
5
+ from .HTML_DEPENDENCY_DIR_NAMES import HTML_DEPENDENCY_DIR_NAMES
6
+ from .HTML_EXTRA_LANGUAGE_BY_SUFFIX import HTML_EXTRA_LANGUAGE_BY_SUFFIX
7
+ from .HTML_HEADING_ELEMENTS import HTML_HEADING_ELEMENTS
8
+ from .HTML_ID_ATTRIBUTE_PATTERN import HTML_ID_ATTRIBUTE_PATTERN
9
+ from .HTML_IMPLIED_END import HTML_IMPLIED_END
10
+ from .HTML_LICENSE_START import HTML_LICENSE_START
11
+ from .HTML_LICENSE_TAGS import HTML_LICENSE_TAGS
12
+ from .HTML_OUTLINE_ELEMENTS import HTML_OUTLINE_ELEMENTS
13
+ from .HTML_OUTLINE_TEXT_LIMIT import HTML_OUTLINE_TEXT_LIMIT
14
+ from .HTML_OUTPUT_DIR_NAMES import HTML_OUTPUT_DIR_NAMES
15
+ from .HTML_PLAIN_SUFFIXES import HTML_PLAIN_SUFFIXES
16
+ from .HTML_RAW_TEXT_END_PATTERNS import HTML_RAW_TEXT_END_PATTERNS
17
+ from .HTML_SUFFIXES import HTML_SUFFIXES
18
+ from .HTML_TAG_NAME_PATTERN import HTML_TAG_NAME_PATTERN
19
+ from .HTML_TEMPLATE_BLOCKS import HTML_TEMPLATE_BLOCKS
20
+ from .HTML_TEMPLATE_IMPORT_TAGS import HTML_TEMPLATE_IMPORT_TAGS
21
+ from .HTML_TEMPLATE_OUTLINE_TAGS import HTML_TEMPLATE_OUTLINE_TAGS
22
+ from .HTML_TEMPLATE_SUFFIXES import HTML_TEMPLATE_SUFFIXES
23
+ from .HTML_TEMPLATE_TAG_NAME_PATTERN import HTML_TEMPLATE_TAG_NAME_PATTERN
24
+ from .HTML_TEMPLATE_TOKEN_PATTERN import HTML_TEMPLATE_TOKEN_PATTERN
25
+ from .HTML_TEXT_ELEMENTS import HTML_TEXT_ELEMENTS
26
+ from .HTML_TOKEN_PATTERN import HTML_TOKEN_PATTERN
27
+ from .HTML_TYPE_ATTRIBUTE_PATTERN import HTML_TYPE_ATTRIBUTE_PATTERN
28
+ from .HTML_VOID_ELEMENTS import HTML_VOID_ELEMENTS
29
+ from .HTML_WRAPPED_STEM_ENDING import HTML_WRAPPED_STEM_ENDING
30
+ from .HTML_WRAPPED_SUFFIXES import HTML_WRAPPED_SUFFIXES
31
+
32
+
33
+ _DESIGN_NOTES = """
34
+ # constants — Fixed Values of simplibs-extractor-html
35
+
36
+ Plain imports, no `__all__` (the package root decides what is public).
37
+
38
+ ## Internal Components Registry
39
+
40
+ | Component | Type | Description |
41
+ | :------------------------------- | :------- | :------------------------------------------------------------------- |
42
+ | `HTML_ANY_TAG_PATTERN` | Pattern | Anything that looks like a tag. |
43
+ | `HTML_BLOCK_LANGUAGE_BY_TYPE` | Constant | Which `type` values make a `script` or `style` code, and of what language. |
44
+ | `HTML_COMMENT_END_PATTERN` | Pattern | `-->` and `--!>`. |
45
+ | `HTML_CONDITIONAL_PATTERN` | Pattern | The beginning of an IE conditional comment. |
46
+ | `HTML_DEPENDENCY_DIR_NAMES` | Constant | Folders of pages written by other people. |
47
+ | `HTML_EXTRA_LANGUAGE_BY_SUFFIX` | Constant | The fence language of the suffixes the extractor does not know. |
48
+ | `HTML_HEADING_ELEMENTS` | Constant | The six heading elements. |
49
+ | `HTML_ID_ATTRIBUTE_PATTERN` | Pattern | The `id` attribute of a tag. |
50
+ | `HTML_IMPLIED_END` | Constant | Which start tags close which open elements. |
51
+ | `HTML_LICENSE_START` | Constant | How a comment that has to survive minification begins. |
52
+ | `HTML_LICENSE_TAGS` | Constant | Words that mark a comment as one to keep. |
53
+ | `HTML_OUTLINE_ELEMENTS` | Constant | The elements that always appear in the outline of a page. |
54
+ | `HTML_OUTLINE_TEXT_LIMIT` | Constant | The longest heading text in the outline. |
55
+ | `HTML_OUTPUT_DIR_NAMES` | Constant | Folders of generated pages and reports. |
56
+ | `HTML_PLAIN_SUFFIXES` | Constant | Suffixes of HTML pages and Django templates. |
57
+ | `HTML_RAW_TEXT_END_PATTERNS` | Constant | The end tag of each element with raw text. |
58
+ | `HTML_SUFFIXES` | Constant | Every suffix the library may read. |
59
+ | `HTML_TAG_NAME_PATTERN` | Pattern | The name of a tag. |
60
+ | `HTML_TEMPLATE_BLOCKS` | Constant | The template tags that swallow everything up to an end tag. |
61
+ | `HTML_TEMPLATE_IMPORT_TAGS` | Constant | The template tags that bring in names from elsewhere. |
62
+ | `HTML_TEMPLATE_OUTLINE_TAGS` | Constant | The template tags of the outline: open, close, standalone. |
63
+ | `HTML_TEMPLATE_SUFFIXES` | Constant | Suffixes of Jinja and Nunjucks templates. |
64
+ | `HTML_TEMPLATE_TAG_NAME_PATTERN` | Pattern | The name of a template tag. |
65
+ | `HTML_TEMPLATE_TOKEN_PATTERN` | Pattern | Where a template construct begins. |
66
+ | `HTML_TEXT_ELEMENTS` | Constant | The title and the headings: listed with their text. |
67
+ | `HTML_TOKEN_PATTERN` | Pattern | Where markup begins in a page. |
68
+ | `HTML_TYPE_ATTRIBUTE_PATTERN` | Pattern | The `type` attribute of a tag. |
69
+ | `HTML_VOID_ELEMENTS` | Constant | The elements that have no content and no end tag. |
70
+ | `HTML_WRAPPED_STEM_ENDING` | Constant | What the stem of a wrapped page ends with. |
71
+ | `HTML_WRAPPED_SUFFIXES` | Constant | The `.j2` wrapper around the real suffix. |
72
+
73
+ ## Layering & Design
74
+ - Every value is a tuple, a plain string, a small dict or a compiled pattern: the rules and the steps are built from them.
75
+ - The names of version-control folders are not here: they come from `IGNORE_VCS` of `simplibs-path`.
76
+ - There is no list of configuration names and no list of minified names: no tool keeps its settings in a page, and a minified page is not a convention.
77
+ """
@@ -0,0 +1,56 @@
1
+ from .atomic import (
2
+ DEPENDENCY_DIRS,
3
+ DOT_NAME,
4
+ OUTPUT_DIRS,
5
+ VCS_DIRS,
6
+ WRAPPED_HTML,
7
+ )
8
+ from .html import (
9
+ HTML_BASE,
10
+ HTML_FILES,
11
+ HTML_PLAIN_BASE,
12
+ HTML_STRICT_EXCLUDE,
13
+ )
14
+
15
+
16
+ __all__ = [
17
+ # atomic
18
+ "DEPENDENCY_DIRS",
19
+ "DOT_NAME",
20
+ "OUTPUT_DIRS",
21
+ "VCS_DIRS",
22
+ "WRAPPED_HTML",
23
+ # html
24
+ "HTML_BASE",
25
+ "HTML_FILES",
26
+ "HTML_PLAIN_BASE",
27
+ "HTML_STRICT_EXCLUDE",
28
+ ]
29
+
30
+
31
+ _DESIGN_NOTES = """
32
+ # simplibs.extractor_html.file_rules — Which Files Are Worth Reading
33
+
34
+ ## Purpose
35
+ Rules on the path of a file, relative to the source folder. The profiles use
36
+ them as `include` and `exclude`; they compose with `&`, `|` and `~`, so a
37
+ program can build its own selection from them:
38
+
39
+ from simplibs.extractor_html.file_rules import HTML_BASE, OUTPUT_DIRS
40
+ pages_without_output = HTML_BASE & ~OUTPUT_DIRS
41
+
42
+ ## Domain Folder
43
+ `file_rules/` has its own `__all__` and is not re-exported from the package root.
44
+
45
+ ## Internal Components Registry
46
+
47
+ | Component | Type | Description |
48
+ | :-------- | :------ | :----------------------------------------------------------------------- |
49
+ | `atomic` | Package | The shared pieces: dot names, the folder rules and the `.j2` wrapper. |
50
+ | `html` | Package | Rules for pages and templates. |
51
+
52
+ ## Layering & Design
53
+ - `atomic` ← `html`.
54
+ - Every rule is built once, when the package is imported.
55
+ - A rule about the folders above a file is `AnyParentNameIs` of `simplibs-path`; a set of names is `IsIn` of `simplibs-rules`.
56
+ """
@@ -0,0 +1,17 @@
1
+ from typing import Final
2
+ from simplibs.path.rules import AnyParentNameIs
3
+ from simplibs.rules import IsIn, Rule
4
+ # Outers
5
+ from ...constants import HTML_DEPENDENCY_DIR_NAMES
6
+
7
+
8
+ DEPENDENCY_DIRS: Final[Rule] = AnyParentNameIs(IsIn(HTML_DEPENDENCY_DIR_NAMES))
9
+ """The file lies inside a folder of pages written by other people (`node_modules`, `vendor`)."""
10
+
11
+
12
+ _DESIGN_NOTES = """
13
+ # DEPENDENCY_DIRS — Other People's Pages
14
+
15
+ ## Purpose
16
+ Part of the strict HTML exclusion. See `HTML_DEPENDENCY_DIR_NAMES`.
17
+ """
@@ -0,0 +1,19 @@
1
+ from typing import Final
2
+ from simplibs.path.rules import NameIs
3
+ from simplibs.rules import Rule, StartsWith
4
+
5
+
6
+ DOT_NAME: Final[Rule] = NameIs(StartsWith("."))
7
+ """The file name starts with a dot (`.hidden.html`)."""
8
+
9
+
10
+ _DESIGN_NOTES = """
11
+ # DOT_NAME — Hidden by Convention
12
+
13
+ ## Purpose
14
+ Dot files are settings and tool state, not source. Used by `HTML_BASE`.
15
+
16
+ ## Name Only
17
+ Only the name of the file is judged. A visible file inside a `.cache` folder
18
+ is not hidden by this rule (the strict exclusions look at folders).
19
+ """
@@ -0,0 +1,17 @@
1
+ from typing import Final
2
+ from simplibs.path.rules import AnyParentNameIs
3
+ from simplibs.rules import IsIn, Rule
4
+ # Outers
5
+ from ...constants import HTML_OUTPUT_DIR_NAMES
6
+
7
+
8
+ OUTPUT_DIRS: Final[Rule] = AnyParentNameIs(IsIn(HTML_OUTPUT_DIR_NAMES))
9
+ """The file lies inside a folder of generated pages (`dist`, `_build`, `htmlcov`...)."""
10
+
11
+
12
+ _DESIGN_NOTES = """
13
+ # OUTPUT_DIRS — Generated Pages
14
+
15
+ ## Purpose
16
+ Part of the strict HTML exclusion. See `HTML_OUTPUT_DIR_NAMES`.
17
+ """