@usetheo/ui 0.1.0-next.0 → 0.1.0-next.1
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/CHANGELOG.md +14 -0
- package/README.md +116 -9
- package/dist/index.d.ts +1 -1
- package/dist/index.js.map +1 -1
- package/dist/plugin-Atb0VKtr.d.ts +172 -0
- package/dist/slide/index.d.ts +212 -0
- package/dist/slide/index.js +714 -0
- package/dist/slide/index.js.map +1 -0
- package/dist/slide/plugins/emoji/index.d.ts +29 -0
- package/dist/slide/plugins/emoji/index.js +157 -0
- package/dist/slide/plugins/emoji/index.js.map +1 -0
- package/dist/slide/plugins/math/index.d.ts +13 -0
- package/dist/slide/plugins/math/index.js +145 -0
- package/dist/slide/plugins/math/index.js.map +1 -0
- package/dist/slide/plugins/mermaid/index.d.ts +55 -0
- package/dist/slide/plugins/mermaid/index.js +218 -0
- package/dist/slide/plugins/mermaid/index.js.map +1 -0
- package/dist/slide/plugins/shiki/index.d.ts +18 -0
- package/dist/slide/plugins/shiki/index.js +87 -0
- package/dist/slide/plugins/shiki/index.js.map +1 -0
- package/dist/slide/themes/default.css +256 -0
- package/dist/slide/themes/layouts.css +143 -0
- package/dist/slide/themes/violet-forge.css +256 -0
- package/dist/slide-deck/index.css +52 -0
- package/dist/slide-deck/index.css.map +1 -0
- package/dist/slide-deck/index.d.ts +377 -0
- package/dist/slide-deck/index.js +1797 -0
- package/dist/slide-deck/index.js.map +1 -0
- package/dist/whiteboard/index.d.ts +258 -0
- package/dist/whiteboard/index.js +738 -0
- package/dist/whiteboard/index.js.map +1 -0
- package/package.json +141 -9
- package/registry/r/agent-composer.json +4 -4
- package/registry/r/agent-editor.json +9 -9
- package/registry/r/agent-error-card.json +2 -2
- package/registry/r/agent-event.json +4 -4
- package/registry/r/agent-handoff.json +2 -2
- package/registry/r/agent-profile.json +2 -2
- package/registry/r/agent-starting-state.json +2 -2
- package/registry/r/agent-stream.json +9 -9
- package/registry/r/agent-streaming.json +2 -2
- package/registry/r/agent-timeline.json +4 -4
- package/registry/r/approval-card.json +4 -4
- package/registry/r/artifact-preview.json +2 -2
- package/registry/r/attachment-chip.json +4 -4
- package/registry/r/audit-log-entry.json +3 -3
- package/registry/r/auto-compact-notice.json +2 -2
- package/registry/r/avatar.json +2 -2
- package/registry/r/badge.json +2 -2
- package/registry/r/browser-controls.json +2 -2
- package/registry/r/build-log-stream.json +2 -2
- package/registry/r/button.json +2 -2
- package/registry/r/capability-indicator.json +3 -3
- package/registry/r/card.json +2 -2
- package/registry/r/chat-composer.json +3 -3
- package/registry/r/chat-message.json +3 -3
- package/registry/r/chat-thread.json +2 -2
- package/registry/r/checkbox.json +2 -2
- package/registry/r/command-palette.json +4 -4
- package/registry/r/context-card.json +3 -3
- package/registry/r/context-window-bar.json +2 -2
- package/registry/r/cost-meter.json +2 -2
- package/registry/r/created-files-card.json +3 -3
- package/registry/r/cron-job-card.json +2 -2
- package/registry/r/cron-jobs-list.json +3 -3
- package/registry/r/deployment-row.json +3 -3
- package/registry/r/dialog.json +2 -2
- package/registry/r/diff-viewer.json +2 -2
- package/registry/r/domain-config.json +6 -6
- package/registry/r/empty-state.json +3 -3
- package/registry/r/env-var-editor.json +5 -5
- package/registry/r/folder-context-card.json +3 -3
- package/registry/r/folder-selector.json +2 -2
- package/registry/r/form-field.json +2 -2
- package/registry/r/hook-config.json +2 -2
- package/registry/r/hook-event-log.json +2 -2
- package/registry/r/input.json +2 -2
- package/registry/r/intent-selector.json +3 -3
- package/registry/r/label.json +2 -2
- package/registry/r/lane-board.json +2 -2
- package/registry/r/login-split.json +2 -2
- package/registry/r/mcp-server-card.json +2 -2
- package/registry/r/mcp-server-list.json +3 -3
- package/registry/r/memory-editor.json +3 -3
- package/registry/r/mention-menu.json +3 -3
- package/registry/r/metrics-panel.json +2 -2
- package/registry/r/model-card.json +3 -3
- package/registry/r/model-selector.json +2 -2
- package/registry/r/permission-matrix.json +2 -2
- package/registry/r/permission-modal.json +4 -4
- package/registry/r/preview-env-card.json +5 -5
- package/registry/r/preview-panel.json +3 -3
- package/registry/r/progress-checklist.json +3 -3
- package/registry/r/project-card.json +5 -5
- package/registry/r/project-switcher.json +2 -2
- package/registry/r/quick-action-chips.json +3 -3
- package/registry/r/radio-group.json +2 -2
- package/registry/r/recent-folders-list.json +2 -2
- package/registry/r/rollback-ui.json +4 -4
- package/registry/r/rule-card.json +3 -3
- package/registry/r/rule-editor.json +10 -10
- package/registry/r/rule-types.json +1 -1
- package/registry/r/run-stats.json +2 -2
- package/registry/r/running-tasks-panel.json +2 -2
- package/registry/r/scroll-area.json +2 -2
- package/registry/r/select.json +2 -2
- package/registry/r/session-list-item.json +2 -2
- package/registry/r/session-timeline.json +2 -2
- package/registry/r/sheet.json +2 -2
- package/registry/r/sidebar.json +2 -2
- package/registry/r/skeleton.json +2 -2
- package/registry/r/skill-card.json +4 -4
- package/registry/r/skill-editor.json +10 -10
- package/registry/r/skills-list.json +3 -3
- package/registry/r/social-auth-row.json +3 -3
- package/registry/r/steps-rail.json +2 -2
- package/registry/r/sub-agent-dispatch.json +2 -2
- package/registry/r/switch.json +2 -2
- package/registry/r/system-prompt-editor.json +2 -2
- package/registry/r/tabs.json +2 -2
- package/registry/r/task-header.json +4 -4
- package/registry/r/task-plan.json +2 -2
- package/registry/r/terminal-panel.json +2 -2
- package/registry/r/textarea.json +2 -2
- package/registry/r/theme-provider.json +2 -2
- package/registry/r/theme-script.json +1 -1
- package/registry/r/theo-ui-provider.json +2 -2
- package/registry/r/toast.json +2 -2
- package/registry/r/token-usage-chart.json +2 -2
- package/registry/r/tool-call-card.json +3 -3
- package/registry/r/tool-call.json +2 -2
- package/registry/r/tool-result.json +2 -2
- package/registry/r/tools-list.json +3 -3
- package/registry/r/tooltip.json +2 -2
- package/registry/r/topnav.json +2 -2
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { Root as Root$1 } from 'hast';
|
|
2
|
+
import { Root } from 'mdast';
|
|
3
|
+
import { FC } from 'react';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Zod schema for the Slide YAML frontmatter (`SlideFrontmatter`) and the
|
|
8
|
+
* composed `SlideInput` (frontmatter + body).
|
|
9
|
+
*
|
|
10
|
+
* Design (see RFC 0002 and the plan in
|
|
11
|
+
* `.claude/knowledge-base/plans/slide-view-primitive-plan.md` §16.3 and ADRs D4 / D14):
|
|
12
|
+
*
|
|
13
|
+
* - **`.strict()`** on frontmatter — unknown keys produce `INVALID_FRONTMATTER`
|
|
14
|
+
* with a precise path, so an LLM can self-correct.
|
|
15
|
+
* - Numeric values are `.finite()` to reject `NaN` / `Infinity`. (Currently no
|
|
16
|
+
* numeric directives ship; keep the helper for future fields.)
|
|
17
|
+
* - String values capped to defensible sizes to reject DoS-shaped inputs.
|
|
18
|
+
* - `body` capped to 50 KB (≈30 slides' worth of text) per the sanity rule.
|
|
19
|
+
* - `theme` is the canonical enum of built-in themes. Custom themes are not
|
|
20
|
+
* registered via frontmatter in v0.1 — caller wraps `<Slide>` with their
|
|
21
|
+
* own CSS overrides.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
/** Built-in slide themes. Adding a theme means landing a CSS file in `themes/`. */
|
|
25
|
+
declare const slideTheme: z.ZodEnum<{
|
|
26
|
+
default: "default";
|
|
27
|
+
"violet-forge": "violet-forge";
|
|
28
|
+
}>;
|
|
29
|
+
/** YAML frontmatter accepted by `<Slide>`. */
|
|
30
|
+
declare const slideFrontmatter: z.ZodObject<{
|
|
31
|
+
theme: z.ZodOptional<z.ZodEnum<{
|
|
32
|
+
default: "default";
|
|
33
|
+
"violet-forge": "violet-forge";
|
|
34
|
+
}>>;
|
|
35
|
+
layout: z.ZodOptional<z.ZodEnum<{
|
|
36
|
+
default: "default";
|
|
37
|
+
title: "title";
|
|
38
|
+
"two-column": "two-column";
|
|
39
|
+
"image-right": "image-right";
|
|
40
|
+
"image-left": "image-left";
|
|
41
|
+
"code-output": "code-output";
|
|
42
|
+
section: "section";
|
|
43
|
+
}>>;
|
|
44
|
+
backgroundImage: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<string | undefined, string>>>;
|
|
45
|
+
backgroundGradient: z.ZodOptional<z.ZodString>;
|
|
46
|
+
header: z.ZodOptional<z.ZodString>;
|
|
47
|
+
footer: z.ZodOptional<z.ZodString>;
|
|
48
|
+
paginate: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"skip">, z.ZodLiteral<"hold">]>>;
|
|
49
|
+
lang: z.ZodOptional<z.ZodString>;
|
|
50
|
+
color: z.ZodOptional<z.ZodString>;
|
|
51
|
+
backgroundColor: z.ZodOptional<z.ZodString>;
|
|
52
|
+
}, z.core.$strict>;
|
|
53
|
+
type SlideFrontmatter = z.infer<typeof slideFrontmatter>;
|
|
54
|
+
/** Composed input: validated frontmatter object + raw markdown body string. */
|
|
55
|
+
declare const slideInput: z.ZodObject<{
|
|
56
|
+
frontmatter: z.ZodObject<{
|
|
57
|
+
theme: z.ZodOptional<z.ZodEnum<{
|
|
58
|
+
default: "default";
|
|
59
|
+
"violet-forge": "violet-forge";
|
|
60
|
+
}>>;
|
|
61
|
+
layout: z.ZodOptional<z.ZodEnum<{
|
|
62
|
+
default: "default";
|
|
63
|
+
title: "title";
|
|
64
|
+
"two-column": "two-column";
|
|
65
|
+
"image-right": "image-right";
|
|
66
|
+
"image-left": "image-left";
|
|
67
|
+
"code-output": "code-output";
|
|
68
|
+
section: "section";
|
|
69
|
+
}>>;
|
|
70
|
+
backgroundImage: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<string | undefined, string>>>;
|
|
71
|
+
backgroundGradient: z.ZodOptional<z.ZodString>;
|
|
72
|
+
header: z.ZodOptional<z.ZodString>;
|
|
73
|
+
footer: z.ZodOptional<z.ZodString>;
|
|
74
|
+
paginate: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"skip">, z.ZodLiteral<"hold">]>>;
|
|
75
|
+
lang: z.ZodOptional<z.ZodString>;
|
|
76
|
+
color: z.ZodOptional<z.ZodString>;
|
|
77
|
+
backgroundColor: z.ZodOptional<z.ZodString>;
|
|
78
|
+
}, z.core.$strict>;
|
|
79
|
+
body: z.ZodString;
|
|
80
|
+
}, z.core.$strip>;
|
|
81
|
+
type SlideInput = z.infer<typeof slideInput>;
|
|
82
|
+
/** Discrete validation-error codes — kept centralized so consumers can pattern-match safely. */
|
|
83
|
+
type SlideValidationErrorCode = "INVALID_FRONTMATTER" | "FRONTMATTER_TOO_LARGE" | "MULTIPLE_SLIDES" | "CONTENT_TOO_LARGE" | "BANNED_TAG" | "BANNED_ATTRIBUTE" | "INVALID_ASPECT_RATIO" | "PLUGIN_ERROR" | "PLUGIN_PEER_DEP_MISSING" | "MARPIT_BG_UNSAFE_URL";
|
|
84
|
+
interface SlideValidationError {
|
|
85
|
+
/** Path inside the input (frontmatter key, ['body'], or []). */
|
|
86
|
+
path: (string | number)[];
|
|
87
|
+
/** Human-readable explanation. */
|
|
88
|
+
message: string;
|
|
89
|
+
/** Discriminator for consumers. */
|
|
90
|
+
code: SlideValidationErrorCode;
|
|
91
|
+
/** Offending value when extractable from Zod's `received` or by walking the input. */
|
|
92
|
+
got?: unknown;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Slide plugin contract — extension points for rich-content engines.
|
|
97
|
+
*
|
|
98
|
+
* Plugins are composable transformers applied during `parseSlide`. Each plugin
|
|
99
|
+
* may inspect/mutate the mdast tree (before HTML conversion), the hast tree
|
|
100
|
+
* (after HTML conversion, before sanitize), and override React component
|
|
101
|
+
* renderers (after sanitize). They may also declare sanitize-schema extensions
|
|
102
|
+
* so custom tags (e.g. Shiki spans, KaTeX MathML, Mermaid SVG) survive the
|
|
103
|
+
* security barrier.
|
|
104
|
+
*
|
|
105
|
+
* Design rules (ADRs in `.claude/knowledge-base/plans/slide-rich-content-plan.md`):
|
|
106
|
+
* D1 — explicit `plugins` prop (no auto-detect).
|
|
107
|
+
* D2 — plugin shape: { name, mdastTransform?, hastTransform?, components? }.
|
|
108
|
+
* D13 — execution order: mdast → hast → sanitize (with merged extensions) → components.
|
|
109
|
+
* D16 — plugin error isolation: each plugin call is try/catch wrapped; errors
|
|
110
|
+
* are collected, not thrown.
|
|
111
|
+
* D17 — sanitize-schema merge is OBLIGATORY for plugins emitting non-default
|
|
112
|
+
* tags; without it, the sanitize step silently strips the content.
|
|
113
|
+
*
|
|
114
|
+
* Sanitize is the security barrier. Plugins NEVER bypass `hast-util-sanitize`.
|
|
115
|
+
*/
|
|
116
|
+
|
|
117
|
+
/** Sanitize schema extension declared by a plugin. Merged with `defaultSchema` in `parseSlide`. */
|
|
118
|
+
interface SlideSanitizeExtension {
|
|
119
|
+
/** Additional element tag names allowed past the sanitizer. */
|
|
120
|
+
tagNames?: string[];
|
|
121
|
+
/** Additional attribute allow-list keyed by tag name (or `"*"` for all tags). */
|
|
122
|
+
attributes?: Record<string, string[]>;
|
|
123
|
+
}
|
|
124
|
+
/** A composable transformer + component-override unit. */
|
|
125
|
+
interface SlidePlugin {
|
|
126
|
+
/** Stable identifier used in PLUGIN_ERROR messages and dev logs. */
|
|
127
|
+
name: string;
|
|
128
|
+
/** Mutate the mdast tree before HTML conversion. Return value is forwarded. */
|
|
129
|
+
mdastTransform?: (tree: Root) => Promise<Root> | Root;
|
|
130
|
+
/** Mutate the hast tree after HTML conversion, before sanitize. */
|
|
131
|
+
hastTransform?: (tree: Root$1) => Promise<Root$1> | Root$1;
|
|
132
|
+
/** React component overrides merged into the consumer's `components` map. */
|
|
133
|
+
components?: Record<string, FC<any>>;
|
|
134
|
+
/** Sanitize-schema extension. Required for plugins emitting non-default tags. */
|
|
135
|
+
sanitizeSchemaExtension?: SlideSanitizeExtension;
|
|
136
|
+
}
|
|
137
|
+
/** Merged sanitize-schema extensions from all plugins. */
|
|
138
|
+
interface MergedSanitizeExtensions {
|
|
139
|
+
tagNames: string[];
|
|
140
|
+
attributes: Record<string, string[]>;
|
|
141
|
+
}
|
|
142
|
+
/** Composer over a plugin array. Hooks orchestrate transformation + error isolation. */
|
|
143
|
+
interface PluginComposer {
|
|
144
|
+
/** Run all `mdastTransform` hooks in array order. Collects errors. */
|
|
145
|
+
runMdast(tree: Root, errors: SlideValidationError[]): Promise<Root>;
|
|
146
|
+
/** Run all `hastTransform` hooks in array order. Collects errors. */
|
|
147
|
+
runHast(tree: Root$1, errors: SlideValidationError[]): Promise<Root$1>;
|
|
148
|
+
/** Merge all plugin component overrides; later-plugin-wins on conflict. */
|
|
149
|
+
mergedComponents(): Record<string, FC<any>>;
|
|
150
|
+
/** Merge sanitize-schema extensions across all plugins (dedupes tag names). */
|
|
151
|
+
mergedSanitizeExtensions(): MergedSanitizeExtensions;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Build a composer over an array of plugins.
|
|
155
|
+
*
|
|
156
|
+
* Order semantics:
|
|
157
|
+
* - mdast transforms run sequentially in array order.
|
|
158
|
+
* - hast transforms run sequentially in array order.
|
|
159
|
+
* - components merge: later plugin wins on conflict (Object.assign semantics).
|
|
160
|
+
* - sanitize-schema extensions: union of tag names; union of attributes by tag.
|
|
161
|
+
*
|
|
162
|
+
* Error semantics (D16):
|
|
163
|
+
* - Each plugin call is wrapped in try/catch.
|
|
164
|
+
* - On throw, an error of code `PLUGIN_ERROR` is pushed to `errors[]` and the
|
|
165
|
+
* pipeline continues with the **non-transformed** input from that plugin
|
|
166
|
+
* (i.e. subsequent plugins see the tree that failed plugin received).
|
|
167
|
+
* - The composer NEVER throws; `parseSlide` keeps its "never throws on input"
|
|
168
|
+
* contract (RFC 0002 D9).
|
|
169
|
+
*/
|
|
170
|
+
declare function composePlugins(plugins: SlidePlugin[]): PluginComposer;
|
|
171
|
+
|
|
172
|
+
export { type MergedSanitizeExtensions as M, type PluginComposer as P, type SlideValidationError as S, type SlidePlugin as a, type SlideFrontmatter as b, type SlideInput as c, type SlideSanitizeExtension as d, type SlideValidationErrorCode as e, composePlugins as f, slideInput as g, slideTheme as h, slideFrontmatter as s };
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { FC, ReactElement, RefObject } from 'react';
|
|
2
|
+
import { S as SlideValidationError, a as SlidePlugin, b as SlideFrontmatter, M as MergedSanitizeExtensions, c as SlideInput } from '../plugin-Atb0VKtr.js';
|
|
3
|
+
export { P as PluginComposer, d as SlideSanitizeExtension, e as SlideValidationErrorCode, f as composePlugins, s as slideFrontmatter, g as slideInput, h as slideTheme } from '../plugin-Atb0VKtr.js';
|
|
4
|
+
import { Root, Element } from 'hast';
|
|
5
|
+
import { Root as Root$1 } from 'mdast';
|
|
6
|
+
import * as hast_util_sanitize from 'hast-util-sanitize';
|
|
7
|
+
import 'zod';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Theme registry for the Slide primitive. Built-in themes that ship with the
|
|
11
|
+
* `@usetheo/ui/slide` subpath. Custom themes are NOT registered through this
|
|
12
|
+
* module in v0.1 — consumers override CSS variables on `.theo-slide` directly.
|
|
13
|
+
*/
|
|
14
|
+
declare const slideThemes: readonly ["default", "violet-forge"];
|
|
15
|
+
type SlideTheme = (typeof slideThemes)[number];
|
|
16
|
+
/** Returns true if `value` is a recognized built-in theme. */
|
|
17
|
+
declare function isSlideTheme(value: unknown): value is SlideTheme;
|
|
18
|
+
|
|
19
|
+
interface SlideAspectRatio {
|
|
20
|
+
width: number;
|
|
21
|
+
height: number;
|
|
22
|
+
}
|
|
23
|
+
interface SlideProps {
|
|
24
|
+
/**
|
|
25
|
+
* Slide markdown. CommonMark + GFM + optional YAML frontmatter delimited
|
|
26
|
+
* by `---`. Top-level horizontal rules (`---` on their own line outside
|
|
27
|
+
* frontmatter) imply a deck split and trigger `MULTIPLE_SLIDES`; only the
|
|
28
|
+
* first slide is rendered.
|
|
29
|
+
*
|
|
30
|
+
* Note: `<figure>`/`<figcaption>` tags are stripped by the default
|
|
31
|
+
* sanitize schema (D8). Use `<img>` directly for captionless images.
|
|
32
|
+
*/
|
|
33
|
+
markdown: string;
|
|
34
|
+
/** Theme name. Defaults to `"default"`. */
|
|
35
|
+
theme?: SlideTheme;
|
|
36
|
+
/**
|
|
37
|
+
* Aspect ratio of the logical canvas. Default `"16:9"` → 1280×720.
|
|
38
|
+
* Custom `{ width, height }` accepted; zero/negative/NaN fallback to 16:9.
|
|
39
|
+
*/
|
|
40
|
+
aspectRatio?: "16:9" | "4:3" | SlideAspectRatio;
|
|
41
|
+
/** Lower clamp for container-fit scale. Default 0.1. */
|
|
42
|
+
minScale?: number;
|
|
43
|
+
/** Upper clamp for container-fit scale. Default 4. */
|
|
44
|
+
maxScale?: number;
|
|
45
|
+
/** Best-effort callback invoked in useEffect when validation/sanitize emits errors. */
|
|
46
|
+
onValidationError?: (errors: SlideValidationError[]) => void;
|
|
47
|
+
/** Override individual element renderers (passed to hast-util-to-jsx-runtime). */
|
|
48
|
+
components?: Record<string, FC<any>>;
|
|
49
|
+
/**
|
|
50
|
+
* Rich-content plugins (Tier 2). Each plugin transforms the mdast/hast tree
|
|
51
|
+
* or adds React component overrides. Pass MEMOIZED arrays to avoid re-parses
|
|
52
|
+
* on every render (D15).
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* const plugins = useMemo(() => [emojiPlugin(), shikiPlugin()], []);
|
|
56
|
+
* <Slide markdown={md} plugins={plugins} />
|
|
57
|
+
*/
|
|
58
|
+
plugins?: SlidePlugin[];
|
|
59
|
+
/** Accessible label for the slide. Defaults to `"Slide"`. */
|
|
60
|
+
"aria-label"?: string;
|
|
61
|
+
/** Optional class applied to the outer host element (sizing/positioning hook). */
|
|
62
|
+
className?: string;
|
|
63
|
+
}
|
|
64
|
+
declare const Slide: FC<SlideProps>;
|
|
65
|
+
|
|
66
|
+
interface ParseSlideOptions {
|
|
67
|
+
/** Override individual element renderers (passed to hast-util-to-jsx-runtime). */
|
|
68
|
+
components?: Record<string, unknown>;
|
|
69
|
+
/** Rich-content plugins (Tier 2). Order matters — D13 / RFC 0004. */
|
|
70
|
+
plugins?: SlidePlugin[];
|
|
71
|
+
}
|
|
72
|
+
interface ExtractedBackground {
|
|
73
|
+
/** Sanitized URL (http/https only). */
|
|
74
|
+
url: string;
|
|
75
|
+
/** Optional Marpit modifier: `cover` | `fit` | `left` | `right`. */
|
|
76
|
+
modifier?: "cover" | "fit" | "left" | "right";
|
|
77
|
+
}
|
|
78
|
+
interface ParsedSlide {
|
|
79
|
+
frontmatter: SlideFrontmatter;
|
|
80
|
+
/** React element renderable as the body of a slide. Always defined (may be empty Fragment). */
|
|
81
|
+
tree: ReactElement;
|
|
82
|
+
/** Validation + sanitize errors collected during parsing. Empty on success. */
|
|
83
|
+
errors: SlideValidationError[];
|
|
84
|
+
/** True when the input contained a top-level thematic break and only the first slide was rendered. */
|
|
85
|
+
truncated: boolean;
|
|
86
|
+
/**
|
|
87
|
+
* Background image extracted from Marpit `` syntax (D18 / EC-5).
|
|
88
|
+
* Precedence: `frontmatter.backgroundImage` > `extractedBackground.url`.
|
|
89
|
+
*/
|
|
90
|
+
extractedBackground?: ExtractedBackground;
|
|
91
|
+
}
|
|
92
|
+
declare function parseBody(body: string): Promise<Root$1>;
|
|
93
|
+
declare function mdastToHast(tree: Root$1): Promise<Root>;
|
|
94
|
+
declare function sanitizeHast(tree: Root, extensions?: MergedSanitizeExtensions): Promise<{
|
|
95
|
+
tree: Root;
|
|
96
|
+
bannedTags: string[];
|
|
97
|
+
}>;
|
|
98
|
+
declare function hastToReact(tree: Root, components?: Record<string, unknown>): Promise<ReactElement>;
|
|
99
|
+
/**
|
|
100
|
+
* Public entry point. Validates → parses → sanitizes → returns a React tree.
|
|
101
|
+
*
|
|
102
|
+
* Never throws on input. Errors (validation, BANNED_TAG) are collected into
|
|
103
|
+
* `errors[]` so callers can show them via `onValidationError`.
|
|
104
|
+
*/
|
|
105
|
+
declare function parseSlide(markdown: string, opts?: ParseSlideOptions): Promise<ParsedSlide>;
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Async validator for slide markdown input.
|
|
109
|
+
*
|
|
110
|
+
* Returns `Promise<ValidationResult>` (ADR D11 — sync impossible because
|
|
111
|
+
* `yaml` and `mdast-util-from-markdown` are lazy-imported peer-deps).
|
|
112
|
+
*
|
|
113
|
+
* Pipeline:
|
|
114
|
+
* 1. Strip BOM + extract frontmatter (`frontmatter.ts`).
|
|
115
|
+
* 2. Reject `FRONTMATTER_TOO_LARGE` early if raw > 10 KB (ADR D14).
|
|
116
|
+
* 3. Parse YAML in safe mode → validate against `slideFrontmatter` (Zod).
|
|
117
|
+
* 4. Validate body length → emit `CONTENT_TOO_LARGE` if > 50 KB.
|
|
118
|
+
* 5. Detect multi-slide via mdast `thematicBreak` walk (ADR D12) — not
|
|
119
|
+
* a regex, so `---` inside fenced code blocks does not false-positive.
|
|
120
|
+
* 6. Return `{ ok, input, errors[] }`.
|
|
121
|
+
*
|
|
122
|
+
* Errors are structured so an LLM can self-correct from the callback.
|
|
123
|
+
*/
|
|
124
|
+
|
|
125
|
+
type ValidationResult = {
|
|
126
|
+
ok: true;
|
|
127
|
+
input: SlideInput;
|
|
128
|
+
errors: SlideValidationError[];
|
|
129
|
+
} | {
|
|
130
|
+
ok: false;
|
|
131
|
+
errors: SlideValidationError[];
|
|
132
|
+
};
|
|
133
|
+
/**
|
|
134
|
+
* Validate the markdown input. Returns errors structured for LLM self-correction.
|
|
135
|
+
*
|
|
136
|
+
* Async because frontmatter YAML parsing and mdast multi-slide detection both
|
|
137
|
+
* use lazy-imported peer-deps (yaml + mdast-util-from-markdown).
|
|
138
|
+
*/
|
|
139
|
+
declare function validateSlide(markdown: string): Promise<ValidationResult>;
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Lightweight, dependency-free extractor that separates YAML frontmatter from
|
|
143
|
+
* the markdown body.
|
|
144
|
+
*
|
|
145
|
+
* Strips a leading BOM (``) before matching the regex — common when
|
|
146
|
+
* markdown is pasted from Word/Notion. See plan ADR D14 and edge-case EC-4.
|
|
147
|
+
*
|
|
148
|
+
* Returns `{ rawFrontmatter, body, tooLarge? }`:
|
|
149
|
+
* - `rawFrontmatter`: the YAML string between the two `---` delimiters, or
|
|
150
|
+
* `null` if no frontmatter is present.
|
|
151
|
+
* - `body`: the markdown after the closing `---\n` (or the full input when
|
|
152
|
+
* no frontmatter).
|
|
153
|
+
* - `tooLarge`: `true` if `rawFrontmatter` exceeds `MAX_RAW_FRONTMATTER`
|
|
154
|
+
* bytes — the caller turns this into `FRONTMATTER_TOO_LARGE`.
|
|
155
|
+
*/
|
|
156
|
+
/** Maximum size of the raw frontmatter string before YAML parsing. 10 KB cap. */
|
|
157
|
+
declare const MAX_RAW_FRONTMATTER = 10240;
|
|
158
|
+
interface ExtractFrontmatterResult {
|
|
159
|
+
rawFrontmatter: string | null;
|
|
160
|
+
body: string;
|
|
161
|
+
tooLarge?: boolean;
|
|
162
|
+
}
|
|
163
|
+
declare function extractFrontmatter(md: string): ExtractFrontmatterResult;
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Container-fit hook for the Slide primitive.
|
|
167
|
+
*
|
|
168
|
+
* Observes the host element via `ResizeObserver` and computes a CSS scale
|
|
169
|
+
* factor that fits the fixed logical canvas (default 1280×720) inside it,
|
|
170
|
+
* preserving aspect ratio. Clamped to `[minScale, maxScale]`.
|
|
171
|
+
*
|
|
172
|
+
* Algorithm: `scale = clamp(min(W / canvasW, H / canvasH), min, max)`.
|
|
173
|
+
*
|
|
174
|
+
* Adapted from Reveal.js `transformSlides` (see reference doc §4.5 / §14.2).
|
|
175
|
+
*
|
|
176
|
+
* Cleanup: disconnects the observer on unmount or when deps change.
|
|
177
|
+
*/
|
|
178
|
+
|
|
179
|
+
interface UseSlideFitOptions {
|
|
180
|
+
/** Lower clamp for scale. Default 0.1. */
|
|
181
|
+
minScale?: number;
|
|
182
|
+
/** Upper clamp for scale. Default 4. */
|
|
183
|
+
maxScale?: number;
|
|
184
|
+
}
|
|
185
|
+
declare function useSlideFit(ref: RefObject<HTMLElement | null>, canvasW: number, canvasH: number, opts?: UseSlideFitOptions): number;
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Lazy accessor for the sanitize schema.
|
|
189
|
+
*
|
|
190
|
+
* Always merges `defaultSchema` with the Tier 1 baseline (aside + className).
|
|
191
|
+
* When `extensions` is provided, plugin-declared tag names + attributes are
|
|
192
|
+
* unioned on top (D17 / EC-3). Plugins NEVER bypass sanitize — they declare
|
|
193
|
+
* what they need via `sanitizeSchemaExtension`.
|
|
194
|
+
*
|
|
195
|
+
* Implementation notes:
|
|
196
|
+
* - The baseline schema (default + Tier 1) is cached.
|
|
197
|
+
* - Plugin-merged schemas are NOT cached (depends on combination).
|
|
198
|
+
*/
|
|
199
|
+
declare function getSlideSanitizeSchema(extensions?: MergedSanitizeExtensions): Promise<hast_util_sanitize.Schema>;
|
|
200
|
+
/** Count elements by tagName in a hast tree. Used for BANNED_TAG detection (ADR D13). */
|
|
201
|
+
declare function collectTagCounts(tree: Root | Element): Map<string, number>;
|
|
202
|
+
|
|
203
|
+
interface JsonSchemaProperties {
|
|
204
|
+
[key: string]: Record<string, unknown>;
|
|
205
|
+
}
|
|
206
|
+
interface JsonSchemaWithProperties {
|
|
207
|
+
properties?: JsonSchemaProperties;
|
|
208
|
+
[key: string]: unknown;
|
|
209
|
+
}
|
|
210
|
+
declare const slideFrontmatterJsonSchema: JsonSchemaWithProperties;
|
|
211
|
+
|
|
212
|
+
export { type ExtractFrontmatterResult, MAX_RAW_FRONTMATTER, MergedSanitizeExtensions, type ParseSlideOptions, type ParsedSlide, Slide, type SlideAspectRatio, SlideFrontmatter, SlideInput, SlidePlugin, type SlideProps, type SlideTheme, SlideValidationError, type UseSlideFitOptions, type ValidationResult, collectTagCounts, extractFrontmatter, getSlideSanitizeSchema, hastToReact, isSlideTheme, mdastToHast, parseBody, parseSlide, sanitizeHast, slideFrontmatterJsonSchema, slideThemes, useSlideFit, validateSlide };
|