lhtml-markup 2.4.0__tar.gz → 2.5.0__tar.gz
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.
- {lhtml_markup-2.4.0 → lhtml_markup-2.5.0}/PKG-INFO +241 -15
- {lhtml_markup-2.4.0 → lhtml_markup-2.5.0}/README.md +240 -14
- {lhtml_markup-2.4.0 → lhtml_markup-2.5.0}/pyproject.toml +4 -1
- {lhtml_markup-2.4.0 → lhtml_markup-2.5.0}/src/lhtml/__init__.py +8 -4
- {lhtml_markup-2.4.0 → lhtml_markup-2.5.0}/src/lhtml/cli.py +15 -0
- {lhtml_markup-2.4.0 → lhtml_markup-2.5.0}/src/lhtml/errors.py +4 -0
- lhtml_markup-2.5.0/src/lhtml/macros.py +276 -0
- {lhtml_markup-2.4.0 → lhtml_markup-2.5.0}/src/lhtml/pipeline.py +21 -2
- {lhtml_markup-2.4.0 → lhtml_markup-2.5.0}/src/lhtml/process.py +4 -2
- {lhtml_markup-2.4.0 → lhtml_markup-2.5.0}/src/lhtml_markup.egg-info/PKG-INFO +241 -15
- {lhtml_markup-2.4.0 → lhtml_markup-2.5.0}/src/lhtml_markup.egg-info/SOURCES.txt +1 -0
- {lhtml_markup-2.4.0 → lhtml_markup-2.5.0}/test/test_lhtml.py +241 -1
- {lhtml_markup-2.4.0 → lhtml_markup-2.5.0}/LICENSE.md +0 -0
- {lhtml_markup-2.4.0 → lhtml_markup-2.5.0}/setup.cfg +0 -0
- {lhtml_markup-2.4.0 → lhtml_markup-2.5.0}/src/lhtml/__main__.py +0 -0
- {lhtml_markup-2.4.0 → lhtml_markup-2.5.0}/src/lhtml/code.py +0 -0
- {lhtml_markup-2.4.0 → lhtml_markup-2.5.0}/src/lhtml/element_extract.py +0 -0
- {lhtml_markup-2.4.0 → lhtml_markup-2.5.0}/src/lhtml/export_html.py +0 -0
- {lhtml_markup-2.4.0 → lhtml_markup-2.5.0}/src/lhtml/insert_in_text.py +0 -0
- {lhtml_markup-2.4.0 → lhtml_markup-2.5.0}/src/lhtml/listing.py +0 -0
- {lhtml_markup-2.4.0 → lhtml_markup-2.5.0}/src/lhtml/patterns.py +0 -0
- {lhtml_markup-2.4.0 → lhtml_markup-2.5.0}/src/lhtml/tag_element.lark +0 -0
- {lhtml_markup-2.4.0 → lhtml_markup-2.5.0}/src/lhtml/tag_parser.py +0 -0
- {lhtml_markup-2.4.0 → lhtml_markup-2.5.0}/src/lhtml/wrap_html.py +0 -0
- {lhtml_markup-2.4.0 → lhtml_markup-2.5.0}/src/lhtml_markup.egg-info/dependency_links.txt +0 -0
- {lhtml_markup-2.4.0 → lhtml_markup-2.5.0}/src/lhtml_markup.egg-info/entry_points.txt +0 -0
- {lhtml_markup-2.4.0 → lhtml_markup-2.5.0}/src/lhtml_markup.egg-info/requires.txt +0 -0
- {lhtml_markup-2.4.0 → lhtml_markup-2.5.0}/src/lhtml_markup.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: lhtml-markup
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.5.0
|
|
4
4
|
Summary: Lightweight HTML markup language — simplifies HTML authoring with shorthand syntax
|
|
5
5
|
License: MIT
|
|
6
6
|
Project-URL: Homepage, https://github.com/drohmer/lhtml
|
|
@@ -26,6 +26,8 @@ LHTML is a markup language that simplifies HTML authoring with embedded CSS styl
|
|
|
26
26
|
|
|
27
27
|
LHTML is used to build static websites and presentation slides, typically combined with Jinja2 templates.
|
|
28
28
|
|
|
29
|
+
See the [examples](examples/) and the [changelog](CHANGELOG.md).
|
|
30
|
+
|
|
29
31
|
## Installation
|
|
30
32
|
|
|
31
33
|
From PyPI:
|
|
@@ -58,14 +60,45 @@ Dependencies (`lark`, `pygments`, `pyyaml`) are installed automatically.
|
|
|
58
60
|
```bash
|
|
59
61
|
lhtml input.l.html # Convert to stdout
|
|
60
62
|
lhtml input.l.html -o output.html # Convert to file
|
|
61
|
-
lhtml input.l.html -w # Wrap in full HTML document
|
|
62
|
-
lhtml input.l.html -b # Render source line breaks as <br>
|
|
63
|
+
lhtml input.l.html -w # Wrap in full HTML document (--wrapAuto)
|
|
64
|
+
lhtml input.l.html -b # Render source line breaks as <br> (--line-breaks)
|
|
65
|
+
lhtml input.l.html -m macros.yaml # Declare macros, custom :: tags (--macros)
|
|
63
66
|
lhtml a.l.html b.l.html # Several files: a.html, b.html next to sources
|
|
64
67
|
lhtml a.l.html b.l.html -o build/ # Several files into a directory
|
|
65
68
|
python -m lhtml input.l.html # Alternative invocation
|
|
69
|
+
lhtml --version # Show the version (also lhtml.__version__)
|
|
66
70
|
```
|
|
67
71
|
|
|
68
|
-
|
|
72
|
+
Without `-o`, `page.l.html` is written to `page.html` next to its source.
|
|
73
|
+
|
|
74
|
+
- Files are read and written as UTF-8 (a BOM is accepted).
|
|
75
|
+
- Errors and warnings are reported on stderr with the file name. The remaining files are still processed, and the exit code is non-zero if any file failed.
|
|
76
|
+
- An input file is never overwritten: `lhtml page.html` (output `page.html`) is an error, as is an output that is another input of the batch, or a symbolic or hard link to one.
|
|
77
|
+
- Includes are looked up in the input file's directory first, then in the current directory.
|
|
78
|
+
|
|
79
|
+
With `-w`, the result is wrapped in a minimal HTML document using the `title`, `css` and `js` of the front matter:
|
|
80
|
+
|
|
81
|
+
```html
|
|
82
|
+
<!DOCTYPE html>
|
|
83
|
+
|
|
84
|
+
<html lang="en">
|
|
85
|
+
|
|
86
|
+
<head>
|
|
87
|
+
<meta charset="utf-8">
|
|
88
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
89
|
+
<title>My Page</title>
|
|
90
|
+
<link rel="stylesheet" type="text/css" href="style.css">
|
|
91
|
+
<script src="app.js" defer></script>
|
|
92
|
+
</head>
|
|
93
|
+
|
|
94
|
+
<body>
|
|
95
|
+
<h1>Hello</h1>
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
</body>
|
|
99
|
+
|
|
100
|
+
</html>
|
|
101
|
+
```
|
|
69
102
|
|
|
70
103
|
### Python API
|
|
71
104
|
|
|
@@ -80,6 +113,12 @@ html = lhtml.run(text, {
|
|
|
80
113
|
'css': ['style.css'],
|
|
81
114
|
'js': ['script.js'],
|
|
82
115
|
})
|
|
116
|
+
|
|
117
|
+
# Macros (custom :: tags, see Macros below)
|
|
118
|
+
html = lhtml.run('box:: x ::\n', {'macros': {'box': {'class': 'box'}}})
|
|
119
|
+
macros = lhtml.load_macros('macros.yaml') # definitions from files or dicts
|
|
120
|
+
registry = lhtml.registry_with_macros(macros) # validates them (LHTMLMacroError)
|
|
121
|
+
info = lhtml.describe_macro('box', macros['box']) # what a definition renders, for docs
|
|
83
122
|
```
|
|
84
123
|
|
|
85
124
|
|
|
@@ -114,13 +153,33 @@ With classes/IDs:
|
|
|
114
153
|
```
|
|
115
154
|
* First item
|
|
116
155
|
* Second item
|
|
117
|
-
** Nested item
|
|
118
|
-
** Nested item B
|
|
119
|
-
*** Deep nested
|
|
156
|
+
** Nested item
|
|
120
157
|
* Back to top level
|
|
121
158
|
```
|
|
122
159
|
|
|
123
|
-
|
|
160
|
+
Output (a nested list is placed in its own `<li>`):
|
|
161
|
+
```html
|
|
162
|
+
<ul>
|
|
163
|
+
<li>
|
|
164
|
+
First item
|
|
165
|
+
</li>
|
|
166
|
+
<li>
|
|
167
|
+
Second item
|
|
168
|
+
</li>
|
|
169
|
+
<li>
|
|
170
|
+
<ul>
|
|
171
|
+
<li>
|
|
172
|
+
Nested item
|
|
173
|
+
</li>
|
|
174
|
+
</ul>
|
|
175
|
+
</li>
|
|
176
|
+
<li>
|
|
177
|
+
Back to top level
|
|
178
|
+
</li>
|
|
179
|
+
</ul>
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Each `*` adds one level (`***` is level 3). A list ends at the first line that is not an item.
|
|
124
183
|
|
|
125
184
|
|
|
126
185
|
### Inline Formatting
|
|
@@ -155,7 +214,7 @@ Tag names start with a letter and may contain letters, digits, `_` and `-` (usef
|
|
|
155
214
|
|
|
156
215
|
A closing `::` may be directly followed by punctuation or HTML (`**span::[c] x ::**`, `important ::,`). In a run of colons, `::` markers are the pairs ending the run: `::::[...]` is a closing `::` followed by `::[...]`, and `x:::nl` is `x:` followed by `::nl`. A `::` between two HTML tags (as in pre-highlighted code `<span>::</span>`) is left untouched.
|
|
157
216
|
|
|
158
|
-
A tag that is opened but never closed, or a `::` without matching opening tag, produces an `LHTMLWarning` quoting the beginning of the tag.
|
|
217
|
+
A tag that is opened but never closed, or a `::` without matching opening tag, produces an `LHTMLWarning` quoting the beginning of the tag. An unmatched `::` is kept as text in the output.
|
|
159
218
|
|
|
160
219
|
#### Div / Span with Styles
|
|
161
220
|
|
|
@@ -219,6 +278,25 @@ Output:
|
|
|
219
278
|
<div style="color:blue;"> short text </div>
|
|
220
279
|
```
|
|
221
280
|
|
|
281
|
+
#### Explicit Closing Tags
|
|
282
|
+
|
|
283
|
+
A bare `::` closes the last opened tag. To make long or nested blocks easier to read, name the tag you close with `::name[-]` (`::[-]` closes the last one, like `::`):
|
|
284
|
+
|
|
285
|
+
```
|
|
286
|
+
div::[color:red;]
|
|
287
|
+
Red **text**
|
|
288
|
+
::div[-]
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
Output:
|
|
292
|
+
```html
|
|
293
|
+
<div style="color:red;">
|
|
294
|
+
Red <strong>text</strong>
|
|
295
|
+
</div>
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
If the name does not match the last opened tag, a `LHTMLWarning` is emitted and the last opened tag is closed.
|
|
299
|
+
|
|
222
300
|
|
|
223
301
|
### Links
|
|
224
302
|
|
|
@@ -267,7 +345,22 @@ def hello():
|
|
|
267
345
|
code::[-]
|
|
268
346
|
````
|
|
269
347
|
|
|
270
|
-
|
|
348
|
+
Output (Pygments HTML inside `<div class="code">`):
|
|
349
|
+
```html
|
|
350
|
+
<div class="code"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">hello</span><span class="p">():</span>
|
|
351
|
+
...
|
|
352
|
+
</pre></div>
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
Syntax highlighting is powered by Pygments: any language supported by Pygments can be used, case-insensitively. An empty language (`code::[]`) renders plain text; an unknown language renders plain text with a warning. The built-in `c++` language is C++ with the types of the [CGP library](https://github.com/drohmer/cgp) highlighted; other languages can be added (see [Custom Code Lexers](#custom-code-lexers)).
|
|
356
|
+
|
|
357
|
+
The colors come from a Pygments stylesheet, which you must include in your page. Generate one for the `.code` class (any [Pygments style](https://pygments.org/styles/) can replace `default`):
|
|
358
|
+
|
|
359
|
+
```bash
|
|
360
|
+
pygmentize -S default -f html -a .code > code.css
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
`include::file` directives inside a code block insert the file as raw code.
|
|
271
364
|
|
|
272
365
|
|
|
273
366
|
### Spacer
|
|
@@ -328,6 +421,85 @@ include::components/nav.html
|
|
|
328
421
|
Included files are recursively processed (up to 20 levels); their own YAML front matter is ignored. An included file looks for its own includes first in its own directory, then in `directory_include`. A circular include raises `LHTMLIncludeLoopError`.
|
|
329
422
|
|
|
330
423
|
|
|
424
|
+
### Macros (custom tags from a configuration)
|
|
425
|
+
|
|
426
|
+
A macro is a named `::` tag declared in YAML (or a dict): a shortcut for an
|
|
427
|
+
HTML element with default classes, style and attributes. The styling stays
|
|
428
|
+
in CSS, so a deck or a site changes its look in one place.
|
|
429
|
+
|
|
430
|
+
```yaml
|
|
431
|
+
# macros.yaml (the definitions may also be at the top level)
|
|
432
|
+
macros:
|
|
433
|
+
small: {class: small}
|
|
434
|
+
credit: {tag: span, class: credit}
|
|
435
|
+
aside: {class: aside}
|
|
436
|
+
box: {class: box}
|
|
437
|
+
gap: {class: gap, empty: true, variant: [s, m, l], default: m}
|
|
438
|
+
demo: {tag: iframe, class: demo, empty: true, url: src, attrs: 'frameborder="0"'}
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
```
|
|
442
|
+
aside::[top:400px;]
|
|
443
|
+
img::assets/figure.png[width:450px;]
|
|
444
|
+
::
|
|
445
|
+
|
|
446
|
+
box::(.good) **Correct** ::
|
|
447
|
+
gap::l
|
|
448
|
+
credit:: Image: Wikimedia Commons ::
|
|
449
|
+
demo::assets/demo/index.html
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
Output:
|
|
453
|
+
```html
|
|
454
|
+
<div class="aside" style="top:400px;">
|
|
455
|
+
<img style="width:450px;" src="assets/figure.png" alt="assets/figure.png">
|
|
456
|
+
</div>
|
|
457
|
+
|
|
458
|
+
<div class="box good"> <strong>Correct</strong> </div>
|
|
459
|
+
<div class="gap gap-l"></div>
|
|
460
|
+
<span class="credit"> Image: Wikimedia Commons </span>
|
|
461
|
+
<iframe class="demo" src="assets/demo/index.html" frameborder="0"></iframe>
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
| Field | Description |
|
|
465
|
+
|-------|-------------|
|
|
466
|
+
| `tag` | HTML element (default `div`) |
|
|
467
|
+
| `class` | Default classes (space separated) |
|
|
468
|
+
| `style` | Default inline style, placed before the style of the source |
|
|
469
|
+
| `attrs` | Default HTML attributes |
|
|
470
|
+
| `empty` | No content: the element is closed at once (`gap::`, `demo::url`) |
|
|
471
|
+
| `url` | The text after `::` is the value of this attribute (`src`, `data-src`, ...). Not needed for `tag: img`, `video`, `videoplay`, `link`: their text is already the URL |
|
|
472
|
+
| `variant` | The text after `::` selects a variant, added as the class `<first class>-<variant>`; a list restricts the allowed values (an unknown one gives a warning) |
|
|
473
|
+
| `default` | Variant used when none is given (one of the variants) |
|
|
474
|
+
| `doc` | Description, ignored by LHTML (for documentation tools; `lhtml.describe_macro(name, spec)` gives what a definition renders) |
|
|
475
|
+
|
|
476
|
+
The classes, style and attributes written in the source are added to the
|
|
477
|
+
defaults, then the element is rendered like any element: a macro whose `tag`
|
|
478
|
+
is an LHTML tag (`img`, `video`, `videoplay`, `link`, ...) uses that tag
|
|
479
|
+
(`photo: {tag: img, class: photo}` gives `photo::a.png` an `alt`, `videoplay`
|
|
480
|
+
keeps its codec variants, the `style` of a `link` macro is an attribute since
|
|
481
|
+
`[]` is the link text); a macro never renders through another macro. A macro is closed by `::` or by its name (`::box[-]`). Macros are
|
|
482
|
+
not active inside inline code (`` `box::` `` stays text), and a macro cannot
|
|
483
|
+
replace a built-in tag (`div`, `img`, ...). Unlike `img::`, the URL of a `url`
|
|
484
|
+
macro is not protected from inline formatting (avoid `__` in it).
|
|
485
|
+
|
|
486
|
+
A variant may be closed at once like any element: `gap::l::`.
|
|
487
|
+
|
|
488
|
+
Declare them with `-m` / `--macros` (repeatable, later files win), with the
|
|
489
|
+
`macros` key of the front matter (file names relative to the page, or
|
|
490
|
+
definitions), or with `lhtml.run(text, {'macros': ...})` (a dict, a file
|
|
491
|
+
name, or a list of them). The macros of the front matter are added to the
|
|
492
|
+
others (a macro of the same name is replaced, `name: null` removes it). A
|
|
493
|
+
file holds the definitions at its top level or under its only key `macros`
|
|
494
|
+
(`macros` is thus not a macro name). An HTML void element
|
|
495
|
+
(`tag: hr`, `br`, ...) is always empty. Invalid definitions (unknown field,
|
|
496
|
+
wrong type) raise `LHTMLMacroError`.
|
|
497
|
+
|
|
498
|
+
```bash
|
|
499
|
+
lhtml -m macros.yaml slide.l.html
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
|
|
331
503
|
### YAML Front Matter
|
|
332
504
|
|
|
333
505
|
The front matter must be at the very beginning of the file (`---` separators elsewhere are kept as text). Input text is normalized first: a leading BOM is removed and CRLF line endings become LF.
|
|
@@ -353,6 +525,51 @@ Supported metadata keys:
|
|
|
353
525
|
| `wrap-auto` | boolean | Wrap output in full HTML document |
|
|
354
526
|
| `line-breaks` | boolean | Render source line breaks as `<br>` |
|
|
355
527
|
| `directory_include` | list | Directories to search for includes |
|
|
528
|
+
| `macros` | string, list or mapping | Macros: YAML file(s) relative to the page, or definitions (see [Macros](#macros-custom-tags-from-a-configuration)) |
|
|
529
|
+
|
|
530
|
+
|
|
531
|
+
## Using LHTML with Jinja2
|
|
532
|
+
|
|
533
|
+
LHTML leaves Jinja2 untouched, so a template can be written in LHTML: convert it to HTML first, then render it with Jinja2 (`pip install jinja2`).
|
|
534
|
+
|
|
535
|
+
`blog.l.html`:
|
|
536
|
+
```
|
|
537
|
+
= {{ page.title }}
|
|
538
|
+
|
|
539
|
+
{% for post in posts %}
|
|
540
|
+
div::(.post)
|
|
541
|
+
== link::{{ post.url }}[{{ post.title }}]
|
|
542
|
+
{{ post.summary }} **Read more**
|
|
543
|
+
::
|
|
544
|
+
{% endfor %}
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
```python
|
|
548
|
+
import jinja2
|
|
549
|
+
import lhtml
|
|
550
|
+
|
|
551
|
+
with open('blog.l.html', encoding='utf-8') as f:
|
|
552
|
+
template = jinja2.Template(lhtml.run(f.read()))
|
|
553
|
+
|
|
554
|
+
html = template.render(page={'title': 'Blog'},
|
|
555
|
+
posts=[{'url': 'first.html', 'title': 'First post', 'summary': 'Hello.'}])
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
`lhtml.run()` produces the Jinja2 template:
|
|
559
|
+
```html
|
|
560
|
+
<h1>{{ page.title }}</h1>
|
|
561
|
+
|
|
562
|
+
|
|
563
|
+
{% for post in posts %}
|
|
564
|
+
<div class="post">
|
|
565
|
+
<h2><a href="{{ post.url }}">{{ post.title }}</a></h2>
|
|
566
|
+
|
|
567
|
+
{{ post.summary }} <strong>Read more</strong>
|
|
568
|
+
</div>
|
|
569
|
+
{% endfor %}
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
Jinja2 expressions can also be used in URLs (`img::{{ base }}/photo.jpg`) and in tag groups (`div::[color:{{ color }};]`).
|
|
356
573
|
|
|
357
574
|
|
|
358
575
|
## Plugin System
|
|
@@ -421,8 +638,9 @@ All keys for the `meta` dict passed to `lhtml.run()`:
|
|
|
421
638
|
'title': 'Webpage', # Document title
|
|
422
639
|
'css': [], # CSS files (string or list)
|
|
423
640
|
'js': [], # JS files (string or list)
|
|
424
|
-
'directory_include': [],
|
|
641
|
+
'directory_include': [cwd], # Search paths for include:: (default: current directory)
|
|
425
642
|
'current_directory': '', # Base directory for video codec detection
|
|
643
|
+
'macros': None, # Macros: dict, YAML file name, or list of them
|
|
426
644
|
}
|
|
427
645
|
```
|
|
428
646
|
|
|
@@ -430,8 +648,8 @@ All keys for the `meta` dict passed to `lhtml.run()`:
|
|
|
430
648
|
## Design Principles
|
|
431
649
|
|
|
432
650
|
- **HTML-first**: Raw HTML is never modified. Only LHTML syntax triggers conversions. In particular, the following are never transformed (not even by `include::` or `::#`): HTML tags and their attributes, including tags spanning multiple lines (URLs containing `__`, quoted values containing `>`, ...), `<script>` and `<style>` blocks (CSS `::before`, ...), HTML comments, and math (`$...$`, `$$...$$`, `\(...\)`, `\[...\]`, so that `$x**2$` reaches MathJax/KaTeX intact). Text between HTML tags is still processed.
|
|
433
|
-
-
|
|
434
|
-
- Jinja2 expressions (`{{ ... }}`), statements (`{% ... %}`) and comments (`{# ... #}`) pass through unchanged.
|
|
651
|
+
- **Attributes stay literal**: styles, classes/IDs and HTML attributes in LHTML tag groups and headings are preserved without inline formatting (`div::(.my__class__)` keeps `my__class__`). Link labels still support formatting.
|
|
652
|
+
- **Template-friendly**: Jinja2 expressions (`{{ ... }}`), statements (`{% ... %}`) and comments (`{# ... #}`) pass through unchanged (see [Using LHTML with Jinja2](#using-lhtml-with-jinja2)).
|
|
435
653
|
- **Island grammar**: LHTML syntax "islands" float in a sea of opaque content (HTML, Jinja2 templates, LaTeX, etc.) that passes through untouched.
|
|
436
654
|
- **Minimal**: A few symbols (`::`, `=`, `*`, `**`, `__`, `` ` ``) cover most needs. No complex configuration required.
|
|
437
655
|
- **Composable**: LHTML works seamlessly with Jinja2 templates, making it suitable for static site generators.
|
|
@@ -441,21 +659,29 @@ All keys for the `meta` dict passed to `lhtml.run()`:
|
|
|
441
659
|
|
|
442
660
|
```
|
|
443
661
|
src/lhtml/
|
|
444
|
-
__init__.py # Public API: run(), analyse_tag(), read_yaml()
|
|
662
|
+
__init__.py # Public API: run(), analyse_tag(), read_yaml(), macro functions
|
|
663
|
+
__main__.py # python -m lhtml
|
|
445
664
|
cli.py # Command-line interface
|
|
446
665
|
pipeline.py # ProcessingPipeline, TagRegistry, LexerRegistry
|
|
666
|
+
macros.py # Macros: custom :: tags declared in YAML
|
|
447
667
|
process.py # Core transformation functions
|
|
448
668
|
patterns.py # Centralized regex patterns and utilities
|
|
449
669
|
tag_parser.py # Lark-based parser for :: bracket syntax
|
|
450
670
|
tag_element.lark # Lark grammar definition
|
|
671
|
+
element_extract.py # extract_bracket_elements() (entry point of the tag parser)
|
|
451
672
|
export_html.py # HTML generation for tag elements
|
|
452
673
|
listing.py # List processing
|
|
453
674
|
code.py # Code syntax highlighting (Pygments)
|
|
454
675
|
wrap_html.py # HTML document wrapping
|
|
455
676
|
errors.py # Structured error types
|
|
677
|
+
insert_in_text.py # Store/restore helpers kept for backward compatibility
|
|
678
|
+
test/ # pytest suite and .l.html / -out.html reference pairs
|
|
679
|
+
examples/ # Example sources (see examples/README.md)
|
|
456
680
|
```
|
|
457
681
|
|
|
682
|
+
Run the tests with `pytest` (after `pip install -e ".[dev]"`).
|
|
683
|
+
|
|
458
684
|
|
|
459
685
|
## License
|
|
460
686
|
|
|
461
|
-
MIT
|
|
687
|
+
MIT, see [LICENSE.md](LICENSE.md).
|