htmlcraft 0.0.0-stage → 0.1.0
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.
- package/LICENSE +21 -0
- package/README.md +77 -2
- package/SECURITY.md +32 -0
- package/THIRD-PARTY-LICENSES.md +1401 -0
- package/dist/cli.js +108625 -0
- package/dist/editor/assets/index-BklY9zS4.css +1 -0
- package/dist/editor/assets/index-CcXgWYEN.js +737 -0
- package/dist/editor/index.html +57 -0
- package/dist/mcp.js +99001 -0
- package/dist/skill/SKILL.md +254 -0
- package/dist/skill/examples/basic.html +742 -0
- package/dist/skill/examples/notes-transitions.html +736 -0
- package/dist/skill/examples/table-chart.html +754 -0
- package/dist/skill/references/authoring.md +160 -0
- package/dist/skill/references/contract.md +177 -0
- package/dist/skill/references/mcp-tools.md +397 -0
- package/dist/skill/references/troubleshooting.md +188 -0
- package/package.json +51 -4
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# Authoring decks for the htmlcraft editor and MCP server
|
|
2
|
+
|
|
3
|
+
These notes cover how to write decks that stay pleasant to edit by hand, by an
|
|
4
|
+
agent, and in the visual editor. The contract itself lives in
|
|
5
|
+
[contract.md](contract.md).
|
|
6
|
+
|
|
7
|
+
## Start from structure, then style
|
|
8
|
+
|
|
9
|
+
1. Create the deck with `create_deck` or `htmlcraft new`. Both produce a valid
|
|
10
|
+
document with slide ids, the canvas size, and the real runtime.
|
|
11
|
+
2. Add or replace content as top-level objects. Each object owns its position,
|
|
12
|
+
size, and typography.
|
|
13
|
+
3. Add a `<style>` block for the shared visual language.
|
|
14
|
+
4. Validate, then open the editor for human review.
|
|
15
|
+
|
|
16
|
+
Prefer one object per visual block over deeply nested layout. The editor and
|
|
17
|
+
MCP tools address top-level objects, so a flat structure is easier to edit and
|
|
18
|
+
survives round trips with fewer surprises.
|
|
19
|
+
|
|
20
|
+
## Editor-friendly structure
|
|
21
|
+
|
|
22
|
+
- Give every top-level object an explicit `data-ppt-el`. Do not rely on a
|
|
23
|
+
generated id when a later call needs to address the object.
|
|
24
|
+
- Keep each object self-contained: position it absolutely inside the slide and
|
|
25
|
+
set an explicit width. Text without a width can overflow the canvas.
|
|
26
|
+
- Use real text nodes for content. Text inside CSS `::before`/`::after`,
|
|
27
|
+
background images, or SVG `<text>` is not editable through `set_text`.
|
|
28
|
+
- Prefer semantic elements (`h1`, `h2`, `p`, `ul`, `table`, `figure`) so the
|
|
29
|
+
outline reports useful summaries and tags.
|
|
30
|
+
- Tables are real `<table>` elements with `<thead>`/`<tbody>`; put
|
|
31
|
+
`data-ppt-el` on the table.
|
|
32
|
+
- A `data-ppt-group` wrapper groups related objects. Do not nest group
|
|
33
|
+
wrappers.
|
|
34
|
+
- Notes are a direct-child `<aside data-ppt-notes hidden>` of the slide. One
|
|
35
|
+
aside per slide is enough.
|
|
36
|
+
|
|
37
|
+
Example object:
|
|
38
|
+
|
|
39
|
+
```html
|
|
40
|
+
<div data-ppt-el="e3" style="position: absolute; left: 140px; top: 300px; width: 900px;">
|
|
41
|
+
<h2 style="margin: 0; font-size: 56px;">Why it matters</h2>
|
|
42
|
+
<p style="margin: 24px 0 0; font-size: 30px; line-height: 1.5; color: #4a4f59;">
|
|
43
|
+
Keep the message in a real paragraph so it can be edited in place.
|
|
44
|
+
</p>
|
|
45
|
+
</div>
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Styling freedom
|
|
49
|
+
|
|
50
|
+
- Put shared rules in a `<style>` block: colors, type scale, shared object
|
|
51
|
+
classes, print rules.
|
|
52
|
+
- Use inline styles for object-specific position, size, and one-off styling.
|
|
53
|
+
`set_style` edits these properties and accepts `null` to remove one.
|
|
54
|
+
- CSS custom properties, gradients, shadows, filters, masks, transforms,
|
|
55
|
+
flexbox, grid, inline SVG, and CSS animations are all allowed.
|
|
56
|
+
- Web fonts must use a `data:` or absolute URL.
|
|
57
|
+
- Keep the fixed canvas in mind. Do not use `position: fixed` or full-height
|
|
58
|
+
`100vh`/`100dvh`/`100svh`/`100lvh` layouts; validation warns (`fixed-layout`)
|
|
59
|
+
because they may not export reliably. Other viewport units are not detected
|
|
60
|
+
by the validator but still scale with the browser window, so avoid them for
|
|
61
|
+
layout. Use absolute positioning inside the 1600x900 (or chosen) canvas.
|
|
62
|
+
- Animations that run on their own are preserved. There is no animation
|
|
63
|
+
timeline or trigger authoring in v1.
|
|
64
|
+
|
|
65
|
+
`set_slide_background` accepts exactly one of `color`, `gradient`, or `image`.
|
|
66
|
+
A color uses the `background` shorthand; a gradient or image uses
|
|
67
|
+
`background-image`, and the other form is cleared.
|
|
68
|
+
|
|
69
|
+
## Content edits
|
|
70
|
+
|
|
71
|
+
- `set_text` replaces an element's text content and escapes HTML. Use it for
|
|
72
|
+
ordinary copy.
|
|
73
|
+
- `set_element_html` replaces inner HTML. Use it for deliberate markup changes,
|
|
74
|
+
then validate immediately.
|
|
75
|
+
- `update_slide_html` replaces a whole slide's inner HTML. Read the slide first
|
|
76
|
+
with `read_slide`; recreating the objects by hand risks losing ids, notes, and
|
|
77
|
+
styles.
|
|
78
|
+
- `add_element` inserts exactly one top-level element. Provide `data-ppt-el` in
|
|
79
|
+
the fragment when you need a stable id; otherwise the returned `elementId`
|
|
80
|
+
tells you the generated id.
|
|
81
|
+
- Removing an element uses a target. The slide itself cannot be removed this
|
|
82
|
+
way; use `delete_slide`, and remember the last slide cannot be deleted.
|
|
83
|
+
- Slide order changes use `move_slide` or `set_slide_order`; the latter must
|
|
84
|
+
list every slide id exactly once.
|
|
85
|
+
|
|
86
|
+
Targets for element tools are exactly one of:
|
|
87
|
+
|
|
88
|
+
```json
|
|
89
|
+
{ "elementId": "e3" }
|
|
90
|
+
{ "selector": ".card > h2" }
|
|
91
|
+
{ "path": [1, 0] }
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
`elementId` matches `data-ppt-el` within the slide. `selector` must match
|
|
95
|
+
exactly one element inside the slide. `path` is child indices starting at the
|
|
96
|
+
slide element. Missing or ambiguous targets produce stable error codes; read
|
|
97
|
+
the outline before guessing.
|
|
98
|
+
|
|
99
|
+
## Notes, transitions, charts, tables, and images
|
|
100
|
+
|
|
101
|
+
- `set_notes` writes or clears the direct-child notes aside. An empty string
|
|
102
|
+
removes it.
|
|
103
|
+
- `set_transition` accepts `none`, `fade`, or `slide`.
|
|
104
|
+
- Chart data lives in `data-ppt-chart` on a `<figure>` as JSON with `type`
|
|
105
|
+
(`bar`, `line`, or `pie`), `labels`, and `series` (`{ name, values }`
|
|
106
|
+
entries). Optional fields are `title`, `colors`, `legend`, and
|
|
107
|
+
`valueLabels`. Labels and each series' values must have the same length, and
|
|
108
|
+
the rendered SVG is derived from the attribute. Use `update_chart` rather
|
|
109
|
+
than editing the SVG. Invalid JSON is a validation error.
|
|
110
|
+
- Tables are real `<table>` elements. `add_table` creates one with a header
|
|
111
|
+
row within the 50-row and 20-column core limits.
|
|
112
|
+
- `add_image` accepts a data URL, an absolute http(s) URL, or a local path.
|
|
113
|
+
Local files are embedded as data URLs after MIME and 8 MB checks; remote
|
|
114
|
+
URLs are validated but never fetched. Keep assets self-contained.
|
|
115
|
+
|
|
116
|
+
## Round-trip rules
|
|
117
|
+
|
|
118
|
+
- Slide ids are unique, non-empty, and stable. Do not renumber slides to
|
|
119
|
+
reorder them; use `move_slide` or `set_slide_order`.
|
|
120
|
+
- Object ids are unique within a slide. Do not recycle an id for a different
|
|
121
|
+
object.
|
|
122
|
+
- Never write `data-ppt-editing` or `data-ppt-frame-slide`; validation rejects
|
|
123
|
+
saved files containing them.
|
|
124
|
+
- Keep the deck self-contained: no relative asset URLs, no external
|
|
125
|
+
stylesheet dependency, no layout that depends on JavaScript.
|
|
126
|
+
- Keep one runtime script with `data-ppt-runtime="1"` and the real body.
|
|
127
|
+
- Export should not change the meaning of the deck. Notes, transitions, chart
|
|
128
|
+
JSON, and object ids survive export.
|
|
129
|
+
|
|
130
|
+
## Revision and conflict discipline
|
|
131
|
+
|
|
132
|
+
Reads and writes are revision-checked. The MCP server remembers the last
|
|
133
|
+
revision per file; a host-attached editor also tracks the file revision. If the
|
|
134
|
+
file changes between your read and write, the write fails with
|
|
135
|
+
`code: "conflict"` and the file is left untouched.
|
|
136
|
+
|
|
137
|
+
On conflict:
|
|
138
|
+
|
|
139
|
+
1. Re-read with `get_outline` or `read_slide`.
|
|
140
|
+
2. Decide how to reconcile the external change. Preserve edits you did not
|
|
141
|
+
intend to replace.
|
|
142
|
+
3. Retry the mutation.
|
|
143
|
+
|
|
144
|
+
Do not bypass a conflict by rewriting the entire deck unless the user
|
|
145
|
+
explicitly asks for that.
|
|
146
|
+
|
|
147
|
+
## Review and export
|
|
148
|
+
|
|
149
|
+
- Use `open_editor` (MCP) or `htmlcraft open <file>` (CLI) for human review. The
|
|
150
|
+
URL contains the deck's capability token; treat it as a secret. The token is
|
|
151
|
+
recorded per deck and reused by later opens until `htmlcraft stop` rotates it;
|
|
152
|
+
replacing a stale-build host rotates it too, because `open` stops the broken
|
|
153
|
+
host first, so a URL bookmarked before the replacement needs the newly printed
|
|
154
|
+
one. The first visit exchanges the token for a 30-day session cookie.
|
|
155
|
+
- Re-read after a person edits in the editor, because their writes create new
|
|
156
|
+
revisions.
|
|
157
|
+
- Run `validate_deck` or `htmlcraft validate` before exporting.
|
|
158
|
+
- `export_deck` writes `<name>.export.html` for `format: "html"`, or a PDF /
|
|
159
|
+
one PNG per slide for `pdf` / `png`. `outDir` resolves against the deck
|
|
160
|
+
directory and must stay inside it.
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# htmlcraft deck contract (htmldeck/v1)
|
|
2
|
+
|
|
3
|
+
The HTML file is both the authoring format and the saved deck. The validator,
|
|
4
|
+
editor, CLI, and MCP server all read and write this same contract.
|
|
5
|
+
|
|
6
|
+
## Document
|
|
7
|
+
|
|
8
|
+
- Start with `<!doctype html>`.
|
|
9
|
+
- Include a non-empty `<title>`. A missing title is a warning
|
|
10
|
+
(`missing-title`), not an error.
|
|
11
|
+
- The document must have content (`empty-document` error otherwise).
|
|
12
|
+
- The deck must contain at least one slide.
|
|
13
|
+
- The deck is self-contained: keep CSS in a `<style>` block or inline `style`
|
|
14
|
+
attributes, and keep assets inline or on absolute URLs. No build step is
|
|
15
|
+
required to open or export it.
|
|
16
|
+
|
|
17
|
+
## Deck wrapper and slides
|
|
18
|
+
|
|
19
|
+
- `<main data-ppt-deck>` is the conventional wrapper. The runtime marks it
|
|
20
|
+
`data-ppt-ready="1"` while presenting.
|
|
21
|
+
- Detection order:
|
|
22
|
+
1. Elements with `data-slide-id`.
|
|
23
|
+
2. `.slide`, then `.page`, then `.slide-page`.
|
|
24
|
+
3. The largest same-parent group of `<section>` elements.
|
|
25
|
+
4. The body as a single slide with the id `body`.
|
|
26
|
+
- Explicit `data-slide-id` values are required for stable addressing. A slide
|
|
27
|
+
without one is a warning (`missing-slide-id`) and normalization assigns one.
|
|
28
|
+
- Slide ids must be unique and non-empty. Duplicates are an error
|
|
29
|
+
(`duplicate-slide-id`).
|
|
30
|
+
- Slides must not be nested inside another slide (`nested-slide` error).
|
|
31
|
+
|
|
32
|
+
Minimal explicit slide:
|
|
33
|
+
|
|
34
|
+
```html
|
|
35
|
+
<section class="slide" data-slide-id="s1" data-width="1600" data-height="900">
|
|
36
|
+
<h1 data-ppt-el="e1">Title</h1>
|
|
37
|
+
</section>
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Canvas
|
|
41
|
+
|
|
42
|
+
- `data-width` and `data-height` are positive pixel numbers.
|
|
43
|
+
- Omit both to use 1600x900, or set both explicitly.
|
|
44
|
+
- An explicitly invalid value is an error (`invalid-canvas-size`).
|
|
45
|
+
- When the attributes are absent, an inline `width: <n>px; height: <n>px` on
|
|
46
|
+
the slide is also honored.
|
|
47
|
+
- Different sizes across slides produce the `mixed-canvas-sizes` warning.
|
|
48
|
+
Keep one canvas size per deck.
|
|
49
|
+
|
|
50
|
+
## Objects
|
|
51
|
+
|
|
52
|
+
- Every top-level child of a slide is an object: text blocks, shapes, images,
|
|
53
|
+
tables, figures, and groups.
|
|
54
|
+
- Put `data-ppt-el="<id>"` on each top-level object. Ids are unique within the
|
|
55
|
+
slide and stay stable across edits.
|
|
56
|
+
- Nested elements may also carry `data-ppt-el`; they share the same uniqueness
|
|
57
|
+
rule within the slide. Duplicate ids are an error (`duplicate-element-id`).
|
|
58
|
+
- Normalization assigns a missing top-level `data-ppt-el` id. It does not
|
|
59
|
+
invent content.
|
|
60
|
+
- A `data-ppt-group` wrapper groups objects. Nested group wrappers are not
|
|
61
|
+
supported (`unsupported-group-nesting` warning).
|
|
62
|
+
- Objects are edited through inline styles and CSS classes. While a deck is
|
|
63
|
+
open, the editor's live frame may carry transient editor-only attributes
|
|
64
|
+
(`data-ppt-editing`, `data-ppt-frame-slide`). They are stripped before save
|
|
65
|
+
and never persist in saved output; see the artifacts rule under
|
|
66
|
+
[Round-trip and writes](#round-trip-and-writes).
|
|
67
|
+
|
|
68
|
+
## Speaker notes
|
|
69
|
+
|
|
70
|
+
- Notes are a direct child of the slide:
|
|
71
|
+
`<aside data-ppt-notes hidden>Talk track</aside>`.
|
|
72
|
+
- Notes outside a slide, or nested deeper than a direct child, are an error
|
|
73
|
+
(`notes-nested-incorrectly`).
|
|
74
|
+
- `set_notes` removes the aside when the notes string is empty.
|
|
75
|
+
|
|
76
|
+
## Transitions and runtime
|
|
77
|
+
|
|
78
|
+
- `data-ppt-transition` is optional and must be `none`, `fade`, or `slide`.
|
|
79
|
+
Any other value is an error (`invalid-transition`).
|
|
80
|
+
- Multi-slide decks should include exactly one runtime:
|
|
81
|
+
`<script data-ppt-runtime="1">...</script>` in the document.
|
|
82
|
+
- A missing runtime on a multi-slide deck is a warning (`missing-runtime`);
|
|
83
|
+
the deck is still valid HTML but cannot present itself.
|
|
84
|
+
- The runtime body must be the real runtime script, not an empty marker.
|
|
85
|
+
`create_deck` and `htmlcraft new` write it. Copy it from
|
|
86
|
+
`../examples/basic.html` when hand-authoring. Validation checks only that a
|
|
87
|
+
marker exists on a `<script>` with value `1`; it does not inspect the body,
|
|
88
|
+
so a comment or an empty script still validates but cannot present.
|
|
89
|
+
- More than one runtime marker is an error (`duplicate-runtime`). A
|
|
90
|
+
`data-ppt-runtime` attribute whose value is not `1`, or on an element other
|
|
91
|
+
than `<script>`, is an error (`invalid-runtime-marker`).
|
|
92
|
+
- The runtime handles the first/last slide, arrow keys, space, Page Up/Down,
|
|
93
|
+
Home/End, the `#/n` URL hash, and print styles. Clicking a noninteractive
|
|
94
|
+
area advances; links, buttons, form controls, and editable content keep their
|
|
95
|
+
own behavior. `F` toggles fullscreen and `P` opens the presenter view (notes,
|
|
96
|
+
next-slide preview, timer, prev/next). Authored `fade`/`slide` transitions
|
|
97
|
+
animate slide changes unless the viewer prefers reduced motion. Do not replace
|
|
98
|
+
the runtime with custom navigation unless the user asks and accepts that the
|
|
99
|
+
editor will not run it.
|
|
100
|
+
|
|
101
|
+
## Charts
|
|
102
|
+
|
|
103
|
+
- Chart data lives in `data-ppt-chart` on a figure (or another element) and
|
|
104
|
+
must be valid JSON (`invalid-chart-json` error otherwise).
|
|
105
|
+
- A typical chart attribute:
|
|
106
|
+
|
|
107
|
+
```html
|
|
108
|
+
<figure
|
|
109
|
+
data-ppt-el="e5"
|
|
110
|
+
data-ppt-chart='{"type":"bar","title":"Revenue","labels":["Q1","Q2"],"series":[{"name":"USD","values":[18,24]}],"colors":["#e8a33d"]}'>
|
|
111
|
+
</figure>
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
- Keep the JSON small enough to read and edit directly. Treat the attribute as
|
|
115
|
+
the source of truth: any rendered chart is derived from it, so editing only
|
|
116
|
+
the rendered output would not change the data.
|
|
117
|
+
|
|
118
|
+
## Assets and styling
|
|
119
|
+
|
|
120
|
+
- Use `data:` URIs or absolute URLs for images, fonts, and other assets.
|
|
121
|
+
- Relative `src`/`href` values and relative `url(...)` values produce the
|
|
122
|
+
`relative-asset` warning. They do not travel with an exported file.
|
|
123
|
+
- Arbitrary CSS is allowed: custom properties, flex/grid inside objects,
|
|
124
|
+
inline SVG, CSS animations, shadows, gradients, and absolute web fonts.
|
|
125
|
+
- `position: fixed` and full-height units (`100vh`, `100dvh`, `100svh`,
|
|
126
|
+
`100lvh`) produce the `fixed-layout` warning because they may not export
|
|
127
|
+
reliably. Other viewport units (for example `50vh`) are not matched by the
|
|
128
|
+
validator but still scale with the browser window, so avoid them for layout.
|
|
129
|
+
- A `<canvas>` produces the `canvas-content` warning: its drawing cannot be
|
|
130
|
+
edited visually.
|
|
131
|
+
- Scripts other than the runtime produce the `script-present` warning. The
|
|
132
|
+
editor does not execute them.
|
|
133
|
+
|
|
134
|
+
## Round-trip and writes
|
|
135
|
+
|
|
136
|
+
- Serialization writes `<!doctype html>` followed by the document element. The
|
|
137
|
+
MCP/editor path removes editor-only attributes before writing:
|
|
138
|
+
`data-ppt-editing` and `data-ppt-frame-slide` are always rejected by
|
|
139
|
+
validation (`editor-artifacts` error) if present in a saved file.
|
|
140
|
+
- HTML export adds the generator comment
|
|
141
|
+
`<!-- Edited with htmlcraft. Format: htmldeck/v1. -->` and, for a multi-slide
|
|
142
|
+
deck with no runtime and no script at all, appends the runtime.
|
|
143
|
+
- Writes are atomic (temporary file plus rename) and compare against the
|
|
144
|
+
revision last read or written. A changed file produces a structured
|
|
145
|
+
`conflict` error; re-read and retry.
|
|
146
|
+
- Normalization may add missing slide/object ids; the editor may also add a
|
|
147
|
+
relative position to statically positioned slide roots. Unknown HTML and CSS
|
|
148
|
+
are preserved otherwise.
|
|
149
|
+
|
|
150
|
+
## Validation summary
|
|
151
|
+
|
|
152
|
+
Errors make a deck invalid; warnings do not.
|
|
153
|
+
|
|
154
|
+
| Severity | Code | Meaning |
|
|
155
|
+
| --- | --- | --- |
|
|
156
|
+
| error | `empty-document` | No content in the document. |
|
|
157
|
+
| error | `nested-slide` | A slide is inside another slide. |
|
|
158
|
+
| error | `invalid-canvas-size` | Explicit canvas width/height is not positive. |
|
|
159
|
+
| error | `invalid-transition` | Transition is not none, fade, or slide. |
|
|
160
|
+
| error | `duplicate-element-id` | An element id repeats within a slide. |
|
|
161
|
+
| error | `invalid-chart-json` | `data-ppt-chart` is not valid JSON. |
|
|
162
|
+
| error | `duplicate-slide-id` | A slide id repeats. |
|
|
163
|
+
| error | `invalid-runtime-marker` | Runtime attribute is not `1` on a script. |
|
|
164
|
+
| error | `duplicate-runtime` | More than one runtime script. |
|
|
165
|
+
| error | `notes-nested-incorrectly` | Notes are not a direct child of a slide. |
|
|
166
|
+
| error | `editor-artifacts` | Editor-only attributes are present. |
|
|
167
|
+
| warning | `missing-title` | No `<title>`. |
|
|
168
|
+
| warning | `single-body-fallback` | No slides found; the body is one slide. |
|
|
169
|
+
| warning | `missing-slide-id` | A slide has no `data-slide-id`. |
|
|
170
|
+
| warning | `missing-runtime` | Multiple slides but no runtime. |
|
|
171
|
+
| warning | `script-present` | A non-runtime script is present. |
|
|
172
|
+
| warning | `relative-asset` | A relative asset URL is present. |
|
|
173
|
+
| warning | `fixed-layout` | `position: fixed` or a full-height `100vh` unit is present. |
|
|
174
|
+
| warning | `mixed-canvas-sizes` | Slides use different canvas sizes. |
|
|
175
|
+
| warning | `canvas-content` | A `<canvas>` cannot be edited visually. |
|
|
176
|
+
| warning | `unsupported-group-nesting` | Groups are nested. |
|
|
177
|
+
| info | `slide-count` | Number of detected slides. |
|