@ox-content/vite-plugin 2.62.0 → 2.64.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.
@@ -0,0 +1,179 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ require("./chunk.cjs");
3
+ //#region src/incremental-dom-styles.ts
4
+ const DEFAULT_COMMITTED_CLASS = "ox-incremental-committed";
5
+ const DEFAULT_PENDING_CLASS = "ox-incremental-pending";
6
+ const DEFAULT_CHAR_CLASS = "ox-incremental-char";
7
+ const DEFAULT_VISIBLE_CLASS = "ox-incremental-char--visible";
8
+ const DEFAULT_ATOM_CLASS = "ox-incremental-atom";
9
+ const incrementalMarkdownDomStyles = `
10
+ .${DEFAULT_COMMITTED_CLASS},
11
+ .${DEFAULT_PENDING_CLASS} {
12
+ display: contents;
13
+ }
14
+
15
+ .${DEFAULT_CHAR_CLASS},
16
+ .${DEFAULT_ATOM_CLASS} {
17
+ animation: ox-incremental-char-in var(--ox-incremental-duration, 170ms) ease-out both;
18
+ animation-delay: var(--ox-incremental-delay, 0ms);
19
+ }
20
+
21
+ .${DEFAULT_VISIBLE_CLASS} {
22
+ animation: none;
23
+ opacity: 1;
24
+ }
25
+
26
+ @keyframes ox-incremental-char-in {
27
+ from {
28
+ opacity: 0;
29
+ }
30
+ to {
31
+ opacity: 1;
32
+ }
33
+ }
34
+ `.trim();
35
+ function injectIncrementalMarkdownDomStyles(document = globalThis.document) {
36
+ const existing = document.querySelector("style[data-ox-incremental-dom]");
37
+ if (existing) return existing;
38
+ const style = document.createElement("style");
39
+ style.dataset.oxIncrementalDom = "";
40
+ style.textContent = incrementalMarkdownDomStyles;
41
+ document.head.append(style);
42
+ return style;
43
+ }
44
+ //#endregion
45
+ //#region src/incremental-dom-animation.ts
46
+ function resolveAnimationOptions(animation) {
47
+ if (!animation) return {
48
+ mode: "none",
49
+ durationMs: 0,
50
+ staggerMs: 0,
51
+ committed: false,
52
+ pending: false,
53
+ charClassName: DEFAULT_CHAR_CLASS,
54
+ visibleClassName: DEFAULT_VISIBLE_CLASS,
55
+ atomClassName: DEFAULT_ATOM_CLASS
56
+ };
57
+ const options = animation === true ? {} : animation;
58
+ return {
59
+ mode: options.mode ?? "character",
60
+ durationMs: options.durationMs ?? 170,
61
+ staggerMs: options.staggerMs ?? 2,
62
+ committed: options.committed ?? true,
63
+ pending: options.pending ?? true,
64
+ charClassName: options.charClassName ?? "ox-incremental-char",
65
+ visibleClassName: options.visibleClassName ?? "ox-incremental-char--visible",
66
+ atomClassName: options.atomClassName ?? "ox-incremental-atom"
67
+ };
68
+ }
69
+ function prepareCharacterFade(document, root, animation, visibleTextPrefix) {
70
+ if (animation.mode === "none") return;
71
+ const textNodes = collectTextNodes(document, root);
72
+ let index = 0;
73
+ let textOffset = 0;
74
+ for (const textNode of textNodes) {
75
+ const value = textNode.nodeValue ?? "";
76
+ const parent = textNode.parentElement;
77
+ const preserveWhitespace = Boolean(parent?.closest("pre, code"));
78
+ if (!value || !preserveWhitespace && !value.trim()) continue;
79
+ const fragment = document.createDocumentFragment();
80
+ for (const char of [...value]) {
81
+ const span = document.createElement("span");
82
+ if (textOffset < visibleTextPrefix) span.className = `${animation.charClassName} ${animation.visibleClassName}`;
83
+ else {
84
+ span.className = animation.charClassName;
85
+ span.style.setProperty("--ox-incremental-delay", `${index * animation.staggerMs}ms`);
86
+ span.style.setProperty("--ox-incremental-duration", `${animation.durationMs}ms`);
87
+ index += 1;
88
+ }
89
+ span.textContent = char;
90
+ fragment.append(span);
91
+ textOffset += 1;
92
+ }
93
+ textNode.replaceWith(fragment);
94
+ }
95
+ for (const atom of root.querySelectorAll("input, img, hr, br, iframe, svg")) {
96
+ if (textOffset < visibleTextPrefix) continue;
97
+ const element = atom;
98
+ atom.classList.add(animation.atomClassName);
99
+ element.style.setProperty("--ox-incremental-delay", `${index * animation.staggerMs}ms`);
100
+ element.style.setProperty("--ox-incremental-duration", `${animation.durationMs}ms`);
101
+ index += 1;
102
+ }
103
+ }
104
+ function collectTextNodes(document, root) {
105
+ const textNodes = [];
106
+ const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
107
+ while (walker.nextNode()) textNodes.push(walker.currentNode);
108
+ return textNodes;
109
+ }
110
+ //#endregion
111
+ //#region src/incremental-dom-renderer.ts
112
+ function createIncrementalMarkdownDomRenderer(options) {
113
+ const document = options.preview.ownerDocument;
114
+ const animation = resolveAnimationOptions(options.animation);
115
+ const committedRoot = document.createElement("div");
116
+ const pendingRoot = document.createElement("div");
117
+ const committedClassName = options.committedClassName ?? "ox-incremental-committed";
118
+ const pendingClassName = options.pendingClassName ?? "ox-incremental-pending";
119
+ let markdown = "";
120
+ committedRoot.className = committedClassName;
121
+ pendingRoot.className = pendingClassName;
122
+ options.preview.replaceChildren(committedRoot, pendingRoot);
123
+ function apply(result, applyOptions = {}) {
124
+ const previousPendingText = pendingRoot.textContent ?? "";
125
+ if (applyOptions.chunk !== void 0 && options.source) {
126
+ markdown += applyOptions.chunk;
127
+ options.source.textContent = markdown;
128
+ }
129
+ if (result.deltaHtml) appendCommittedHtml(result.deltaHtml, previousPendingText);
130
+ setPendingHtml(result.pendingHtml);
131
+ }
132
+ function reset() {
133
+ markdown = "";
134
+ if (options.source) options.source.textContent = "";
135
+ committedRoot.replaceChildren();
136
+ pendingRoot.replaceChildren();
137
+ }
138
+ function appendCommittedHtml(html, previousPendingText) {
139
+ const fragment = parseHtml(html);
140
+ const visiblePrefix = commonPrefixLength(previousPendingText, fragment.textContent ?? "");
141
+ prepareCharacterFade(document, fragment, animation, animation.committed ? visiblePrefix : Infinity);
142
+ committedRoot.append(fragment);
143
+ }
144
+ function setPendingHtml(html) {
145
+ const previousText = pendingRoot.textContent ?? "";
146
+ const fragment = parseHtml(html);
147
+ const nextText = fragment.textContent ?? "";
148
+ prepareCharacterFade(document, fragment, animation, animation.pending ? commonPrefixLength(previousText, nextText) : Infinity);
149
+ pendingRoot.replaceChildren(fragment);
150
+ }
151
+ function parseHtml(html) {
152
+ const template = document.createElement("template");
153
+ template.innerHTML = html;
154
+ return template.content;
155
+ }
156
+ return {
157
+ committedRoot,
158
+ pendingRoot,
159
+ apply,
160
+ reset
161
+ };
162
+ }
163
+ function commonPrefixLength(left, right) {
164
+ const max = Math.min(left.length, right.length);
165
+ let index = 0;
166
+ while (index < max && left[index] === right[index]) index += 1;
167
+ return index;
168
+ }
169
+ //#endregion
170
+ exports.DEFAULT_ATOM_CLASS = DEFAULT_ATOM_CLASS;
171
+ exports.DEFAULT_CHAR_CLASS = DEFAULT_CHAR_CLASS;
172
+ exports.DEFAULT_COMMITTED_CLASS = DEFAULT_COMMITTED_CLASS;
173
+ exports.DEFAULT_PENDING_CLASS = DEFAULT_PENDING_CLASS;
174
+ exports.DEFAULT_VISIBLE_CLASS = DEFAULT_VISIBLE_CLASS;
175
+ exports.createIncrementalMarkdownDomRenderer = createIncrementalMarkdownDomRenderer;
176
+ exports.incrementalMarkdownDomStyles = incrementalMarkdownDomStyles;
177
+ exports.injectIncrementalMarkdownDomStyles = injectIncrementalMarkdownDomStyles;
178
+
179
+ //# sourceMappingURL=incremental-dom.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"incremental-dom.cjs","names":[],"sources":["../src/incremental-dom-styles.ts","../src/incremental-dom-animation.ts","../src/incremental-dom-renderer.ts"],"sourcesContent":["/// <reference lib=\"dom\" />\n\nexport const DEFAULT_COMMITTED_CLASS = \"ox-incremental-committed\";\nexport const DEFAULT_PENDING_CLASS = \"ox-incremental-pending\";\nexport const DEFAULT_CHAR_CLASS = \"ox-incremental-char\";\nexport const DEFAULT_VISIBLE_CLASS = \"ox-incremental-char--visible\";\nexport const DEFAULT_ATOM_CLASS = \"ox-incremental-atom\";\n\nexport const incrementalMarkdownDomStyles = `\n.${DEFAULT_COMMITTED_CLASS},\n.${DEFAULT_PENDING_CLASS} {\n display: contents;\n}\n\n.${DEFAULT_CHAR_CLASS},\n.${DEFAULT_ATOM_CLASS} {\n animation: ox-incremental-char-in var(--ox-incremental-duration, 170ms) ease-out both;\n animation-delay: var(--ox-incremental-delay, 0ms);\n}\n\n.${DEFAULT_VISIBLE_CLASS} {\n animation: none;\n opacity: 1;\n}\n\n@keyframes ox-incremental-char-in {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n`.trim();\n\nexport function injectIncrementalMarkdownDomStyles(\n document: Document = globalThis.document,\n): HTMLStyleElement {\n const existing = document.querySelector<HTMLStyleElement>(\"style[data-ox-incremental-dom]\");\n if (existing) {\n return existing;\n }\n\n const style = document.createElement(\"style\");\n style.dataset.oxIncrementalDom = \"\";\n style.textContent = incrementalMarkdownDomStyles;\n document.head.append(style);\n return style;\n}\n","/// <reference lib=\"dom\" />\n\nimport {\n DEFAULT_ATOM_CLASS,\n DEFAULT_CHAR_CLASS,\n DEFAULT_VISIBLE_CLASS,\n} from \"./incremental-dom-styles\";\nimport type { IncrementalMarkdownDomAnimationOptions } from \"./incremental-dom-types\";\n\nexport interface ResolvedAnimationOptions {\n mode: \"none\" | \"character\";\n durationMs: number;\n staggerMs: number;\n committed: boolean;\n pending: boolean;\n charClassName: string;\n visibleClassName: string;\n atomClassName: string;\n}\n\nexport function resolveAnimationOptions(\n animation: boolean | IncrementalMarkdownDomAnimationOptions | undefined,\n): ResolvedAnimationOptions {\n if (!animation) {\n return {\n mode: \"none\",\n durationMs: 0,\n staggerMs: 0,\n committed: false,\n pending: false,\n charClassName: DEFAULT_CHAR_CLASS,\n visibleClassName: DEFAULT_VISIBLE_CLASS,\n atomClassName: DEFAULT_ATOM_CLASS,\n };\n }\n\n const options = animation === true ? {} : animation;\n return {\n mode: options.mode ?? \"character\",\n durationMs: options.durationMs ?? 170,\n staggerMs: options.staggerMs ?? 2,\n committed: options.committed ?? true,\n pending: options.pending ?? true,\n charClassName: options.charClassName ?? DEFAULT_CHAR_CLASS,\n visibleClassName: options.visibleClassName ?? DEFAULT_VISIBLE_CLASS,\n atomClassName: options.atomClassName ?? DEFAULT_ATOM_CLASS,\n };\n}\n\nexport function prepareCharacterFade(\n document: Document,\n root: ParentNode,\n animation: ResolvedAnimationOptions,\n visibleTextPrefix: number,\n): void {\n if (animation.mode === \"none\") {\n return;\n }\n\n const textNodes = collectTextNodes(document, root);\n let index = 0;\n let textOffset = 0;\n\n for (const textNode of textNodes) {\n const value = textNode.nodeValue ?? \"\";\n const parent = textNode.parentElement;\n const preserveWhitespace = Boolean(parent?.closest(\"pre, code\"));\n\n if (!value || (!preserveWhitespace && !value.trim())) {\n continue;\n }\n\n const fragment = document.createDocumentFragment();\n for (const char of [...value]) {\n const span = document.createElement(\"span\");\n if (textOffset < visibleTextPrefix) {\n span.className = `${animation.charClassName} ${animation.visibleClassName}`;\n } else {\n span.className = animation.charClassName;\n span.style.setProperty(\"--ox-incremental-delay\", `${index * animation.staggerMs}ms`);\n span.style.setProperty(\"--ox-incremental-duration\", `${animation.durationMs}ms`);\n index += 1;\n }\n span.textContent = char;\n fragment.append(span);\n textOffset += 1;\n }\n textNode.replaceWith(fragment);\n }\n\n for (const atom of root.querySelectorAll(\"input, img, hr, br, iframe, svg\")) {\n if (textOffset < visibleTextPrefix) {\n continue;\n }\n const element = atom as HTMLElement;\n atom.classList.add(animation.atomClassName);\n element.style.setProperty(\"--ox-incremental-delay\", `${index * animation.staggerMs}ms`);\n element.style.setProperty(\"--ox-incremental-duration\", `${animation.durationMs}ms`);\n index += 1;\n }\n}\n\nfunction collectTextNodes(document: Document, root: ParentNode): Text[] {\n const textNodes: Text[] = [];\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);\n\n while (walker.nextNode()) {\n textNodes.push(walker.currentNode as Text);\n }\n\n return textNodes;\n}\n","/// <reference lib=\"dom\" />\n\nimport { prepareCharacterFade, resolveAnimationOptions } from \"./incremental-dom-animation\";\nimport { DEFAULT_COMMITTED_CLASS, DEFAULT_PENDING_CLASS } from \"./incremental-dom-styles\";\nimport type {\n IncrementalMarkdownDomApplyOptions,\n IncrementalMarkdownDomOptions,\n IncrementalMarkdownDomRenderer,\n IncrementalMarkdownRenderResultLike,\n} from \"./incremental-dom-types\";\n\nexport function createIncrementalMarkdownDomRenderer(\n options: IncrementalMarkdownDomOptions,\n): IncrementalMarkdownDomRenderer {\n const document = options.preview.ownerDocument;\n const animation = resolveAnimationOptions(options.animation);\n const committedRoot = document.createElement(\"div\");\n const pendingRoot = document.createElement(\"div\");\n const committedClassName = options.committedClassName ?? DEFAULT_COMMITTED_CLASS;\n const pendingClassName = options.pendingClassName ?? DEFAULT_PENDING_CLASS;\n let markdown = \"\";\n\n committedRoot.className = committedClassName;\n pendingRoot.className = pendingClassName;\n options.preview.replaceChildren(committedRoot, pendingRoot);\n\n function apply(\n result: IncrementalMarkdownRenderResultLike,\n applyOptions: IncrementalMarkdownDomApplyOptions = {},\n ): void {\n const previousPendingText = pendingRoot.textContent ?? \"\";\n\n if (applyOptions.chunk !== undefined && options.source) {\n markdown += applyOptions.chunk;\n options.source.textContent = markdown;\n }\n\n if (result.deltaHtml) {\n appendCommittedHtml(result.deltaHtml, previousPendingText);\n }\n\n setPendingHtml(result.pendingHtml);\n }\n\n function reset(): void {\n markdown = \"\";\n if (options.source) {\n options.source.textContent = \"\";\n }\n committedRoot.replaceChildren();\n pendingRoot.replaceChildren();\n }\n\n function appendCommittedHtml(html: string, previousPendingText: string): void {\n const fragment = parseHtml(html);\n const committedText = fragment.textContent ?? \"\";\n const visiblePrefix = commonPrefixLength(previousPendingText, committedText);\n prepareCharacterFade(\n document,\n fragment,\n animation,\n animation.committed ? visiblePrefix : Infinity,\n );\n committedRoot.append(fragment);\n }\n\n function setPendingHtml(html: string): void {\n const previousText = pendingRoot.textContent ?? \"\";\n const fragment = parseHtml(html);\n const nextText = fragment.textContent ?? \"\";\n const visiblePrefix = animation.pending ? commonPrefixLength(previousText, nextText) : Infinity;\n prepareCharacterFade(document, fragment, animation, visiblePrefix);\n pendingRoot.replaceChildren(fragment);\n }\n\n function parseHtml(html: string): DocumentFragment {\n const template = document.createElement(\"template\");\n template.innerHTML = html;\n return template.content;\n }\n\n return { committedRoot, pendingRoot, apply, reset };\n}\n\nfunction commonPrefixLength(left: string, right: string): number {\n const max = Math.min(left.length, right.length);\n let index = 0;\n\n while (index < max && left[index] === right[index]) {\n index += 1;\n }\n\n return index;\n}\n"],"mappings":"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"}
@@ -0,0 +1,101 @@
1
+ //#region src/incremental-dom-styles.d.ts
2
+ declare const DEFAULT_COMMITTED_CLASS = "ox-incremental-committed";
3
+ declare const DEFAULT_PENDING_CLASS = "ox-incremental-pending";
4
+ declare const DEFAULT_CHAR_CLASS = "ox-incremental-char";
5
+ declare const DEFAULT_VISIBLE_CLASS = "ox-incremental-char--visible";
6
+ declare const DEFAULT_ATOM_CLASS = "ox-incremental-atom";
7
+ declare const incrementalMarkdownDomStyles: string;
8
+ declare function injectIncrementalMarkdownDomStyles(document?: Document): HTMLStyleElement;
9
+ //#endregion
10
+ //#region src/incremental-dom-types.d.ts
11
+ interface IncrementalMarkdownRenderResultLike {
12
+ deltaHtml: string;
13
+ committedHtml: string;
14
+ pendingHtml: string;
15
+ html: string;
16
+ committedBytes: number;
17
+ pendingBytes: number;
18
+ totalBytes: number;
19
+ didCommit: boolean;
20
+ isFinal: boolean;
21
+ errors: string[];
22
+ }
23
+ interface IncrementalMarkdownDomAnimationOptions {
24
+ /**
25
+ * Animate newly-seen text one character at a time.
26
+ * @default "character"
27
+ */
28
+ mode?: "none" | "character";
29
+ /**
30
+ * Duration for each character fade.
31
+ * @default 170
32
+ */
33
+ durationMs?: number;
34
+ /**
35
+ * Delay added per new character.
36
+ * @default 2
37
+ */
38
+ staggerMs?: number;
39
+ /**
40
+ * Animate newly committed HTML.
41
+ * @default true
42
+ */
43
+ committed?: boolean;
44
+ /**
45
+ * Animate newly appended pending text. Existing pending prefixes are not re-animated.
46
+ * @default true
47
+ */
48
+ pending?: boolean;
49
+ /**
50
+ * CSS class for animated characters.
51
+ * @default "ox-incremental-char"
52
+ */
53
+ charClassName?: string;
54
+ /**
55
+ * CSS class for characters that have already been visible in the pending region.
56
+ * @default "ox-incremental-char--visible"
57
+ */
58
+ visibleClassName?: string;
59
+ /**
60
+ * CSS class for non-text atoms such as checkboxes, images, and rules.
61
+ * @default "ox-incremental-atom"
62
+ */
63
+ atomClassName?: string;
64
+ }
65
+ interface IncrementalMarkdownDomOptions {
66
+ /** Element that owns the committed and pending render regions. */
67
+ preview: Element;
68
+ /** Optional element that displays the raw Markdown stream. */
69
+ source?: HTMLElement;
70
+ /**
71
+ * Character fade is opt-in. Pass `true` for defaults or an option object.
72
+ * @default false
73
+ */
74
+ animation?: boolean | IncrementalMarkdownDomAnimationOptions;
75
+ /**
76
+ * CSS class for the committed render root.
77
+ * @default "ox-incremental-committed"
78
+ */
79
+ committedClassName?: string;
80
+ /**
81
+ * CSS class for the replaceable pending render root.
82
+ * @default "ox-incremental-pending"
83
+ */
84
+ pendingClassName?: string;
85
+ }
86
+ interface IncrementalMarkdownDomApplyOptions {
87
+ /** Raw Markdown chunk to append to `source`, when one is configured. */
88
+ chunk?: string;
89
+ }
90
+ interface IncrementalMarkdownDomRenderer {
91
+ readonly committedRoot: HTMLElement;
92
+ readonly pendingRoot: HTMLElement;
93
+ apply(result: IncrementalMarkdownRenderResultLike, options?: IncrementalMarkdownDomApplyOptions): void;
94
+ reset(): void;
95
+ }
96
+ //#endregion
97
+ //#region src/incremental-dom-renderer.d.ts
98
+ declare function createIncrementalMarkdownDomRenderer(options: IncrementalMarkdownDomOptions): IncrementalMarkdownDomRenderer;
99
+ //#endregion
100
+ export { DEFAULT_ATOM_CLASS, DEFAULT_CHAR_CLASS, DEFAULT_COMMITTED_CLASS, DEFAULT_PENDING_CLASS, DEFAULT_VISIBLE_CLASS, type IncrementalMarkdownDomAnimationOptions, type IncrementalMarkdownDomApplyOptions, type IncrementalMarkdownDomOptions, type IncrementalMarkdownDomRenderer, type IncrementalMarkdownRenderResultLike, createIncrementalMarkdownDomRenderer, incrementalMarkdownDomStyles, injectIncrementalMarkdownDomStyles };
101
+ //# sourceMappingURL=incremental-dom.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"incremental-dom.d.cts","names":[],"sources":["../src/incremental-dom-styles.ts","../src/incremental-dom-types.ts","../src/incremental-dom-renderer.ts"],"mappings":";cAEa,uBAAA;AAAA,cACA,qBAAA;AAAA,cACA,kBAAA;AAAA,cACA,qBAAA;AAAA,cACA,kBAAA;AAAA,cAEA,4BAAA;AAAA,iBA2BG,kCAAA,CACd,QAAA,GAAU,QAAA,GACT,gBAAA;;;UCnCc,mCAAA;EACf,SAAA;EACA,aAAA;EACA,WAAA;EACA,IAAA;EACA,cAAA;EACA,YAAA;EACA,UAAA;EACA,SAAA;EACA,OAAA;EACA,MAAA;AAAA;AAAA,UAGe,sCAAA;;;;ADVjB;ECeE,IAAA;;;;ADdF;ECmBE,UAAA;;;;ADjBF;ECsBE,SAAA;;;;ADKF;ECAE,SAAA;;;;;EAKA,OAAA;EDHiB;;;;ECQjB,aAAA;EA3Ce;;;;EAgDf,gBAAA;EA9CA;;;;EAmDA,aAAA;AAAA;AAAA,UAGe,6BAAA;EA/Cf;EAiDA,OAAA,EAAS,OAAA;EAhDH;EAkDN,MAAA,GAAS,WAAA;EA/CM;;;;EAoDf,SAAA,aAAsB,sCAAA;EA1CtB;;;;EA+CA,kBAAA;EAtBA;;;;EA2BA,gBAAA;AAAA;AAAA,UAGe,kCAAA;EApBN;EAsBT,KAAA;AAAA;AAAA,UAGe,8BAAA;EAAA,SACN,aAAA,EAAe,WAAA;EAAA,SACf,WAAA,EAAa,WAAA;EACtB,KAAA,CACE,MAAA,EAAQ,mCAAA,EACR,OAAA,GAAU,kCAAA;EAEZ,KAAA;AAAA;;;iBCjFc,oCAAA,CACd,OAAA,EAAS,6BAAA,GACR,8BAAA"}
@@ -0,0 +1,101 @@
1
+ //#region src/incremental-dom-styles.d.ts
2
+ declare const DEFAULT_COMMITTED_CLASS = "ox-incremental-committed";
3
+ declare const DEFAULT_PENDING_CLASS = "ox-incremental-pending";
4
+ declare const DEFAULT_CHAR_CLASS = "ox-incremental-char";
5
+ declare const DEFAULT_VISIBLE_CLASS = "ox-incremental-char--visible";
6
+ declare const DEFAULT_ATOM_CLASS = "ox-incremental-atom";
7
+ declare const incrementalMarkdownDomStyles: string;
8
+ declare function injectIncrementalMarkdownDomStyles(document?: Document): HTMLStyleElement;
9
+ //#endregion
10
+ //#region src/incremental-dom-types.d.ts
11
+ interface IncrementalMarkdownRenderResultLike {
12
+ deltaHtml: string;
13
+ committedHtml: string;
14
+ pendingHtml: string;
15
+ html: string;
16
+ committedBytes: number;
17
+ pendingBytes: number;
18
+ totalBytes: number;
19
+ didCommit: boolean;
20
+ isFinal: boolean;
21
+ errors: string[];
22
+ }
23
+ interface IncrementalMarkdownDomAnimationOptions {
24
+ /**
25
+ * Animate newly-seen text one character at a time.
26
+ * @default "character"
27
+ */
28
+ mode?: "none" | "character";
29
+ /**
30
+ * Duration for each character fade.
31
+ * @default 170
32
+ */
33
+ durationMs?: number;
34
+ /**
35
+ * Delay added per new character.
36
+ * @default 2
37
+ */
38
+ staggerMs?: number;
39
+ /**
40
+ * Animate newly committed HTML.
41
+ * @default true
42
+ */
43
+ committed?: boolean;
44
+ /**
45
+ * Animate newly appended pending text. Existing pending prefixes are not re-animated.
46
+ * @default true
47
+ */
48
+ pending?: boolean;
49
+ /**
50
+ * CSS class for animated characters.
51
+ * @default "ox-incremental-char"
52
+ */
53
+ charClassName?: string;
54
+ /**
55
+ * CSS class for characters that have already been visible in the pending region.
56
+ * @default "ox-incremental-char--visible"
57
+ */
58
+ visibleClassName?: string;
59
+ /**
60
+ * CSS class for non-text atoms such as checkboxes, images, and rules.
61
+ * @default "ox-incremental-atom"
62
+ */
63
+ atomClassName?: string;
64
+ }
65
+ interface IncrementalMarkdownDomOptions {
66
+ /** Element that owns the committed and pending render regions. */
67
+ preview: Element;
68
+ /** Optional element that displays the raw Markdown stream. */
69
+ source?: HTMLElement;
70
+ /**
71
+ * Character fade is opt-in. Pass `true` for defaults or an option object.
72
+ * @default false
73
+ */
74
+ animation?: boolean | IncrementalMarkdownDomAnimationOptions;
75
+ /**
76
+ * CSS class for the committed render root.
77
+ * @default "ox-incremental-committed"
78
+ */
79
+ committedClassName?: string;
80
+ /**
81
+ * CSS class for the replaceable pending render root.
82
+ * @default "ox-incremental-pending"
83
+ */
84
+ pendingClassName?: string;
85
+ }
86
+ interface IncrementalMarkdownDomApplyOptions {
87
+ /** Raw Markdown chunk to append to `source`, when one is configured. */
88
+ chunk?: string;
89
+ }
90
+ interface IncrementalMarkdownDomRenderer {
91
+ readonly committedRoot: HTMLElement;
92
+ readonly pendingRoot: HTMLElement;
93
+ apply(result: IncrementalMarkdownRenderResultLike, options?: IncrementalMarkdownDomApplyOptions): void;
94
+ reset(): void;
95
+ }
96
+ //#endregion
97
+ //#region src/incremental-dom-renderer.d.ts
98
+ declare function createIncrementalMarkdownDomRenderer(options: IncrementalMarkdownDomOptions): IncrementalMarkdownDomRenderer;
99
+ //#endregion
100
+ export { DEFAULT_ATOM_CLASS, DEFAULT_CHAR_CLASS, DEFAULT_COMMITTED_CLASS, DEFAULT_PENDING_CLASS, DEFAULT_VISIBLE_CLASS, type IncrementalMarkdownDomAnimationOptions, type IncrementalMarkdownDomApplyOptions, type IncrementalMarkdownDomOptions, type IncrementalMarkdownDomRenderer, type IncrementalMarkdownRenderResultLike, createIncrementalMarkdownDomRenderer, incrementalMarkdownDomStyles, injectIncrementalMarkdownDomStyles };
101
+ //# sourceMappingURL=incremental-dom.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"incremental-dom.d.mts","names":[],"sources":["../src/incremental-dom-styles.ts","../src/incremental-dom-types.ts","../src/incremental-dom-renderer.ts"],"mappings":";cAEa,uBAAA;AAAA,cACA,qBAAA;AAAA,cACA,kBAAA;AAAA,cACA,qBAAA;AAAA,cACA,kBAAA;AAAA,cAEA,4BAAA;AAAA,iBA2BG,kCAAA,CACd,QAAA,GAAU,QAAA,GACT,gBAAA;;;UCnCc,mCAAA;EACf,SAAA;EACA,aAAA;EACA,WAAA;EACA,IAAA;EACA,cAAA;EACA,YAAA;EACA,UAAA;EACA,SAAA;EACA,OAAA;EACA,MAAA;AAAA;AAAA,UAGe,sCAAA;;;;ADVjB;ECeE,IAAA;;;;ADdF;ECmBE,UAAA;;;;ADjBF;ECsBE,SAAA;;;;ADKF;ECAE,SAAA;;;;;EAKA,OAAA;EDHiB;;;;ECQjB,aAAA;EA3Ce;;;;EAgDf,gBAAA;EA9CA;;;;EAmDA,aAAA;AAAA;AAAA,UAGe,6BAAA;EA/Cf;EAiDA,OAAA,EAAS,OAAA;EAhDH;EAkDN,MAAA,GAAS,WAAA;EA/CM;;;;EAoDf,SAAA,aAAsB,sCAAA;EA1CtB;;;;EA+CA,kBAAA;EAtBA;;;;EA2BA,gBAAA;AAAA;AAAA,UAGe,kCAAA;EApBN;EAsBT,KAAA;AAAA;AAAA,UAGe,8BAAA;EAAA,SACN,aAAA,EAAe,WAAA;EAAA,SACf,WAAA,EAAa,WAAA;EACtB,KAAA,CACE,MAAA,EAAQ,mCAAA,EACR,OAAA,GAAU,kCAAA;EAEZ,KAAA;AAAA;;;iBCjFc,oCAAA,CACd,OAAA,EAAS,6BAAA,GACR,8BAAA"}
@@ -0,0 +1,170 @@
1
+ //#region src/incremental-dom-styles.ts
2
+ const DEFAULT_COMMITTED_CLASS = "ox-incremental-committed";
3
+ const DEFAULT_PENDING_CLASS = "ox-incremental-pending";
4
+ const DEFAULT_CHAR_CLASS = "ox-incremental-char";
5
+ const DEFAULT_VISIBLE_CLASS = "ox-incremental-char--visible";
6
+ const DEFAULT_ATOM_CLASS = "ox-incremental-atom";
7
+ const incrementalMarkdownDomStyles = `
8
+ .${DEFAULT_COMMITTED_CLASS},
9
+ .${DEFAULT_PENDING_CLASS} {
10
+ display: contents;
11
+ }
12
+
13
+ .${DEFAULT_CHAR_CLASS},
14
+ .${DEFAULT_ATOM_CLASS} {
15
+ animation: ox-incremental-char-in var(--ox-incremental-duration, 170ms) ease-out both;
16
+ animation-delay: var(--ox-incremental-delay, 0ms);
17
+ }
18
+
19
+ .${DEFAULT_VISIBLE_CLASS} {
20
+ animation: none;
21
+ opacity: 1;
22
+ }
23
+
24
+ @keyframes ox-incremental-char-in {
25
+ from {
26
+ opacity: 0;
27
+ }
28
+ to {
29
+ opacity: 1;
30
+ }
31
+ }
32
+ `.trim();
33
+ function injectIncrementalMarkdownDomStyles(document = globalThis.document) {
34
+ const existing = document.querySelector("style[data-ox-incremental-dom]");
35
+ if (existing) return existing;
36
+ const style = document.createElement("style");
37
+ style.dataset.oxIncrementalDom = "";
38
+ style.textContent = incrementalMarkdownDomStyles;
39
+ document.head.append(style);
40
+ return style;
41
+ }
42
+ //#endregion
43
+ //#region src/incremental-dom-animation.ts
44
+ function resolveAnimationOptions(animation) {
45
+ if (!animation) return {
46
+ mode: "none",
47
+ durationMs: 0,
48
+ staggerMs: 0,
49
+ committed: false,
50
+ pending: false,
51
+ charClassName: DEFAULT_CHAR_CLASS,
52
+ visibleClassName: DEFAULT_VISIBLE_CLASS,
53
+ atomClassName: DEFAULT_ATOM_CLASS
54
+ };
55
+ const options = animation === true ? {} : animation;
56
+ return {
57
+ mode: options.mode ?? "character",
58
+ durationMs: options.durationMs ?? 170,
59
+ staggerMs: options.staggerMs ?? 2,
60
+ committed: options.committed ?? true,
61
+ pending: options.pending ?? true,
62
+ charClassName: options.charClassName ?? "ox-incremental-char",
63
+ visibleClassName: options.visibleClassName ?? "ox-incremental-char--visible",
64
+ atomClassName: options.atomClassName ?? "ox-incremental-atom"
65
+ };
66
+ }
67
+ function prepareCharacterFade(document, root, animation, visibleTextPrefix) {
68
+ if (animation.mode === "none") return;
69
+ const textNodes = collectTextNodes(document, root);
70
+ let index = 0;
71
+ let textOffset = 0;
72
+ for (const textNode of textNodes) {
73
+ const value = textNode.nodeValue ?? "";
74
+ const parent = textNode.parentElement;
75
+ const preserveWhitespace = Boolean(parent?.closest("pre, code"));
76
+ if (!value || !preserveWhitespace && !value.trim()) continue;
77
+ const fragment = document.createDocumentFragment();
78
+ for (const char of [...value]) {
79
+ const span = document.createElement("span");
80
+ if (textOffset < visibleTextPrefix) span.className = `${animation.charClassName} ${animation.visibleClassName}`;
81
+ else {
82
+ span.className = animation.charClassName;
83
+ span.style.setProperty("--ox-incremental-delay", `${index * animation.staggerMs}ms`);
84
+ span.style.setProperty("--ox-incremental-duration", `${animation.durationMs}ms`);
85
+ index += 1;
86
+ }
87
+ span.textContent = char;
88
+ fragment.append(span);
89
+ textOffset += 1;
90
+ }
91
+ textNode.replaceWith(fragment);
92
+ }
93
+ for (const atom of root.querySelectorAll("input, img, hr, br, iframe, svg")) {
94
+ if (textOffset < visibleTextPrefix) continue;
95
+ const element = atom;
96
+ atom.classList.add(animation.atomClassName);
97
+ element.style.setProperty("--ox-incremental-delay", `${index * animation.staggerMs}ms`);
98
+ element.style.setProperty("--ox-incremental-duration", `${animation.durationMs}ms`);
99
+ index += 1;
100
+ }
101
+ }
102
+ function collectTextNodes(document, root) {
103
+ const textNodes = [];
104
+ const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
105
+ while (walker.nextNode()) textNodes.push(walker.currentNode);
106
+ return textNodes;
107
+ }
108
+ //#endregion
109
+ //#region src/incremental-dom-renderer.ts
110
+ function createIncrementalMarkdownDomRenderer(options) {
111
+ const document = options.preview.ownerDocument;
112
+ const animation = resolveAnimationOptions(options.animation);
113
+ const committedRoot = document.createElement("div");
114
+ const pendingRoot = document.createElement("div");
115
+ const committedClassName = options.committedClassName ?? "ox-incremental-committed";
116
+ const pendingClassName = options.pendingClassName ?? "ox-incremental-pending";
117
+ let markdown = "";
118
+ committedRoot.className = committedClassName;
119
+ pendingRoot.className = pendingClassName;
120
+ options.preview.replaceChildren(committedRoot, pendingRoot);
121
+ function apply(result, applyOptions = {}) {
122
+ const previousPendingText = pendingRoot.textContent ?? "";
123
+ if (applyOptions.chunk !== void 0 && options.source) {
124
+ markdown += applyOptions.chunk;
125
+ options.source.textContent = markdown;
126
+ }
127
+ if (result.deltaHtml) appendCommittedHtml(result.deltaHtml, previousPendingText);
128
+ setPendingHtml(result.pendingHtml);
129
+ }
130
+ function reset() {
131
+ markdown = "";
132
+ if (options.source) options.source.textContent = "";
133
+ committedRoot.replaceChildren();
134
+ pendingRoot.replaceChildren();
135
+ }
136
+ function appendCommittedHtml(html, previousPendingText) {
137
+ const fragment = parseHtml(html);
138
+ const visiblePrefix = commonPrefixLength(previousPendingText, fragment.textContent ?? "");
139
+ prepareCharacterFade(document, fragment, animation, animation.committed ? visiblePrefix : Infinity);
140
+ committedRoot.append(fragment);
141
+ }
142
+ function setPendingHtml(html) {
143
+ const previousText = pendingRoot.textContent ?? "";
144
+ const fragment = parseHtml(html);
145
+ const nextText = fragment.textContent ?? "";
146
+ prepareCharacterFade(document, fragment, animation, animation.pending ? commonPrefixLength(previousText, nextText) : Infinity);
147
+ pendingRoot.replaceChildren(fragment);
148
+ }
149
+ function parseHtml(html) {
150
+ const template = document.createElement("template");
151
+ template.innerHTML = html;
152
+ return template.content;
153
+ }
154
+ return {
155
+ committedRoot,
156
+ pendingRoot,
157
+ apply,
158
+ reset
159
+ };
160
+ }
161
+ function commonPrefixLength(left, right) {
162
+ const max = Math.min(left.length, right.length);
163
+ let index = 0;
164
+ while (index < max && left[index] === right[index]) index += 1;
165
+ return index;
166
+ }
167
+ //#endregion
168
+ export { DEFAULT_ATOM_CLASS, DEFAULT_CHAR_CLASS, DEFAULT_COMMITTED_CLASS, DEFAULT_PENDING_CLASS, DEFAULT_VISIBLE_CLASS, createIncrementalMarkdownDomRenderer, incrementalMarkdownDomStyles, injectIncrementalMarkdownDomStyles };
169
+
170
+ //# sourceMappingURL=incremental-dom.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"incremental-dom.mjs","names":[],"sources":["../src/incremental-dom-styles.ts","../src/incremental-dom-animation.ts","../src/incremental-dom-renderer.ts"],"sourcesContent":["/// <reference lib=\"dom\" />\n\nexport const DEFAULT_COMMITTED_CLASS = \"ox-incremental-committed\";\nexport const DEFAULT_PENDING_CLASS = \"ox-incremental-pending\";\nexport const DEFAULT_CHAR_CLASS = \"ox-incremental-char\";\nexport const DEFAULT_VISIBLE_CLASS = \"ox-incremental-char--visible\";\nexport const DEFAULT_ATOM_CLASS = \"ox-incremental-atom\";\n\nexport const incrementalMarkdownDomStyles = `\n.${DEFAULT_COMMITTED_CLASS},\n.${DEFAULT_PENDING_CLASS} {\n display: contents;\n}\n\n.${DEFAULT_CHAR_CLASS},\n.${DEFAULT_ATOM_CLASS} {\n animation: ox-incremental-char-in var(--ox-incremental-duration, 170ms) ease-out both;\n animation-delay: var(--ox-incremental-delay, 0ms);\n}\n\n.${DEFAULT_VISIBLE_CLASS} {\n animation: none;\n opacity: 1;\n}\n\n@keyframes ox-incremental-char-in {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n`.trim();\n\nexport function injectIncrementalMarkdownDomStyles(\n document: Document = globalThis.document,\n): HTMLStyleElement {\n const existing = document.querySelector<HTMLStyleElement>(\"style[data-ox-incremental-dom]\");\n if (existing) {\n return existing;\n }\n\n const style = document.createElement(\"style\");\n style.dataset.oxIncrementalDom = \"\";\n style.textContent = incrementalMarkdownDomStyles;\n document.head.append(style);\n return style;\n}\n","/// <reference lib=\"dom\" />\n\nimport {\n DEFAULT_ATOM_CLASS,\n DEFAULT_CHAR_CLASS,\n DEFAULT_VISIBLE_CLASS,\n} from \"./incremental-dom-styles\";\nimport type { IncrementalMarkdownDomAnimationOptions } from \"./incremental-dom-types\";\n\nexport interface ResolvedAnimationOptions {\n mode: \"none\" | \"character\";\n durationMs: number;\n staggerMs: number;\n committed: boolean;\n pending: boolean;\n charClassName: string;\n visibleClassName: string;\n atomClassName: string;\n}\n\nexport function resolveAnimationOptions(\n animation: boolean | IncrementalMarkdownDomAnimationOptions | undefined,\n): ResolvedAnimationOptions {\n if (!animation) {\n return {\n mode: \"none\",\n durationMs: 0,\n staggerMs: 0,\n committed: false,\n pending: false,\n charClassName: DEFAULT_CHAR_CLASS,\n visibleClassName: DEFAULT_VISIBLE_CLASS,\n atomClassName: DEFAULT_ATOM_CLASS,\n };\n }\n\n const options = animation === true ? {} : animation;\n return {\n mode: options.mode ?? \"character\",\n durationMs: options.durationMs ?? 170,\n staggerMs: options.staggerMs ?? 2,\n committed: options.committed ?? true,\n pending: options.pending ?? true,\n charClassName: options.charClassName ?? DEFAULT_CHAR_CLASS,\n visibleClassName: options.visibleClassName ?? DEFAULT_VISIBLE_CLASS,\n atomClassName: options.atomClassName ?? DEFAULT_ATOM_CLASS,\n };\n}\n\nexport function prepareCharacterFade(\n document: Document,\n root: ParentNode,\n animation: ResolvedAnimationOptions,\n visibleTextPrefix: number,\n): void {\n if (animation.mode === \"none\") {\n return;\n }\n\n const textNodes = collectTextNodes(document, root);\n let index = 0;\n let textOffset = 0;\n\n for (const textNode of textNodes) {\n const value = textNode.nodeValue ?? \"\";\n const parent = textNode.parentElement;\n const preserveWhitespace = Boolean(parent?.closest(\"pre, code\"));\n\n if (!value || (!preserveWhitespace && !value.trim())) {\n continue;\n }\n\n const fragment = document.createDocumentFragment();\n for (const char of [...value]) {\n const span = document.createElement(\"span\");\n if (textOffset < visibleTextPrefix) {\n span.className = `${animation.charClassName} ${animation.visibleClassName}`;\n } else {\n span.className = animation.charClassName;\n span.style.setProperty(\"--ox-incremental-delay\", `${index * animation.staggerMs}ms`);\n span.style.setProperty(\"--ox-incremental-duration\", `${animation.durationMs}ms`);\n index += 1;\n }\n span.textContent = char;\n fragment.append(span);\n textOffset += 1;\n }\n textNode.replaceWith(fragment);\n }\n\n for (const atom of root.querySelectorAll(\"input, img, hr, br, iframe, svg\")) {\n if (textOffset < visibleTextPrefix) {\n continue;\n }\n const element = atom as HTMLElement;\n atom.classList.add(animation.atomClassName);\n element.style.setProperty(\"--ox-incremental-delay\", `${index * animation.staggerMs}ms`);\n element.style.setProperty(\"--ox-incremental-duration\", `${animation.durationMs}ms`);\n index += 1;\n }\n}\n\nfunction collectTextNodes(document: Document, root: ParentNode): Text[] {\n const textNodes: Text[] = [];\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);\n\n while (walker.nextNode()) {\n textNodes.push(walker.currentNode as Text);\n }\n\n return textNodes;\n}\n","/// <reference lib=\"dom\" />\n\nimport { prepareCharacterFade, resolveAnimationOptions } from \"./incremental-dom-animation\";\nimport { DEFAULT_COMMITTED_CLASS, DEFAULT_PENDING_CLASS } from \"./incremental-dom-styles\";\nimport type {\n IncrementalMarkdownDomApplyOptions,\n IncrementalMarkdownDomOptions,\n IncrementalMarkdownDomRenderer,\n IncrementalMarkdownRenderResultLike,\n} from \"./incremental-dom-types\";\n\nexport function createIncrementalMarkdownDomRenderer(\n options: IncrementalMarkdownDomOptions,\n): IncrementalMarkdownDomRenderer {\n const document = options.preview.ownerDocument;\n const animation = resolveAnimationOptions(options.animation);\n const committedRoot = document.createElement(\"div\");\n const pendingRoot = document.createElement(\"div\");\n const committedClassName = options.committedClassName ?? DEFAULT_COMMITTED_CLASS;\n const pendingClassName = options.pendingClassName ?? DEFAULT_PENDING_CLASS;\n let markdown = \"\";\n\n committedRoot.className = committedClassName;\n pendingRoot.className = pendingClassName;\n options.preview.replaceChildren(committedRoot, pendingRoot);\n\n function apply(\n result: IncrementalMarkdownRenderResultLike,\n applyOptions: IncrementalMarkdownDomApplyOptions = {},\n ): void {\n const previousPendingText = pendingRoot.textContent ?? \"\";\n\n if (applyOptions.chunk !== undefined && options.source) {\n markdown += applyOptions.chunk;\n options.source.textContent = markdown;\n }\n\n if (result.deltaHtml) {\n appendCommittedHtml(result.deltaHtml, previousPendingText);\n }\n\n setPendingHtml(result.pendingHtml);\n }\n\n function reset(): void {\n markdown = \"\";\n if (options.source) {\n options.source.textContent = \"\";\n }\n committedRoot.replaceChildren();\n pendingRoot.replaceChildren();\n }\n\n function appendCommittedHtml(html: string, previousPendingText: string): void {\n const fragment = parseHtml(html);\n const committedText = fragment.textContent ?? \"\";\n const visiblePrefix = commonPrefixLength(previousPendingText, committedText);\n prepareCharacterFade(\n document,\n fragment,\n animation,\n animation.committed ? visiblePrefix : Infinity,\n );\n committedRoot.append(fragment);\n }\n\n function setPendingHtml(html: string): void {\n const previousText = pendingRoot.textContent ?? \"\";\n const fragment = parseHtml(html);\n const nextText = fragment.textContent ?? \"\";\n const visiblePrefix = animation.pending ? commonPrefixLength(previousText, nextText) : Infinity;\n prepareCharacterFade(document, fragment, animation, visiblePrefix);\n pendingRoot.replaceChildren(fragment);\n }\n\n function parseHtml(html: string): DocumentFragment {\n const template = document.createElement(\"template\");\n template.innerHTML = html;\n return template.content;\n }\n\n return { committedRoot, pendingRoot, apply, reset };\n}\n\nfunction commonPrefixLength(left: string, right: string): number {\n const max = Math.min(left.length, right.length);\n let index = 0;\n\n while (index < max && left[index] === right[index]) {\n index += 1;\n }\n\n return index;\n}\n"],"mappings":"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"}