@tycoworks/tycoslide 0.7.0 → 0.9.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/README.md +6 -6
- package/SKILL.md +2 -1
- package/dist/cli.js +8 -107
- package/dist/engine/dom.d.ts +5 -0
- package/dist/engine/dom.js +19 -3
- package/dist/engine/fillers/filler.d.ts +21 -13
- package/dist/engine/fillers/filler.js +21 -27
- package/dist/engine/fillers/image.d.ts +46 -7
- package/dist/engine/fillers/image.js +78 -36
- package/dist/engine/fillers/table.d.ts +4 -3
- package/dist/engine/fillers/table.js +58 -9
- package/dist/engine/generate.d.ts +34 -18
- package/dist/engine/generate.js +234 -65
- package/dist/engine/index.d.ts +3 -2
- package/dist/engine/index.js +1 -1
- package/dist/engine/notes.d.ts +76 -0
- package/dist/engine/notes.js +313 -0
- package/dist/engine/types.d.ts +57 -24
- package/dist/engine/types.js +11 -7
- package/dist/index.d.ts +19 -25
- package/dist/index.js +65 -92
- package/dist/manifest.js +19 -29
- package/dist/markdown/blocks/code.d.ts +15 -0
- package/dist/markdown/blocks/code.js +50 -0
- package/dist/markdown/blocks/image.d.ts +2 -0
- package/dist/markdown/blocks/image.js +9 -0
- package/dist/markdown/blocks/mermaid.d.ts +15 -0
- package/dist/markdown/blocks/mermaid.js +227 -0
- package/dist/markdown/{resolvers → blocks}/mermaidTheme.d.ts +1 -1
- package/dist/markdown/{resolvers → blocks}/mermaidTheme.js +1 -1
- package/dist/markdown/blocks/registry.d.ts +16 -0
- package/dist/markdown/blocks/registry.js +44 -0
- package/dist/markdown/blocks/table.d.ts +2 -0
- package/dist/markdown/blocks/table.js +23 -0
- package/dist/markdown/blocks/text.d.ts +12 -0
- package/dist/markdown/blocks/text.js +90 -0
- package/dist/markdown/deckCompiler.d.ts +18 -30
- package/dist/markdown/deckCompiler.js +167 -122
- package/dist/markdown/index.d.ts +11 -11
- package/dist/markdown/index.js +9 -8
- package/dist/markdown/inline.d.ts +26 -0
- package/dist/markdown/inline.js +136 -0
- package/dist/markdown/mdast.d.ts +25 -0
- package/dist/markdown/mdast.js +49 -0
- package/dist/markdown/schema/deckSchema.d.ts +30 -0
- package/dist/markdown/schema/deckSchema.js +51 -0
- package/dist/markdown/schema/strict.d.ts +9 -0
- package/dist/markdown/schema/strict.js +18 -0
- package/dist/markdown/schema/themeConfigSchema.d.ts +99 -0
- package/dist/markdown/schema/themeConfigSchema.js +145 -0
- package/dist/markdown/types.d.ts +184 -137
- package/dist/markdown/types.js +30 -19
- package/package.json +7 -3
- package/syntax.md +25 -5
- package/dist/markdown/parsers.d.ts +0 -32
- package/dist/markdown/parsers.js +0 -233
- package/dist/markdown/resolvers/code.d.ts +0 -17
- package/dist/markdown/resolvers/code.js +0 -44
- package/dist/markdown/resolvers/mermaid.d.ts +0 -14
- package/dist/markdown/resolvers/mermaid.js +0 -89
- package/dist/markdown/resolvers/resolver.d.ts +0 -42
- package/dist/markdown/resolvers/resolver.js +0 -52
package/dist/markdown/types.d.ts
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
|
-
import
|
|
2
|
-
import type
|
|
1
|
+
import type { RootContent } from "mdast";
|
|
2
|
+
import { type Frame, type ImageFill, type TableFill, type TemplateFill, type TextFill } from "../engine/index.js";
|
|
3
|
+
import type { MermaidConfig } from "./blocks/mermaidTheme.js";
|
|
4
|
+
/**
|
|
5
|
+
* An asset's scaling/cropping tolerance, declared in the theme catalog. The
|
|
6
|
+
* compiler maps it to the engine's object-fit `fit`. `icon`: never enlarge,
|
|
7
|
+
* never crop. `image`: never crop, may scale. `background`: crop and scale freely.
|
|
8
|
+
*/
|
|
9
|
+
export declare const AssetType: {
|
|
10
|
+
readonly Icon: "icon";
|
|
11
|
+
readonly Image: "image";
|
|
12
|
+
readonly Background: "background";
|
|
13
|
+
};
|
|
14
|
+
export type AssetType = (typeof AssetType)[keyof typeof AssetType];
|
|
3
15
|
/**
|
|
4
16
|
* A theme's declaration of a reusable image asset. Purely compiler-facing —
|
|
5
17
|
* the engine never sees this type; the compiler resolves an entry's `path`
|
|
@@ -8,23 +20,13 @@ import type { MermaidConfig } from "./resolvers/mermaidTheme.js";
|
|
|
8
20
|
*/
|
|
9
21
|
export type AssetEntry = {
|
|
10
22
|
path: string;
|
|
23
|
+
/** Required — a missing type is a fail-fast error. */
|
|
24
|
+
type: AssetType;
|
|
11
25
|
description: string;
|
|
12
26
|
whenToUse?: string;
|
|
13
27
|
};
|
|
14
28
|
/** Two-level catalog: `{ category: { name: AssetEntry } }`. */
|
|
15
29
|
export type AssetCatalog = Record<string, Record<string, AssetEntry>>;
|
|
16
|
-
/**
|
|
17
|
-
* Discriminator strings for the compiler-internal fence shapes produced by
|
|
18
|
-
* deckCompiler.ts. `Code` and `Mermaid` are resolved away entirely (syntax
|
|
19
|
-
* highlighting → TextFill, PNG rendering → ImageFill), so neither reaches the
|
|
20
|
-
* engine. Prose has no FenceType: it becomes a `TextFill` (`{ paragraphs }`),
|
|
21
|
-
* one of the engine's own fill shapes.
|
|
22
|
-
*/
|
|
23
|
-
export declare const FenceType: {
|
|
24
|
-
readonly Code: "code";
|
|
25
|
-
readonly Mermaid: "mermaid";
|
|
26
|
-
};
|
|
27
|
-
export type FenceType = (typeof FenceType)[keyof typeof FenceType];
|
|
28
30
|
/**
|
|
29
31
|
* Discriminator for a layout's frontmatter *parameters* — inputs the author
|
|
30
32
|
* writes as a single `key: value` line. Two kinds: `Template` (fills a styled
|
|
@@ -38,58 +40,84 @@ export declare const ParameterType: {
|
|
|
38
40
|
};
|
|
39
41
|
export type ParameterType = (typeof ParameterType)[keyof typeof ParameterType];
|
|
40
42
|
/**
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
* `
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
43
|
+
* The engine content types a slot may `accept`. A subset of the engine's
|
|
44
|
+
* `SlotType`: `Template` is parameter-only, never a body block. There is no
|
|
45
|
+
* `code` / `mermaid` accept type — a code fence folds into a `Text`-accepting
|
|
46
|
+
* slot (syntax highlighting → TextFill) and a mermaid fence into an
|
|
47
|
+
* `Image`-accepting slot (PNG render → ImageFill), the same fold the engine
|
|
48
|
+
* already performs. The author's markdown shape selects which accepted type a
|
|
49
|
+
* region routes to.
|
|
47
50
|
*/
|
|
48
|
-
export declare const
|
|
51
|
+
export declare const AcceptType: {
|
|
49
52
|
readonly Text: "text";
|
|
50
53
|
readonly Table: "table";
|
|
51
|
-
readonly
|
|
52
|
-
readonly Mermaid: "mermaid";
|
|
54
|
+
readonly Image: "image";
|
|
53
55
|
};
|
|
54
|
-
export type
|
|
56
|
+
export type AcceptType = (typeof AcceptType)[keyof typeof AcceptType];
|
|
55
57
|
/**
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
+
* The four engine content shapes a slot's compiled content can be — the value
|
|
59
|
+
* `compile` produces and the engine fills. ImageFill carries a `.type`
|
|
60
|
+
* discriminator; the other three — TextFill, TableFill, TemplateFill — are
|
|
61
|
+
* identified structurally by their signature field.
|
|
58
62
|
*/
|
|
59
|
-
export type
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
63
|
+
export type EngineFill = TextFill | TableFill | ImageFill | TemplateFill;
|
|
64
|
+
/**
|
|
65
|
+
* The three engine content shapes a block handler can produce. A subset of
|
|
66
|
+
* `EngineFill` — `TemplateFill` is parameter-only (`AcceptType` excludes
|
|
67
|
+
* `Template`), so no block handler ever compiles one.
|
|
68
|
+
*/
|
|
69
|
+
export type BlockFill = TextFill | TableFill | ImageFill;
|
|
64
70
|
/**
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
71
|
+
* Everything a block handler needs to compile a node into its engine fill: the
|
|
72
|
+
* asset resolver, the diagnostic context to name the offending layout/slide/slot
|
|
73
|
+
* when a region's markdown shape is illegal (a stray standalone block mixed into
|
|
74
|
+
* prose), and the theme-level `config` — from which code/mermaid compile read
|
|
75
|
+
* their one-per-theme style (`codeTheme`, `mermaid`, `mermaidVariant`,
|
|
76
|
+
* `outputDir`), not the slot.
|
|
77
|
+
*
|
|
78
|
+
* Lives in types.ts (not in `blocks/registry.ts`, which re-exports it) so a
|
|
79
|
+
* per-kind block file can import it without importing the registry — the registry
|
|
80
|
+
* imports the per-kind handlers, so the reverse would cycle.
|
|
68
81
|
*/
|
|
69
|
-
export type
|
|
70
|
-
|
|
71
|
-
|
|
82
|
+
export type BlockContext = {
|
|
83
|
+
resolveAssetRef: (ref: string) => ImageFill;
|
|
84
|
+
layoutName: string;
|
|
85
|
+
slideIdx: number;
|
|
86
|
+
source: string;
|
|
87
|
+
config: CompilerConfig;
|
|
72
88
|
};
|
|
73
89
|
/**
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
90
|
+
* A block handler recognizes one content kind at the region's top level, folds
|
|
91
|
+
* it to the engine `AcceptType` it fills, and compiles the node straight into the
|
|
92
|
+
* matching engine fill — highlighting a code fence to a TextFill, rendering a
|
|
93
|
+
* mermaid fence to an ImageFill. Recognition (`match`), type (`acceptType`), and
|
|
94
|
+
* build (`compile`) live together — a new content kind is one file, one registry
|
|
95
|
+
* row. Non-generic like the engine's `Filler`: the array can't correlate a
|
|
96
|
+
* per-element type guard with `compile`'s param, so each handler narrows the node
|
|
97
|
+
* internally with a single-hop cast. Mirrors the old sdk's `SyntaxHandler`.
|
|
79
98
|
*/
|
|
80
|
-
export type
|
|
99
|
+
export type BlockHandler = {
|
|
100
|
+
match(node: RootContent): boolean;
|
|
101
|
+
acceptType: AcceptType;
|
|
102
|
+
compile(node: RootContent, ctx: BlockContext): Promise<BlockFill>;
|
|
103
|
+
};
|
|
81
104
|
/**
|
|
82
|
-
* A DeckStep as
|
|
83
|
-
*
|
|
84
|
-
*
|
|
105
|
+
* A DeckStep as the compiler produces it. Content is already engine-shaped —
|
|
106
|
+
* code fences highlighted to TextFill and mermaid fences rendered to ImageFill
|
|
107
|
+
* during `compile` — so this is structurally equivalent to the engine's DeckStep
|
|
108
|
+
* and needs no further resolution.
|
|
85
109
|
*/
|
|
86
110
|
export type CompilerDeckStep = {
|
|
87
111
|
layout: string;
|
|
88
|
-
content?: Record<string,
|
|
112
|
+
content?: Record<string, EngineFill>;
|
|
113
|
+
/** Slide-level speaker notes, stripped from frontmatter. Plain text. */
|
|
114
|
+
notes?: string;
|
|
89
115
|
};
|
|
90
116
|
/**
|
|
91
|
-
* The
|
|
92
|
-
*
|
|
117
|
+
* The deck shape the compiler produces. `output` may be unset until a caller
|
|
118
|
+
* (the CLI, or a programmatic caller) assigns one; `buildDeck` fails fast if it
|
|
119
|
+
* is still missing. Once `output` is present this is structurally equivalent to
|
|
120
|
+
* the engine's Deck, so `generate` consumes it without any cast.
|
|
93
121
|
*/
|
|
94
122
|
export type CompilerDeck = {
|
|
95
123
|
theme: string;
|
|
@@ -97,50 +125,15 @@ export type CompilerDeck = {
|
|
|
97
125
|
steps: CompilerDeckStep[];
|
|
98
126
|
};
|
|
99
127
|
/**
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
128
|
+
* Markdown-flavored measurement hints on a slot or template parameter: caps on
|
|
129
|
+
* expanded run text, line count, or list items. All optional — a missing cap is
|
|
130
|
+
* "no limit." Advisory metadata surfaced in the manifest; the fill never enforces
|
|
131
|
+
* it.
|
|
103
132
|
*/
|
|
104
|
-
export type
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* A CompilerDeck whose steps have been passed through the resolvers via
|
|
110
|
-
* `resolveFences`. Structurally equivalent to the engine's Deck — deck
|
|
111
|
-
* resolution returns this shape so `generate` can consume it without any cast.
|
|
112
|
-
*/
|
|
113
|
-
export type ResolvedCompilerDeck = {
|
|
114
|
-
theme: string;
|
|
115
|
-
output: string;
|
|
116
|
-
steps: ResolvedCompilerDeckStep[];
|
|
117
|
-
};
|
|
118
|
-
/**
|
|
119
|
-
* Fields common to every text shape, image parameter, and slot. A text shape is
|
|
120
|
-
* addressed by `shapeName` and owns a `template` (its placeholders are the
|
|
121
|
-
* fillable keys); image parameters and slots additionally carry a single `key`.
|
|
122
|
-
*/
|
|
123
|
-
type CompilerShapeBase = {
|
|
124
|
-
shapeName: string;
|
|
125
|
-
limit?: {
|
|
126
|
-
maxChars?: number;
|
|
127
|
-
maxLines?: number;
|
|
128
|
-
maxItems?: number;
|
|
129
|
-
};
|
|
130
|
-
/**
|
|
131
|
-
* Whether the parameter/slot may be omitted from a slide. Optional (defaults
|
|
132
|
-
* to false): a required one with no value causes the compiler to throw with
|
|
133
|
-
* layout + key names.
|
|
134
|
-
*/
|
|
135
|
-
required?: boolean;
|
|
136
|
-
};
|
|
137
|
-
/**
|
|
138
|
-
* Shape base plus a single `key` — the addressing model for image parameters
|
|
139
|
-
* and every slot. Template parameters do NOT extend this: their fillable keys are
|
|
140
|
-
* the placeholders in their `template`, not a single top-level key.
|
|
141
|
-
*/
|
|
142
|
-
type CompilerSlotBase = CompilerShapeBase & {
|
|
143
|
-
key: string;
|
|
133
|
+
export type Limit = {
|
|
134
|
+
maxChars?: number;
|
|
135
|
+
maxLines?: number;
|
|
136
|
+
maxItems?: number;
|
|
144
137
|
};
|
|
145
138
|
/**
|
|
146
139
|
* Template parameter: a styled text shape filled by expanding a `template` into the
|
|
@@ -150,76 +143,117 @@ type CompilerSlotBase = CompilerShapeBase & {
|
|
|
150
143
|
* placeholders in its template. The shape carries no top-level `key`; its
|
|
151
144
|
* placeholders are the keys the author fills in frontmatter.
|
|
152
145
|
*/
|
|
153
|
-
export type CompilerTemplateParameter =
|
|
146
|
+
export type CompilerTemplateParameter = {
|
|
147
|
+
shapeName: string;
|
|
148
|
+
limit?: Limit;
|
|
149
|
+
/**
|
|
150
|
+
* Whether the parameter may be omitted from a slide. Optional (defaults to
|
|
151
|
+
* false): a required one with no value causes the compiler to throw with
|
|
152
|
+
* layout + key names.
|
|
153
|
+
*/
|
|
154
|
+
required?: boolean;
|
|
154
155
|
type: typeof ParameterType.Template;
|
|
155
156
|
/** The shape's text as one template with `{key}` placeholders; newlines are line breaks. */
|
|
156
157
|
template: string;
|
|
157
158
|
};
|
|
158
|
-
/** Image parameter: one frontmatter path filled by fillImage.
|
|
159
|
-
|
|
159
|
+
/** Image parameter: one frontmatter path filled by fillImage. Sizing/crop
|
|
160
|
+
* behaviour comes from the resolved asset's `type`, not the slot. Carries no
|
|
161
|
+
* `limit` — measuring an image path against char/line caps is meaningless. */
|
|
162
|
+
export type CompilerImageParameter = {
|
|
163
|
+
shapeName: string;
|
|
164
|
+
/**
|
|
165
|
+
* Whether the parameter may be omitted from a slide. Optional (defaults to
|
|
166
|
+
* false): a required one with no value causes the compiler to throw with
|
|
167
|
+
* layout + key names.
|
|
168
|
+
*/
|
|
169
|
+
required?: boolean;
|
|
170
|
+
key: string;
|
|
160
171
|
type: typeof ParameterType.Image;
|
|
161
|
-
/** How the picture scales inside its frame (required — no silent default). */
|
|
162
|
-
fit: FitMode;
|
|
163
172
|
};
|
|
164
173
|
/**
|
|
165
174
|
* Compiler-facing parameter. A layout's frontmatter inputs — each written as a
|
|
166
175
|
* single `key: value` line, resolved against the layout's `parameters` list.
|
|
167
176
|
*/
|
|
168
177
|
export type CompilerParameter = CompilerTemplateParameter | CompilerImageParameter;
|
|
169
|
-
/** Multi-paragraph body filled by fillText (specimen-style rebuild). */
|
|
170
|
-
export type CompilerTextSlot = CompilerSlotBase & {
|
|
171
|
-
type: typeof CompilerSlotType.Text;
|
|
172
|
-
/** Leave the first N specimen paragraphs untouched. */
|
|
173
|
-
startAt?: number;
|
|
174
|
-
};
|
|
175
|
-
/** Table shape backed by an `<a:tbl>` with header + data specimen rows. */
|
|
176
|
-
export type CompilerTableSlot = CompilerSlotBase & {
|
|
177
|
-
type: typeof CompilerSlotType.Table;
|
|
178
|
-
/** Enforced column count. */
|
|
179
|
-
columns?: number;
|
|
180
|
-
};
|
|
181
178
|
/**
|
|
182
|
-
*
|
|
183
|
-
*
|
|
184
|
-
*
|
|
179
|
+
* Reserved keys in a deck's frontmatter — global (theme, output) and per-slide
|
|
180
|
+
* (layout, body). Exported so callers (e.g. cli.ts) reference the constants
|
|
181
|
+
* instead of literal strings.
|
|
185
182
|
*/
|
|
186
|
-
export
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
183
|
+
export declare const RESERVED_KEY: {
|
|
184
|
+
readonly LAYOUT: "layout";
|
|
185
|
+
readonly BODY: "body";
|
|
186
|
+
readonly OUTPUT: "output";
|
|
187
|
+
readonly THEME: "theme";
|
|
188
|
+
readonly NOTES: "notes";
|
|
190
189
|
};
|
|
191
190
|
/**
|
|
192
|
-
*
|
|
193
|
-
*
|
|
194
|
-
*
|
|
195
|
-
*
|
|
191
|
+
* A kind of content a slot accepts, and the real template shape that realizes
|
|
192
|
+
* it — the compiler mirror of the engine's `Block`. `type` is an engine content
|
|
193
|
+
* type (`text` | `table` | `image`); `shapeName` names the shape on
|
|
194
|
+
* `sourceSlide` carrying the specimen styling. When `sourceSlide` equals the
|
|
195
|
+
* layout's `slideNumber` the shape is already on the cloned slide (fill in
|
|
196
|
+
* place); otherwise it is transplanted into the slot's `frame`. `startAt` is a
|
|
197
|
+
* text-specimen concern (leave the first N specimen paragraphs untouched), only
|
|
198
|
+
* meaningful on a text block. Named `CompilerBlock` to stay distinct from the
|
|
199
|
+
* engine's `Block` and the compiler's `BlockHandler`.
|
|
196
200
|
*/
|
|
197
|
-
export type
|
|
198
|
-
type:
|
|
199
|
-
|
|
200
|
-
|
|
201
|
+
export type CompilerBlock = {
|
|
202
|
+
type: AcceptType;
|
|
203
|
+
sourceSlide: number;
|
|
204
|
+
shapeName: string;
|
|
205
|
+
startAt?: number;
|
|
201
206
|
};
|
|
202
207
|
/**
|
|
203
|
-
* Compiler-facing slot.
|
|
204
|
-
*
|
|
205
|
-
*
|
|
206
|
-
*
|
|
207
|
-
*
|
|
208
|
-
*
|
|
209
|
-
*
|
|
208
|
+
* Compiler-facing slot. A layout's body region (the default region, or a
|
|
209
|
+
* `::name::` region), no longer welded to one shape+type: it `accepts` a set of
|
|
210
|
+
* `CompilerBlock`s and owns a `frame` (real observed EMU coordinates, never
|
|
211
|
+
* computed). The author's markdown shape selects which accepted block a region
|
|
212
|
+
* routes to; a type the slot does not accept fails fast. `frame` is required
|
|
213
|
+
* only when a slot has a transplant block (a block whose `sourceSlide` differs
|
|
214
|
+
* from the layout's `slideNumber`); a base-only slot fills in place and needs
|
|
215
|
+
* none. Adds markdown-flavored `limit` hints on top of the engine's minimal
|
|
216
|
+
* Slot; per-slot `codeTheme` / `mermaidVariant` moved to the theme level.
|
|
210
217
|
*/
|
|
211
|
-
export type CompilerSlot =
|
|
218
|
+
export type CompilerSlot = {
|
|
219
|
+
key: string;
|
|
220
|
+
accepts: CompilerBlock[];
|
|
221
|
+
frame?: Frame;
|
|
222
|
+
limit?: Limit;
|
|
223
|
+
/**
|
|
224
|
+
* Whether the slot may be omitted from a slide. Optional (defaults to false):
|
|
225
|
+
* a required slot with no content throws with layout + key names.
|
|
226
|
+
*/
|
|
227
|
+
required?: boolean;
|
|
228
|
+
};
|
|
212
229
|
export type CompilerLayout = {
|
|
213
230
|
name: string;
|
|
214
231
|
slideNumber: number;
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
232
|
+
/** Optional prose — a layout is a shape, not a purpose (agent-guidance descoped). */
|
|
233
|
+
description?: string;
|
|
234
|
+
whenToUse?: string;
|
|
235
|
+
whenNotToUse?: string;
|
|
218
236
|
/** Frontmatter inputs (template, image) — one value per `key: value` line. */
|
|
219
237
|
parameters: CompilerParameter[];
|
|
220
|
-
/** Body regions
|
|
238
|
+
/** Body regions — the default body or `::name::` regions; each `accepts` blocks. */
|
|
221
239
|
slots: CompilerSlot[];
|
|
222
240
|
};
|
|
241
|
+
/**
|
|
242
|
+
* A brand font the theme hands the compiler for HTML-based rendering (currently
|
|
243
|
+
* mermaid). Purely compiler-facing — the engine fills PPTX shapes, whose fonts
|
|
244
|
+
* live in the template, and never sees this. `path` is a module specifier
|
|
245
|
+
* (`@fontsource/inter/files/inter-latin-400-normal.woff2`) resolved from the
|
|
246
|
+
* theme's directory, or a `./`- / `/`-prefixed filesystem path resolved against
|
|
247
|
+
* `rootDir`; `family` is the CSS `font-family` name the mermaid variant's
|
|
248
|
+
* `fontFamily` must match. Register weight 400 + 700 to avoid synthetic bold on
|
|
249
|
+
* node labels. The mechanism is generic — the theme names its own fonts.
|
|
250
|
+
*/
|
|
251
|
+
export type ThemeFont = {
|
|
252
|
+
family: string;
|
|
253
|
+
path: string;
|
|
254
|
+
/** OpenType weight (default 400). */
|
|
255
|
+
weight?: number;
|
|
256
|
+
};
|
|
223
257
|
/**
|
|
224
258
|
* Compiler-facing theme configuration. Mirrors the engine's ThemeConfig but
|
|
225
259
|
* carries markdown-flavored fields (mermaid variants) that live outside the
|
|
@@ -232,8 +266,21 @@ export type CompilerThemeConfig = {
|
|
|
232
266
|
template: string;
|
|
233
267
|
outputDir?: string;
|
|
234
268
|
mermaid?: MermaidConfig;
|
|
269
|
+
/**
|
|
270
|
+
* Brand fonts injected as `@font-face` when rendering mermaid, so diagram text
|
|
271
|
+
* uses the theme font instead of a Chromium fallback. Optional — with none
|
|
272
|
+
* declared, mermaid renders in whatever the OS substitutes.
|
|
273
|
+
*/
|
|
274
|
+
fonts?: ThemeFont[];
|
|
275
|
+
/**
|
|
276
|
+
* Theme-level defaults for the two content types the compiler resolves before
|
|
277
|
+
* the engine sees them. One code style and one mermaid style per theme (the
|
|
278
|
+
* design-system framing) — they can't sit on a multi-type slot. `codeTheme` is
|
|
279
|
+
* a Shiki theme id; `mermaidVariant` names an entry in `mermaid`.
|
|
280
|
+
*/
|
|
281
|
+
codeTheme?: string;
|
|
282
|
+
mermaidVariant?: string;
|
|
235
283
|
};
|
|
236
284
|
export type CompilerConfig = CompilerThemeConfig & {
|
|
237
285
|
rootDir: string;
|
|
238
286
|
};
|
|
239
|
-
export {};
|
package/dist/markdown/types.js
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import { SlotType, } from "../engine/index.js";
|
|
2
|
-
// ──
|
|
2
|
+
// ── Asset catalog (compiler / theme-metadata only) ───────────────────────────
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* engine. Prose has no FenceType: it becomes a `TextFill` (`{ paragraphs }`),
|
|
8
|
-
* one of the engine's own fill shapes.
|
|
4
|
+
* An asset's scaling/cropping tolerance, declared in the theme catalog. The
|
|
5
|
+
* compiler maps it to the engine's object-fit `fit`. `icon`: never enlarge,
|
|
6
|
+
* never crop. `image`: never crop, may scale. `background`: crop and scale freely.
|
|
9
7
|
*/
|
|
10
|
-
export const
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
export const AssetType = {
|
|
9
|
+
Icon: "icon",
|
|
10
|
+
Image: "image",
|
|
11
|
+
Background: "background",
|
|
13
12
|
};
|
|
14
13
|
// ── ParameterType discriminator (frontmatter, one value) ──────────────────────
|
|
15
14
|
/**
|
|
@@ -23,18 +22,30 @@ export const ParameterType = {
|
|
|
23
22
|
Template: SlotType.Template,
|
|
24
23
|
Image: SlotType.Image,
|
|
25
24
|
};
|
|
26
|
-
// ──
|
|
25
|
+
// ── AcceptType discriminator (what a slot accepts) ────────────────────────────
|
|
27
26
|
/**
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* `
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
27
|
+
* The engine content types a slot may `accept`. A subset of the engine's
|
|
28
|
+
* `SlotType`: `Template` is parameter-only, never a body block. There is no
|
|
29
|
+
* `code` / `mermaid` accept type — a code fence folds into a `Text`-accepting
|
|
30
|
+
* slot (syntax highlighting → TextFill) and a mermaid fence into an
|
|
31
|
+
* `Image`-accepting slot (PNG render → ImageFill), the same fold the engine
|
|
32
|
+
* already performs. The author's markdown shape selects which accepted type a
|
|
33
|
+
* region routes to.
|
|
34
34
|
*/
|
|
35
|
-
export const
|
|
35
|
+
export const AcceptType = {
|
|
36
36
|
Text: SlotType.Text,
|
|
37
37
|
Table: SlotType.Table,
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
Image: SlotType.Image,
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Reserved keys in a deck's frontmatter — global (theme, output) and per-slide
|
|
42
|
+
* (layout, body). Exported so callers (e.g. cli.ts) reference the constants
|
|
43
|
+
* instead of literal strings.
|
|
44
|
+
*/
|
|
45
|
+
export const RESERVED_KEY = {
|
|
46
|
+
LAYOUT: "layout",
|
|
47
|
+
BODY: "body",
|
|
48
|
+
OUTPUT: "output",
|
|
49
|
+
THEME: "theme",
|
|
50
|
+
NOTES: "notes",
|
|
40
51
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tycoworks/tycoslide",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -22,20 +22,24 @@
|
|
|
22
22
|
"format": "biome format --write ."
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
+
"@xmldom/xmldom": "^0.9.10",
|
|
25
26
|
"commander": "^15.0.0",
|
|
26
27
|
"image-size": "^2.0.2",
|
|
28
|
+
"mermaid": "^11.16.1",
|
|
29
|
+
"playwright": "^1.58.2",
|
|
27
30
|
"pptx-automizer": "^0.8.2",
|
|
28
31
|
"remark-gfm": "^4.0.1",
|
|
29
32
|
"remark-ins": "^1.2.5",
|
|
30
33
|
"remark-parse": "^11.0.0",
|
|
31
34
|
"shiki": "^4.3.0",
|
|
32
35
|
"unified": "^11.0.0",
|
|
33
|
-
"yaml": "^2.0.0"
|
|
36
|
+
"yaml": "^2.0.0",
|
|
37
|
+
"zod": "^4.4.3"
|
|
34
38
|
},
|
|
35
39
|
"devDependencies": {
|
|
36
40
|
"@biomejs/biome": "^2.5.1",
|
|
37
41
|
"@types/node": "^22.20.0",
|
|
38
|
-
"
|
|
42
|
+
"jszip": "^3.10.1",
|
|
39
43
|
"typescript": "^5.8.0"
|
|
40
44
|
}
|
|
41
45
|
}
|
package/syntax.md
CHANGED
|
@@ -91,7 +91,7 @@ A layout advertises two kinds of author-facing input, split by one rule: **a par
|
|
|
91
91
|
"parameters": [
|
|
92
92
|
{ "key": "title", "type": "template" },
|
|
93
93
|
{ "key": "subtitle", "type": "template" },
|
|
94
|
-
{ "key": "logo", "type": "image", "
|
|
94
|
+
{ "key": "logo", "type": "image", "required": true }
|
|
95
95
|
],
|
|
96
96
|
"slots": [
|
|
97
97
|
{ "key": "body", "type": "text" },
|
|
@@ -114,7 +114,7 @@ Fill a parameter by putting a value under its key in the slide's frontmatter.
|
|
|
114
114
|
jobTitle: CEO, Acme Corp
|
|
115
115
|
```
|
|
116
116
|
The engine substitutes each value into the run that carries its style, so if the designer made the name bold and the job title grey, the filled name stays bold and the filled title stays grey.
|
|
117
|
-
- **`image`** -- a picture placeholder. Set it in frontmatter with the image path (from an asset catalog entry, or an absolute path).
|
|
117
|
+
- **`image`** -- a picture placeholder. Set it in frontmatter with the image path (from an asset catalog entry, or an absolute path). How it is scaled and cropped is set by the **asset's `type`** in the catalog (`icon` never enlarges past native and never crops; `image` fits the whole picture without cropping; `background` fills the frame and center-crops).
|
|
118
118
|
```yaml
|
|
119
119
|
hero: assets/diagrams/architecture.png
|
|
120
120
|
```
|
|
@@ -136,13 +136,13 @@ Fill a slot by writing a region in the body: the default (unmarked) region maps
|
|
|
136
136
|
```
|
|
137
137
|
````
|
|
138
138
|
The language tag (e.g. `sql`, `python`, `typescript`) is required -- it drives syntax highlighting. Colors are applied as native text runs in the output, not images.
|
|
139
|
-
- **`mermaid`** -- a mermaid diagram rendered as a themed PNG (see below). Written as a fenced `mermaid` region; the resulting PNG
|
|
139
|
+
- **`mermaid`** -- a mermaid diagram rendered as a themed PNG (see below). Written as a fenced `mermaid` region; the resulting PNG is shown contained (in its entirety).
|
|
140
140
|
|
|
141
141
|
---
|
|
142
142
|
|
|
143
143
|
## Mermaid diagrams
|
|
144
144
|
|
|
145
|
-
Mermaid diagrams are rendered as themed PNGs and delivered to any slot declared with `type: mermaid`. Write a fenced code block with the `mermaid` language tag in a named slot whose layout declares that slot as `type: mermaid` (with a `mermaidVariant` naming the theme's color variant). The resulting PNG behaves like any other image in the slot -- always shown in its entirety
|
|
145
|
+
Mermaid diagrams are rendered as themed PNGs and delivered to any slot declared with `type: mermaid`. Write a fenced code block with the `mermaid` language tag in a named slot whose layout declares that slot as `type: mermaid` (with a `mermaidVariant` naming the theme's color variant). The resulting PNG behaves like any other image in the slot -- always shown in its entirety.
|
|
146
146
|
|
|
147
147
|
To let the same physical slide accept either an image or a diagram, the theme author declares two layouts with the same `slideNumber` -- one exposing the fill as an `image` parameter (frontmatter path), one as a `mermaid` slot (a fenced region). Authors pick between them by naming the layout in frontmatter; the compiler routes content based on the layout's declaration, so there is no ambiguity.
|
|
148
148
|
|
|
@@ -214,7 +214,7 @@ hero: assets/diagrams/architecture.png
|
|
|
214
214
|
Each parameter or slot in the layout definition may declare:
|
|
215
215
|
- **`type`** (required) -- parameters: `template`, `image`; slots: `text`, `table`, `code`, `mermaid`.
|
|
216
216
|
- **`required: true`** -- the slide has no usable default and the build fails if the parameter/slot has no value (e.g. team-member photos, icon-grid icons, the quote logo). If you don't have a suitable image, ask the user for one.
|
|
217
|
-
-
|
|
217
|
+
- **image sizing** -- each catalog asset declares a `type` (`icon` | `image` | `background`) that determines how it is scaled and cropped: `icon` never enlarges past native and never crops; `image` fits the whole picture (no crop, may scale); `background` fills and center-crops. Mermaid renders as `image` (contained).
|
|
218
218
|
- **`codeTheme`** -- code slots only (required): the Shiki theme id used to syntax-highlight fenced code that lands in this slot (e.g. `"github-dark"`).
|
|
219
219
|
- **`mermaidVariant`** -- mermaid slots only (required): names the color variant from `theme.mermaid` (e.g. `"dark"`). See [Mermaid diagrams](#mermaid-diagrams) above.
|
|
220
220
|
|
|
@@ -222,6 +222,26 @@ Each layout also declares a `slideNumber` pointing at the physical slide in the
|
|
|
222
222
|
|
|
223
223
|
---
|
|
224
224
|
|
|
225
|
+
## Speaker notes
|
|
226
|
+
|
|
227
|
+
Any slide may carry a `notes:` key in its frontmatter -- a plain-text speaker-notes block attached to that slide's notes page. It is slide-level metadata, not a parameter or a slot: it is never routed to a shape and never appears on the slide face, only in the presenter/notes view.
|
|
228
|
+
|
|
229
|
+
Write multiple lines with a YAML block scalar (`|`); each line becomes one notes paragraph. Blank template notes on the underlying slide are always stripped, so only what you author here shows up.
|
|
230
|
+
|
|
231
|
+
```yaml
|
|
232
|
+
---
|
|
233
|
+
layout: Body
|
|
234
|
+
title: Key Achievements
|
|
235
|
+
notes: |
|
|
236
|
+
Open by thanking the regional teams.
|
|
237
|
+
Land the 23% number, then pause before the churn stat.
|
|
238
|
+
---
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
To build with all speaker notes omitted, pass `--no-notes` to `tycoslide build` (see [README](README.md#cli)).
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
225
245
|
## Slides with no body
|
|
226
246
|
|
|
227
247
|
Slides that have all their content in frontmatter (common for title slides, section dividers) need no body:
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import type { StyledParagraph, TableFill, TextRun } from "../engine/index.js";
|
|
2
|
-
/**
|
|
3
|
-
* Parse inline markdown formatting in a single line of text into TextRun arrays.
|
|
4
|
-
* Handles **bold**, *italic*, ***bold italic***, ~~strikethrough~~, ++underline++,
|
|
5
|
-
* [link](url), and `inline code`.
|
|
6
|
-
*/
|
|
7
|
-
export declare function parseInlineRuns(text: string): TextRun[];
|
|
8
|
-
/**
|
|
9
|
-
* Parse a raw prose line into a StyledParagraph with bullet detection and inline
|
|
10
|
-
* formatting. The caller provides the raw line including leading whitespace and
|
|
11
|
-
* bullet markers.
|
|
12
|
-
*/
|
|
13
|
-
export declare function parseStyledParagraph(raw: string): StyledParagraph;
|
|
14
|
-
/**
|
|
15
|
-
* Parse a single line of prose into its structural components.
|
|
16
|
-
*
|
|
17
|
-
* Lines beginning with `- ` or `* ` (optionally preceded by spaces) are
|
|
18
|
-
* recognized as bullet items. Every 2 spaces of leading indent on a bullet
|
|
19
|
-
* line increase its level by 1. A leading dash without a trailing space is
|
|
20
|
-
* NOT a bullet (e.g. `-foo`).
|
|
21
|
-
*/
|
|
22
|
-
export declare function parseProseLine(raw: string): {
|
|
23
|
-
text: string;
|
|
24
|
-
bullet: boolean;
|
|
25
|
-
level: number;
|
|
26
|
-
};
|
|
27
|
-
/**
|
|
28
|
-
* Parse a GFM table into TableFill (StyledParagraph[] cells). Returns null
|
|
29
|
-
* for non-table text. Cells carry rich runs so inline formatting works
|
|
30
|
-
* inside tables for free.
|
|
31
|
-
*/
|
|
32
|
-
export declare function parseGfmTable(text: string): TableFill | null;
|