@tycoworks/tycoslide 0.11.0 → 0.11.2
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/README.md +2 -0
- package/SKILL.md +0 -1
- package/dist/cli.js +2 -1
- package/dist/engine/generate.js +2 -2
- package/dist/engine/index.d.ts +1 -1
- package/dist/engine/index.js +1 -1
- package/dist/engine/types.d.ts +6 -0
- package/dist/engine/types.js +6 -0
- package/dist/skillZip.d.ts +7 -8
- package/dist/skillZip.js +38 -34
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -16,6 +16,8 @@ Create editable, on-brand PowerPoint slides from markdown.
|
|
|
16
16
|
npm install @tycoworks/tycoslide
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
+
Installing also downloads Chromium (~554MB), via `@playwright/browser-chromium`, which tycoslide uses to render mermaid diagrams. If you install with `--ignore-scripts`, run `npx playwright install chromium-headless-shell` before building a deck with diagrams.
|
|
20
|
+
|
|
19
21
|
Create `deck.md`:
|
|
20
22
|
|
|
21
23
|
```markdown
|
package/SKILL.md
CHANGED
|
@@ -162,7 +162,6 @@ Build the deck again ([Build](#build)) and read the output carefully. Common err
|
|
|
162
162
|
| YAML parse error | Fix the YAML syntax in the slide's frontmatter |
|
|
163
163
|
| `Skipped setting relation target` | The asset image couldn't be placed; check the path and file |
|
|
164
164
|
| `forbidden style directive` | Remove `style`, `classDef`, `linkStyle`, or `%%{init}` from your mermaid block -- use `class` for grouping instead |
|
|
165
|
-
| `Mermaid render failed` | The engine renders diagrams with Playwright's Chromium; install it once with `npx playwright install chromium` |
|
|
166
165
|
| `no "mermaid" block` | The theme has no mermaid color config -- add a `mermaid` section to theme.json |
|
|
167
166
|
|
|
168
167
|
### Verification Loop
|
package/dist/cli.js
CHANGED
|
@@ -79,7 +79,8 @@ program
|
|
|
79
79
|
// Bundle the WHOLE theme so the skill is self-contained: unzip ->
|
|
80
80
|
// `npm install` (pulls the engine + its deps) -> `npx tycoslide build`.
|
|
81
81
|
const zipFile = `${skillName}.zip`;
|
|
82
|
-
|
|
82
|
+
const generated = [opts.config, MANIFEST_FILE, SKILL_FILE, SYNTAX_FILE];
|
|
83
|
+
writeFileSync(resolve(process.cwd(), zipFile), await zipDir(process.cwd(), skillName, config, generated));
|
|
83
84
|
console.log(`WROTE ${zipFile}`);
|
|
84
85
|
});
|
|
85
86
|
await program.parseAsync(process.argv);
|
package/dist/engine/generate.js
CHANGED
|
@@ -33,7 +33,7 @@ import { Automizer, modify } from "pptx-automizer";
|
|
|
33
33
|
import { FILLERS } from "./fillers/filler.js";
|
|
34
34
|
import { isImageFill } from "./fillers/image.js";
|
|
35
35
|
import { applyNotesToSlide, sweepOrphanNotes } from "./notes.js";
|
|
36
|
-
import { SlotType } from "./types.js";
|
|
36
|
+
import { SlotType, TEMPLATE_DIR, } from "./types.js";
|
|
37
37
|
/**
|
|
38
38
|
* Generate a PPTX file from a deck definition and a theme configuration.
|
|
39
39
|
*
|
|
@@ -53,7 +53,7 @@ export async function generate(deck, config, options = {}) {
|
|
|
53
53
|
const outDir = dirname(deck.output);
|
|
54
54
|
const outFile = basename(deck.output);
|
|
55
55
|
const automizer = new Automizer({
|
|
56
|
-
templateDir: resolve(rootDir,
|
|
56
|
+
templateDir: resolve(rootDir, TEMPLATE_DIR),
|
|
57
57
|
outputDir: outDir,
|
|
58
58
|
removeExistingSlides: true,
|
|
59
59
|
autoImportSlideMasters: true,
|
package/dist/engine/index.d.ts
CHANGED
|
@@ -6,4 +6,4 @@ export { fillText, isTextFill } from "./fillers/text.js";
|
|
|
6
6
|
export type { GenerateOptions } from "./generate.js";
|
|
7
7
|
export { generate } from "./generate.js";
|
|
8
8
|
export type { Block, BodyRows, Config, Deck, DeckStep, Frame, ImageFill, Layout, Slot, StyledParagraph, TableFill, TemplateFill, TemplateSegment, TextFill, TextRun, ThemeConfig, } from "./types.js";
|
|
9
|
-
export { ImageFit, SlotType } from "./types.js";
|
|
9
|
+
export { ImageFit, SlotType, TEMPLATE_DIR } from "./types.js";
|
package/dist/engine/index.js
CHANGED
|
@@ -4,4 +4,4 @@ export { fillTable, isTableFill } from "./fillers/table.js";
|
|
|
4
4
|
export { fillTemplate } from "./fillers/template.js";
|
|
5
5
|
export { fillText, isTextFill } from "./fillers/text.js";
|
|
6
6
|
export { generate } from "./generate.js";
|
|
7
|
-
export { ImageFit, SlotType } from "./types.js";
|
|
7
|
+
export { ImageFit, SlotType, TEMPLATE_DIR } from "./types.js";
|
package/dist/engine/types.d.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Theme subdirectory holding the source `.pptx` template. Fixed by convention:
|
|
3
|
+
* `theme.json` names only the file, so the engine resolves the template under
|
|
4
|
+
* this directory and packaging reads it from the same place.
|
|
5
|
+
*/
|
|
6
|
+
export declare const TEMPLATE_DIR = "template";
|
|
1
7
|
/**
|
|
2
8
|
* Fill-strategy discriminator carried on every Slot. Required — there is no
|
|
3
9
|
* silent default. The engine dispatches to fillTemplate / fillText / fillTable /
|
package/dist/engine/types.js
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Theme subdirectory holding the source `.pptx` template. Fixed by convention:
|
|
3
|
+
* `theme.json` names only the file, so the engine resolves the template under
|
|
4
|
+
* this directory and packaging reads it from the same place.
|
|
5
|
+
*/
|
|
6
|
+
export const TEMPLATE_DIR = "template";
|
|
1
7
|
/**
|
|
2
8
|
* Fill-strategy discriminator carried on every Slot. Required — there is no
|
|
3
9
|
* silent default. The engine dispatches to fillTemplate / fillText / fillTable /
|
package/dist/skillZip.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { CompilerThemeConfig } from "./markdown/types.js";
|
|
1
2
|
/**
|
|
2
3
|
* Rewrite the `name:` value in a skill.md's leading YAML frontmatter so the
|
|
3
4
|
* packaged skill is named after the consuming theme, not the source template.
|
|
@@ -6,12 +7,10 @@
|
|
|
6
7
|
*/
|
|
7
8
|
export declare function renameSkill(md: string, name: string): string;
|
|
8
9
|
/**
|
|
9
|
-
* Zip
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* .pptx under template/ is kept). Subdirectory structure is preserved with
|
|
15
|
-
* POSIX slashes. Fails fast if nothing is left to zip.
|
|
10
|
+
* Zip a theme into an uploadable Agent Skill archive whose entries all live
|
|
11
|
+
* under a single root folder (e.g. `mz-slides/theme.json`), matching Anthropic's
|
|
12
|
+
* custom-skill format. `generated` names the files the caller just wrote (the
|
|
13
|
+
* config, manifest, skill.md, syntax.md). Optional support files are skipped
|
|
14
|
+
* when absent; anything the config declares but that is missing is an error.
|
|
16
15
|
*/
|
|
17
|
-
export declare function zipDir(rootDir: string, folderName: string): Promise<Buffer>;
|
|
16
|
+
export declare function zipDir(rootDir: string, folderName: string, config: CompilerThemeConfig, generated: string[]): Promise<Buffer>;
|
package/dist/skillZip.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
3
|
import JSZip from "jszip";
|
|
4
|
+
import { TEMPLATE_DIR } from "./engine/index.js";
|
|
4
5
|
const FRONTMATTER = /^---\n([\s\S]*?)\n---/;
|
|
5
6
|
const NAME_LINE = /^name:[ \t]*.*$/m;
|
|
6
7
|
/**
|
|
@@ -17,47 +18,50 @@ export function renameSkill(md, name) {
|
|
|
17
18
|
throw new Error('skill.md frontmatter has no "name:" line');
|
|
18
19
|
return md.replace(block[0], block[0].replace(NAME_LINE, `name: ${name}`));
|
|
19
20
|
}
|
|
20
|
-
// Never packaged: dependencies (npm install rebuilds them) and hidden entries
|
|
21
|
-
// (name starting with "." — covers VCS, tooling, caches, secrets like .env/.npmrc).
|
|
22
|
-
const EXCLUDE_DIRS = new Set(["node_modules"]);
|
|
23
|
-
// Build artifacts, dropped ONLY at the repo root: decks build to cwd
|
|
24
|
-
// (showcase.pptx, deck.pptx, the output .zip), while the template .pptx lives
|
|
25
|
-
// under template/ and must be kept — so these extensions are pruned top-level only.
|
|
26
|
-
const ROOT_ARTIFACT_EXTS = new Set([".pptx", ".pdf", ".zip"]);
|
|
27
21
|
/**
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
* top-level build artifacts (.pptx/.pdf/.zip at the repo root; the template
|
|
33
|
-
* .pptx under template/ is kept). Subdirectory structure is preserved with
|
|
34
|
-
* POSIX slashes. Fails fast if nothing is left to zip.
|
|
22
|
+
* Files a packaged skill needs beyond the theme's own declarations. `package.json`
|
|
23
|
+
* matters most: the unzip flow is `npm install` -> `npx tycoslide build`, so it
|
|
24
|
+
* restores the engine and any npm-resolved brand fonts. The lockfile is taken
|
|
25
|
+
* when present so that install is reproducible.
|
|
35
26
|
*/
|
|
36
|
-
|
|
27
|
+
const SUPPORT_FILES = ["package.json", "package-lock.json"];
|
|
28
|
+
/**
|
|
29
|
+
* Every path a packaged theme needs, relative to `rootDir` and POSIX-separated.
|
|
30
|
+
*
|
|
31
|
+
* Derived from the theme config rather than filtered out of a directory walk:
|
|
32
|
+
* the config already declares its template and its whole asset catalog, so an
|
|
33
|
+
* allowlist stays correct no matter what else sits in the working directory --
|
|
34
|
+
* built decks, PDFs, slide PNGs, scratch files. Font paths are deliberately
|
|
35
|
+
* absent: they resolve from node_modules, which `npm install` restores.
|
|
36
|
+
*/
|
|
37
|
+
function skillPaths(config, generated) {
|
|
38
|
+
const assets = Object.values(config.assets).flatMap((category) => Object.values(category).map((entry) => entry.path));
|
|
39
|
+
return [...SUPPORT_FILES, ...generated, `${TEMPLATE_DIR}/${config.template}`, ...assets];
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Zip a theme into an uploadable Agent Skill archive whose entries all live
|
|
43
|
+
* under a single root folder (e.g. `mz-slides/theme.json`), matching Anthropic's
|
|
44
|
+
* custom-skill format. `generated` names the files the caller just wrote (the
|
|
45
|
+
* config, manifest, skill.md, syntax.md). Optional support files are skipped
|
|
46
|
+
* when absent; anything the config declares but that is missing is an error.
|
|
47
|
+
*/
|
|
48
|
+
export async function zipDir(rootDir, folderName, config, generated) {
|
|
37
49
|
const zip = new JSZip();
|
|
38
50
|
const folder = zip.folder(folderName);
|
|
39
51
|
if (!folder)
|
|
40
52
|
throw new Error(`Failed to create zip folder: ${folderName}`);
|
|
53
|
+
const optional = new Set(SUPPORT_FILES);
|
|
41
54
|
let count = 0;
|
|
42
|
-
const
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
if (
|
|
55
|
+
for (const rel of skillPaths(config, generated)) {
|
|
56
|
+
const abs = join(rootDir, ...rel.split("/"));
|
|
57
|
+
if (!existsSync(abs)) {
|
|
58
|
+
if (optional.has(rel))
|
|
46
59
|
continue;
|
|
47
|
-
|
|
48
|
-
if (entry.isDirectory()) {
|
|
49
|
-
if (!EXCLUDE_DIRS.has(entry.name))
|
|
50
|
-
walk(abs);
|
|
51
|
-
}
|
|
52
|
-
else if (entry.isFile()) {
|
|
53
|
-
if (atRoot && ROOT_ARTIFACT_EXTS.has(extname(entry.name)))
|
|
54
|
-
continue;
|
|
55
|
-
folder.file(relative(rootDir, abs).split(sep).join("/"), readFileSync(abs));
|
|
56
|
-
count++;
|
|
57
|
-
}
|
|
60
|
+
throw new Error(`Theme declares "${rel}", but no such file exists`);
|
|
58
61
|
}
|
|
59
|
-
|
|
60
|
-
|
|
62
|
+
folder.file(rel, readFileSync(abs));
|
|
63
|
+
count++;
|
|
64
|
+
}
|
|
61
65
|
if (count === 0)
|
|
62
66
|
throw new Error(`No files to zip in directory: ${rootDir}`);
|
|
63
67
|
return zip.generateAsync({ type: "nodebuffer" });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tycoworks/tycoslide",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.2",
|
|
4
4
|
"description": "Create editable, on-brand PowerPoint slides from markdown.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -23,12 +23,13 @@
|
|
|
23
23
|
"format": "biome format --write ."
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
+
"@playwright/browser-chromium": "^1.62.1",
|
|
26
27
|
"@xmldom/xmldom": "^0.9.10",
|
|
27
28
|
"commander": "^15.0.0",
|
|
28
29
|
"image-size": "^2.0.2",
|
|
29
30
|
"jszip": "^3.10.1",
|
|
30
31
|
"mermaid": "^11.16.1",
|
|
31
|
-
"playwright": "^1.
|
|
32
|
+
"playwright": "^1.62.1",
|
|
32
33
|
"pptx-automizer": "^0.8.2",
|
|
33
34
|
"remark-gfm": "^4.0.1",
|
|
34
35
|
"remark-ins": "^1.2.5",
|