@astryxdesign/core 0.6.2-canary.d993f65 → 0.6.2-canary.eec3a19
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/dist/Markdown/plugins/index.d.ts +2 -0
- package/dist/Markdown/plugins/index.d.ts.map +1 -1
- package/dist/Markdown/plugins/index.js +2 -1
- package/dist/Markdown/plugins/protocol.d.ts +11 -4
- package/dist/Markdown/plugins/protocol.d.ts.map +1 -1
- package/dist/Markdown/plugins/protocol.js +26 -3
- package/dist/Markdown/plugins/textTransform.d.ts +30 -0
- package/dist/Markdown/plugins/textTransform.d.ts.map +1 -0
- package/dist/Markdown/plugins/textTransform.js +226 -0
- package/package.json +3 -3
- package/src/Markdown/Markdown.doc.mjs +25 -12
- package/src/Markdown/Markdown.helpers.perf.test.ts +89 -0
- package/src/Markdown/Markdown.public.test.ts +6 -1
- package/src/Markdown/plugins/index.ts +5 -0
- package/src/Markdown/plugins/protocol.ts +54 -10
- package/src/Markdown/plugins/textTransform.test.ts +355 -0
- package/src/Markdown/plugins/textTransform.ts +318 -0
|
@@ -4,5 +4,7 @@
|
|
|
4
4
|
* @position Subpath entry point: `@astryxdesign/core/Markdown/plugins`
|
|
5
5
|
*/
|
|
6
6
|
export { createMarkdownPlugin, isMarkdownExtensionNode } from './protocol';
|
|
7
|
+
export { createMarkdownTextTransform } from './textTransform';
|
|
8
|
+
export type { MarkdownTextTransformContext, MarkdownTextTransformOptions, } from './textTransform';
|
|
7
9
|
export type { MarkdownPluginData, MarkdownExtensionNode, MarkdownTokenizerInput, MarkdownTokenizeResult, MarkdownSyntaxContribution, MarkdownSyntaxCapability, MarkdownTransformContext, MarkdownTransform, MarkdownExtensionRenderer, MarkdownExtensionRenderers, MarkdownSyntaxPluginDefinition, MarkdownTransformPluginDefinition, MarkdownPluginDefinition, MarkdownPluginEntry, MarkdownNodeOf, MarkdownExtensionsOf, } from './protocol';
|
|
8
10
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/Markdown/plugins/index.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AAEH,OAAO,EAAC,oBAAoB,EAAE,uBAAuB,EAAC,MAAM,YAAY,CAAC;AACzE,YAAY,EACV,kBAAkB,EAClB,qBAAqB,EACrB,sBAAsB,EACtB,sBAAsB,EACtB,0BAA0B,EAC1B,wBAAwB,EACxB,wBAAwB,EACxB,iBAAiB,EACjB,yBAAyB,EACzB,0BAA0B,EAC1B,8BAA8B,EAC9B,iCAAiC,EACjC,wBAAwB,EACxB,mBAAmB,EACnB,cAAc,EACd,oBAAoB,GACrB,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/Markdown/plugins/index.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AAEH,OAAO,EAAC,oBAAoB,EAAE,uBAAuB,EAAC,MAAM,YAAY,CAAC;AACzE,OAAO,EAAC,2BAA2B,EAAC,MAAM,iBAAiB,CAAC;AAC5D,YAAY,EACV,4BAA4B,EAC5B,4BAA4B,GAC7B,MAAM,iBAAiB,CAAC;AACzB,YAAY,EACV,kBAAkB,EAClB,qBAAqB,EACrB,sBAAsB,EACtB,sBAAsB,EACtB,0BAA0B,EAC1B,wBAAwB,EACxB,wBAAwB,EACxB,iBAAiB,EACjB,yBAAyB,EACzB,0BAA0B,EAC1B,8BAA8B,EAC9B,iCAAiC,EACjC,wBAAwB,EACxB,mBAAmB,EACnB,cAAc,EACd,oBAAoB,GACrB,MAAM,YAAY,CAAC"}
|
|
@@ -6,4 +6,5 @@
|
|
|
6
6
|
* @position Subpath entry point: `@astryxdesign/core/Markdown/plugins`
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
export { createMarkdownPlugin, isMarkdownExtensionNode } from "./protocol.js";
|
|
9
|
+
export { createMarkdownPlugin, isMarkdownExtensionNode } from "./protocol.js";
|
|
10
|
+
export { createMarkdownTextTransform } from "./textTransform.js";
|
|
@@ -57,7 +57,13 @@ export interface MarkdownTransformContext {
|
|
|
57
57
|
readonly display: 'inline' | 'block';
|
|
58
58
|
report(message: string): void;
|
|
59
59
|
}
|
|
60
|
-
|
|
60
|
+
declare const markdownTransformNode: unique symbol;
|
|
61
|
+
export interface MarkdownTransform<Node extends MarkdownExtensionNode = never> {
|
|
62
|
+
(document: MarkdownAstRoot<MarkdownExtensionNode>, context: MarkdownTransformContext): MarkdownAstRoot<MarkdownExtensionNode>;
|
|
63
|
+
readonly [markdownTransformNode]?: Node;
|
|
64
|
+
}
|
|
65
|
+
/** @internal Registers a cheap source-level claim check for a helper transform. */
|
|
66
|
+
export declare function markMarkdownTransformClaim<Node extends MarkdownExtensionNode = never>(transform: MarkdownTransform<Node>, claims: (source: string) => boolean): MarkdownTransform<Node>;
|
|
61
67
|
export interface MarkdownExtensionRenderer<Node extends MarkdownExtensionNode> {
|
|
62
68
|
/** Pure render callback. Hooks belong in components returned by this callback. */
|
|
63
69
|
readonly render: (props: {
|
|
@@ -77,11 +83,11 @@ interface MarkdownPluginDefinitionBase<Name extends string> {
|
|
|
77
83
|
export interface MarkdownSyntaxPluginDefinition<Name extends string, Node extends MarkdownExtensionNode<Name>> extends MarkdownPluginDefinitionBase<Name> {
|
|
78
84
|
readonly parseKey: string;
|
|
79
85
|
readonly syntax: MarkdownSyntaxCapability<Node>;
|
|
80
|
-
readonly transform?: MarkdownTransform
|
|
86
|
+
readonly transform?: MarkdownTransform<Node>;
|
|
81
87
|
readonly renderers: MarkdownExtensionRenderers<Node>;
|
|
82
88
|
}
|
|
83
89
|
export type MarkdownTransformPluginDefinition<Name extends string, Node extends MarkdownExtensionNode<Name> = never> = MarkdownPluginDefinitionBase<Name> & {
|
|
84
|
-
readonly transform: MarkdownTransform
|
|
90
|
+
readonly transform: MarkdownTransform<Node>;
|
|
85
91
|
readonly parseKey?: never;
|
|
86
92
|
readonly syntax?: never;
|
|
87
93
|
} & ([Node] extends [never] ? {
|
|
@@ -109,7 +115,8 @@ export interface PreparedSyntaxContribution {
|
|
|
109
115
|
}
|
|
110
116
|
interface PreparedTransform {
|
|
111
117
|
readonly pluginName: string;
|
|
112
|
-
readonly transform: MarkdownTransform
|
|
118
|
+
readonly transform: MarkdownTransform<MarkdownExtensionNode>;
|
|
119
|
+
readonly claims?: (source: string) => boolean;
|
|
113
120
|
}
|
|
114
121
|
interface PreparedRenderer {
|
|
115
122
|
readonly pluginName: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../../src/Markdown/plugins/protocol.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../../src/Markdown/plugins/protocol.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,6 +12,17 @@ import { isSafeMarkdownParserUrl } from "../url.js";
|
|
|
12
12
|
export function isMarkdownExtensionNode(node, plugin, name) {
|
|
13
13
|
return node.type === 'extension' && node.plugin === plugin && node.name === name;
|
|
14
14
|
}
|
|
15
|
+
const markdownTransformClaim = Symbol('MarkdownTransformClaim');
|
|
16
|
+
/** @internal Registers a cheap source-level claim check for a helper transform. */
|
|
17
|
+
export function markMarkdownTransformClaim(transform, claims) {
|
|
18
|
+
Object.defineProperty(transform, markdownTransformClaim, {
|
|
19
|
+
configurable: false,
|
|
20
|
+
enumerable: false,
|
|
21
|
+
value: claims,
|
|
22
|
+
writable: false
|
|
23
|
+
});
|
|
24
|
+
return transform;
|
|
25
|
+
}
|
|
15
26
|
|
|
16
27
|
/** Opaque, covariant entry safe to store in heterogeneous plugin lists. */
|
|
17
28
|
|
|
@@ -147,7 +158,8 @@ export function prepareMarkdownPlugins(plugins) {
|
|
|
147
158
|
if (definition.transform != null) {
|
|
148
159
|
transforms.push({
|
|
149
160
|
pluginName: definition.name,
|
|
150
|
-
transform: definition.transform
|
|
161
|
+
transform: definition.transform,
|
|
162
|
+
claims: definition.transform[markdownTransformClaim]
|
|
151
163
|
});
|
|
152
164
|
}
|
|
153
165
|
if (definition.renderers != null) {
|
|
@@ -503,9 +515,19 @@ export function applyMarkdownTransforms(root, plugins, source, isFinal, display)
|
|
|
503
515
|
}
|
|
504
516
|
const pluginNames = new Set(plugins.entries.map(entry => entry.name));
|
|
505
517
|
const rendererKeys = new Set(plugins.renderers.keys());
|
|
506
|
-
|
|
507
|
-
let
|
|
518
|
+
let document = root;
|
|
519
|
+
let sourceHeadingMarkers;
|
|
520
|
+
let started = false;
|
|
521
|
+
let priorTransformChangedTree = false;
|
|
508
522
|
for (const prepared of plugins.transforms) {
|
|
523
|
+
if (!priorTransformChangedTree && prepared.claims?.(source) === false) {
|
|
524
|
+
continue;
|
|
525
|
+
}
|
|
526
|
+
if (!started) {
|
|
527
|
+
sourceHeadingMarkers = markSourceHeadings(root);
|
|
528
|
+
document = freezeAst(root);
|
|
529
|
+
started = true;
|
|
530
|
+
}
|
|
509
531
|
try {
|
|
510
532
|
const next = prepared.transform(document, {
|
|
511
533
|
source,
|
|
@@ -527,6 +549,7 @@ export function applyMarkdownTransforms(root, plugins, source, isFinal, display)
|
|
|
527
549
|
if (!validateAst(next, pluginNames, rendererKeys, positions, sourceHeadingMarkers, prepared.pluginName, existingExtensions, display)) {
|
|
528
550
|
throw new TypeError('Transform returned an invalid Markdown document');
|
|
529
551
|
}
|
|
552
|
+
priorTransformChangedTree = true;
|
|
530
553
|
document = freezeAst(next);
|
|
531
554
|
} catch (error) {
|
|
532
555
|
reportMarkdownPluginFailure(prepared.pluginName, 'transform', error);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file textTransform.ts
|
|
3
|
+
* @input Regex selectors and replacement callbacks for eligible Markdown prose
|
|
4
|
+
* @output Immutable Markdown transforms with protected-context traversal
|
|
5
|
+
* @position Optional helper layer compiled onto the core transform protocol
|
|
6
|
+
*/
|
|
7
|
+
import type { MarkdownAstPhrasingContent } from '../ast';
|
|
8
|
+
import { type MarkdownExtensionNode, type MarkdownTransform } from './protocol';
|
|
9
|
+
export interface MarkdownTextTransformContext {
|
|
10
|
+
readonly parentType: 'heading' | 'paragraph' | 'strong' | 'emphasis' | 'delete' | 'tableCell';
|
|
11
|
+
}
|
|
12
|
+
export interface MarkdownTextTransformOptions<Node extends MarkdownExtensionNode = never> {
|
|
13
|
+
/** Global expression matched against eligible built-in prose only. */
|
|
14
|
+
readonly pattern: RegExp;
|
|
15
|
+
/**
|
|
16
|
+
* Literal substrings such that source containing an eligible match contains
|
|
17
|
+
* at least one. Core uses them to skip the transform without walking the AST
|
|
18
|
+
* when none are present. Omit this optimization when no conservative literal
|
|
19
|
+
* exists; the helper will inspect eligible prose on every run. This fast path
|
|
20
|
+
* is also disabled for case-insensitive patterns so JavaScript case folding
|
|
21
|
+
* remains exact.
|
|
22
|
+
*/
|
|
23
|
+
readonly requiredSubstrings?: readonly [string, ...string[]];
|
|
24
|
+
/** Optionally decline or extend a regex claim. */
|
|
25
|
+
readonly getEndIndex?: (text: string, match: RegExpExecArray) => number | false;
|
|
26
|
+
replace(match: RegExpExecArray, context: MarkdownTextTransformContext): MarkdownAstPhrasingContent<Node> | ReadonlyArray<MarkdownAstPhrasingContent<Node>>;
|
|
27
|
+
}
|
|
28
|
+
export declare function createMarkdownTextTransform(options: MarkdownTextTransformOptions<never>): MarkdownTransform<never>;
|
|
29
|
+
export declare function createMarkdownTextTransform<Node extends MarkdownExtensionNode>(options: MarkdownTextTransformOptions<Node>): MarkdownTransform<Node>;
|
|
30
|
+
//# sourceMappingURL=textTransform.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"textTransform.d.ts","sourceRoot":"","sources":["../../../src/Markdown/plugins/textTransform.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AAEH,OAAO,KAAK,EAA0B,0BAA0B,EAAC,MAAM,QAAQ,CAAC;AAChF,OAAO,EAEL,KAAK,qBAAqB,EAC1B,KAAK,iBAAiB,EACvB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,UAAU,EACjB,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,UAAU,GAAG,QAAQ,GAAG,WAAW,CAAC;CAC5E;AAED,MAAM,WAAW,4BAA4B,CAC3C,IAAI,SAAS,qBAAqB,GAAG,KAAK;IAE1C,sEAAsE;IACtE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB;;;;;;;OAOG;IACH,QAAQ,CAAC,kBAAkB,CAAC,EAAE,SAAS,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC;IAC7D,kDAAkD;IAClD,QAAQ,CAAC,WAAW,CAAC,EAAE,CACrB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,eAAe,KACnB,MAAM,GAAG,KAAK,CAAC;IACpB,OAAO,CACL,KAAK,EAAE,eAAe,EACtB,OAAO,EAAE,4BAA4B,GAEnC,0BAA0B,CAAC,IAAI,CAAC,GAChC,aAAa,CAAC,0BAA0B,CAAC,IAAI,CAAC,CAAC,CAAC;CACrD;AA6ND,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,4BAA4B,CAAC,KAAK,CAAC,GAC3C,iBAAiB,CAAC,KAAK,CAAC,CAAC;AAC5B,wBAAgB,2BAA2B,CAAC,IAAI,SAAS,qBAAqB,EAC5E,OAAO,EAAE,4BAA4B,CAAC,IAAI,CAAC,GAC1C,iBAAiB,CAAC,IAAI,CAAC,CAAC"}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file textTransform.ts
|
|
5
|
+
* @input Regex selectors and replacement callbacks for eligible Markdown prose
|
|
6
|
+
* @output Immutable Markdown transforms with protected-context traversal
|
|
7
|
+
* @position Optional helper layer compiled onto the core transform protocol
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { markMarkdownTransformClaim } from "./protocol.js";
|
|
11
|
+
function sameItems(left, right) {
|
|
12
|
+
return left.length === right.length && left.every((value, index) => value === right[index]);
|
|
13
|
+
}
|
|
14
|
+
function cloneReplacement(value, seen = new Map()) {
|
|
15
|
+
if (value == null || typeof value !== 'object') {
|
|
16
|
+
return value;
|
|
17
|
+
}
|
|
18
|
+
const cached = seen.get(value);
|
|
19
|
+
if (cached != null) {
|
|
20
|
+
return cached;
|
|
21
|
+
}
|
|
22
|
+
if (Array.isArray(value)) {
|
|
23
|
+
const clone = [];
|
|
24
|
+
seen.set(value, clone);
|
|
25
|
+
for (const item of value) {
|
|
26
|
+
clone.push(cloneReplacement(item, seen));
|
|
27
|
+
}
|
|
28
|
+
return clone;
|
|
29
|
+
}
|
|
30
|
+
if (Object.getPrototypeOf(value) !== Object.prototype) {
|
|
31
|
+
return value;
|
|
32
|
+
}
|
|
33
|
+
const clone = {};
|
|
34
|
+
seen.set(value, clone);
|
|
35
|
+
for (const [key, nested] of Object.entries(value)) {
|
|
36
|
+
clone[key] = cloneReplacement(nested, seen);
|
|
37
|
+
}
|
|
38
|
+
return clone;
|
|
39
|
+
}
|
|
40
|
+
function advanceStringIndex(value, index, unicode) {
|
|
41
|
+
if (!unicode || index >= value.length) {
|
|
42
|
+
return index + 1;
|
|
43
|
+
}
|
|
44
|
+
const first = value.charCodeAt(index);
|
|
45
|
+
if (first < 0xd800 || first > 0xdbff || index + 1 >= value.length) {
|
|
46
|
+
return index + 1;
|
|
47
|
+
}
|
|
48
|
+
const second = value.charCodeAt(index + 1);
|
|
49
|
+
return second >= 0xdc00 && second <= 0xdfff ? index + 2 : index + 1;
|
|
50
|
+
}
|
|
51
|
+
function replaceTextNode(value, options, parentType) {
|
|
52
|
+
const pattern = new RegExp(options.pattern.source, options.pattern.flags);
|
|
53
|
+
const output = [];
|
|
54
|
+
let cursor = 0;
|
|
55
|
+
let changed = false;
|
|
56
|
+
let match;
|
|
57
|
+
while ((match = pattern.exec(value)) != null) {
|
|
58
|
+
const start = match.index;
|
|
59
|
+
const defaultEnd = start + match[0].length;
|
|
60
|
+
const resolvedEnd = options.getEndIndex?.(value, match) ?? defaultEnd;
|
|
61
|
+
if (resolvedEnd === false) {
|
|
62
|
+
if (match[0].length === 0) {
|
|
63
|
+
pattern.lastIndex = advanceStringIndex(value, pattern.lastIndex, pattern.unicode || pattern.flags.includes('v'));
|
|
64
|
+
}
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
if (!Number.isInteger(resolvedEnd) || resolvedEnd < defaultEnd || resolvedEnd < start || resolvedEnd > value.length) {
|
|
68
|
+
throw new TypeError('Markdown text transform returned an invalid end index');
|
|
69
|
+
}
|
|
70
|
+
if (start < cursor) {
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
if (start > cursor) {
|
|
74
|
+
output.push({
|
|
75
|
+
type: 'text',
|
|
76
|
+
value: value.slice(cursor, start)
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
const replacement = options.replace(match, {
|
|
80
|
+
parentType
|
|
81
|
+
});
|
|
82
|
+
const replacements = Array.isArray(replacement) ? replacement : [replacement];
|
|
83
|
+
for (const replacementNode of replacements) {
|
|
84
|
+
output.push(cloneReplacement(replacementNode));
|
|
85
|
+
}
|
|
86
|
+
cursor = resolvedEnd;
|
|
87
|
+
pattern.lastIndex = resolvedEnd === start ? advanceStringIndex(value, pattern.lastIndex, pattern.unicode || pattern.flags.includes('v')) : Math.max(pattern.lastIndex, resolvedEnd);
|
|
88
|
+
changed = true;
|
|
89
|
+
}
|
|
90
|
+
if (!changed) {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
if (cursor < value.length) {
|
|
94
|
+
output.push({
|
|
95
|
+
type: 'text',
|
|
96
|
+
value: value.slice(cursor)
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
return output;
|
|
100
|
+
}
|
|
101
|
+
function transformPhrasing(children, options, parentType) {
|
|
102
|
+
const next = [];
|
|
103
|
+
for (const node of children) {
|
|
104
|
+
if (node.type === 'text') {
|
|
105
|
+
next.push(...(replaceTextNode(node.value, options, parentType) ?? [node]));
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
if (node.type === 'strong' || node.type === 'emphasis' || node.type === 'delete') {
|
|
109
|
+
const nested = transformPhrasing(node.children, options, node.type);
|
|
110
|
+
next.push(sameItems(node.children, nested) ? node : {
|
|
111
|
+
...node,
|
|
112
|
+
children: nested
|
|
113
|
+
});
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
// Links, images, code, math, citations, breaks, and accepted extension
|
|
117
|
+
// syntax are protected contexts owned by their existing semantics.
|
|
118
|
+
next.push(node);
|
|
119
|
+
}
|
|
120
|
+
return sameItems(children, next) ? children : next;
|
|
121
|
+
}
|
|
122
|
+
function transformBlocks(blocks, options) {
|
|
123
|
+
const next = blocks.map(block => {
|
|
124
|
+
switch (block.type) {
|
|
125
|
+
case 'heading':
|
|
126
|
+
case 'paragraph':
|
|
127
|
+
{
|
|
128
|
+
const children = transformPhrasing(block.children, options, block.type);
|
|
129
|
+
return children === block.children ? block : {
|
|
130
|
+
...block,
|
|
131
|
+
children
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
case 'blockquote':
|
|
135
|
+
{
|
|
136
|
+
const children = transformBlocks(block.children, options);
|
|
137
|
+
return children === block.children ? block : {
|
|
138
|
+
...block,
|
|
139
|
+
children
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
case 'list':
|
|
143
|
+
{
|
|
144
|
+
let changed = false;
|
|
145
|
+
const children = block.children.map(item => {
|
|
146
|
+
const itemChildren = transformBlocks(item.children, options);
|
|
147
|
+
if (itemChildren === item.children) {
|
|
148
|
+
return item;
|
|
149
|
+
}
|
|
150
|
+
changed = true;
|
|
151
|
+
return {
|
|
152
|
+
...item,
|
|
153
|
+
children: itemChildren
|
|
154
|
+
};
|
|
155
|
+
});
|
|
156
|
+
return changed ? {
|
|
157
|
+
...block,
|
|
158
|
+
children
|
|
159
|
+
} : block;
|
|
160
|
+
}
|
|
161
|
+
case 'table':
|
|
162
|
+
{
|
|
163
|
+
let changed = false;
|
|
164
|
+
const children = block.children.map(row => {
|
|
165
|
+
let rowChanged = false;
|
|
166
|
+
const cells = row.children.map(cell => {
|
|
167
|
+
const cellChildren = transformPhrasing(cell.children, options, 'tableCell');
|
|
168
|
+
if (cellChildren === cell.children) {
|
|
169
|
+
return cell;
|
|
170
|
+
}
|
|
171
|
+
rowChanged = true;
|
|
172
|
+
return {
|
|
173
|
+
...cell,
|
|
174
|
+
children: cellChildren
|
|
175
|
+
};
|
|
176
|
+
});
|
|
177
|
+
if (!rowChanged) {
|
|
178
|
+
return row;
|
|
179
|
+
}
|
|
180
|
+
changed = true;
|
|
181
|
+
return {
|
|
182
|
+
...row,
|
|
183
|
+
children: cells
|
|
184
|
+
};
|
|
185
|
+
});
|
|
186
|
+
return changed ? {
|
|
187
|
+
...block,
|
|
188
|
+
children
|
|
189
|
+
} : block;
|
|
190
|
+
}
|
|
191
|
+
case 'code':
|
|
192
|
+
case 'math':
|
|
193
|
+
case 'image':
|
|
194
|
+
case 'thematicBreak':
|
|
195
|
+
case 'extension':
|
|
196
|
+
return block;
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
return sameItems(blocks, next) ? blocks : next;
|
|
200
|
+
}
|
|
201
|
+
export function createMarkdownTextTransform(options) {
|
|
202
|
+
if (!options.pattern.global) {
|
|
203
|
+
throw new TypeError('Markdown text transform patterns must use the global flag');
|
|
204
|
+
}
|
|
205
|
+
if (options.requiredSubstrings != null && (!Array.isArray(options.requiredSubstrings) || options.requiredSubstrings.length === 0 || options.requiredSubstrings.some(value => typeof value !== 'string' || value === ''))) {
|
|
206
|
+
throw new TypeError('Markdown text transform requiredSubstrings must be non-empty strings');
|
|
207
|
+
}
|
|
208
|
+
const requiredSubstrings = options.requiredSubstrings == null ? undefined : Object.freeze([...options.requiredSubstrings]);
|
|
209
|
+
const normalizedOptions = Object.freeze({
|
|
210
|
+
pattern: new RegExp(options.pattern.source, options.pattern.flags),
|
|
211
|
+
requiredSubstrings,
|
|
212
|
+
getEndIndex: options.getEndIndex,
|
|
213
|
+
replace: options.replace
|
|
214
|
+
});
|
|
215
|
+
const transform = root => {
|
|
216
|
+
const children = transformBlocks(root.children, normalizedOptions);
|
|
217
|
+
return children === root.children ? root : {
|
|
218
|
+
...root,
|
|
219
|
+
children
|
|
220
|
+
};
|
|
221
|
+
};
|
|
222
|
+
if (requiredSubstrings == null || options.pattern.ignoreCase) {
|
|
223
|
+
return transform;
|
|
224
|
+
}
|
|
225
|
+
return markMarkdownTransformClaim(transform, source => requiredSubstrings.some(required => source.includes(required)));
|
|
226
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astryxdesign/core",
|
|
3
|
-
"version": "0.6.2-canary.
|
|
3
|
+
"version": "0.6.2-canary.eec3a19",
|
|
4
4
|
"displayName": "Astryx Core",
|
|
5
5
|
"description": "The component library. Accessible, themeable React components with built-in spacing, dark mode, and StyleX styling.",
|
|
6
6
|
"author": "Meta Open Source",
|
|
@@ -677,8 +677,8 @@
|
|
|
677
677
|
"react-dom": ">=19.0.0"
|
|
678
678
|
},
|
|
679
679
|
"devDependencies": {
|
|
680
|
-
"@astryxdesign/a11y-spec": "0.6.2-canary.
|
|
681
|
-
"@astryxdesign/cli": "0.6.2-canary.
|
|
680
|
+
"@astryxdesign/a11y-spec": "0.6.2-canary.eec3a19",
|
|
681
|
+
"@astryxdesign/cli": "0.6.2-canary.eec3a19",
|
|
682
682
|
"@babel/cli": "^7.29.7",
|
|
683
683
|
"@babel/core": "^7.29.7",
|
|
684
684
|
"@babel/preset-react": "^7.29.7",
|
|
@@ -252,6 +252,11 @@ export const docs = {
|
|
|
252
252
|
description:
|
|
253
253
|
'Use plugins created by createMarkdownPlugin for reusable syntax, immutable AST transforms, and typed extension rendering. Keep the ordered list stable while its syntax configuration is unchanged.',
|
|
254
254
|
},
|
|
255
|
+
{
|
|
256
|
+
guidance: true,
|
|
257
|
+
description:
|
|
258
|
+
'Use createMarkdownTextTransform for prose matching; it preserves code, links, images, citations, math, and accepted extension syntax as protected contexts. Provide requiredSubstrings only when they conservatively cover every possible match.',
|
|
259
|
+
},
|
|
255
260
|
{
|
|
256
261
|
guidance: true,
|
|
257
262
|
description:
|
|
@@ -302,24 +307,22 @@ import {Text} from '@astryxdesign/core/Text';
|
|
|
302
307
|
`,
|
|
303
308
|
},
|
|
304
309
|
{
|
|
305
|
-
label: '
|
|
310
|
+
label: 'Text transform helper',
|
|
306
311
|
code: `
|
|
307
312
|
import {Markdown} from '@astryxdesign/core/Markdown';
|
|
308
|
-
import {
|
|
313
|
+
import {
|
|
314
|
+
createMarkdownPlugin,
|
|
315
|
+
createMarkdownTextTransform,
|
|
316
|
+
} from '@astryxdesign/core/Markdown/plugins';
|
|
309
317
|
|
|
310
318
|
const finalLabels = createMarkdownPlugin({
|
|
311
319
|
name: 'final-labels',
|
|
312
320
|
apiVersion: 1,
|
|
313
|
-
transform(
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
? {...node, children: [{type: 'text', value: 'Final'}]}
|
|
319
|
-
: node,
|
|
320
|
-
),
|
|
321
|
-
};
|
|
322
|
-
},
|
|
321
|
+
transform: createMarkdownTextTransform({
|
|
322
|
+
pattern: /\\bDraft\\b/g,
|
|
323
|
+
requiredSubstrings: ['Draft'],
|
|
324
|
+
replace: () => ({type: 'text', value: 'Final'}),
|
|
325
|
+
}),
|
|
323
326
|
});
|
|
324
327
|
|
|
325
328
|
<Markdown plugins={[finalLabels]}># Draft</Markdown>;
|
|
@@ -553,6 +556,11 @@ export const docsZh = {
|
|
|
553
556
|
description:
|
|
554
557
|
'Use plugins created by createMarkdownPlugin for reusable syntax, immutable AST transforms, and typed extension rendering. Keep the ordered list stable while its syntax configuration is unchanged.',
|
|
555
558
|
},
|
|
559
|
+
{
|
|
560
|
+
guidance: true,
|
|
561
|
+
description:
|
|
562
|
+
'Use createMarkdownTextTransform for prose matching; it preserves code, links, images, citations, math, and accepted extension syntax as protected contexts. Provide requiredSubstrings only when they conservatively cover every possible match.',
|
|
563
|
+
},
|
|
556
564
|
{
|
|
557
565
|
guidance: true,
|
|
558
566
|
description:
|
|
@@ -605,6 +613,11 @@ export const docsDense = {
|
|
|
605
613
|
description:
|
|
606
614
|
'Use plugins created by createMarkdownPlugin for reusable syntax, immutable AST transforms, and typed extension rendering. Keep the ordered list stable while its syntax configuration is unchanged.',
|
|
607
615
|
},
|
|
616
|
+
{
|
|
617
|
+
guidance: true,
|
|
618
|
+
description:
|
|
619
|
+
'Use createMarkdownTextTransform for prose matching; it preserves code, links, images, citations, math, and accepted extension syntax as protected contexts. Provide requiredSubstrings only when they conservatively cover every possible match.',
|
|
620
|
+
},
|
|
608
621
|
{
|
|
609
622
|
guidance: true,
|
|
610
623
|
description:
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file Markdown.helpers.perf.test.ts
|
|
5
|
+
* @input Deterministic 200/500-section Markdown and zero-work text helpers
|
|
6
|
+
* @output Zero helper-transform invocations for hinted no-claim plugins
|
|
7
|
+
* @position Helper dispatch regression; full FR23 evidence lands after all helpers
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import {describe, expect, it} from 'vitest';
|
|
11
|
+
import {parseMarkdown} from './parser';
|
|
12
|
+
import {createMarkdownPlugin} from './plugins';
|
|
13
|
+
import type {MarkdownTransform} from './plugins/protocol';
|
|
14
|
+
import {createMarkdownTextTransform} from './plugins/textTransform';
|
|
15
|
+
|
|
16
|
+
let transformCalls = 0;
|
|
17
|
+
|
|
18
|
+
function benchmarkDocument(sections: number): string {
|
|
19
|
+
return Array.from({length: sections}, (_, index) =>
|
|
20
|
+
[
|
|
21
|
+
`## Section ${index}`,
|
|
22
|
+
'',
|
|
23
|
+
`AST-${index} belongs to @{owner-${index}} with TODO follow-up.`,
|
|
24
|
+
'',
|
|
25
|
+
`- First item ${index}`,
|
|
26
|
+
'- Second item',
|
|
27
|
+
'',
|
|
28
|
+
`> Quoted detail ${index}`,
|
|
29
|
+
'',
|
|
30
|
+
'| Item | Detail |',
|
|
31
|
+
'| --- | --- |',
|
|
32
|
+
`| ${index} | ordinary prose |`,
|
|
33
|
+
'',
|
|
34
|
+
'```text',
|
|
35
|
+
`opaque ${index}`,
|
|
36
|
+
'```',
|
|
37
|
+
].join('\n'),
|
|
38
|
+
).join('\n\n');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function observeTransformCalls(
|
|
42
|
+
transform: MarkdownTransform,
|
|
43
|
+
): MarkdownTransform {
|
|
44
|
+
const observed: MarkdownTransform = (root, context) => {
|
|
45
|
+
transformCalls++;
|
|
46
|
+
return transform(root, context);
|
|
47
|
+
};
|
|
48
|
+
// Preserve the helper's private source-claim metadata on the observer.
|
|
49
|
+
Object.defineProperties(
|
|
50
|
+
observed,
|
|
51
|
+
Object.getOwnPropertyDescriptors(transform),
|
|
52
|
+
);
|
|
53
|
+
return observed;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const zeroWorkPlugins = Array.from({length: 5}, (_, index) =>
|
|
57
|
+
createMarkdownPlugin({
|
|
58
|
+
name: `zero-work-${index}`,
|
|
59
|
+
apiVersion: 1,
|
|
60
|
+
transform: observeTransformCalls(
|
|
61
|
+
createMarkdownTextTransform({
|
|
62
|
+
pattern: new RegExp(`NEVER_MATCH_${index}`, 'g'),
|
|
63
|
+
requiredSubstrings: [`NEVER_MATCH_${index}`],
|
|
64
|
+
replace: () => {
|
|
65
|
+
throw new Error('An unclaimed helper callback ran');
|
|
66
|
+
},
|
|
67
|
+
}),
|
|
68
|
+
),
|
|
69
|
+
}),
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
describe('Markdown helper performance', () => {
|
|
73
|
+
it.each([200, 500])(
|
|
74
|
+
'skips five hinted no-claim helpers at %i sections',
|
|
75
|
+
sections => {
|
|
76
|
+
const source = benchmarkDocument(sections);
|
|
77
|
+
const baseline = parseMarkdown(source);
|
|
78
|
+
transformCalls = 0;
|
|
79
|
+
|
|
80
|
+
expect(parseMarkdown(source, {plugins: zeroWorkPlugins})).toEqual(
|
|
81
|
+
baseline,
|
|
82
|
+
);
|
|
83
|
+
expect(parseMarkdown(source, {plugins: [...zeroWorkPlugins]})).toEqual(
|
|
84
|
+
baseline,
|
|
85
|
+
);
|
|
86
|
+
expect(transformCalls).toBe(0);
|
|
87
|
+
},
|
|
88
|
+
);
|
|
89
|
+
});
|
|
@@ -15,7 +15,11 @@ import {
|
|
|
15
15
|
parseMarkdownIncremental,
|
|
16
16
|
visitMarkdownNodes,
|
|
17
17
|
} from './index';
|
|
18
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
createMarkdownPlugin,
|
|
20
|
+
createMarkdownTextTransform,
|
|
21
|
+
isMarkdownExtensionNode,
|
|
22
|
+
} from './plugins';
|
|
19
23
|
import type {
|
|
20
24
|
MarkdownExtensionNode,
|
|
21
25
|
MarkdownSyntaxPluginDefinition,
|
|
@@ -193,6 +197,7 @@ describe('Markdown public parser types', () => {
|
|
|
193
197
|
|
|
194
198
|
expectTypeOf(nodes).toEqualTypeOf<InlineNode<PublicNode>[]>();
|
|
195
199
|
expectTypeOf(visitMarkdownNodes).toBeFunction();
|
|
200
|
+
expectTypeOf(createMarkdownTextTransform).toBeFunction();
|
|
196
201
|
expectTypeOf(isMarkdownExtensionNode).toBeFunction();
|
|
197
202
|
|
|
198
203
|
function compileOnlyPluginGuards() {
|
|
@@ -7,6 +7,11 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
export {createMarkdownPlugin, isMarkdownExtensionNode} from './protocol';
|
|
10
|
+
export {createMarkdownTextTransform} from './textTransform';
|
|
11
|
+
export type {
|
|
12
|
+
MarkdownTextTransformContext,
|
|
13
|
+
MarkdownTextTransformOptions,
|
|
14
|
+
} from './textTransform';
|
|
10
15
|
export type {
|
|
11
16
|
MarkdownPluginData,
|
|
12
17
|
MarkdownExtensionNode,
|