htvl-lang 0.2.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.
Files changed (38) hide show
  1. htvl_lang-0.2.0/LICENSE +21 -0
  2. htvl_lang-0.2.0/PKG-INFO +264 -0
  3. htvl_lang-0.2.0/README.md +233 -0
  4. htvl_lang-0.2.0/htvl/__init__.py +44 -0
  5. htvl_lang-0.2.0/htvl/__main__.py +8 -0
  6. htvl_lang-0.2.0/htvl/cli.py +216 -0
  7. htvl_lang-0.2.0/htvl/elements.py +491 -0
  8. htvl_lang-0.2.0/htvl/emitter.py +134 -0
  9. htvl_lang-0.2.0/htvl/errors.py +84 -0
  10. htvl_lang-0.2.0/htvl/lexer.py +204 -0
  11. htvl_lang-0.2.0/htvl/nodes.py +60 -0
  12. htvl_lang-0.2.0/htvl/parser.py +26 -0
  13. htvl_lang-0.2.0/htvl/project.py +183 -0
  14. htvl_lang-0.2.0/htvl/templates.py +55 -0
  15. htvl_lang-0.2.0/htvl/variables.py +53 -0
  16. htvl_lang-0.2.0/htvl/watch.py +170 -0
  17. htvl_lang-0.2.0/htvl_lang.egg-info/PKG-INFO +264 -0
  18. htvl_lang-0.2.0/htvl_lang.egg-info/SOURCES.txt +36 -0
  19. htvl_lang-0.2.0/htvl_lang.egg-info/dependency_links.txt +1 -0
  20. htvl_lang-0.2.0/htvl_lang.egg-info/entry_points.txt +2 -0
  21. htvl_lang-0.2.0/htvl_lang.egg-info/requires.txt +4 -0
  22. htvl_lang-0.2.0/htvl_lang.egg-info/top_level.txt +1 -0
  23. htvl_lang-0.2.0/pyproject.toml +47 -0
  24. htvl_lang-0.2.0/setup.cfg +4 -0
  25. htvl_lang-0.2.0/tests/test_cli.py +56 -0
  26. htvl_lang-0.2.0/tests/test_elements.py +103 -0
  27. htvl_lang-0.2.0/tests/test_emitter.py +81 -0
  28. htvl_lang-0.2.0/tests/test_golden.py +16 -0
  29. htvl_lang-0.2.0/tests/test_lexer.py +94 -0
  30. htvl_lang-0.2.0/tests/test_modern.py +130 -0
  31. htvl_lang-0.2.0/tests/test_packaging.py +87 -0
  32. htvl_lang-0.2.0/tests/test_parser.py +42 -0
  33. htvl_lang-0.2.0/tests/test_playground_lib.py +127 -0
  34. htvl_lang-0.2.0/tests/test_project.py +60 -0
  35. htvl_lang-0.2.0/tests/test_pygments_htvl.py +109 -0
  36. htvl_lang-0.2.0/tests/test_templates.py +49 -0
  37. htvl_lang-0.2.0/tests/test_variables.py +39 -0
  38. htvl_lang-0.2.0/tests/test_watch.py +219 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2020-2026 Nicholas Rotich and HTVL contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,264 @@
1
+ Metadata-Version: 2.4
2
+ Name: htvl-lang
3
+ Version: 0.2.0
4
+ Summary: HTVL - a tiny HTML transpiler: write .htvl files, get HTML.
5
+ Author: Nicholas Rotich, HTVL contributors
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/moinonin/htvl
8
+ Project-URL: Repository, https://github.com/moinonin/htvl
9
+ Project-URL: Bug Tracker, https://github.com/moinonin/htvl/issues
10
+ Project-URL: Changelog, https://github.com/moinonin/htvl/releases
11
+ Keywords: html,transpiler,static-site,compiler,dsl
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Intended Audience :: End Users/Desktop
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Topic :: Software Development :: Compilers
23
+ Classifier: Topic :: Text Processing :: Markup :: HTML
24
+ Requires-Python: >=3.10
25
+ Description-Content-Type: text/markdown
26
+ License-File: LICENSE
27
+ Provides-Extra: dev
28
+ Requires-Dist: pytest>=7; extra == "dev"
29
+ Requires-Dist: pygments>=2.10; extra == "dev"
30
+ Dynamic: license-file
31
+
32
+ # HTVL — a tiny HTML transpiler
33
+
34
+ [![tests](https://github.com/moinonin/htvl/actions/workflows/tests.yml/badge.svg)](https://github.com/moinonin/htvl/actions/workflows/tests.yml)
35
+
36
+ Write short tag calls in `.htvl` files, get plain HTML out. No build step, no
37
+ dependencies, no framework — just a small, well-tested compiler you can read
38
+ in an afternoon.
39
+
40
+ ```text
41
+ $(h 1 '' '' 'Hello HTVL' '')
42
+ ```
43
+
44
+ compiles to
45
+
46
+ ```html
47
+ <h1 class="" id="" style="">Hello HTVL</h1>
48
+ ```
49
+
50
+ ## Install
51
+
52
+ ```bash
53
+ pip install . # from a clone of this repository
54
+ ```
55
+
56
+ or run it straight from the checkout with zero installation:
57
+
58
+ ```bash
59
+ python3 -m htvl compile
60
+ ```
61
+
62
+ Python 3.10+, standard library only.
63
+
64
+ ## Quickstart
65
+
66
+ ```bash
67
+ htvl new mysite # scaffold: index.htvl, templates/, assets/
68
+ cd mysite
69
+ htvl compile # writes public/index.html and copies assets/
70
+ ```
71
+
72
+ A minimal project:
73
+
74
+ ```text
75
+ mysite/
76
+ ├── index.htvl
77
+ ├── templates/
78
+ │ └── headtags.htvl
79
+ └── assets/
80
+ ```
81
+
82
+ `index.htvl`:
83
+
84
+ ```text
85
+ $DOCTYPE_htvl
86
+ $htvl
87
+ $head
88
+ $headtags
89
+ $_head
90
+ $body
91
+ $(nav 'navbar navbar-expand-md bg-dark navbar-dark')
92
+ $(a 'navbar-brand' './' 'Home' '' '' '' '')$_a
93
+ $(ul 'navbar-nav')
94
+ $_ul
95
+ $_nav
96
+
97
+ $(div 'container')
98
+ $(h 1 '' '' 'Hello HTVL' '')
99
+ $(p '' '' 'This page was compiled by the HTVL compiler.' '')
100
+ $_p
101
+ $_div
102
+ $_body
103
+ $_htvl
104
+ ```
105
+
106
+ `templates/headtags.htvl`:
107
+
108
+ ```text
109
+ $(title '' 'My HTVL page')
110
+ $meta
111
+ ```
112
+
113
+ Then `htvl compile` produces `public/index.html`.
114
+
115
+ ## Commands
116
+
117
+ | Command | What it does |
118
+ | --- | --- |
119
+ | `htvl compile [path] [-o DIR] [--modern] [-w]` | Compile every `.htvl` file in `path` (default `.`) into `public/`; `.cal` files become CGI scripts in `cal/`; `assets/` is copied automatically. `--modern` emits clean, escaped HTML; `-w`/`--watch` keeps running and recompiles on change. |
120
+ | `htvl check FILE... [--modern]` | Compile a single file to stdout — great for scripting and debugging. |
121
+ | `htvl new NAME` | Scaffold a new project. |
122
+ | `htvl list` | Print every tag signature and built-in variable. |
123
+
124
+ ### Legacy vs modern output
125
+
126
+ The default output is byte-identical to the original 2020 compiler (empty
127
+ attributes and all, guarded by `tests/test_golden.py`). For new projects, pass
128
+ `--modern` to get clean HTML: empty attributes omitted, text escaped, no
129
+ cosmetic quirks. Same source files, same line structure — only the rendering
130
+ changes:
131
+
132
+ ```text
133
+ $(div 'container') legacy: <div class="container" id="" style="">
134
+ modern: <div class="container">
135
+ ```
136
+
137
+ ### Watch mode
138
+
139
+ ```bash
140
+ htvl compile --watch # or: htvl compile -w
141
+ ```
142
+
143
+ Compiles once, then keeps the output up to date as you edit:
144
+
145
+ ```text
146
+ htvl: compiled public/index.html
147
+ htvl: copied assets -> public/assets
148
+ htvl: watching '/sites/mysite' (Ctrl-C to stop)
149
+ htvl: compiled public/index.html <- you saved index.htvl
150
+ htvl: removed public/index.html <- you deleted index.htvl
151
+ htvl: stopped
152
+ ```
153
+
154
+ Edits are incremental: changing `index.htvl` recompiles that file, changing
155
+ anything in `templates/` rebuilds the project, changing `assets/` re-copies
156
+ it, and deleting a source removes its output. A broken edit (an unknown tag,
157
+ say) is reported but does not stop the watcher — fix the file and it picks up
158
+ where it left off. No dependencies: it polls the filesystem a few times a
159
+ second.
160
+
161
+ Errors include the file, line and column, e.g.
162
+ `htvl: error: unknown tag 'dvi' (line 12). Run 'htvl list' to see every available tag.`
163
+
164
+ ## The language
165
+
166
+ * `$(tag 'arg' ...)` — tag calls, arguments are quoted strings (or bare words),
167
+ nesting allowed: `$(link stylesheet 'text/css' $(bsCdn '4.3.1'))`
168
+ * `$name` — variables such as `$head`, `$_a`, `$meta`, and your own templates
169
+ (`$headtags`)
170
+ * `$_name` — explicit closing tags
171
+ * One source line = one output line; your indentation is your HTML's
172
+ indentation.
173
+
174
+ The full reference — every tag signature, the variables, templates, CGI
175
+ support — is in [docs/grammar.md](https://github.com/moinonin/htvl/blob/master/docs/grammar.md).
176
+
177
+ ### Editor support
178
+
179
+ * **VS Code** — the extension lives in [`editors/vscode/`](https://github.com/moinonin/htvl/blob/master/editors/vscode):
180
+ ```bash
181
+ cd editors/vscode
182
+ npx @vscode/vsce package && code --install-extension htvl-*.vsix
183
+ ```
184
+ It highlights tag calls, variables (`$head`, `$_a`), quoted/bare arguments,
185
+ nested calls and HTML comments, and it is set up for comment blocks and
186
+ indentation-based folding.
187
+ * **Anything Pygments-based** (Sphinx, MkDocs, code renderers) — a Pygments
188
+ lexer ships in [`extras/pygments_htvl.py`](https://github.com/moinonin/htvl/blob/master/extras/pygments_htvl.py):
189
+ ```python
190
+ from pygments.lexers import LEXERS
191
+ LEXERS["htvl"] = (
192
+ "pygments_htvl", "HTVL", ("htvl",), ("*.htvl", "*.cal"), ()
193
+ )
194
+ ```
195
+ Both are covered by the test suite.
196
+
197
+ ### Try it in the browser
198
+
199
+ [`playground/`](https://github.com/moinonin/htvl/blob/master/playground) is a fully static, server-free playground: the
200
+ page loads the **real Python compiler** compiled to WebAssembly with
201
+ [Pyodide](https://pyodide.org) and compiles as you type, with a legacy/modern
202
+ toggle. Open it from any static host:
203
+
204
+ ```bash
205
+ python3 -m http.server 8000 --directory playground
206
+ ```
207
+
208
+ ## Using it as a library
209
+
210
+ ```python
211
+ from htvl import compile_source
212
+
213
+ html = compile_source("$(h 1 '' '' 'Hello' ')\n")
214
+ ```
215
+
216
+ ## About this repository
217
+
218
+ HTVL started in 2020 as a two-line obfuscated bash script that generated HTML
219
+ by `eval`-ing heredocs, complete with a 90-day trial timer that required
220
+ `sudo`. That prototype is preserved untouched in [`legacy/`](https://github.com/moinonin/htvl/blob/master/legacy) — see
221
+ [`legacy/README.original.md`](https://github.com/moinonin/htvl/blob/master/legacy/README.original.md) for the original
222
+ documentation — together with a
223
+ [de-obfuscated copy of its compiler](https://github.com/moinonin/htvl/blob/master/docs/recovered-legacy-compiler.sh) that
224
+ serves as the authoritative definition of the grammar.
225
+
226
+ This repository is the second act: the same language, reimplemented in Python
227
+ as a readable, testable, dependency-free compiler:
228
+
229
+ * `htvl/lexer.py` → `htvl/parser.py` → `htvl/elements.py` →
230
+ `htvl/emitter.py` — a classic tokenize / parse / render pipeline you can
231
+ actually read
232
+ * the trial timer, the `sudo` asset copy and the silent failure modes are
233
+ gone; errors now name the line and column
234
+ * `tests/test_golden.py` proves the port reproduces the original 2020 output
235
+ **byte for byte**, so existing `.htvl` files and `templates/*.sh` keep
236
+ working unchanged
237
+
238
+ ### Development
239
+
240
+ ```bash
241
+ pip install -e ".[dev]" # compiler + pytest + pygments (for the lexer tests)
242
+ python3 -m pytest # 136 tests, including the golden test
243
+ ```
244
+
245
+ CI runs the suite on every push and PR: all supported Python versions
246
+ (3.10–3.13) on Linux, spot-checks on macOS and Windows, and a packaging job
247
+ that builds a wheel, installs it, and compiles a scaffolded project
248
+ (`.github/workflows/tests.yml`).
249
+
250
+ Release notes for v0.2.0 are in [docs/releases/v0.2.0.md](https://github.com/moinonin/htvl/blob/master/docs/releases/v0.2.0.md).
251
+
252
+ ### Roadmap
253
+
254
+ * an opt-in `--modern` mode that fixes the documented `[legacy]` output
255
+ quirks (no empty attributes, proper escaping, real `role` support)
256
+ * ~~watch mode and incremental builds~~ — **done in v0.2.0** (`htvl compile --watch`)
257
+ * ~~syntax highlighting for `.htvl` files~~ — **done in v0.2.0** (VS Code
258
+ extension in `editors/vscode/`, Pygments lexer in `extras/`)
259
+ * ~~a playground on the documentation site~~ — **done in v0.2.0**
260
+ (`playground/`, the real compiler running in-browser via Pyodide)
261
+
262
+ ## License
263
+
264
+ MIT — see [LICENSE](https://github.com/moinonin/htvl/blob/master/LICENSE).
@@ -0,0 +1,233 @@
1
+ # HTVL — a tiny HTML transpiler
2
+
3
+ [![tests](https://github.com/moinonin/htvl/actions/workflows/tests.yml/badge.svg)](https://github.com/moinonin/htvl/actions/workflows/tests.yml)
4
+
5
+ Write short tag calls in `.htvl` files, get plain HTML out. No build step, no
6
+ dependencies, no framework — just a small, well-tested compiler you can read
7
+ in an afternoon.
8
+
9
+ ```text
10
+ $(h 1 '' '' 'Hello HTVL' '')
11
+ ```
12
+
13
+ compiles to
14
+
15
+ ```html
16
+ <h1 class="" id="" style="">Hello HTVL</h1>
17
+ ```
18
+
19
+ ## Install
20
+
21
+ ```bash
22
+ pip install . # from a clone of this repository
23
+ ```
24
+
25
+ or run it straight from the checkout with zero installation:
26
+
27
+ ```bash
28
+ python3 -m htvl compile
29
+ ```
30
+
31
+ Python 3.10+, standard library only.
32
+
33
+ ## Quickstart
34
+
35
+ ```bash
36
+ htvl new mysite # scaffold: index.htvl, templates/, assets/
37
+ cd mysite
38
+ htvl compile # writes public/index.html and copies assets/
39
+ ```
40
+
41
+ A minimal project:
42
+
43
+ ```text
44
+ mysite/
45
+ ├── index.htvl
46
+ ├── templates/
47
+ │ └── headtags.htvl
48
+ └── assets/
49
+ ```
50
+
51
+ `index.htvl`:
52
+
53
+ ```text
54
+ $DOCTYPE_htvl
55
+ $htvl
56
+ $head
57
+ $headtags
58
+ $_head
59
+ $body
60
+ $(nav 'navbar navbar-expand-md bg-dark navbar-dark')
61
+ $(a 'navbar-brand' './' 'Home' '' '' '' '')$_a
62
+ $(ul 'navbar-nav')
63
+ $_ul
64
+ $_nav
65
+
66
+ $(div 'container')
67
+ $(h 1 '' '' 'Hello HTVL' '')
68
+ $(p '' '' 'This page was compiled by the HTVL compiler.' '')
69
+ $_p
70
+ $_div
71
+ $_body
72
+ $_htvl
73
+ ```
74
+
75
+ `templates/headtags.htvl`:
76
+
77
+ ```text
78
+ $(title '' 'My HTVL page')
79
+ $meta
80
+ ```
81
+
82
+ Then `htvl compile` produces `public/index.html`.
83
+
84
+ ## Commands
85
+
86
+ | Command | What it does |
87
+ | --- | --- |
88
+ | `htvl compile [path] [-o DIR] [--modern] [-w]` | Compile every `.htvl` file in `path` (default `.`) into `public/`; `.cal` files become CGI scripts in `cal/`; `assets/` is copied automatically. `--modern` emits clean, escaped HTML; `-w`/`--watch` keeps running and recompiles on change. |
89
+ | `htvl check FILE... [--modern]` | Compile a single file to stdout — great for scripting and debugging. |
90
+ | `htvl new NAME` | Scaffold a new project. |
91
+ | `htvl list` | Print every tag signature and built-in variable. |
92
+
93
+ ### Legacy vs modern output
94
+
95
+ The default output is byte-identical to the original 2020 compiler (empty
96
+ attributes and all, guarded by `tests/test_golden.py`). For new projects, pass
97
+ `--modern` to get clean HTML: empty attributes omitted, text escaped, no
98
+ cosmetic quirks. Same source files, same line structure — only the rendering
99
+ changes:
100
+
101
+ ```text
102
+ $(div 'container') legacy: <div class="container" id="" style="">
103
+ modern: <div class="container">
104
+ ```
105
+
106
+ ### Watch mode
107
+
108
+ ```bash
109
+ htvl compile --watch # or: htvl compile -w
110
+ ```
111
+
112
+ Compiles once, then keeps the output up to date as you edit:
113
+
114
+ ```text
115
+ htvl: compiled public/index.html
116
+ htvl: copied assets -> public/assets
117
+ htvl: watching '/sites/mysite' (Ctrl-C to stop)
118
+ htvl: compiled public/index.html <- you saved index.htvl
119
+ htvl: removed public/index.html <- you deleted index.htvl
120
+ htvl: stopped
121
+ ```
122
+
123
+ Edits are incremental: changing `index.htvl` recompiles that file, changing
124
+ anything in `templates/` rebuilds the project, changing `assets/` re-copies
125
+ it, and deleting a source removes its output. A broken edit (an unknown tag,
126
+ say) is reported but does not stop the watcher — fix the file and it picks up
127
+ where it left off. No dependencies: it polls the filesystem a few times a
128
+ second.
129
+
130
+ Errors include the file, line and column, e.g.
131
+ `htvl: error: unknown tag 'dvi' (line 12). Run 'htvl list' to see every available tag.`
132
+
133
+ ## The language
134
+
135
+ * `$(tag 'arg' ...)` — tag calls, arguments are quoted strings (or bare words),
136
+ nesting allowed: `$(link stylesheet 'text/css' $(bsCdn '4.3.1'))`
137
+ * `$name` — variables such as `$head`, `$_a`, `$meta`, and your own templates
138
+ (`$headtags`)
139
+ * `$_name` — explicit closing tags
140
+ * One source line = one output line; your indentation is your HTML's
141
+ indentation.
142
+
143
+ The full reference — every tag signature, the variables, templates, CGI
144
+ support — is in [docs/grammar.md](https://github.com/moinonin/htvl/blob/master/docs/grammar.md).
145
+
146
+ ### Editor support
147
+
148
+ * **VS Code** — the extension lives in [`editors/vscode/`](https://github.com/moinonin/htvl/blob/master/editors/vscode):
149
+ ```bash
150
+ cd editors/vscode
151
+ npx @vscode/vsce package && code --install-extension htvl-*.vsix
152
+ ```
153
+ It highlights tag calls, variables (`$head`, `$_a`), quoted/bare arguments,
154
+ nested calls and HTML comments, and it is set up for comment blocks and
155
+ indentation-based folding.
156
+ * **Anything Pygments-based** (Sphinx, MkDocs, code renderers) — a Pygments
157
+ lexer ships in [`extras/pygments_htvl.py`](https://github.com/moinonin/htvl/blob/master/extras/pygments_htvl.py):
158
+ ```python
159
+ from pygments.lexers import LEXERS
160
+ LEXERS["htvl"] = (
161
+ "pygments_htvl", "HTVL", ("htvl",), ("*.htvl", "*.cal"), ()
162
+ )
163
+ ```
164
+ Both are covered by the test suite.
165
+
166
+ ### Try it in the browser
167
+
168
+ [`playground/`](https://github.com/moinonin/htvl/blob/master/playground) is a fully static, server-free playground: the
169
+ page loads the **real Python compiler** compiled to WebAssembly with
170
+ [Pyodide](https://pyodide.org) and compiles as you type, with a legacy/modern
171
+ toggle. Open it from any static host:
172
+
173
+ ```bash
174
+ python3 -m http.server 8000 --directory playground
175
+ ```
176
+
177
+ ## Using it as a library
178
+
179
+ ```python
180
+ from htvl import compile_source
181
+
182
+ html = compile_source("$(h 1 '' '' 'Hello' ')\n")
183
+ ```
184
+
185
+ ## About this repository
186
+
187
+ HTVL started in 2020 as a two-line obfuscated bash script that generated HTML
188
+ by `eval`-ing heredocs, complete with a 90-day trial timer that required
189
+ `sudo`. That prototype is preserved untouched in [`legacy/`](https://github.com/moinonin/htvl/blob/master/legacy) — see
190
+ [`legacy/README.original.md`](https://github.com/moinonin/htvl/blob/master/legacy/README.original.md) for the original
191
+ documentation — together with a
192
+ [de-obfuscated copy of its compiler](https://github.com/moinonin/htvl/blob/master/docs/recovered-legacy-compiler.sh) that
193
+ serves as the authoritative definition of the grammar.
194
+
195
+ This repository is the second act: the same language, reimplemented in Python
196
+ as a readable, testable, dependency-free compiler:
197
+
198
+ * `htvl/lexer.py` → `htvl/parser.py` → `htvl/elements.py` →
199
+ `htvl/emitter.py` — a classic tokenize / parse / render pipeline you can
200
+ actually read
201
+ * the trial timer, the `sudo` asset copy and the silent failure modes are
202
+ gone; errors now name the line and column
203
+ * `tests/test_golden.py` proves the port reproduces the original 2020 output
204
+ **byte for byte**, so existing `.htvl` files and `templates/*.sh` keep
205
+ working unchanged
206
+
207
+ ### Development
208
+
209
+ ```bash
210
+ pip install -e ".[dev]" # compiler + pytest + pygments (for the lexer tests)
211
+ python3 -m pytest # 136 tests, including the golden test
212
+ ```
213
+
214
+ CI runs the suite on every push and PR: all supported Python versions
215
+ (3.10–3.13) on Linux, spot-checks on macOS and Windows, and a packaging job
216
+ that builds a wheel, installs it, and compiles a scaffolded project
217
+ (`.github/workflows/tests.yml`).
218
+
219
+ Release notes for v0.2.0 are in [docs/releases/v0.2.0.md](https://github.com/moinonin/htvl/blob/master/docs/releases/v0.2.0.md).
220
+
221
+ ### Roadmap
222
+
223
+ * an opt-in `--modern` mode that fixes the documented `[legacy]` output
224
+ quirks (no empty attributes, proper escaping, real `role` support)
225
+ * ~~watch mode and incremental builds~~ — **done in v0.2.0** (`htvl compile --watch`)
226
+ * ~~syntax highlighting for `.htvl` files~~ — **done in v0.2.0** (VS Code
227
+ extension in `editors/vscode/`, Pygments lexer in `extras/`)
228
+ * ~~a playground on the documentation site~~ — **done in v0.2.0**
229
+ (`playground/`, the real compiler running in-browser via Pyodide)
230
+
231
+ ## License
232
+
233
+ MIT — see [LICENSE](https://github.com/moinonin/htvl/blob/master/LICENSE).
@@ -0,0 +1,44 @@
1
+ """HTVL - a tiny HTML transpiler.
2
+
3
+ Public API::
4
+
5
+ from htvl import compile_source, compile_file, compile_project
6
+
7
+ html = compile_source("$(h 1 '' '' 'Hello' '')")
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ from .emitter import Emitter, emit
13
+ from .errors import (
14
+ HtvlArityError,
15
+ HtvlError,
16
+ HtvlSyntaxError,
17
+ HtvlUnknownTagError,
18
+ HtvlUnknownVariableError,
19
+ )
20
+ from .parser import parse
21
+ from .project import (
22
+ CompileResult,
23
+ compile_file,
24
+ compile_project,
25
+ compile_source,
26
+ )
27
+
28
+ __version__ = "0.2.0"
29
+
30
+ __all__ = [
31
+ "__version__",
32
+ "compile_source",
33
+ "compile_file",
34
+ "compile_project",
35
+ "CompileResult",
36
+ "parse",
37
+ "emit",
38
+ "Emitter",
39
+ "HtvlError",
40
+ "HtvlSyntaxError",
41
+ "HtvlUnknownTagError",
42
+ "HtvlUnknownVariableError",
43
+ "HtvlArityError",
44
+ ]
@@ -0,0 +1,8 @@
1
+ """Entry point for ``python -m htvl``."""
2
+
3
+ import sys
4
+
5
+ from .cli import main
6
+
7
+ if __name__ == "__main__":
8
+ sys.exit(main())