htmldeck 0.1.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.
- htmldeck-0.1.0/LICENSE +21 -0
- htmldeck-0.1.0/PKG-INFO +163 -0
- htmldeck-0.1.0/README.md +135 -0
- htmldeck-0.1.0/htmldeck/__init__.py +0 -0
- htmldeck-0.1.0/htmldeck/__main__.py +4 -0
- htmldeck-0.1.0/htmldeck/notes.py +86 -0
- htmldeck-0.1.0/htmldeck/server.py +739 -0
- htmldeck-0.1.0/htmldeck/web/css/editor.css +474 -0
- htmldeck-0.1.0/htmldeck/web/index.html +449 -0
- htmldeck-0.1.0/htmldeck/web/js/app.mjs +4161 -0
- htmldeck-0.1.0/htmldeck/web/js/core/history.mjs +38 -0
- htmldeck-0.1.0/htmldeck/web/js/core/model.mjs +46 -0
- htmldeck-0.1.0/htmldeck/web/js/core/operations.mjs +62 -0
- htmldeck-0.1.0/htmldeck/web/js/core/sanitize.mjs +11 -0
- htmldeck-0.1.0/htmldeck/web/js/core/serializer.mjs +216 -0
- htmldeck-0.1.0/htmldeck/web/js/core/utils.mjs +25 -0
- htmldeck-0.1.0/htmldeck/web/js/formats/registry.mjs +15 -0
- htmldeck-0.1.0/htmldeck/web/js/formats/reveal.mjs +139 -0
- htmldeck-0.1.0/htmldeck/web/js/fx/runtime.mjs +326 -0
- htmldeck-0.1.0/htmldeck/web/js/i18n.mjs +1227 -0
- htmldeck-0.1.0/htmldeck/web/js/policy/edit-policy.mjs +32 -0
- htmldeck-0.1.0/htmldeck/web/js/present/render.mjs +200 -0
- htmldeck-0.1.0/htmldeck/web/js/present/session.mjs +72 -0
- htmldeck-0.1.0/htmldeck/web/js/runtime/freeze.mjs +37 -0
- htmldeck-0.1.0/htmldeck/web/js/runtime/provenance.mjs +49 -0
- htmldeck-0.1.0/htmldeck/web/js/services/api.mjs +10 -0
- htmldeck-0.1.0/htmldeck.egg-info/PKG-INFO +163 -0
- htmldeck-0.1.0/htmldeck.egg-info/SOURCES.txt +38 -0
- htmldeck-0.1.0/htmldeck.egg-info/dependency_links.txt +1 -0
- htmldeck-0.1.0/htmldeck.egg-info/entry_points.txt +3 -0
- htmldeck-0.1.0/htmldeck.egg-info/requires.txt +5 -0
- htmldeck-0.1.0/htmldeck.egg-info/top_level.txt +1 -0
- htmldeck-0.1.0/pyproject.toml +56 -0
- htmldeck-0.1.0/setup.cfg +4 -0
- htmldeck-0.1.0/tests/test_launcher.py +93 -0
- htmldeck-0.1.0/tests/test_npm.py +29 -0
- htmldeck-0.1.0/tests/test_packaging.py +29 -0
- htmldeck-0.1.0/tests/test_plugin.py +87 -0
- htmldeck-0.1.0/tests/test_portability.py +111 -0
- htmldeck-0.1.0/tests/test_server.py +363 -0
htmldeck-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Avis
|
|
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.
|
htmldeck-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: htmldeck
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Edit and present the HTML documents (decks, reports, pages) of a workspace — in place, without rewriting the file.
|
|
5
|
+
Author-email: Avis <hunganh.freeze@gmail.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/avis309/html-deck
|
|
8
|
+
Project-URL: Repository, https://github.com/avis309/html-deck
|
|
9
|
+
Project-URL: Issues, https://github.com/avis309/html-deck/issues
|
|
10
|
+
Keywords: html,slides,presentation,editor,reveal.js,claude-code,codex
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Environment :: Web Environment
|
|
13
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: Multimedia :: Graphics :: Presentation
|
|
20
|
+
Requires-Python: >=3.11
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
Provides-Extra: dev
|
|
24
|
+
Requires-Dist: pytest>=8; extra == "dev"
|
|
25
|
+
Requires-Dist: ruff>=0.5; extra == "dev"
|
|
26
|
+
Requires-Dist: build>=1; extra == "dev"
|
|
27
|
+
Dynamic: license-file
|
|
28
|
+
|
|
29
|
+
<div align="center">
|
|
30
|
+
|
|
31
|
+
# HTML Deck
|
|
32
|
+
|
|
33
|
+
**A visual editor for the HTML files in your workspace: slide decks, reports, and pages written by
|
|
34
|
+
you or by an AI agent.**
|
|
35
|
+
|
|
36
|
+
Click text to edit it, restyle it, move blocks, add effects and present. The file is patched
|
|
37
|
+
**only where you changed it**, so a save with no edits is byte-identical.
|
|
38
|
+
|
|
39
|
+
[](https://github.com/avis309/html-deck/actions/workflows/ci.yml)
|
|
40
|
+
[](https://pypi.org/project/htmldeck/)
|
|
41
|
+
[](https://www.npmjs.com/package/@avis309/htmldeck)
|
|
42
|
+
[](https://www.python.org/downloads/)
|
|
43
|
+
[](LICENSE)
|
|
44
|
+
|
|
45
|
+
<img src="https://raw.githubusercontent.com/avis309/html-deck/main/.github/assets/edit.png" alt="Editing a slide title in HTML Deck" width="900">
|
|
46
|
+
|
|
47
|
+
</div>
|
|
48
|
+
|
|
49
|
+
## Why
|
|
50
|
+
|
|
51
|
+
- **Edits stay minimal.** HTML Deck patches the source text where you made a change and leaves
|
|
52
|
+
everything else as it was, including formatting, comments and the agent's own markup. That keeps
|
|
53
|
+
diffs small and reviewable.
|
|
54
|
+
- **Works with your agent.** Pin a note on any element ("make this shorter"), then ask Claude Code
|
|
55
|
+
or Codex to apply your HTML Deck notes. The agent reads them, edits the HTML and marks them done.
|
|
56
|
+
- **Presents the real thing.** Presentation runs the deck's own scripts and animations in a
|
|
57
|
+
separate frame, so presenting never touches the document you are editing.
|
|
58
|
+
- **Local and dependency-free.** One Python 3.11+ standard-library server on `127.0.0.1`. Nothing
|
|
59
|
+
leaves your machine.
|
|
60
|
+
|
|
61
|
+
<table>
|
|
62
|
+
<tr>
|
|
63
|
+
<td width="50%"><img src="https://raw.githubusercontent.com/avis309/html-deck/main/.github/assets/feedback.png" alt="AI Feedback panel with a pinned note"></td>
|
|
64
|
+
<td width="50%"><img src="https://raw.githubusercontent.com/avis309/html-deck/main/.github/assets/present.png" alt="Presenting a deck"></td>
|
|
65
|
+
</tr>
|
|
66
|
+
<tr>
|
|
67
|
+
<td align="center"><b>AI Feedback</b>: pin notes for your agent</td>
|
|
68
|
+
<td align="center"><b>Present</b> with the deck's own animations</td>
|
|
69
|
+
</tr>
|
|
70
|
+
</table>
|
|
71
|
+
|
|
72
|
+
## Install
|
|
73
|
+
|
|
74
|
+
| Where | Command |
|
|
75
|
+
|---|---|
|
|
76
|
+
| Claude Code | `/plugin marketplace add avis309/html-deck` then `/plugin install htmldeck@htmldeck` |
|
|
77
|
+
| Codex | `codex plugin marketplace add avis309/html-deck` then `codex plugin add htmldeck@htmldeck` |
|
|
78
|
+
| uv | `uvx htmldeck` (one-off) · `uv tool install htmldeck` |
|
|
79
|
+
| pipx / pip | `pipx install htmldeck` · `pip install htmldeck` |
|
|
80
|
+
| npm | `npx @avis309/htmldeck` (one-off) · `npm i -g @avis309/htmldeck` |
|
|
81
|
+
|
|
82
|
+
HTML Deck needs Python 3.11+ and nothing else. The npm package and the plugins find Python and run
|
|
83
|
+
it for you. It works on Linux, macOS and Windows.
|
|
84
|
+
|
|
85
|
+
## Use it with an agent
|
|
86
|
+
|
|
87
|
+
In Claude Code or Codex:
|
|
88
|
+
|
|
89
|
+
1. Ask the agent to *"open slides/q3.html in HTML Deck"*. Claude Code also has `/htmldeck [file]`.
|
|
90
|
+
2. Edit in the browser, and pin **AI Feedback** notes where you want the agent to change something.
|
|
91
|
+
3. Ask the agent to *"apply my HTML Deck notes"*.
|
|
92
|
+
|
|
93
|
+
## Run it yourself
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
cd ~/my-workspace
|
|
97
|
+
htmldeck # workspace = current folder
|
|
98
|
+
htmldeck --file decks/q3.html # open a document first
|
|
99
|
+
htmldeck --root ~/my-workspace --port 8765 --no-browser
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
To try it on the sample deck from the screenshots (24 slides with anime.js scenes) in a clone of
|
|
103
|
+
this repo, run `htmldeck --root samples --file ai-foundation-deck.html`.
|
|
104
|
+
|
|
105
|
+
The workspace is the folder HTML Deck runs in, or the folder given with `--root`. Every path is
|
|
106
|
+
relative to it, and nothing outside it is served or written, except the file passed with `--file`.
|
|
107
|
+
Each save keeps a timestamped backup in `.htmldeck_bak/` next to the document.
|
|
108
|
+
|
|
109
|
+
Review notes live beside each document in `.htmldeck_notes/<name>.json`. Scripts and agents read
|
|
110
|
+
and resolve them with:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
htmldeck-notes --file decks/q3.html # list open notes
|
|
114
|
+
htmldeck-notes --file decks/q3.html --done ID # mark one done
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## What it supports
|
|
118
|
+
|
|
119
|
+
- **Formats:** plain HTML pages and reports; decks of `.slide` blocks; hand-written Reveal.js
|
|
120
|
+
decks, including vertical stacks, fragments, notes and backgrounds. Reveal's Markdown slides
|
|
121
|
+
are read-only.
|
|
122
|
+
- **Safe editing:** content that the page's own scripts create or change is locked, and the editor
|
|
123
|
+
shows why. Animations are frozen while editing. You also get undo/redo and draft recovery.
|
|
124
|
+
- **Effects:** set `data-fx` entrance effects (fade, zoom, slide, count-up) from the toolbar.
|
|
125
|
+
HTML Deck also manages *scenes*, the document's own animation code. "Enable FX in the file" adds a
|
|
126
|
+
small inline runtime, so effects still run when the file is opened on its own.
|
|
127
|
+
- **Isolation:** presentations run on a second origin that has no access to the editor's API. The
|
|
128
|
+
edit view blocks remote scripts (from a CDN, for example) unless you trust the file. Workspace
|
|
129
|
+
files opened directly on the editor origin are sandboxed.
|
|
130
|
+
|
|
131
|
+
<details>
|
|
132
|
+
<summary><b>Develop</b></summary>
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
python3 -m venv .venv && .venv/bin/pip install -e '.[dev]'
|
|
136
|
+
npm install
|
|
137
|
+
npm run check # eslint (editor modules) + pytest (server) + browser spec
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
- `htmldeck/server.py`: HTTP server, workspace guards, save/backup/notes API, preview origin.
|
|
141
|
+
- `htmldeck/web/`: the editor, as native ES modules with no bundler. `js/core` holds the model,
|
|
142
|
+
serializer and history; `js/runtime` holds provenance and motion freeze; also `js/policy`,
|
|
143
|
+
`js/formats` (Reveal), `js/present` and `js/fx` (the effects runtime, which is also inlined
|
|
144
|
+
into documents).
|
|
145
|
+
- `tests/spec/characterization.spec.mjs`: black-box Playwright spec over fixtures in a temporary
|
|
146
|
+
workspace. To run it on another workspace's files too:
|
|
147
|
+
`HTMLDECK_REAL_ROOT=… HTMLDECK_REAL_FILES="a.html,b.html" npm run spec`.
|
|
148
|
+
- `tools/align-report.mjs`: `npm run align -- <workspace>` reports what share of a workspace's
|
|
149
|
+
HTML files save as an in-place patch. The rest still save correctly, through a full rewrite that
|
|
150
|
+
the editor asks you to confirm.
|
|
151
|
+
- Plugin: `.claude-plugin/`, `.codex-plugin/`, `.agents/plugins/` (marketplaces),
|
|
152
|
+
`skills/htmldeck/`, `commands/`, and `scripts/htmldeck-run[.cmd]`, which runs this copy with any
|
|
153
|
+
Python 3.11+.
|
|
154
|
+
- npm wrapper: `packaging/npm/` bundles `htmldeck/` at pack time and runs it with the user's
|
|
155
|
+
Python.
|
|
156
|
+
- Release: run `python tools/bump_version.py X.Y.Z`, commit, then tag `vX.Y.Z` and push the tag.
|
|
157
|
+
`.github/workflows/release.yml` publishes to PyPI, then npm, then creates the GitHub Release.
|
|
158
|
+
|
|
159
|
+
</details>
|
|
160
|
+
|
|
161
|
+
## License
|
|
162
|
+
|
|
163
|
+
[MIT](LICENSE) © Avis
|
htmldeck-0.1.0/README.md
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# HTML Deck
|
|
4
|
+
|
|
5
|
+
**A visual editor for the HTML files in your workspace: slide decks, reports, and pages written by
|
|
6
|
+
you or by an AI agent.**
|
|
7
|
+
|
|
8
|
+
Click text to edit it, restyle it, move blocks, add effects and present. The file is patched
|
|
9
|
+
**only where you changed it**, so a save with no edits is byte-identical.
|
|
10
|
+
|
|
11
|
+
[](https://github.com/avis309/html-deck/actions/workflows/ci.yml)
|
|
12
|
+
[](https://pypi.org/project/htmldeck/)
|
|
13
|
+
[](https://www.npmjs.com/package/@avis309/htmldeck)
|
|
14
|
+
[](https://www.python.org/downloads/)
|
|
15
|
+
[](LICENSE)
|
|
16
|
+
|
|
17
|
+
<img src="https://raw.githubusercontent.com/avis309/html-deck/main/.github/assets/edit.png" alt="Editing a slide title in HTML Deck" width="900">
|
|
18
|
+
|
|
19
|
+
</div>
|
|
20
|
+
|
|
21
|
+
## Why
|
|
22
|
+
|
|
23
|
+
- **Edits stay minimal.** HTML Deck patches the source text where you made a change and leaves
|
|
24
|
+
everything else as it was, including formatting, comments and the agent's own markup. That keeps
|
|
25
|
+
diffs small and reviewable.
|
|
26
|
+
- **Works with your agent.** Pin a note on any element ("make this shorter"), then ask Claude Code
|
|
27
|
+
or Codex to apply your HTML Deck notes. The agent reads them, edits the HTML and marks them done.
|
|
28
|
+
- **Presents the real thing.** Presentation runs the deck's own scripts and animations in a
|
|
29
|
+
separate frame, so presenting never touches the document you are editing.
|
|
30
|
+
- **Local and dependency-free.** One Python 3.11+ standard-library server on `127.0.0.1`. Nothing
|
|
31
|
+
leaves your machine.
|
|
32
|
+
|
|
33
|
+
<table>
|
|
34
|
+
<tr>
|
|
35
|
+
<td width="50%"><img src="https://raw.githubusercontent.com/avis309/html-deck/main/.github/assets/feedback.png" alt="AI Feedback panel with a pinned note"></td>
|
|
36
|
+
<td width="50%"><img src="https://raw.githubusercontent.com/avis309/html-deck/main/.github/assets/present.png" alt="Presenting a deck"></td>
|
|
37
|
+
</tr>
|
|
38
|
+
<tr>
|
|
39
|
+
<td align="center"><b>AI Feedback</b>: pin notes for your agent</td>
|
|
40
|
+
<td align="center"><b>Present</b> with the deck's own animations</td>
|
|
41
|
+
</tr>
|
|
42
|
+
</table>
|
|
43
|
+
|
|
44
|
+
## Install
|
|
45
|
+
|
|
46
|
+
| Where | Command |
|
|
47
|
+
|---|---|
|
|
48
|
+
| Claude Code | `/plugin marketplace add avis309/html-deck` then `/plugin install htmldeck@htmldeck` |
|
|
49
|
+
| Codex | `codex plugin marketplace add avis309/html-deck` then `codex plugin add htmldeck@htmldeck` |
|
|
50
|
+
| uv | `uvx htmldeck` (one-off) · `uv tool install htmldeck` |
|
|
51
|
+
| pipx / pip | `pipx install htmldeck` · `pip install htmldeck` |
|
|
52
|
+
| npm | `npx @avis309/htmldeck` (one-off) · `npm i -g @avis309/htmldeck` |
|
|
53
|
+
|
|
54
|
+
HTML Deck needs Python 3.11+ and nothing else. The npm package and the plugins find Python and run
|
|
55
|
+
it for you. It works on Linux, macOS and Windows.
|
|
56
|
+
|
|
57
|
+
## Use it with an agent
|
|
58
|
+
|
|
59
|
+
In Claude Code or Codex:
|
|
60
|
+
|
|
61
|
+
1. Ask the agent to *"open slides/q3.html in HTML Deck"*. Claude Code also has `/htmldeck [file]`.
|
|
62
|
+
2. Edit in the browser, and pin **AI Feedback** notes where you want the agent to change something.
|
|
63
|
+
3. Ask the agent to *"apply my HTML Deck notes"*.
|
|
64
|
+
|
|
65
|
+
## Run it yourself
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
cd ~/my-workspace
|
|
69
|
+
htmldeck # workspace = current folder
|
|
70
|
+
htmldeck --file decks/q3.html # open a document first
|
|
71
|
+
htmldeck --root ~/my-workspace --port 8765 --no-browser
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
To try it on the sample deck from the screenshots (24 slides with anime.js scenes) in a clone of
|
|
75
|
+
this repo, run `htmldeck --root samples --file ai-foundation-deck.html`.
|
|
76
|
+
|
|
77
|
+
The workspace is the folder HTML Deck runs in, or the folder given with `--root`. Every path is
|
|
78
|
+
relative to it, and nothing outside it is served or written, except the file passed with `--file`.
|
|
79
|
+
Each save keeps a timestamped backup in `.htmldeck_bak/` next to the document.
|
|
80
|
+
|
|
81
|
+
Review notes live beside each document in `.htmldeck_notes/<name>.json`. Scripts and agents read
|
|
82
|
+
and resolve them with:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
htmldeck-notes --file decks/q3.html # list open notes
|
|
86
|
+
htmldeck-notes --file decks/q3.html --done ID # mark one done
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## What it supports
|
|
90
|
+
|
|
91
|
+
- **Formats:** plain HTML pages and reports; decks of `.slide` blocks; hand-written Reveal.js
|
|
92
|
+
decks, including vertical stacks, fragments, notes and backgrounds. Reveal's Markdown slides
|
|
93
|
+
are read-only.
|
|
94
|
+
- **Safe editing:** content that the page's own scripts create or change is locked, and the editor
|
|
95
|
+
shows why. Animations are frozen while editing. You also get undo/redo and draft recovery.
|
|
96
|
+
- **Effects:** set `data-fx` entrance effects (fade, zoom, slide, count-up) from the toolbar.
|
|
97
|
+
HTML Deck also manages *scenes*, the document's own animation code. "Enable FX in the file" adds a
|
|
98
|
+
small inline runtime, so effects still run when the file is opened on its own.
|
|
99
|
+
- **Isolation:** presentations run on a second origin that has no access to the editor's API. The
|
|
100
|
+
edit view blocks remote scripts (from a CDN, for example) unless you trust the file. Workspace
|
|
101
|
+
files opened directly on the editor origin are sandboxed.
|
|
102
|
+
|
|
103
|
+
<details>
|
|
104
|
+
<summary><b>Develop</b></summary>
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
python3 -m venv .venv && .venv/bin/pip install -e '.[dev]'
|
|
108
|
+
npm install
|
|
109
|
+
npm run check # eslint (editor modules) + pytest (server) + browser spec
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
- `htmldeck/server.py`: HTTP server, workspace guards, save/backup/notes API, preview origin.
|
|
113
|
+
- `htmldeck/web/`: the editor, as native ES modules with no bundler. `js/core` holds the model,
|
|
114
|
+
serializer and history; `js/runtime` holds provenance and motion freeze; also `js/policy`,
|
|
115
|
+
`js/formats` (Reveal), `js/present` and `js/fx` (the effects runtime, which is also inlined
|
|
116
|
+
into documents).
|
|
117
|
+
- `tests/spec/characterization.spec.mjs`: black-box Playwright spec over fixtures in a temporary
|
|
118
|
+
workspace. To run it on another workspace's files too:
|
|
119
|
+
`HTMLDECK_REAL_ROOT=… HTMLDECK_REAL_FILES="a.html,b.html" npm run spec`.
|
|
120
|
+
- `tools/align-report.mjs`: `npm run align -- <workspace>` reports what share of a workspace's
|
|
121
|
+
HTML files save as an in-place patch. The rest still save correctly, through a full rewrite that
|
|
122
|
+
the editor asks you to confirm.
|
|
123
|
+
- Plugin: `.claude-plugin/`, `.codex-plugin/`, `.agents/plugins/` (marketplaces),
|
|
124
|
+
`skills/htmldeck/`, `commands/`, and `scripts/htmldeck-run[.cmd]`, which runs this copy with any
|
|
125
|
+
Python 3.11+.
|
|
126
|
+
- npm wrapper: `packaging/npm/` bundles `htmldeck/` at pack time and runs it with the user's
|
|
127
|
+
Python.
|
|
128
|
+
- Release: run `python tools/bump_version.py X.Y.Z`, commit, then tag `vX.Y.Z` and push the tag.
|
|
129
|
+
`.github/workflows/release.yml` publishes to PyPI, then npm, then creates the GitHub Release.
|
|
130
|
+
|
|
131
|
+
</details>
|
|
132
|
+
|
|
133
|
+
## License
|
|
134
|
+
|
|
135
|
+
[MIT](LICENSE) © Avis
|
|
File without changes
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"""List (or resolve) review notes pinned in the HTML editor, for an agent to act on.
|
|
2
|
+
|
|
3
|
+
Notes live beside the document in ``.htmldeck_notes/<name>.json``. Each carries the CSS
|
|
4
|
+
selector of the element, the source line at the time it was pinned, and a text snippet;
|
|
5
|
+
this runner re-locates the line in the current file so it stays useful after edits.
|
|
6
|
+
|
|
7
|
+
Run (in the workspace, or with --root):
|
|
8
|
+
htmldeck-notes --file output/deck.html
|
|
9
|
+
htmldeck-notes --file output/deck.html --done <id>
|
|
10
|
+
(or python -m htmldeck.notes ...)
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import argparse
|
|
16
|
+
import sys
|
|
17
|
+
from pathlib import Path
|
|
18
|
+
|
|
19
|
+
from htmldeck.server import EditorError, apply_note_ops, display_path, notes_path, read_notes, utf8_stdio
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def current_line(source: str, note: dict) -> int | None:
|
|
23
|
+
"""Line of the note's snippet nearest to where it was pinned, else the pinned line."""
|
|
24
|
+
snippet = " ".join(note.get("text", "").split())[:40]
|
|
25
|
+
pinned = note.get("line")
|
|
26
|
+
lines = []
|
|
27
|
+
idx = source.find(snippet) if snippet else -1
|
|
28
|
+
while idx >= 0:
|
|
29
|
+
lines.append(source.count("\n", 0, idx) + 1)
|
|
30
|
+
idx = source.find(snippet, idx + 1)
|
|
31
|
+
if not lines:
|
|
32
|
+
return pinned
|
|
33
|
+
return min(lines, key=lambda n: abs(n - pinned)) if pinned else lines[0]
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def format_notes(target: Path, notes: list[dict], show_all: bool, root: Path | None = None) -> str:
|
|
37
|
+
root = root or Path.cwd()
|
|
38
|
+
source = target.read_text(encoding="utf-8") if target.is_file() else ""
|
|
39
|
+
shown = [n for n in notes if show_all or n.get("status") == "open"]
|
|
40
|
+
if not shown:
|
|
41
|
+
return f"Không có ghi chú {'nào' if show_all else 'đang mở'} cho {display_path(target, root)}."
|
|
42
|
+
lines = [f"# Ghi chú cần sửa — {display_path(target, root)} ({len(shown)})", ""]
|
|
43
|
+
for i, n in enumerate(shown, 1):
|
|
44
|
+
where = [f"dòng {current_line(source, n) or '?'}"]
|
|
45
|
+
if n.get("slide") is not None:
|
|
46
|
+
where.append(f"slide {n['slide'] + 1}")
|
|
47
|
+
lines.append(f"{i}. [{n['status']}] id={n['id']} · {' · '.join(where)} · <{n.get('tag', '?')}>")
|
|
48
|
+
lines.append(f" selector: {n.get('selector', '')}")
|
|
49
|
+
if n.get("text"):
|
|
50
|
+
lines.append(f" đoạn chữ: \"{n['text'][:160]}\"")
|
|
51
|
+
lines.append(f" → {n['note']}")
|
|
52
|
+
lines.append("")
|
|
53
|
+
return "\n".join(lines).rstrip()
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def main(argv: list[str] | None = None):
|
|
57
|
+
parser = argparse.ArgumentParser(description="List review notes left in the HTML editor")
|
|
58
|
+
parser.add_argument("--root", default=".", help="Workspace folder (default: the current folder)")
|
|
59
|
+
parser.add_argument("--file", required=True, help="HTML document the notes belong to")
|
|
60
|
+
parser.add_argument("--all", action="store_true", help="Include notes already marked done")
|
|
61
|
+
parser.add_argument("--done", metavar="ID", action="append", default=[], help="Mark a note as done (repeatable)")
|
|
62
|
+
args = parser.parse_args(argv)
|
|
63
|
+
utf8_stdio()
|
|
64
|
+
|
|
65
|
+
root = Path(args.root).expanduser().resolve()
|
|
66
|
+
target = Path(args.file).expanduser()
|
|
67
|
+
target = (target if target.is_absolute() else root / target).resolve()
|
|
68
|
+
notes = read_notes(target)
|
|
69
|
+
if args.done:
|
|
70
|
+
known = {n["id"] for n in notes}
|
|
71
|
+
missing = [i for i in args.done if i not in known]
|
|
72
|
+
if missing:
|
|
73
|
+
print(f"Không tìm thấy ghi chú: {', '.join(missing)}", file=sys.stderr)
|
|
74
|
+
sys.exit(1)
|
|
75
|
+
try:
|
|
76
|
+
apply_note_ops(target, [{"op": "update", "id": i, "patch": {"status": "done"}} for i in args.done], root)
|
|
77
|
+
except EditorError as exc:
|
|
78
|
+
print(f"Error: {exc}", file=sys.stderr)
|
|
79
|
+
sys.exit(1)
|
|
80
|
+
print(f"Đã đánh dấu xong {len(args.done)} ghi chú → {display_path(notes_path(target), root)}")
|
|
81
|
+
return
|
|
82
|
+
print(format_notes(target, notes, args.all, root))
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
if __name__ == "__main__":
|
|
86
|
+
main()
|