@taloswork/ose-shared 0.1.9 → 0.1.11
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/mcp/gen/mcp.json +2 -2
- package/package.json +3 -3
- package/skills/diagram-design/SKILL.md +1 -1
- package/skills/document/SKILL.md +63 -75
- package/skills/document/bin/deck-build.cjs +51 -1
- package/skills/document/bin/deck-qa.cjs +18745 -279
- package/skills/document/bin/doc-convert.cjs +9280 -76489
- package/skills/document/bin/doc-fill.cjs +0 -0
- package/skills/document/bin/doc-gen.cjs +3043 -46825
- package/skills/document/bin/doc-run.cjs +65095 -1967
- package/skills/document/bin/doc-scan.cjs +0 -0
- package/skills/document/bin/doc-text.cjs +0 -0
- package/skills/document/bin/doc-validate.cjs +18067 -226
- package/skills/document/bin/doc-xml.cjs +1 -1
- package/skills/document/bin/docx-annotate.cjs +0 -0
- package/skills/document/bin/html2pptx.cjs +32498 -145280
- package/skills/document/bin/ocr-worker.cjs +0 -0
- package/skills/document/bin/ocr.cjs +0 -0
- package/skills/document/bin/pdf-form.cjs +0 -0
- package/skills/document/bin/pdf-images.cjs +0 -0
- package/skills/document/bin/pdf-ops.cjs +0 -0
- package/skills/document/bin/pdf-render.cjs +11 -9
- package/skills/document/bin/pdf-tables.cjs +0 -0
- package/skills/document/bin/pptx-clone.cjs +21 -25
- package/skills/document/bin/pptx-embed-fonts.cjs +8 -6
- package/skills/document/bin/pptx-set-image.cjs +0 -0
- package/skills/document/bin/pptx-slide.cjs +22 -32
- package/skills/document/bin/pptx-theme.cjs +1 -20
- package/skills/document/bin/pptx-tokenize.cjs +1 -1
- package/skills/document/bin/xlsx-query.cjs +0 -0
- package/skills/document/bin/xlsx-recalc.cjs +0 -0
- package/skills/document/bin-reference.md +35 -0
- package/skills/document/content-pipeline.md +19 -18
- package/skills/document/deck-design.md +110 -211
- package/skills/document/layouts/README.md +4 -33
- package/skills/document/motion/README.md +4 -2
- package/skills/document/office.md +5 -1
- package/skills/document/rewrite.md +43 -99
- package/skills/document/styles/README.md +0 -7
- package/skills/document/theme-system.md +1 -0
- package/skills/document/themes/README.md +5 -5
- package/skills/document/themes/anthropic-clay.json +1 -7
- package/skills/document/themes/apple-keynote.json +1 -7
- package/skills/document/themes/black-gold.json +1 -2
- package/skills/document/themes/cinereel.json +1 -2
- package/skills/document/themes/cool-tech.json +1 -2
- package/skills/document/themes/hand-drawn.json +1 -2
- package/skills/document/themes/ivory-gold.json +1 -2
- package/skills/document/themes/magazine-ink.json +1 -2
- package/skills/document/themes/mckinsey-consulting.json +1 -7
- package/skills/document/themes/mono.json +1 -2
- package/skills/document/themes/swiss-grid.json +1 -2
- package/skills/document/themes/warm-editorial.json +1 -2
- package/skills/image-layout/SKILL.md +1 -1
- package/skills/image-layout/bin/html2img.cjs +0 -0
- package/skills/cozy-static-svg/SKILL.md +0 -76
- package/skills/cozy-static-svg/references/approved-preview.png +0 -0
- package/skills/cozy-static-svg/references/cross-platform.md +0 -73
- package/skills/cozy-static-svg/references/moon_keeps_watch.svg +0 -229
- package/skills/cozy-static-svg/references/style-anchor.md +0 -271
- package/skills/cozy-static-svg/scripts/artkit.py +0 -321
- package/skills/cozy-static-svg/scripts/to_png.py +0 -333
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
# Deck design — html2pptx (hybrid) is THE deck engine
|
|
2
2
|
|
|
3
3
|
**Every deck is built ONE way:** author slide HTML and render with `html2pptx` in
|
|
4
|
-
its default **HYBRID** mode — `bin/html2pptx.cjs deck.html out.pptx --
|
|
4
|
+
its default **HYBRID** mode — `bin/html2pptx.cjs deck.html out.pptx --style <id>`
|
|
5
5
|
(no `--editable`/`--rasterize`). Chromium gives you the full power of HTML/CSS
|
|
6
6
|
(flexbox/grid, layering, per-element SVG) and converts to NATIVE editable pptx
|
|
7
7
|
text boxes/shapes, with the decorative visual layer baked into one pixel-perfect
|
|
8
8
|
backdrop — designed look **AND** editable words + editable `data-chart`. This is
|
|
9
9
|
the path for every deck: pitch / keynote / report / design-y / plain alike.
|
|
10
10
|
|
|
11
|
-
`doc-gen
|
|
12
|
-
do not use
|
|
13
|
-
data tables, batch/deterministic
|
|
11
|
+
`doc-gen` makes no decks, and `doc-run` PptxGenJS is **NOT a deck-building path** —
|
|
12
|
+
do not use it to build a deck. (It remains for NON-deck jobs only: structured
|
|
13
|
+
data tables, batch/deterministic generation, shape-level one-offs.)
|
|
14
14
|
|
|
15
15
|
html2pptx needs a browser — the app's Chromium service or the bundled Playwright.
|
|
16
16
|
If neither is available, **say so and stop; never silently downgrade** to a lesser
|
|
@@ -33,11 +33,11 @@ every slide from zero is the #1 "AI-generated" tell; compose from the catalog fi
|
|
|
33
33
|
## html2pptx — HTML/CSS is the layout engine
|
|
34
34
|
|
|
35
35
|
```
|
|
36
|
-
node <skill>/bin/html2pptx.cjs deck.html out.pptx --
|
|
37
|
-
node <skill>/bin/html2pptx.cjs deck.html
|
|
38
|
-
node <skill>/bin/html2pptx.cjs deck.html out.pptx --
|
|
39
|
-
node <skill>/bin/html2pptx.cjs deck.html out.pptx --
|
|
40
|
-
node <skill>/bin/html2pptx.cjs snapshot.layout.json out.pptx
|
|
36
|
+
node <skill>/bin/html2pptx.cjs deck.html out.pptx --style <id> [--theme-v2] # DEFAULT = hybrid: paint layouts/ with the catalog entry
|
|
37
|
+
node <skill>/bin/html2pptx.cjs deck.html --preview-dir <dir> --style <id> # authoring preview: PNG per slide, no pptx
|
|
38
|
+
node <skill>/bin/html2pptx.cjs deck.html out.pptx --style <id> --editable # plain native (effects flatten)
|
|
39
|
+
node <skill>/bin/html2pptx.cjs deck.html out.pptx --style <id> --rasterize # pixel-perfect, NOT editable
|
|
40
|
+
node <skill>/bin/html2pptx.cjs snapshot.layout.json out.pptx # headless-safe input (always plain native)
|
|
41
41
|
```
|
|
42
42
|
|
|
43
43
|
### ⭐ PREFERRED workflow — structure/skin split (`--style`)
|
|
@@ -128,12 +128,15 @@ needs) so it becomes reusable: bespoke first, then graduate the winners into the
|
|
|
128
128
|
Contract (violations fail loudly, nothing degrades silently):
|
|
129
129
|
|
|
130
130
|
- One `<section class="slide">` per slide, laid out on a **1280×720 px** canvas
|
|
131
|
-
(= 13.33×7.5 in).
|
|
132
|
-
|
|
133
|
-
--
|
|
134
|
-
hardcode brand colors
|
|
135
|
-
|
|
136
|
-
|
|
131
|
+
(= 13.33×7.5 in). Color comes from the skin (`--style`), whose tokens every skin
|
|
132
|
+
defines: `var(--accent|--title|--body|--muted|--hair|--slide-bg|--title-color|
|
|
133
|
+
--body-color|--font-heading|--font-body)` plus the ramp `var(--c1..--c4)` — never
|
|
134
|
+
hardcode brand colors, and never use a name outside this set (`--primary`,
|
|
135
|
+
`--text`, `--card-bg`, `--border` are NOT defined by skins: they only exist under
|
|
136
|
+
the legacy `--theme` path, so on a `--style` deck they silently stick on their
|
|
137
|
+
fallback). html2pptx **warns** (`N hardcoded brand color(s) bypass theme vars`)
|
|
138
|
+
when a slide writes a hex instead of a `var(--…)` — that deck won't re-skin, so
|
|
139
|
+
fix it before shipping. (SVG diagram semantic colors are exempt.)
|
|
137
140
|
- **Tailwind utility classes are available** (vendored offline — no CDN needed):
|
|
138
141
|
author like a modern web deck — `grid grid-cols-2 gap-16`, `flex items-center
|
|
139
142
|
justify-center`, `p-16`, `text-6xl font-bold`, `rounded-3xl`, `bg-blue-600`,
|
|
@@ -176,8 +179,8 @@ Contract (violations fail loudly, nothing degrades silently):
|
|
|
176
179
|
- Fonts are measured by Chromium but re-laid-out by PowerPoint — keep ~10%
|
|
177
180
|
slack in text boxes; don't butt text against box edges.
|
|
178
181
|
|
|
179
|
-
After generating: `
|
|
180
|
-
|
|
182
|
+
After generating: the build reports `valid` and `qa` itself; sign off with
|
|
183
|
+
`deck-qa --final` like any deck ("Verify before delivering").
|
|
181
184
|
|
|
182
185
|
## HTML slide authoring — the design-first route
|
|
183
186
|
|
|
@@ -281,12 +284,17 @@ The shipped `layouts/*.tpl` are this recipe applied as structure-only slides —
|
|
|
281
284
|
paste the nearest one and paint it with a skin (`--style`) rather than rebuilding
|
|
282
285
|
the stack by hand; each already carries the 8 layers correctly wired.
|
|
283
286
|
|
|
284
|
-
|
|
285
|
-
`
|
|
286
|
-
|
|
287
|
-
`
|
|
288
|
-
|
|
289
|
-
|
|
287
|
+
**Every catalog entry ships a motion preset; the scenario decides whether
|
|
288
|
+
`deck-build` applies it.** (`motion/<id>.json`, named by the entry's `motion` field.)
|
|
289
|
+
Put the confirmed scenario in the spec as `"scenario"`: a **presented** deck (pitch /
|
|
290
|
+
路演 / 发布会 / keynote / 大会 / 讲座 / 销售) gets the preset — `data-anim*` /
|
|
291
|
+
`data-transition*` injected per slide by the layout's role; a **read** deck (内审 /
|
|
292
|
+
评审 / 报告 / 汇报 / 讲义 / 培训 / 述职) gets none; no or an unknown scenario keeps the
|
|
293
|
+
preset. `"motion": true|false` overrides the scenario. The build's JSON says which
|
|
294
|
+
applied and why (`motion: {on, reason}`). Hand-written `data-anim` /
|
|
295
|
+
`data-transition` always wins — `deck-build` only adds an attribute an element does
|
|
296
|
+
not already have, and a deck authored straight into `deck.html` animates only
|
|
297
|
+
where you write `data-anim`.
|
|
290
298
|
|
|
291
299
|
## Motion — entrance animation + slide transitions
|
|
292
300
|
|
|
@@ -297,10 +305,10 @@ build sequence — not a video, not a GIF). Mark an element with `data-anim` and
|
|
|
297
305
|
becomes one build step; the deck then plays like a keynote instead of appearing
|
|
298
306
|
all at once.
|
|
299
307
|
|
|
300
|
-
**
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
308
|
+
**The attribute itself is opt-in.** No `data-anim` on the page → no `<p:timing>`.
|
|
309
|
+
Write your own when the scenario is a **stage** — 发布会 / 路演 / pitch / 主题演讲;
|
|
310
|
+
for 内审 / 报告 / 讲义 decks that people read rather than watch, add none beyond
|
|
311
|
+
what the preset already injects.
|
|
304
312
|
|
|
305
313
|
#### The attribute contract
|
|
306
314
|
|
|
@@ -472,56 +480,11 @@ A face that is bundled but neither baked nor embedded is *still worth bundling*
|
|
|
472
480
|
backdrop and the picker previews come out right), just don't assume the native text
|
|
473
481
|
followed. `hand-drawn`'s Gochi Hand heading is exactly that case today.
|
|
474
482
|
|
|
475
|
-
## Running a script (PptxGenJS via doc-run — NOT for decks)
|
|
476
|
-
|
|
477
|
-
> **This section is reference for NON-deck freeform PptxGenJS only** (bespoke
|
|
478
|
-
> one-off shapes, non-deck pptx). **Do not build a deck this way** — every deck
|
|
479
|
-
> goes through html2pptx hybrid (see the top of this file). Kept here so the
|
|
480
|
-
> capability is documented, not as a deck path.
|
|
481
|
-
|
|
482
|
-
Write `deck.js`, run it with **`node <skill>/bin/doc-run.cjs deck.js`** —
|
|
483
|
-
`pptxgenjs` (and `jszip`, `pdf-lib`, `docx`, `xlsx`, `hyperformula`) are bundled
|
|
484
|
-
inside doc-run, so `require("pptxgenjs")` works on any machine with no install
|
|
485
|
-
step (packaged app included; `doc-run --list` prints the registry). Bare
|
|
486
|
-
`node deck.js` only resolves those libs on a dev checkout — always use doc-run.
|
|
487
|
-
|
|
488
|
-
## Canvas & grid
|
|
489
|
-
|
|
490
|
-
- Layout: 16:9 wide = **13.33 × 7.5 inches**, origin top-left, units in inches.
|
|
491
|
-
- Safe margins: 0.6 left/right, 0.3 top, 0.45 bottom (footer/page number zone).
|
|
492
|
-
- Use a 12-column mental grid: column width ≈ 1.0", gutters 0.1".
|
|
493
|
-
- Vertical rhythm: title zone y 0.3–1.05; content y 1.25–7.0.
|
|
494
|
-
|
|
495
|
-
```js
|
|
496
|
-
const pptxgen = require("pptxgenjs");
|
|
497
|
-
const p = new pptxgen();
|
|
498
|
-
p.defineLayout({ name: "WIDE", width: 13.33, height: 7.5 });
|
|
499
|
-
p.layout = "WIDE";
|
|
500
|
-
```
|
|
501
|
-
|
|
502
|
-
## Theme first — never hardcode colors
|
|
503
|
-
|
|
504
|
-
Load the active theme (the user's template skill ships one, or use the document
|
|
505
|
-
skill's `themes/mckinsey-consulting.json`). PptxGenJS colors are bare hex (no `#`).
|
|
506
|
-
|
|
507
|
-
```js
|
|
508
|
-
const { readFileSync } = require("node:fs");
|
|
509
|
-
const t = JSON.parse(readFileSync(process.env.TALOS_DOC_THEME ?? "<skill>/themes/mckinsey-consulting.json", "utf8"));
|
|
510
|
-
const C = {
|
|
511
|
-
primary: (t.colors?.primary ?? "#1a3c6e").replace("#", ""),
|
|
512
|
-
text: (t.colors?.text ?? "#1f2328").replace("#", ""),
|
|
513
|
-
muted: (t.colors?.muted ?? "#5b6570").replace("#", ""),
|
|
514
|
-
cardBg: (t.colors?.tableHeaderBg ?? "#eef2f8").replace("#", ""),
|
|
515
|
-
border: (t.colors?.tableBorder ?? "#c6d0dd").replace("#", ""),
|
|
516
|
-
};
|
|
517
|
-
const FONT = t.fonts?.body || undefined; // undefined → platform default (CJK-safe)
|
|
518
|
-
```
|
|
519
|
-
|
|
520
483
|
## Design principles (the constraint EVERY deck honors)
|
|
521
484
|
|
|
522
|
-
This is the "design ideas" bar for a freeform deck. The
|
|
523
|
-
|
|
524
|
-
no under-title lines); when you hand-build slides YOU are responsible for it.
|
|
485
|
+
This is the "design ideas" bar for a freeform deck. The catalog layouts
|
|
486
|
+
(`layouts/*.tpl`) already bake most of it in (dominant accent, contrast-picked
|
|
487
|
+
text, motif, no under-title lines); when you hand-build slides YOU are responsible for it.
|
|
525
488
|
Not a menu — treat it as a checklist the deck must pass.
|
|
526
489
|
|
|
527
490
|
**Color — commit, don't sprinkle.**
|
|
@@ -537,7 +500,7 @@ Not a menu — treat it as a checklist the deck must pass.
|
|
|
537
500
|
- No slide is a wall of text. Each one gets a structural element: a colored band,
|
|
538
501
|
a big number, an icon row, a 2×2, a chart, or a supporting image. A title +
|
|
539
502
|
bullets on white is the classic AI tell — restructure it (this is exactly what
|
|
540
|
-
|
|
503
|
+
the build's `qa` flags as `text-only-slide`).
|
|
541
504
|
- Reach for the strong composition patterns: two-column split, icon+label rows,
|
|
542
505
|
a 2×2 grid, a half-bleed image with text on the other half, one hero figure.
|
|
543
506
|
- Vary the layout slide-to-slide. Ten identical bullet slides is the single
|
|
@@ -563,7 +526,7 @@ Not a menu — treat it as a checklist the deck must pass.
|
|
|
563
526
|
**Contrast — readability is non-negotiable.**
|
|
564
527
|
- Text on fills must clear ~4.5:1 (large/bold ~3:1). Dark fills → light text
|
|
565
528
|
(`F1FAEE`/`FFFFFF`); light fills → the `text` color. When unsure compute
|
|
566
|
-
luminance.
|
|
529
|
+
luminance. The build's `qa` flags the worst offenders as `low-contrast-text`.
|
|
567
530
|
|
|
568
531
|
**The AI tells to avoid** (these scream "template"):
|
|
569
532
|
- A thin accent LINE under the title. Never. It's the #1 giveaway; use space,
|
|
@@ -612,17 +575,17 @@ per page; add them as the deck needs. Catalogs in `assets/snippets/`:
|
|
|
612
575
|
|
|
613
576
|
All snippets are hybrid-native: chips, rules, frames, gradients, SVG **bake into the
|
|
614
577
|
backdrop**; labels, page numbers, chart data stay **native/editable**. Route every
|
|
615
|
-
color through
|
|
578
|
+
color through the skin tokens (`var(--accent, …)`) so one skin reskins them — the same
|
|
616
579
|
`footer-pageno` fragment becomes tech-cyan or 国风-朱红 by swapping `--accent`.
|
|
617
580
|
|
|
618
581
|
**Pairing a snippet with the theme** — two independent dimensions:
|
|
619
|
-
- **Color = automatic.** Snippets read only the
|
|
620
|
-
|
|
621
|
-
--body-color --font-heading --font-body`).
|
|
622
|
-
recolors for free; the value after the comma is just the
|
|
623
|
-
OTHER var name (e.g. `--accent2`) is
|
|
624
|
-
fallback, so **only use those
|
|
625
|
-
Override on its `<section>`: `style="--accent:#b8292e;--muted:#9a8b76"`.
|
|
582
|
+
- **Color = automatic.** Snippets read only the skin tokens listed in the slide
|
|
583
|
+
contract above (`--accent --title --body --muted --hair --slide-bg --title-color
|
|
584
|
+
--body-color --font-heading --font-body --c1..--c4`). Pick the skin and every
|
|
585
|
+
snippet recolors for free; the value after the comma is just the fallback. Any
|
|
586
|
+
OTHER var name (e.g. `--accent2`, `--primary`) is not defined → it silently sticks
|
|
587
|
+
on its fallback, so **only use those names**. Need one snippet in an off-skin
|
|
588
|
+
color? Override on its `<section>`: `style="--accent:#b8292e;--muted:#9a8b76"`.
|
|
626
589
|
- **Form = your choice.** The theme supplies the palette, NOT the shape. A `neon-dot`
|
|
627
590
|
on a 侘寂 light theme reads wrong even recolored — pick the motif/functional family
|
|
628
591
|
that matches the style's aesthetic (seal→chinese, gold-flourish→black-gold,
|
|
@@ -632,139 +595,75 @@ color through theme vars (`var(--accent, …)`) so one `--theme` reskins them
|
|
|
632
595
|
are intentionally hardcoded; the theme reskins their title/bg/accent but the ramp
|
|
633
596
|
stays so the hierarchy reads.
|
|
634
597
|
|
|
635
|
-
## Shape vocabulary (the pieces everything is built from)
|
|
636
|
-
|
|
637
|
-
```js
|
|
638
|
-
// Card
|
|
639
|
-
s.addShape("roundRect", { x, y, w, h, rectRadius: 0.07, fill: { color: C.cardBg }, line: { color: C.border, width: 1 } });
|
|
640
|
-
// Accent bar (left edge of a card, or under a heading)
|
|
641
|
-
s.addShape("rect", { x, y, w: 0.07, h, fill: { color: C.primary } });
|
|
642
|
-
// Divider / timeline spine
|
|
643
|
-
s.addShape("line", { x, y, w, h: 0, line: { color: C.primary, width: 2 } });
|
|
644
|
-
// Node / dot
|
|
645
|
-
s.addShape("ellipse", { x, y, w: 0.18, h: 0.18, fill: { color: C.primary } });
|
|
646
|
-
// Chevron / arrow for flows
|
|
647
|
-
s.addShape("chevron", { x, y, w: 1.2, h: 0.5, fill: { color: C.primary } });
|
|
648
|
-
// Layered stack (architecture): repeat roundRects with y += h + 0.15, widths shrinking
|
|
649
|
-
```
|
|
650
|
-
|
|
651
|
-
Text goes ON shapes as separate `addText` (easier to position than shape text):
|
|
652
|
-
|
|
653
|
-
```js
|
|
654
|
-
s.addText("标题", { x, y, w, h, fontSize: 14, bold: true, color: C.text, fontFace: FONT, align: "left", valign: "top" });
|
|
655
|
-
```
|
|
656
|
-
|
|
657
|
-
## Complete skeleton (title + custom quadrant slide)
|
|
658
|
-
|
|
659
|
-
```js
|
|
660
|
-
const pptxgen = require("pptxgenjs"); const { readFileSync } = require("node:fs");
|
|
661
|
-
const t = JSON.parse(readFileSync("<theme.json path>", "utf8"));
|
|
662
|
-
const hex = (c, d) => (c ?? d).replace("#", "");
|
|
663
|
-
const C = { primary: hex(t.colors?.primary, "#1a3c6e"), text: hex(t.colors?.text, "#1f2328"),
|
|
664
|
-
muted: hex(t.colors?.muted, "#5b6570"), cardBg: hex(t.colors?.tableHeaderBg, "#eef2f8") };
|
|
665
|
-
const p = new pptxgen();
|
|
666
|
-
p.defineLayout({ name: "W", width: 13.33, height: 7.5 }); p.layout = "W";
|
|
667
|
-
|
|
668
|
-
// ── cover
|
|
669
|
-
let s = p.addSlide();
|
|
670
|
-
s.background = { color: C.primary };
|
|
671
|
-
s.addShape("rect", { x: 0.6, y: 3.0, w: 1.1, h: 0.06, fill: { color: "FFFFFF" } });
|
|
672
|
-
s.addText("WorkBuddy 产品路演", { x: 0.6, y: 3.15, w: 12, h: 1, fontSize: 38, bold: true, color: "FFFFFF" });
|
|
673
|
-
s.addText("AI Agent 数字员工 · 2026 Q3", { x: 0.6, y: 4.2, w: 12, h: 0.5, fontSize: 15, color: "E8EEF6" });
|
|
674
|
-
|
|
675
|
-
// ── custom: 2×2 quadrant (no archetype for this — the freeform case)
|
|
676
|
-
s = p.addSlide();
|
|
677
|
-
s.addText("市场象限", { x: 0.6, y: 0.3, w: 12, h: 0.7, fontSize: 26, bold: true, color: C.primary });
|
|
678
|
-
const qx = 0.9, qy = 1.4, qw = 11.5, qh = 5.4;
|
|
679
|
-
s.addShape("line", { x: qx + qw / 2, y: qy, w: 0, h: qh, line: { color: C.muted, width: 1 } });
|
|
680
|
-
s.addShape("line", { x: qx, y: qy + qh / 2, w: qw, h: 0, line: { color: C.muted, width: 1 } });
|
|
681
|
-
const cell = (cx, cy, title, body, hot) => {
|
|
682
|
-
s.addShape("roundRect", { x: cx, y: cy, w: qw / 2 - 0.3, h: qh / 2 - 0.3, rectRadius: 0.08,
|
|
683
|
-
fill: { color: hot ? C.primary : C.cardBg }, line: { color: C.muted, width: 1 } });
|
|
684
|
-
s.addText(title, { x: cx + 0.2, y: cy + 0.15, w: qw / 2 - 0.7, h: 0.4, fontSize: 14, bold: true, color: hot ? "FFFFFF" : C.text });
|
|
685
|
-
s.addText(body, { x: cx + 0.2, y: cy + 0.6, w: qw / 2 - 0.7, h: qh / 2 - 1.0, fontSize: 11.5, color: hot ? "E8EEF6" : C.text, valign: "top" });
|
|
686
|
-
};
|
|
687
|
-
cell(qx + 0.15, qy + 0.15, "高频 × 高价值", "跨境电商对账 —— 切入点", true);
|
|
688
|
-
cell(qx + qw / 2 + 0.15, qy + 0.15, "低频 × 高价值", "合同合规勾稽", false);
|
|
689
|
-
cell(qx + 0.15, qy + qh / 2 + 0.15, "高频 × 低价值", "日报汇总", false);
|
|
690
|
-
cell(qx + qw / 2 + 0.15, qy + qh / 2 + 0.15, "低频 × 低价值", "暂不投入", false);
|
|
691
|
-
|
|
692
|
-
p.writeFile({ fileName: "deck.pptx" }).then(() => console.log("ok"));
|
|
693
|
-
```
|
|
694
|
-
|
|
695
598
|
## Verify before delivering (MANDATORY automated visual-QA loop)
|
|
696
599
|
|
|
697
600
|
**Assume there are problems — your job is to find them.** Treat QA as a bug hunt,
|
|
698
|
-
not a confirmation step. Use the cheapest faithful surface for each stage:
|
|
699
|
-
|
|
700
|
-
Do not launch LibreOffice after every
|
|
701
|
-
|
|
702
|
-
**
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
**
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
**
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
in a Latin-only font → 豆腐; expected language defaults to the system locale,
|
|
713
|
-
override with `TALOS_DECK_LANG`). **Fix every finding first** — these
|
|
714
|
-
are objective bugs and free to detect, so they must never reach the vision pass or
|
|
715
|
-
delivery. (This is the same lint as `doc-validate --design-lint`, JSON-shaped for
|
|
716
|
-
the loop.)
|
|
601
|
+
not a confirmation step. Use the cheapest faithful surface for each stage: HTML
|
|
602
|
+
screenshots while authoring, the build's own checks on every build, and one
|
|
603
|
+
Office-rendered sign-off at the end. Do not launch LibreOffice after every edit.
|
|
604
|
+
|
|
605
|
+
**Machine checks come with the build.** Every `html2pptx … out.pptx` run prints,
|
|
606
|
+
next to the build result, `valid` (does the file open — `false` exits 1: never
|
|
607
|
+
deliver) and `qa: { ok, findings:[{slide,code,message}] }` — deck-qa's lint:
|
|
608
|
+
**off-canvas**, **tiny-font** (<10pt), **shape-overlap**, **text-only-slide**,
|
|
609
|
+
**low-contrast-text**, **placeholder-text** (替换为…/占位/在这里写/Lorem left in a
|
|
610
|
+
slide) and **font-mismatch** (CJK in a Latin-only font → 豆腐; language defaults to
|
|
611
|
+
the system locale, override with `TALOS_DECK_LANG`). **Fix every finding before
|
|
612
|
+
anything else** — they are objective and free, so they must never reach the
|
|
613
|
+
vision pass or delivery. No separate `doc-validate` / `deck-qa` call is needed
|
|
614
|
+
after a build.
|
|
717
615
|
|
|
718
616
|
**The loop** (≤2 delivery rounds, then report residuals — never silently ship):
|
|
719
617
|
|
|
720
|
-
1. **
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
2. **Build
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
`doc-convert
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
618
|
+
1. **Author against the HTML preview.** `html2pptx.cjs deck.html --preview-dir
|
|
619
|
+
<dir> --style <id> …` renders every slide the first time; after a fix,
|
|
620
|
+
`--preview-pages 3,7-8` renders only the changed ones. Read these images and
|
|
621
|
+
iterate until the composition is clean.
|
|
622
|
+
2. **Build and fix the build's findings** (`html2pptx … deck.pptx`, see above).
|
|
623
|
+
3. **Sign off once: `deck-qa.cjs deck.pptx --final`.** One call runs strict XSD
|
|
624
|
+
validation (a failure exits 1), the lint, an Office render (LibreOffice via
|
|
625
|
+
`doc-convert`, cached), and the render check: `render-overflow` (text Office
|
|
626
|
+
re-wrapped onto more lines than its box holds, or past its side) and
|
|
627
|
+
`render-collision` (text that grew out of its box onto another). It returns
|
|
628
|
+
`review` — the slides with such a finding or a native chart (Office draws
|
|
629
|
+
charts; the preview never showed them) — and `previews`, a ≈72dpi image of
|
|
630
|
+
each. **Read only `previews`.** Every other slide already passed your eyes in
|
|
631
|
+
the HTML preview, and in the default hybrid mode its visuals are baked from
|
|
632
|
+
that same render; Office only re-lays the native text, which was just
|
|
633
|
+
measured. Re-wrapping at a different word, spacing CJK and Latin apart or a
|
|
634
|
+
substituted Latin face is normal, not a defect.
|
|
635
|
+
- **Read every slide instead** (`pdf-render.cjs <deck>.office.pdf all 1`) when
|
|
636
|
+
`html2pptx` reported a `layout (fallback)` engine (no baked visuals, so the
|
|
637
|
+
preview no longer matches) or you changed the PPTX after building it
|
|
638
|
+
(`doc-xml`, `pptx-slide`, a script).
|
|
639
|
+
- `office.faithful: false` (no LibreOffice, only a Chromium reconstruction) or
|
|
640
|
+
`office.error`: there is no Office layout to check. The HTML preview stands;
|
|
641
|
+
say so when delivering.
|
|
642
|
+
4. **Vision critic — the part only a model can do.** It judges the HTML preview
|
|
643
|
+
images (step 1) and the `previews` of step 3 — never a second full pass over
|
|
644
|
+
slides already judged. LOOK at every image you critique (not "glance").
|
|
645
|
+
**Either you critique a slide or a sub-agent does, not both:** with sub-agent
|
|
646
|
+
dispatch, hand slides to fresh-eyes critics in parallel and read their verdicts
|
|
647
|
+
instead of opening the images yourself. Give each critic the slide's findings
|
|
648
|
+
so it does NOT re-report them — it judges only what a machine can't: balance
|
|
649
|
+
and whitespace, hierarchy and focal point, a real visual anchor (not a text
|
|
650
|
+
wall), palette/motif consistency, image quality, crowding and uneven gaps,
|
|
651
|
+
misaligned sibling columns, decorative lines sized for one-line text when the
|
|
652
|
+
title wrapped, and leftovers the lint can't phrase-match (`{{tokens}}`,
|
|
653
|
+
"undefined", stray "xxx"). Each critic returns **{slide, verdict: pass|fail,
|
|
753
654
|
defects:[…]}**.
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
**Do not declare done before at least one complete gate→critic→fix cycle.**
|
|
655
|
+
5. **Regenerate only the failing slides.** Re-author that `<section>` (one section
|
|
656
|
+
per file lets a slide rebuild in isolation) and rebuild, or use `pptx-slide`
|
|
657
|
+
(dup/remove/reorder) / `pptx-clone` for template-driven slides. Then preview
|
|
658
|
+
the changed slides, rebuild and run `--final` again — one fix often creates
|
|
659
|
+
another. Stop when a pass finds nothing new **or** after 2 rounds; if defects
|
|
660
|
+
remain, **deliver with an explicit note listing them**.
|
|
661
|
+
|
|
662
|
+
**Reading images is the most token-expensive step of the deck flow** (≈ w×h∕750
|
|
663
|
+
tokens each; a 1280×720 slide ≈ 1.2k). Preview and `--final` images are ≈72dpi,
|
|
664
|
+
¼ of the default render; `pdf-render … 2` only when fine print must be legible.
|
|
665
|
+
|
|
666
|
+
**Do not declare done before at least one complete build→sign-off→critic cycle.**
|
|
768
667
|
|
|
769
668
|
## CJK notes
|
|
770
669
|
|
|
@@ -66,8 +66,10 @@ after touching a `.tpl`.
|
|
|
66
66
|
让高度由内容决定:网格用 `grid-auto-rows:min-content`(下限必须显式写 `min-content` ——
|
|
67
67
|
`1fr`/`auto` 的自动下限对 `overflow` 非 visible 的网格项一律归零),余量交给外层
|
|
68
68
|
`justify-content:space-between`。这样内容超量时会把后续元素顶出页面,被 `deck-qa` 的
|
|
69
|
-
`off-canvas`/`overlap`
|
|
70
|
-
|
|
69
|
+
`off-canvas`/`overlap` 抓到,而不是变成一排缺了下半截的字。被祖先 `overflow:hidden`
|
|
70
|
+
裁掉的文字不会出现在 pptx 的几何里,运行时的 `deck-qa` 看不到——它只在版式生产线的
|
|
71
|
+
`scripts/deck/deck-qa-sweep.mjs`(`clipped` 硬失败,逐个版式扫整册库)里被拦截;写 bespoke
|
|
72
|
+
页时请直接避免定高容器。
|
|
71
73
|
|
|
72
74
|
## Catalog
|
|
73
75
|
|
|
@@ -186,34 +188,3 @@ styles change their visual grammar without changing layout HTML.
|
|
|
186
188
|
|
|
187
189
|
Adding a **Theme binding** = one entry in `theme-system.json`; adding a **layout** = one
|
|
188
190
|
`layouts/<id>.tpl` plus a candidate role in `profiles.json`. Regenerate `slots.json`.
|
|
189
|
-
|
|
190
|
-
## 反向通道 —— 包内版式如何进入共享库
|
|
191
|
-
|
|
192
|
-
一个 `packs/<id>/` 可以带自己的专属版式(`packs/<id>/layouts/<id>.tpl`,与共享同名
|
|
193
|
-
即遮蔽)。当包里做出来的某一页被证明**不是**包专属的装饰、而是别的族/包也会用得上
|
|
194
|
-
的结构时,把它提升进这个共享库,而不是让每个包各自重复发明。
|
|
195
|
-
|
|
196
|
-
**准入判据**(spec §7.3):**剥掉所有颜色与 `font-family` 之后,它仍表达一个共享库
|
|
197
|
-
没有的结构。** 是 → 提升;否(结构其实通用,专属感全靠色彩/字体/图形语汇撑)→ 留在
|
|
198
|
-
包内,不要提升。
|
|
199
|
-
|
|
200
|
-
跑 `node scripts/ppt-tpl/promote-layout.mjs <packId> <layoutId>`。它只机械校验"可
|
|
201
|
-
提升"的必要条件(零硬编码色、不带私有 `font-family`、只用契约内 class、规范的
|
|
202
|
-
1280×720 单 `section` + `data-layout`、至少一个可填槽位、`layouts/README.md` 表头
|
|
203
|
-
格式没变)——**是不是结构性创新仍需人来判**,脚本不代劳。任一条不满足就拒绝写入
|
|
204
|
-
(不移动文件),并逐条报出缺什么。
|
|
205
|
-
|
|
206
|
-
校验通过后脚本会:把 `.tpl` 移到 `layouts/`、重跑 `scripts/deck/gen-slots.mjs` 重生成
|
|
207
|
-
`slots.json`、在本文件的 Catalog 表格里插入一行占位(`role`/`structure`/`density`/
|
|
208
|
-
`has-image`/`pick when` 均为 `TODO`,附 `promoted from packs/<packId>`)。写入中途
|
|
209
|
-
任何一步失败都会整体回滚(删掉刚写的 `.tpl`,`slots.json`/本文件复原),不会留下
|
|
210
|
-
半成品。
|
|
211
|
-
|
|
212
|
-
提升不是终点,脚本打印的四步收尾都要做:补全本文件里那一行的全部 `TODO`、从
|
|
213
|
-
`packs/<packId>/layouts/` 删掉原文件(否则同名遮蔽会让包永远看不到共享版本、也
|
|
214
|
-
永远吃不到后续对共享版式的修复)、`node scripts/deck/deck-skin-samples.mjs && node
|
|
215
|
-
scripts/deck/deck-fidelity.mjs` 确认它在所有皮肤下都成立、再跑
|
|
216
|
-
`TALOS_TEST_SCOPE=unit npx vitest run tests/unit/deck-layouts.test.ts`。
|
|
217
|
-
|
|
218
|
-
新版式若用到契约外的 class,先扩 `styles/_contract-defaults.css`(本脚本不代劳)——
|
|
219
|
-
但只有 **≥3 个族/包各自独立地需要同一个新原语**时才扩,避免契约被单个包的口味撑肥。
|
|
@@ -4,8 +4,10 @@
|
|
|
4
4
|
`deck-build` 填槽时按 role 注入 `data-anim*` / `data-transition*`;deck.html 里已有的
|
|
5
5
|
同名属性优先,不被覆盖。
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
**`catalog.json` 的每个 entry 都配了预设**(33/33)。用不用由 spec 的 `scenario` 决定
|
|
8
|
+
(`packages/core/src/document/deck-motion.ts::motionForDeck`):演示型场景(pitch/路演/发布会/
|
|
9
|
+
大会/讲座/销售)注入,阅读型场景(内审/评审/报告/汇报/讲义/培训/述职)不注入,未写或认不出
|
|
10
|
+
的场景保持注入;`"motion": true|false` 显式覆盖。没有预设的族不注入任何动画。
|
|
9
11
|
|
|
10
12
|
效果集必须与 `packages/core/src/document/pptx-anim.ts` 一致:
|
|
11
13
|
fade · fade-up · float · appear · fly-up · fly-down · fly-left · fly-right
|
|
@@ -10,7 +10,11 @@ prompt carries a `delivery="file"` pointer at that sidecar. So:
|
|
|
10
10
|
|
|
11
11
|
## What this skill IS for (Office)
|
|
12
12
|
|
|
13
|
-
- **Generate
|
|
13
|
+
- **Generate** a .docx → `doc-gen` (read **rewrite.md**); a deck → the deck path
|
|
14
|
+
(SKILL.md → deck-design.md; `doc-gen` makes no decks).
|
|
15
|
+
- **Edit** an existing .docx / .pptx → **rewrite.md**: `doc-xml replace` for text,
|
|
16
|
+
`doc-fill` for `{{tokens}}`, `pptx-slide` / `pptx-clone` for slides,
|
|
17
|
+
`docx-annotate` for comments and tracked changes.
|
|
14
18
|
- Everything visual (a diagram/chart that matters) → if you can see images, look
|
|
15
19
|
at the original (see vision.md).
|
|
16
20
|
|