@stream-mdx/core 0.0.1 → 0.0.3
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 +20 -0
- package/README.md +26 -37
- package/dist/code-highlighting.cjs +0 -1
- package/dist/code-highlighting.mjs +0 -1
- package/dist/index.cjs +87 -16
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.mjs +86 -16
- package/dist/inline-parser.cjs +24 -16
- package/dist/inline-parser.d.cts +5 -0
- package/dist/inline-parser.d.ts +5 -0
- package/dist/inline-parser.mjs +24 -16
- package/dist/mixed-content.cjs +0 -1
- package/dist/mixed-content.mjs +0 -1
- package/dist/perf/backpressure.cjs +0 -1
- package/dist/perf/backpressure.mjs +0 -1
- package/dist/perf/patch-batching.cjs +0 -1
- package/dist/perf/patch-batching.mjs +0 -1
- package/dist/perf/patch-coalescing.cjs +0 -1
- package/dist/perf/patch-coalescing.mjs +0 -1
- package/dist/security.cjs +0 -1
- package/dist/security.mjs +0 -1
- package/dist/streaming/custom-matcher.cjs +0 -1
- package/dist/streaming/custom-matcher.mjs +0 -1
- package/dist/streaming/inline-streaming.cjs +88 -0
- package/dist/streaming/inline-streaming.d.cts +17 -0
- package/dist/streaming/inline-streaming.d.ts +17 -0
- package/dist/streaming/inline-streaming.mjs +63 -0
- package/dist/types.cjs +0 -1
- package/dist/types.d.cts +3 -0
- package/dist/types.d.ts +3 -0
- package/dist/types.mjs +0 -1
- package/dist/utils.cjs +0 -1
- package/dist/utils.mjs +0 -1
- package/dist/worker-html-sanitizer.cjs +0 -1
- package/dist/worker-html-sanitizer.mjs +0 -1
- package/package.json +9 -2
- package/dist/code-highlighting.cjs.map +0 -1
- package/dist/code-highlighting.mjs.map +0 -1
- package/dist/index.cjs.map +0 -1
- package/dist/index.mjs.map +0 -1
- package/dist/inline-parser.cjs.map +0 -1
- package/dist/inline-parser.mjs.map +0 -1
- package/dist/mixed-content.cjs.map +0 -1
- package/dist/mixed-content.mjs.map +0 -1
- package/dist/perf/backpressure.cjs.map +0 -1
- package/dist/perf/backpressure.mjs.map +0 -1
- package/dist/perf/patch-batching.cjs.map +0 -1
- package/dist/perf/patch-batching.mjs.map +0 -1
- package/dist/perf/patch-coalescing.cjs.map +0 -1
- package/dist/perf/patch-coalescing.mjs.map +0 -1
- package/dist/security.cjs.map +0 -1
- package/dist/security.mjs.map +0 -1
- package/dist/streaming/custom-matcher.cjs.map +0 -1
- package/dist/streaming/custom-matcher.mjs.map +0 -1
- package/dist/types.cjs.map +0 -1
- package/dist/types.mjs.map +0 -1
- package/dist/utils.cjs.map +0 -1
- package/dist/utils.mjs.map +0 -1
- package/dist/worker-html-sanitizer.cjs.map +0 -1
- package/dist/worker-html-sanitizer.mjs.map +0 -1
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# @stream-mdx/core
|
|
2
|
+
|
|
3
|
+
## 0.0.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 47d1374: Add opt-in streaming format anticipation and an optional Mermaid diagram addon for ` ```mermaid ` code blocks.
|
|
8
|
+
- 7c79f09: Port the docs demo page to match the ql-homepage streaming UI, and fix several streaming parser/rendering edge cases (hard line breaks and display-math handling) while keeping the hosted worker bundle self-contained for static hosting.
|
|
9
|
+
|
|
10
|
+
## 0.0.2
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- 9e94660: Docs and release-quality improvements: ship package READMEs/CHANGELOGs, add pack+install smoke tests, expose MDX parity helper entrypoints, and add a deployable docs site workflow.
|
|
15
|
+
|
|
16
|
+
## 0.0.1
|
|
17
|
+
|
|
18
|
+
### Patch Changes
|
|
19
|
+
|
|
20
|
+
- Release maintenance: CI/build fixes, missing runtime deps (e.g. `rehype-katex`), and improved docs/README wiring for the `stream-mdx` package page.
|
package/README.md
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
# `@stream-mdx/core`
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Core types + utilities shared across the StreamMDX stack.
|
|
4
|
+
|
|
5
|
+
This package is intentionally React-free. It contains structured-clone-safe types and helpers used by both the worker and the renderer.
|
|
6
|
+
|
|
7
|
+
Most consumers should install `stream-mdx` and follow the main docs. Use `@stream-mdx/core` directly if you’re building tooling or customizing lower-level behavior.
|
|
4
8
|
|
|
5
9
|
## Install
|
|
6
10
|
|
|
@@ -8,47 +12,32 @@ Pure TypeScript primitives shared across the streaming renderer stack. This pack
|
|
|
8
12
|
npm install @stream-mdx/core
|
|
9
13
|
```
|
|
10
14
|
|
|
11
|
-
##
|
|
15
|
+
## Entry points
|
|
12
16
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
17
|
+
- `@stream-mdx/core` (root)
|
|
18
|
+
- `@stream-mdx/core/types`
|
|
19
|
+
- `@stream-mdx/core/utils`
|
|
20
|
+
- `@stream-mdx/core/code-highlighting`
|
|
21
|
+
- `@stream-mdx/core/inline-parser`
|
|
22
|
+
- `@stream-mdx/core/mixed-content`
|
|
23
|
+
- `@stream-mdx/core/worker-html-sanitizer`
|
|
24
|
+
- `@stream-mdx/core/security`
|
|
25
|
+
- `@stream-mdx/core/perf/backpressure`
|
|
26
|
+
- `@stream-mdx/core/perf/patch-batching`
|
|
27
|
+
- `@stream-mdx/core/perf/patch-coalescing`
|
|
28
|
+
- `@stream-mdx/core/streaming/custom-matcher`
|
|
24
29
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
## Usage
|
|
30
|
+
## Example
|
|
28
31
|
|
|
29
32
|
```ts
|
|
30
|
-
import
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const snapshot = createInitialSnapshot();
|
|
35
|
-
for (const patch of patches) {
|
|
36
|
-
applyPatchBatch(snapshot, [patch]);
|
|
37
|
-
}
|
|
38
|
-
return snapshot;
|
|
33
|
+
import { DEFAULT_BACKPRESSURE_CONFIG } from "@stream-mdx/core/perf/backpressure";
|
|
34
|
+
|
|
35
|
+
export function makeConfig(overrides?: Partial<typeof DEFAULT_BACKPRESSURE_CONFIG>) {
|
|
36
|
+
return { ...DEFAULT_BACKPRESSURE_CONFIG, ...overrides };
|
|
39
37
|
}
|
|
40
38
|
```
|
|
41
39
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
> For end-to-end math/MDX registration steps (worker + renderer), see [`docs/STREAMING_MARKDOWN_PLUGINS_COOKBOOK.md#5-math--mdx-workerrenderer-registration`](../../docs/STREAMING_MARKDOWN_PLUGINS_COOKBOOK.md#5-math--mdx-workerrenderer-registration).
|
|
45
|
-
|
|
46
|
-
## Security notes
|
|
47
|
-
|
|
48
|
-
- Sanitization helpers assume you pass trusted markdown inputs or run the worker in an isolated thread. If you enable raw HTML rendering, ensure you serve KaTeX/MDX assets from trusted origins and set CSP headers accordingly.
|
|
49
|
-
- `worker-html-sanitizer` exports a minimal schema. Override/augment it if you need to allow additional tags/attributes (e.g., custom `data-*` props).
|
|
50
|
-
|
|
51
|
-
## Roadmap
|
|
40
|
+
## Docs
|
|
52
41
|
|
|
53
|
-
-
|
|
54
|
-
-
|
|
42
|
+
- API reference: `docs/PUBLIC_API.md`
|
|
43
|
+
- Security model: `docs/SECURITY_MODEL.md`
|
package/dist/index.cjs
CHANGED
|
@@ -74,6 +74,7 @@ __export(index_exports, {
|
|
|
74
74
|
normalizeBlockquoteText: () => normalizeBlockquoteText,
|
|
75
75
|
normalizeLang: () => normalizeLang,
|
|
76
76
|
parseCodeFenceInfo: () => parseCodeFenceInfo,
|
|
77
|
+
prepareInlineStreamingContent: () => prepareInlineStreamingContent,
|
|
77
78
|
removeHeadingMarkers: () => removeHeadingMarkers,
|
|
78
79
|
sanitizeCodeHTML: () => sanitizeCodeHTML,
|
|
79
80
|
sanitizeHTML: () => sanitizeHTML,
|
|
@@ -294,7 +295,7 @@ var InlineParser = class {
|
|
|
294
295
|
this.plugins = [];
|
|
295
296
|
this.cache = /* @__PURE__ */ new Map();
|
|
296
297
|
this.maxCacheEntries = Number.isFinite(options.maxCacheEntries ?? Number.NaN) ? Math.max(0, options.maxCacheEntries ?? 0) : 2e3;
|
|
297
|
-
this.registerDefaultPlugins();
|
|
298
|
+
this.registerDefaultPlugins({ enableMath: options.enableMath !== false });
|
|
298
299
|
}
|
|
299
300
|
/**
|
|
300
301
|
* Register a plugin with the parser
|
|
@@ -360,10 +361,27 @@ var InlineParser = class {
|
|
|
360
361
|
* Register default plugins with proper precedence ordering
|
|
361
362
|
* Lower priority numbers = higher precedence (run first)
|
|
362
363
|
*/
|
|
363
|
-
registerDefaultPlugins() {
|
|
364
|
+
registerDefaultPlugins(options) {
|
|
365
|
+
if (options.enableMath) {
|
|
366
|
+
this.registerPlugin({
|
|
367
|
+
id: "math-display",
|
|
368
|
+
priority: 0,
|
|
369
|
+
re: /\$\$([\s\S]+?)\$\$/g,
|
|
370
|
+
toNode: (match) => ({ kind: "math-display", tex: match[1].trim() }),
|
|
371
|
+
fastCheck: (text) => text.indexOf("$$") !== -1
|
|
372
|
+
});
|
|
373
|
+
this.registerPlugin({
|
|
374
|
+
id: "math-inline",
|
|
375
|
+
priority: 1,
|
|
376
|
+
re: /\$([^$\n]+?)\$/g,
|
|
377
|
+
// Non-greedy to prevent spanning multiple expressions
|
|
378
|
+
toNode: (match) => ({ kind: "math-inline", tex: match[1].trim() }),
|
|
379
|
+
fastCheck: (text) => text.indexOf("$") !== -1
|
|
380
|
+
});
|
|
381
|
+
}
|
|
364
382
|
this.registerPlugin({
|
|
365
383
|
id: "escaped-character",
|
|
366
|
-
priority:
|
|
384
|
+
priority: 2,
|
|
367
385
|
re: /\\([\\`*_{}\[\]()#+\-.!>])/g,
|
|
368
386
|
toNode: (match) => ({
|
|
369
387
|
kind: "text",
|
|
@@ -372,19 +390,11 @@ var InlineParser = class {
|
|
|
372
390
|
fastCheck: (text) => text.indexOf("\\") !== -1
|
|
373
391
|
});
|
|
374
392
|
this.registerPlugin({
|
|
375
|
-
id: "
|
|
376
|
-
priority: 1,
|
|
377
|
-
re: /\$\$([^$]+?)\$\$/g,
|
|
378
|
-
toNode: (match) => ({ kind: "math-display", tex: match[1].trim() }),
|
|
379
|
-
fastCheck: (text) => text.indexOf("$$") !== -1
|
|
380
|
-
});
|
|
381
|
-
this.registerPlugin({
|
|
382
|
-
id: "math-inline",
|
|
393
|
+
id: "hard-break",
|
|
383
394
|
priority: 2,
|
|
384
|
-
re:
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
fastCheck: (text) => text.indexOf("$") !== -1
|
|
395
|
+
re: /\\\r?\n| {2,}\r?\n/g,
|
|
396
|
+
toNode: (_match) => ({ kind: "br" }),
|
|
397
|
+
fastCheck: (text) => text.indexOf("\n") !== -1 || text.indexOf("\r") !== -1
|
|
388
398
|
});
|
|
389
399
|
this.registerPlugin({
|
|
390
400
|
id: "code-spans",
|
|
@@ -2799,6 +2809,67 @@ var CustomStreamingMatcher = class {
|
|
|
2799
2809
|
return false;
|
|
2800
2810
|
}
|
|
2801
2811
|
};
|
|
2812
|
+
|
|
2813
|
+
// src/streaming/inline-streaming.ts
|
|
2814
|
+
function prepareInlineStreamingContent(content, options) {
|
|
2815
|
+
const enableAnticipation = Boolean(options?.formatAnticipation);
|
|
2816
|
+
const enableMath = options?.math !== false;
|
|
2817
|
+
let dollarCount = 0;
|
|
2818
|
+
let backtickCount = 0;
|
|
2819
|
+
let starCount = 0;
|
|
2820
|
+
let doubleStarCount = 0;
|
|
2821
|
+
let tildePairCount = 0;
|
|
2822
|
+
for (let i = 0; i < content.length; i++) {
|
|
2823
|
+
const code = content.charCodeAt(i);
|
|
2824
|
+
if (code === 36) {
|
|
2825
|
+
dollarCount += 1;
|
|
2826
|
+
continue;
|
|
2827
|
+
}
|
|
2828
|
+
if (code === 96) {
|
|
2829
|
+
backtickCount += 1;
|
|
2830
|
+
continue;
|
|
2831
|
+
}
|
|
2832
|
+
if (code === 42) {
|
|
2833
|
+
if (i + 1 < content.length && content.charCodeAt(i + 1) === 42) {
|
|
2834
|
+
doubleStarCount += 1;
|
|
2835
|
+
starCount += 2;
|
|
2836
|
+
i += 1;
|
|
2837
|
+
} else {
|
|
2838
|
+
starCount += 1;
|
|
2839
|
+
}
|
|
2840
|
+
continue;
|
|
2841
|
+
}
|
|
2842
|
+
if (code === 126) {
|
|
2843
|
+
if (i + 1 < content.length && content.charCodeAt(i + 1) === 126) {
|
|
2844
|
+
tildePairCount += 1;
|
|
2845
|
+
i += 1;
|
|
2846
|
+
}
|
|
2847
|
+
}
|
|
2848
|
+
}
|
|
2849
|
+
const hasIncompleteMath = enableMath && dollarCount % 2 !== 0;
|
|
2850
|
+
if (hasIncompleteMath) {
|
|
2851
|
+
return { kind: "raw", status: "raw", reason: "incomplete-math" };
|
|
2852
|
+
}
|
|
2853
|
+
const hasIncompleteCode = backtickCount % 2 !== 0;
|
|
2854
|
+
const hasIncompleteStrong = doubleStarCount % 2 !== 0;
|
|
2855
|
+
const singleStarCount = starCount - doubleStarCount * 2;
|
|
2856
|
+
const hasIncompleteEmphasis = singleStarCount % 2 !== 0;
|
|
2857
|
+
const hasIncompleteStrike = tildePairCount % 2 !== 0;
|
|
2858
|
+
const hasAnyIncomplete = hasIncompleteCode || hasIncompleteStrong || hasIncompleteEmphasis || hasIncompleteStrike;
|
|
2859
|
+
if (!hasAnyIncomplete) {
|
|
2860
|
+
return { kind: "parse", status: "complete", content, appended: "" };
|
|
2861
|
+
}
|
|
2862
|
+
if (!enableAnticipation) {
|
|
2863
|
+
return { kind: "raw", status: "raw", reason: "incomplete-formatting" };
|
|
2864
|
+
}
|
|
2865
|
+
let appended = "";
|
|
2866
|
+
if (hasIncompleteCode) appended += "`";
|
|
2867
|
+
if (hasIncompleteStrike) appended += "~~";
|
|
2868
|
+
if (hasIncompleteStrong && hasIncompleteEmphasis) appended += "***";
|
|
2869
|
+
else if (hasIncompleteStrong) appended += "**";
|
|
2870
|
+
else if (hasIncompleteEmphasis) appended += "*";
|
|
2871
|
+
return { kind: "parse", status: "anticipated", content: content + appended, appended };
|
|
2872
|
+
}
|
|
2802
2873
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2803
2874
|
0 && (module.exports = {
|
|
2804
2875
|
CSP_HEADERS,
|
|
@@ -2845,6 +2916,7 @@ var CustomStreamingMatcher = class {
|
|
|
2845
2916
|
normalizeBlockquoteText,
|
|
2846
2917
|
normalizeLang,
|
|
2847
2918
|
parseCodeFenceInfo,
|
|
2919
|
+
prepareInlineStreamingContent,
|
|
2848
2920
|
removeHeadingMarkers,
|
|
2849
2921
|
sanitizeCodeHTML,
|
|
2850
2922
|
sanitizeHTML,
|
|
@@ -2854,4 +2926,3 @@ var CustomStreamingMatcher = class {
|
|
|
2854
2926
|
smoothCredit,
|
|
2855
2927
|
stripCodeFence
|
|
2856
2928
|
});
|
|
2857
|
-
//# sourceMappingURL=index.cjs.map
|
package/dist/index.d.cts
CHANGED
|
@@ -9,6 +9,7 @@ export { sanitizeHtmlInWorker } from './worker-html-sanitizer.cjs';
|
|
|
9
9
|
export { BackpressureConfig, DEFAULT_BACKPRESSURE_CONFIG, calculateRawCredit, calculateSmoothedCredit, clampCredit, computeHeavyPatchBudget, smoothCredit } from './perf/backpressure.cjs';
|
|
10
10
|
export { CoalesceConfig, DEFAULT_COALESCE_CONFIG, coalescePatches, coalescePatchesLinear, coalescePatchesQuadratic, coalescePatchesWithMetrics } from './perf/patch-coalescing.cjs';
|
|
11
11
|
export { CustomStreamingMatcher, MatchResult } from './streaming/custom-matcher.cjs';
|
|
12
|
+
export { InlineStreamingInlineStatus, InlineStreamingPrepareResult, prepareInlineStreamingContent } from './streaming/inline-streaming.cjs';
|
|
12
13
|
import 'dompurify';
|
|
13
14
|
|
|
14
15
|
declare function cloneBlock(block: Block): Block;
|
package/dist/index.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export { sanitizeHtmlInWorker } from './worker-html-sanitizer.js';
|
|
|
9
9
|
export { BackpressureConfig, DEFAULT_BACKPRESSURE_CONFIG, calculateRawCredit, calculateSmoothedCredit, clampCredit, computeHeavyPatchBudget, smoothCredit } from './perf/backpressure.js';
|
|
10
10
|
export { CoalesceConfig, DEFAULT_COALESCE_CONFIG, coalescePatches, coalescePatchesLinear, coalescePatchesQuadratic, coalescePatchesWithMetrics } from './perf/patch-coalescing.js';
|
|
11
11
|
export { CustomStreamingMatcher, MatchResult } from './streaming/custom-matcher.js';
|
|
12
|
+
export { InlineStreamingInlineStatus, InlineStreamingPrepareResult, prepareInlineStreamingContent } from './streaming/inline-streaming.js';
|
|
12
13
|
import 'dompurify';
|
|
13
14
|
|
|
14
15
|
declare function cloneBlock(block: Block): Block;
|
package/dist/index.mjs
CHANGED
|
@@ -207,7 +207,7 @@ var InlineParser = class {
|
|
|
207
207
|
this.plugins = [];
|
|
208
208
|
this.cache = /* @__PURE__ */ new Map();
|
|
209
209
|
this.maxCacheEntries = Number.isFinite(options.maxCacheEntries ?? Number.NaN) ? Math.max(0, options.maxCacheEntries ?? 0) : 2e3;
|
|
210
|
-
this.registerDefaultPlugins();
|
|
210
|
+
this.registerDefaultPlugins({ enableMath: options.enableMath !== false });
|
|
211
211
|
}
|
|
212
212
|
/**
|
|
213
213
|
* Register a plugin with the parser
|
|
@@ -273,10 +273,27 @@ var InlineParser = class {
|
|
|
273
273
|
* Register default plugins with proper precedence ordering
|
|
274
274
|
* Lower priority numbers = higher precedence (run first)
|
|
275
275
|
*/
|
|
276
|
-
registerDefaultPlugins() {
|
|
276
|
+
registerDefaultPlugins(options) {
|
|
277
|
+
if (options.enableMath) {
|
|
278
|
+
this.registerPlugin({
|
|
279
|
+
id: "math-display",
|
|
280
|
+
priority: 0,
|
|
281
|
+
re: /\$\$([\s\S]+?)\$\$/g,
|
|
282
|
+
toNode: (match) => ({ kind: "math-display", tex: match[1].trim() }),
|
|
283
|
+
fastCheck: (text) => text.indexOf("$$") !== -1
|
|
284
|
+
});
|
|
285
|
+
this.registerPlugin({
|
|
286
|
+
id: "math-inline",
|
|
287
|
+
priority: 1,
|
|
288
|
+
re: /\$([^$\n]+?)\$/g,
|
|
289
|
+
// Non-greedy to prevent spanning multiple expressions
|
|
290
|
+
toNode: (match) => ({ kind: "math-inline", tex: match[1].trim() }),
|
|
291
|
+
fastCheck: (text) => text.indexOf("$") !== -1
|
|
292
|
+
});
|
|
293
|
+
}
|
|
277
294
|
this.registerPlugin({
|
|
278
295
|
id: "escaped-character",
|
|
279
|
-
priority:
|
|
296
|
+
priority: 2,
|
|
280
297
|
re: /\\([\\`*_{}\[\]()#+\-.!>])/g,
|
|
281
298
|
toNode: (match) => ({
|
|
282
299
|
kind: "text",
|
|
@@ -285,19 +302,11 @@ var InlineParser = class {
|
|
|
285
302
|
fastCheck: (text) => text.indexOf("\\") !== -1
|
|
286
303
|
});
|
|
287
304
|
this.registerPlugin({
|
|
288
|
-
id: "
|
|
289
|
-
priority: 1,
|
|
290
|
-
re: /\$\$([^$]+?)\$\$/g,
|
|
291
|
-
toNode: (match) => ({ kind: "math-display", tex: match[1].trim() }),
|
|
292
|
-
fastCheck: (text) => text.indexOf("$$") !== -1
|
|
293
|
-
});
|
|
294
|
-
this.registerPlugin({
|
|
295
|
-
id: "math-inline",
|
|
305
|
+
id: "hard-break",
|
|
296
306
|
priority: 2,
|
|
297
|
-
re:
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
fastCheck: (text) => text.indexOf("$") !== -1
|
|
307
|
+
re: /\\\r?\n| {2,}\r?\n/g,
|
|
308
|
+
toNode: (_match) => ({ kind: "br" }),
|
|
309
|
+
fastCheck: (text) => text.indexOf("\n") !== -1 || text.indexOf("\r") !== -1
|
|
301
310
|
});
|
|
302
311
|
this.registerPlugin({
|
|
303
312
|
id: "code-spans",
|
|
@@ -2712,6 +2721,67 @@ var CustomStreamingMatcher = class {
|
|
|
2712
2721
|
return false;
|
|
2713
2722
|
}
|
|
2714
2723
|
};
|
|
2724
|
+
|
|
2725
|
+
// src/streaming/inline-streaming.ts
|
|
2726
|
+
function prepareInlineStreamingContent(content, options) {
|
|
2727
|
+
const enableAnticipation = Boolean(options?.formatAnticipation);
|
|
2728
|
+
const enableMath = options?.math !== false;
|
|
2729
|
+
let dollarCount = 0;
|
|
2730
|
+
let backtickCount = 0;
|
|
2731
|
+
let starCount = 0;
|
|
2732
|
+
let doubleStarCount = 0;
|
|
2733
|
+
let tildePairCount = 0;
|
|
2734
|
+
for (let i = 0; i < content.length; i++) {
|
|
2735
|
+
const code = content.charCodeAt(i);
|
|
2736
|
+
if (code === 36) {
|
|
2737
|
+
dollarCount += 1;
|
|
2738
|
+
continue;
|
|
2739
|
+
}
|
|
2740
|
+
if (code === 96) {
|
|
2741
|
+
backtickCount += 1;
|
|
2742
|
+
continue;
|
|
2743
|
+
}
|
|
2744
|
+
if (code === 42) {
|
|
2745
|
+
if (i + 1 < content.length && content.charCodeAt(i + 1) === 42) {
|
|
2746
|
+
doubleStarCount += 1;
|
|
2747
|
+
starCount += 2;
|
|
2748
|
+
i += 1;
|
|
2749
|
+
} else {
|
|
2750
|
+
starCount += 1;
|
|
2751
|
+
}
|
|
2752
|
+
continue;
|
|
2753
|
+
}
|
|
2754
|
+
if (code === 126) {
|
|
2755
|
+
if (i + 1 < content.length && content.charCodeAt(i + 1) === 126) {
|
|
2756
|
+
tildePairCount += 1;
|
|
2757
|
+
i += 1;
|
|
2758
|
+
}
|
|
2759
|
+
}
|
|
2760
|
+
}
|
|
2761
|
+
const hasIncompleteMath = enableMath && dollarCount % 2 !== 0;
|
|
2762
|
+
if (hasIncompleteMath) {
|
|
2763
|
+
return { kind: "raw", status: "raw", reason: "incomplete-math" };
|
|
2764
|
+
}
|
|
2765
|
+
const hasIncompleteCode = backtickCount % 2 !== 0;
|
|
2766
|
+
const hasIncompleteStrong = doubleStarCount % 2 !== 0;
|
|
2767
|
+
const singleStarCount = starCount - doubleStarCount * 2;
|
|
2768
|
+
const hasIncompleteEmphasis = singleStarCount % 2 !== 0;
|
|
2769
|
+
const hasIncompleteStrike = tildePairCount % 2 !== 0;
|
|
2770
|
+
const hasAnyIncomplete = hasIncompleteCode || hasIncompleteStrong || hasIncompleteEmphasis || hasIncompleteStrike;
|
|
2771
|
+
if (!hasAnyIncomplete) {
|
|
2772
|
+
return { kind: "parse", status: "complete", content, appended: "" };
|
|
2773
|
+
}
|
|
2774
|
+
if (!enableAnticipation) {
|
|
2775
|
+
return { kind: "raw", status: "raw", reason: "incomplete-formatting" };
|
|
2776
|
+
}
|
|
2777
|
+
let appended = "";
|
|
2778
|
+
if (hasIncompleteCode) appended += "`";
|
|
2779
|
+
if (hasIncompleteStrike) appended += "~~";
|
|
2780
|
+
if (hasIncompleteStrong && hasIncompleteEmphasis) appended += "***";
|
|
2781
|
+
else if (hasIncompleteStrong) appended += "**";
|
|
2782
|
+
else if (hasIncompleteEmphasis) appended += "*";
|
|
2783
|
+
return { kind: "parse", status: "anticipated", content: content + appended, appended };
|
|
2784
|
+
}
|
|
2715
2785
|
export {
|
|
2716
2786
|
CSP_HEADERS,
|
|
2717
2787
|
CustomStreamingMatcher,
|
|
@@ -2757,6 +2827,7 @@ export {
|
|
|
2757
2827
|
normalizeBlockquoteText,
|
|
2758
2828
|
normalizeLang,
|
|
2759
2829
|
parseCodeFenceInfo,
|
|
2830
|
+
prepareInlineStreamingContent,
|
|
2760
2831
|
removeHeadingMarkers,
|
|
2761
2832
|
sanitizeCodeHTML,
|
|
2762
2833
|
sanitizeHTML,
|
|
@@ -2766,4 +2837,3 @@ export {
|
|
|
2766
2837
|
smoothCredit,
|
|
2767
2838
|
stripCodeFence
|
|
2768
2839
|
};
|
|
2769
|
-
//# sourceMappingURL=index.mjs.map
|
package/dist/inline-parser.cjs
CHANGED
|
@@ -30,7 +30,7 @@ var InlineParser = class {
|
|
|
30
30
|
this.plugins = [];
|
|
31
31
|
this.cache = /* @__PURE__ */ new Map();
|
|
32
32
|
this.maxCacheEntries = Number.isFinite(options.maxCacheEntries ?? Number.NaN) ? Math.max(0, options.maxCacheEntries ?? 0) : 2e3;
|
|
33
|
-
this.registerDefaultPlugins();
|
|
33
|
+
this.registerDefaultPlugins({ enableMath: options.enableMath !== false });
|
|
34
34
|
}
|
|
35
35
|
/**
|
|
36
36
|
* Register a plugin with the parser
|
|
@@ -96,10 +96,27 @@ var InlineParser = class {
|
|
|
96
96
|
* Register default plugins with proper precedence ordering
|
|
97
97
|
* Lower priority numbers = higher precedence (run first)
|
|
98
98
|
*/
|
|
99
|
-
registerDefaultPlugins() {
|
|
99
|
+
registerDefaultPlugins(options) {
|
|
100
|
+
if (options.enableMath) {
|
|
101
|
+
this.registerPlugin({
|
|
102
|
+
id: "math-display",
|
|
103
|
+
priority: 0,
|
|
104
|
+
re: /\$\$([\s\S]+?)\$\$/g,
|
|
105
|
+
toNode: (match) => ({ kind: "math-display", tex: match[1].trim() }),
|
|
106
|
+
fastCheck: (text) => text.indexOf("$$") !== -1
|
|
107
|
+
});
|
|
108
|
+
this.registerPlugin({
|
|
109
|
+
id: "math-inline",
|
|
110
|
+
priority: 1,
|
|
111
|
+
re: /\$([^$\n]+?)\$/g,
|
|
112
|
+
// Non-greedy to prevent spanning multiple expressions
|
|
113
|
+
toNode: (match) => ({ kind: "math-inline", tex: match[1].trim() }),
|
|
114
|
+
fastCheck: (text) => text.indexOf("$") !== -1
|
|
115
|
+
});
|
|
116
|
+
}
|
|
100
117
|
this.registerPlugin({
|
|
101
118
|
id: "escaped-character",
|
|
102
|
-
priority:
|
|
119
|
+
priority: 2,
|
|
103
120
|
re: /\\([\\`*_{}\[\]()#+\-.!>])/g,
|
|
104
121
|
toNode: (match) => ({
|
|
105
122
|
kind: "text",
|
|
@@ -108,19 +125,11 @@ var InlineParser = class {
|
|
|
108
125
|
fastCheck: (text) => text.indexOf("\\") !== -1
|
|
109
126
|
});
|
|
110
127
|
this.registerPlugin({
|
|
111
|
-
id: "
|
|
112
|
-
priority: 1,
|
|
113
|
-
re: /\$\$([^$]+?)\$\$/g,
|
|
114
|
-
toNode: (match) => ({ kind: "math-display", tex: match[1].trim() }),
|
|
115
|
-
fastCheck: (text) => text.indexOf("$$") !== -1
|
|
116
|
-
});
|
|
117
|
-
this.registerPlugin({
|
|
118
|
-
id: "math-inline",
|
|
128
|
+
id: "hard-break",
|
|
119
129
|
priority: 2,
|
|
120
|
-
re:
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
fastCheck: (text) => text.indexOf("$") !== -1
|
|
130
|
+
re: /\\\r?\n| {2,}\r?\n/g,
|
|
131
|
+
toNode: (_match) => ({ kind: "br" }),
|
|
132
|
+
fastCheck: (text) => text.indexOf("\n") !== -1 || text.indexOf("\r") !== -1
|
|
124
133
|
});
|
|
125
134
|
this.registerPlugin({
|
|
126
135
|
id: "code-spans",
|
|
@@ -293,4 +302,3 @@ function splitTextByRegexWithPrecedence(text, regex, toNode) {
|
|
|
293
302
|
applyASTPlugin,
|
|
294
303
|
applyRegexPlugin
|
|
295
304
|
});
|
|
296
|
-
//# sourceMappingURL=inline-parser.cjs.map
|
package/dist/inline-parser.d.cts
CHANGED
|
@@ -7,6 +7,11 @@ interface InlineParserOptions {
|
|
|
7
7
|
* parsing many intermediate states.
|
|
8
8
|
*/
|
|
9
9
|
maxCacheEntries?: number;
|
|
10
|
+
/**
|
|
11
|
+
* Enable parsing `$...$` and `$$...$$` math nodes.
|
|
12
|
+
* Defaults to `true`.
|
|
13
|
+
*/
|
|
14
|
+
enableMath?: boolean;
|
|
10
15
|
}
|
|
11
16
|
interface InlineParseOptions {
|
|
12
17
|
/**
|
package/dist/inline-parser.d.ts
CHANGED
|
@@ -7,6 +7,11 @@ interface InlineParserOptions {
|
|
|
7
7
|
* parsing many intermediate states.
|
|
8
8
|
*/
|
|
9
9
|
maxCacheEntries?: number;
|
|
10
|
+
/**
|
|
11
|
+
* Enable parsing `$...$` and `$$...$$` math nodes.
|
|
12
|
+
* Defaults to `true`.
|
|
13
|
+
*/
|
|
14
|
+
enableMath?: boolean;
|
|
10
15
|
}
|
|
11
16
|
interface InlineParseOptions {
|
|
12
17
|
/**
|
package/dist/inline-parser.mjs
CHANGED
|
@@ -4,7 +4,7 @@ var InlineParser = class {
|
|
|
4
4
|
this.plugins = [];
|
|
5
5
|
this.cache = /* @__PURE__ */ new Map();
|
|
6
6
|
this.maxCacheEntries = Number.isFinite(options.maxCacheEntries ?? Number.NaN) ? Math.max(0, options.maxCacheEntries ?? 0) : 2e3;
|
|
7
|
-
this.registerDefaultPlugins();
|
|
7
|
+
this.registerDefaultPlugins({ enableMath: options.enableMath !== false });
|
|
8
8
|
}
|
|
9
9
|
/**
|
|
10
10
|
* Register a plugin with the parser
|
|
@@ -70,10 +70,27 @@ var InlineParser = class {
|
|
|
70
70
|
* Register default plugins with proper precedence ordering
|
|
71
71
|
* Lower priority numbers = higher precedence (run first)
|
|
72
72
|
*/
|
|
73
|
-
registerDefaultPlugins() {
|
|
73
|
+
registerDefaultPlugins(options) {
|
|
74
|
+
if (options.enableMath) {
|
|
75
|
+
this.registerPlugin({
|
|
76
|
+
id: "math-display",
|
|
77
|
+
priority: 0,
|
|
78
|
+
re: /\$\$([\s\S]+?)\$\$/g,
|
|
79
|
+
toNode: (match) => ({ kind: "math-display", tex: match[1].trim() }),
|
|
80
|
+
fastCheck: (text) => text.indexOf("$$") !== -1
|
|
81
|
+
});
|
|
82
|
+
this.registerPlugin({
|
|
83
|
+
id: "math-inline",
|
|
84
|
+
priority: 1,
|
|
85
|
+
re: /\$([^$\n]+?)\$/g,
|
|
86
|
+
// Non-greedy to prevent spanning multiple expressions
|
|
87
|
+
toNode: (match) => ({ kind: "math-inline", tex: match[1].trim() }),
|
|
88
|
+
fastCheck: (text) => text.indexOf("$") !== -1
|
|
89
|
+
});
|
|
90
|
+
}
|
|
74
91
|
this.registerPlugin({
|
|
75
92
|
id: "escaped-character",
|
|
76
|
-
priority:
|
|
93
|
+
priority: 2,
|
|
77
94
|
re: /\\([\\`*_{}\[\]()#+\-.!>])/g,
|
|
78
95
|
toNode: (match) => ({
|
|
79
96
|
kind: "text",
|
|
@@ -82,19 +99,11 @@ var InlineParser = class {
|
|
|
82
99
|
fastCheck: (text) => text.indexOf("\\") !== -1
|
|
83
100
|
});
|
|
84
101
|
this.registerPlugin({
|
|
85
|
-
id: "
|
|
86
|
-
priority: 1,
|
|
87
|
-
re: /\$\$([^$]+?)\$\$/g,
|
|
88
|
-
toNode: (match) => ({ kind: "math-display", tex: match[1].trim() }),
|
|
89
|
-
fastCheck: (text) => text.indexOf("$$") !== -1
|
|
90
|
-
});
|
|
91
|
-
this.registerPlugin({
|
|
92
|
-
id: "math-inline",
|
|
102
|
+
id: "hard-break",
|
|
93
103
|
priority: 2,
|
|
94
|
-
re:
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
fastCheck: (text) => text.indexOf("$") !== -1
|
|
104
|
+
re: /\\\r?\n| {2,}\r?\n/g,
|
|
105
|
+
toNode: (_match) => ({ kind: "br" }),
|
|
106
|
+
fastCheck: (text) => text.indexOf("\n") !== -1 || text.indexOf("\r") !== -1
|
|
98
107
|
});
|
|
99
108
|
this.registerPlugin({
|
|
100
109
|
id: "code-spans",
|
|
@@ -266,4 +275,3 @@ export {
|
|
|
266
275
|
applyASTPlugin,
|
|
267
276
|
applyRegexPlugin
|
|
268
277
|
};
|
|
269
|
-
//# sourceMappingURL=inline-parser.mjs.map
|
package/dist/mixed-content.cjs
CHANGED
package/dist/mixed-content.mjs
CHANGED
package/dist/security.cjs
CHANGED
package/dist/security.mjs
CHANGED