@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.
@@ -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
- export type MarkdownTransform = (document: MarkdownAstRoot<MarkdownExtensionNode>, context: MarkdownTransformContext) => MarkdownAstRoot<MarkdownExtensionNode>;
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
- const sourceHeadingMarkers = markSourceHeadings(root);
507
- let document = freezeAst(root);
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.d993f65",
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.d993f65",
681
- "@astryxdesign/cli": "0.6.2-canary.d993f65",
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: 'Immutable transform plugin',
310
+ label: 'Text transform helper',
306
311
  code: `
307
312
  import {Markdown} from '@astryxdesign/core/Markdown';
308
- import {createMarkdownPlugin} from '@astryxdesign/core/Markdown/plugins';
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(root) {
314
- return {
315
- ...root,
316
- children: root.children.map(node =>
317
- node.type === 'heading'
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 {createMarkdownPlugin, isMarkdownExtensionNode} from './plugins';
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,