@readme/markdown 14.13.1 → 14.14.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.
package/dist/main.js CHANGED
@@ -11602,6 +11602,7 @@ __webpack_require__.d(__webpack_exports__, {
11602
11602
  extractToc: () => (/* reexport */ lib_extractToc),
11603
11603
  gemojiRegex: () => (/* reexport */ gemoji_regex),
11604
11604
  hast: () => (/* reexport */ lib_hast),
11605
+ htmlToMarkdown: () => (/* reexport */ htmlToMarkdown),
11605
11606
  mdast: () => (/* reexport */ lib_mdast),
11606
11607
  mdastV6: () => (/* reexport */ lib_mdastV6),
11607
11608
  mdx: () => (/* reexport */ lib_mdx),
@@ -12645,6 +12646,10 @@ const tailwindPrefix = 'readme-tailwind';
12645
12646
 
12646
12647
 
12647
12648
  const TailwindRoot = ({ children, flow }) => {
12649
+ // `styles/gfm.scss` spaces the wrapped block children through this element and
12650
+ // relies on their margins collapsing through it. Keep it a plain block — no
12651
+ // border, padding, or block formatting context (overflow, display: flow-root/
12652
+ // flex/grid) — or the spacing breaks.
12648
12653
  const Tag = flow ? 'div' : 'span';
12649
12654
  return external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_default().createElement(Tag, { className: tailwindPrefix }, children);
12650
12655
  };
@@ -54506,6 +54511,13 @@ const mdast = (text, opts = {}) => {
54506
54511
  * to parse expressions containing JSX.
54507
54512
  */
54508
54513
  const jsxAcornParser = external_acorn_.Parser.extend(acorn_jsx_default()());
54514
+ /**
54515
+ * Disables CommonMark's indented-code-block construct (4+ spaces)
54516
+ * The micromark tokenizers use follow the CommonMark specification: https://spec.commonmark.org/0.28/#indented-code-blocks
54517
+ * So any lines indented 4+ spaces are considered as a code block,
54518
+ * which is unexpected from users that used MDX before.
54519
+ */
54520
+ const disableIndentedCode = { disable: { null: ['codeIndented'] } };
54509
54521
  /**
54510
54522
  * Evaluate a JavaScript expression source and return its value.
54511
54523
  *
@@ -92490,185 +92502,70 @@ const hast = (text, opts = {}) => {
92490
92502
  };
92491
92503
  /* harmony default export */ const lib_hast = (hast);
92492
92504
 
92493
- ;// ./processor/migration/emphasis.ts
92494
-
92495
- const emphasis_strongTest = (node) => ['emphasis', 'strong'].includes(node.type);
92496
- const addSpaceBefore = (index, parent) => {
92497
- if (!(index > 0 && parent.children[index - 1]))
92498
- return;
92499
- const prev = parent.children[index - 1];
92500
- if (!('value' in prev) || prev.value.endsWith(' ') || prev.type === 'escape')
92501
- return;
92502
- parent.children.splice(index, 0, { type: 'text', value: ' ' });
92503
- };
92504
- const addSpaceAfter = (index, parent) => {
92505
- if (!(index < parent.children.length - 1 && parent.children[index + 1]))
92506
- return;
92507
- const nextChild = parent.children[index + 1];
92508
- if (!('value' in nextChild) || nextChild.value.startsWith(' '))
92509
- return;
92510
- parent.children.splice(index + 1, 0, { type: 'text', value: ' ' });
92511
- };
92512
- const trimEmphasis = (node, index, parent) => {
92513
- let trimmed = false;
92514
- visit(node, 'text', (child) => {
92515
- const newValue = child.value.trimStart();
92516
- if (newValue !== child.value) {
92517
- trimmed = true;
92518
- child.value = newValue;
92519
- }
92520
- return EXIT;
92521
- });
92522
- visit(node, 'text', (child) => {
92523
- const newValue = child.value.trimEnd();
92524
- if (newValue !== child.value) {
92525
- trimmed = true;
92526
- child.value = newValue;
92527
- }
92528
- return EXIT;
92529
- }, true);
92530
- if (trimmed) {
92531
- addSpaceBefore(index, parent);
92532
- addSpaceAfter(index, parent);
92533
- }
92534
- };
92535
- const emphasisTransfomer = () => (tree) => {
92536
- visit(tree, emphasis_strongTest, trimEmphasis);
92537
- return tree;
92538
- };
92539
- /* harmony default export */ const migration_emphasis = (emphasisTransfomer);
92505
+ ;// ./node_modules/rehype-parse/lib/index.js
92506
+ /**
92507
+ * @import {Root} from 'hast'
92508
+ * @import {Options as FromHtmlOptions} from 'hast-util-from-html'
92509
+ * @import {Parser, Processor} from 'unified'
92510
+ */
92540
92511
 
92541
- ;// ./processor/migration/images.ts
92512
+ /**
92513
+ * @typedef {Omit<FromHtmlOptions, 'onerror'> & RehypeParseFields} Options
92514
+ * Configuration.
92515
+ *
92516
+ * @typedef RehypeParseFields
92517
+ * Extra fields.
92518
+ * @property {boolean | null | undefined} [emitParseErrors=false]
92519
+ * Whether to emit parse errors while parsing (default: `false`).
92520
+ *
92521
+ * > 👉 **Note**: parse errors are currently being added to HTML.
92522
+ * > Not all errors emitted by parse5 (or us) are specced yet.
92523
+ * > Some documentation may still be missing.
92524
+ */
92542
92525
 
92543
- const images_imageTransformer = () => tree => {
92544
- visit(tree, 'image', (image) => {
92545
- if (image.data?.hProperties?.className === 'border') {
92546
- image.data.hProperties.border = true;
92547
- }
92548
- });
92549
- };
92550
- /* harmony default export */ const migration_images = (images_imageTransformer);
92551
92526
 
92552
- ;// ./processor/migration/linkReference.ts
92553
92527
 
92554
- const linkReferenceTransformer = () => (tree) => {
92555
- visit(tree, 'linkReference', (node, index, parent) => {
92556
- const definitions = {};
92557
- visit(tree, 'definition', (def) => {
92558
- definitions[def.identifier] = def;
92559
- });
92560
- if (node.label === node.identifier && parent) {
92561
- if (!(node.identifier in definitions)) {
92562
- parent.children[index] = {
92563
- type: 'text',
92564
- value: `[${node.label}]`,
92565
- position: node.position,
92566
- };
92567
- }
92568
- }
92569
- });
92570
- return tree;
92571
- };
92572
- /* harmony default export */ const migration_linkReference = (linkReferenceTransformer);
92528
+ /**
92529
+ * Plugin to add support for parsing from HTML.
92530
+ *
92531
+ * > 👉 **Note**: this is not an XML parser.
92532
+ * > It supports SVG as embedded in HTML.
92533
+ * > It does not support the features available in XML.
92534
+ * > Passing SVG files might break but fragments of modern SVG should be fine.
92535
+ * > Use [`xast-util-from-xml`][xast-util-from-xml] to parse XML.
92536
+ *
92537
+ * @param {Options | null | undefined} [options]
92538
+ * Configuration (optional).
92539
+ * @returns {undefined}
92540
+ * Nothing.
92541
+ */
92542
+ function rehypeParse(options) {
92543
+ /** @type {Processor<Root>} */
92544
+ // @ts-expect-error: TS in JSDoc generates wrong types if `this` is typed regularly.
92545
+ const self = this
92546
+ const {emitParseErrors, ...settings} = {...self.data('settings'), ...options}
92573
92547
 
92574
- ;// ./processor/migration/table-cell.ts
92548
+ self.parser = parser
92575
92549
 
92576
- const magicIndex = (i, j) => `${i === 0 ? 'h' : `${i - 1}`}-${j}`;
92577
- const isInlineHtml = node => node.type === 'html' && !node.block;
92578
- // @note: This regex is detect malformed lists that were created by the
92579
- // markdown editor. Consider the following markdown:
92580
- //
92581
- // ```
92582
- // * item 1
92583
- // * item 2
92584
- // * item 3
92585
- // ```
92586
- //
92587
- // This is a perfectly valid list. But when you put that text into a table
92588
- // cell, the editor does **bad** things. After a save and load cycle, it gets
92589
- // converted to this:
92590
- //
92591
- // ```
92592
- // \_ item 1
92593
- // \_ item 2
92594
- // \* item 3
92595
- // ```
92596
- //
92597
- // The following regex attempts to detect this pattern, and we'll convert it to
92598
- // something more standard.
92599
- const psuedoListRegex = /^(?![ \t]*([*_]+).*\1[ \t]*$)(?<ws>[ \t]*)\\?([*_])\s*(?<item>.*)$/gm;
92600
- const migrateTableCells = (vfile, rdmd) => (table) => {
92601
- let json;
92602
- try {
92603
- const { position } = table;
92604
- if (position) {
92605
- json = JSON.parse(vfile
92606
- .toString()
92607
- .slice(position.start.offset, position.end.offset)
92608
- .replace(/.*\[block:parameters\](.*)\[\/block\].*/s, '$1'));
92609
- }
92610
- }
92611
- catch (err) {
92612
- /**
92613
- * This failure case is already handled by the following logic. Plus,
92614
- * because it's being handled internally, there's no way for our
92615
- * migration script to catch the error or keep track of it, and it just
92616
- * ends up blowing up the output logs.
92617
- */
92618
- // console.error(err);
92619
- }
92620
- visit(table, 'tableRow', (row, i) => {
92621
- visit(row, 'tableCell', (cell, j) => {
92622
- let children = cell.children;
92623
- if (json && json.data[magicIndex(i, j)]) {
92624
- const string = json.data[magicIndex(i, j)].replace(psuedoListRegex, '$<ws>- $<item>');
92625
- children = rdmd.mdast(string).children;
92550
+ /**
92551
+ * @type {Parser<Root>}
92552
+ */
92553
+ function parser(document, file) {
92554
+ return fromHtml(document, {
92555
+ ...settings,
92556
+ onerror: emitParseErrors
92557
+ ? function (message) {
92558
+ if (file.path) {
92559
+ message.name = file.path + ':' + message.name
92560
+ message.file = file.path
92626
92561
  }
92627
- cell.children =
92628
- children.length > 1 && !children.some(isInlineHtml)
92629
- ? children
92630
- : [{ type: 'paragraph', children }];
92631
- return SKIP;
92632
- });
92633
- return SKIP;
92634
- });
92635
- visit(table, 'inlineCode', (code) => {
92636
- if (code.value.includes('\n')) {
92637
- code.type = 'code';
92638
- }
92639
- });
92640
- };
92641
- function tableCellTransformer() {
92642
- const rdmd = this.data('rdmd');
92643
- return (tree, vfile) => {
92644
- visit(tree, 'table', migrateTableCells(vfile, rdmd));
92645
- return tree;
92646
- };
92647
- }
92648
- /* harmony default export */ const table_cell = (tableCellTransformer);
92649
-
92650
- ;// ./processor/migration/index.ts
92651
-
92652
-
92653
-
92654
-
92655
- const transformers = [migration_emphasis, migration_images, migration_linkReference, table_cell];
92656
- /* harmony default export */ const migration = (transformers);
92657
92562
 
92658
- ;// ./lib/mdastV6.ts
92659
-
92660
- const migrationNormalize = (doc) => {
92661
- return doc.replaceAll(/^(<!--.*?)\\-->$/gms, '$1-->');
92662
- };
92663
- const mdastV6 = (doc, { rdmd }) => {
92664
- const [_normalizedDoc] = rdmd.setup(doc);
92665
- const normalizedDoc = migrationNormalize(_normalizedDoc);
92666
- const proc = rdmd.processor().use(migration).data('rdmd', rdmd);
92667
- const tree = proc.parse(normalizedDoc);
92668
- proc.runSync(tree, normalizedDoc);
92669
- return tree;
92670
- };
92671
- /* harmony default export */ const lib_mdastV6 = (mdastV6);
92563
+ file.messages.push(message)
92564
+ }
92565
+ : undefined
92566
+ })
92567
+ }
92568
+ }
92672
92569
 
92673
92570
  ;// ./node_modules/hast-util-is-element/lib/index.js
92674
92571
  /**
@@ -97195,6 +97092,227 @@ function rehypeRemark(destination, options) {
97195
97092
  }
97196
97093
  }
97197
97094
 
97095
+ ;// ./lib/htmlToMarkdown.ts
97096
+
97097
+
97098
+
97099
+
97100
+
97101
+ /**
97102
+ * Converts an HTML fragment to GitHub-flavored Markdown.
97103
+ *
97104
+ * `remark-gfm` is load-bearing: without it, `<table>` and `<del>` input throws
97105
+ * at serialization. `iframe` (default: becomes a link) and `noscript` (default:
97106
+ * keeps its text) are dropped by the handlers so raw markup never leaks;
97107
+ * `script`, `style`, and `template` already drop by default and are overridden
97108
+ * defensively. HTML comments are dropped via `nodeHandlers`.
97109
+ */
97110
+ const processor = unified()
97111
+ .use(rehypeParse, { fragment: true })
97112
+ .use(rehypeRemark, {
97113
+ // A comment is a `comment` node, not an element, so it goes in
97114
+ // `nodeHandlers` rather than `handlers`.
97115
+ handlers: {
97116
+ iframe: () => undefined,
97117
+ noscript: () => undefined,
97118
+ script: () => undefined,
97119
+ style: () => undefined,
97120
+ template: () => undefined,
97121
+ },
97122
+ nodeHandlers: { comment: () => undefined },
97123
+ })
97124
+ .use(remarkGfm)
97125
+ .use(remarkStringify, { bullet: '-', emphasis: '_', fences: true });
97126
+ /**
97127
+ * Returns the Markdown form of `html`, or an empty string when there is no
97128
+ * usable input. Synchronous, so it can run inside non-async serializers.
97129
+ */
97130
+ function htmlToMarkdown(html) {
97131
+ if (typeof html !== 'string' || !html.trim())
97132
+ return '';
97133
+ return processor.processSync(html).toString().trim();
97134
+ }
97135
+
97136
+ ;// ./processor/migration/emphasis.ts
97137
+
97138
+ const emphasis_strongTest = (node) => ['emphasis', 'strong'].includes(node.type);
97139
+ const addSpaceBefore = (index, parent) => {
97140
+ if (!(index > 0 && parent.children[index - 1]))
97141
+ return;
97142
+ const prev = parent.children[index - 1];
97143
+ if (!('value' in prev) || prev.value.endsWith(' ') || prev.type === 'escape')
97144
+ return;
97145
+ parent.children.splice(index, 0, { type: 'text', value: ' ' });
97146
+ };
97147
+ const addSpaceAfter = (index, parent) => {
97148
+ if (!(index < parent.children.length - 1 && parent.children[index + 1]))
97149
+ return;
97150
+ const nextChild = parent.children[index + 1];
97151
+ if (!('value' in nextChild) || nextChild.value.startsWith(' '))
97152
+ return;
97153
+ parent.children.splice(index + 1, 0, { type: 'text', value: ' ' });
97154
+ };
97155
+ const trimEmphasis = (node, index, parent) => {
97156
+ let trimmed = false;
97157
+ visit(node, 'text', (child) => {
97158
+ const newValue = child.value.trimStart();
97159
+ if (newValue !== child.value) {
97160
+ trimmed = true;
97161
+ child.value = newValue;
97162
+ }
97163
+ return EXIT;
97164
+ });
97165
+ visit(node, 'text', (child) => {
97166
+ const newValue = child.value.trimEnd();
97167
+ if (newValue !== child.value) {
97168
+ trimmed = true;
97169
+ child.value = newValue;
97170
+ }
97171
+ return EXIT;
97172
+ }, true);
97173
+ if (trimmed) {
97174
+ addSpaceBefore(index, parent);
97175
+ addSpaceAfter(index, parent);
97176
+ }
97177
+ };
97178
+ const emphasisTransfomer = () => (tree) => {
97179
+ visit(tree, emphasis_strongTest, trimEmphasis);
97180
+ return tree;
97181
+ };
97182
+ /* harmony default export */ const migration_emphasis = (emphasisTransfomer);
97183
+
97184
+ ;// ./processor/migration/images.ts
97185
+
97186
+ const images_imageTransformer = () => tree => {
97187
+ visit(tree, 'image', (image) => {
97188
+ if (image.data?.hProperties?.className === 'border') {
97189
+ image.data.hProperties.border = true;
97190
+ }
97191
+ });
97192
+ };
97193
+ /* harmony default export */ const migration_images = (images_imageTransformer);
97194
+
97195
+ ;// ./processor/migration/linkReference.ts
97196
+
97197
+ const linkReferenceTransformer = () => (tree) => {
97198
+ visit(tree, 'linkReference', (node, index, parent) => {
97199
+ const definitions = {};
97200
+ visit(tree, 'definition', (def) => {
97201
+ definitions[def.identifier] = def;
97202
+ });
97203
+ if (node.label === node.identifier && parent) {
97204
+ if (!(node.identifier in definitions)) {
97205
+ parent.children[index] = {
97206
+ type: 'text',
97207
+ value: `[${node.label}]`,
97208
+ position: node.position,
97209
+ };
97210
+ }
97211
+ }
97212
+ });
97213
+ return tree;
97214
+ };
97215
+ /* harmony default export */ const migration_linkReference = (linkReferenceTransformer);
97216
+
97217
+ ;// ./processor/migration/table-cell.ts
97218
+
97219
+ const magicIndex = (i, j) => `${i === 0 ? 'h' : `${i - 1}`}-${j}`;
97220
+ const isInlineHtml = node => node.type === 'html' && !node.block;
97221
+ // @note: This regex is detect malformed lists that were created by the
97222
+ // markdown editor. Consider the following markdown:
97223
+ //
97224
+ // ```
97225
+ // * item 1
97226
+ // * item 2
97227
+ // * item 3
97228
+ // ```
97229
+ //
97230
+ // This is a perfectly valid list. But when you put that text into a table
97231
+ // cell, the editor does **bad** things. After a save and load cycle, it gets
97232
+ // converted to this:
97233
+ //
97234
+ // ```
97235
+ // \_ item 1
97236
+ // \_ item 2
97237
+ // \* item 3
97238
+ // ```
97239
+ //
97240
+ // The following regex attempts to detect this pattern, and we'll convert it to
97241
+ // something more standard.
97242
+ const psuedoListRegex = /^(?![ \t]*([*_]+).*\1[ \t]*$)(?<ws>[ \t]*)\\?([*_])\s*(?<item>.*)$/gm;
97243
+ const migrateTableCells = (vfile, rdmd) => (table) => {
97244
+ let json;
97245
+ try {
97246
+ const { position } = table;
97247
+ if (position) {
97248
+ json = JSON.parse(vfile
97249
+ .toString()
97250
+ .slice(position.start.offset, position.end.offset)
97251
+ .replace(/.*\[block:parameters\](.*)\[\/block\].*/s, '$1'));
97252
+ }
97253
+ }
97254
+ catch (err) {
97255
+ /**
97256
+ * This failure case is already handled by the following logic. Plus,
97257
+ * because it's being handled internally, there's no way for our
97258
+ * migration script to catch the error or keep track of it, and it just
97259
+ * ends up blowing up the output logs.
97260
+ */
97261
+ // console.error(err);
97262
+ }
97263
+ visit(table, 'tableRow', (row, i) => {
97264
+ visit(row, 'tableCell', (cell, j) => {
97265
+ let children = cell.children;
97266
+ if (json && json.data[magicIndex(i, j)]) {
97267
+ const string = json.data[magicIndex(i, j)].replace(psuedoListRegex, '$<ws>- $<item>');
97268
+ children = rdmd.mdast(string).children;
97269
+ }
97270
+ cell.children =
97271
+ children.length > 1 && !children.some(isInlineHtml)
97272
+ ? children
97273
+ : [{ type: 'paragraph', children }];
97274
+ return SKIP;
97275
+ });
97276
+ return SKIP;
97277
+ });
97278
+ visit(table, 'inlineCode', (code) => {
97279
+ if (code.value.includes('\n')) {
97280
+ code.type = 'code';
97281
+ }
97282
+ });
97283
+ };
97284
+ function tableCellTransformer() {
97285
+ const rdmd = this.data('rdmd');
97286
+ return (tree, vfile) => {
97287
+ visit(tree, 'table', migrateTableCells(vfile, rdmd));
97288
+ return tree;
97289
+ };
97290
+ }
97291
+ /* harmony default export */ const table_cell = (tableCellTransformer);
97292
+
97293
+ ;// ./processor/migration/index.ts
97294
+
97295
+
97296
+
97297
+
97298
+ const transformers = [migration_emphasis, migration_images, migration_linkReference, table_cell];
97299
+ /* harmony default export */ const migration = (transformers);
97300
+
97301
+ ;// ./lib/mdastV6.ts
97302
+
97303
+ const migrationNormalize = (doc) => {
97304
+ return doc.replaceAll(/^(<!--.*?)\\-->$/gms, '$1-->');
97305
+ };
97306
+ const mdastV6 = (doc, { rdmd }) => {
97307
+ const [_normalizedDoc] = rdmd.setup(doc);
97308
+ const normalizedDoc = migrationNormalize(_normalizedDoc);
97309
+ const proc = rdmd.processor().use(migration).data('rdmd', rdmd);
97310
+ const tree = proc.parse(normalizedDoc);
97311
+ proc.runSync(tree, normalizedDoc);
97312
+ return tree;
97313
+ };
97314
+ /* harmony default export */ const lib_mdastV6 = (mdastV6);
97315
+
97198
97316
  ;// ./processor/compile/anchor.ts
97199
97317
 
97200
97318
 
@@ -99107,7 +99225,7 @@ function normalizeProperties(node) {
99107
99225
  * Identifies custom MDX components and recursively parses markdown children.
99108
99226
  * Replaces tagName with PascalCase component name for React component resolution.
99109
99227
  *
99110
- * @see {@link https://github.com/readmeio/rmdx/blob/main/docs/mdxish-flow.md}
99228
+ * @see .claude/context/MDXish/Processor Overview.md
99111
99229
  * @param {Options} options - Configuration options
99112
99230
  * @param {CustomComponents} options.components - Available custom components
99113
99231
  * @param {Function} options.processMarkdown - Function to process markdown content
@@ -101605,6 +101723,13 @@ const htmlFlowTagNames = new Set([...htmlRawNames, ...htmlBlockNames]);
101605
101723
  // blank lines between nested JSX siblings don't fragment the block. Excludes table
101606
101724
  // tags (mdxishTables owns their blank lines) and voids (never close).
101607
101725
  const plainBlockClaimTagNames = new Set([...htmlBlockNames].filter(tag => !HTML_TABLE_STRUCTURE_TAGS.has(tag) && !HTML_VOID_ELEMENTS.has(tag)));
101726
+ const foreignContentTags = new Set(FOREIGN_CONTENT_TAGS);
101727
+ // Type-7 lowercase tags (a, span, button, and unknown names): CommonMark ends their
101728
+ // block at a blank line, fragmenting 4+ column children into indented code. Claimable
101729
+ // only in block-wrapper shape (see `blockWrapperOpenerRest`); lookalike openers
101730
+ // (`<https://…>`) never find a closer, so their claim retreats cleanly to CommonMark.
101731
+ // Voids never close and raw/foreign-content bodies have dedicated owners.
101732
+ const isBlockWrapperClaimTagName = (tag) => !htmlFlowTagNames.has(tag) && !HTML_VOID_ELEMENTS.has(tag) && !foreignContentTags.has(tag);
101608
101733
  // Both are 4 columns per CommonMark, but they mean different things: a tab advances
101609
101734
  // to the next multiple of TAB_STOP_WIDTH, and INDENTED_CODE_MIN_COLUMNS is the depth
101610
101735
  // at which a line would fragment into indented code. Named separately so the two
@@ -101669,6 +101794,11 @@ function createTokenize(mode) {
101669
101794
  // `plainClaimLineStart`: after a blank line it may only continue on a tag line.
101670
101795
  let isPlainBlockClaim = false;
101671
101796
  let pendingBlankLine = false;
101797
+ // Type-7 tag claimed pending the block-wrapper (opener alone on its line) check.
101798
+ let pendingBlockWrapperClaim = false;
101799
+ // True once a block-wrapper claim is confirmed; relaxes the top-of-body island gate
101800
+ // below (type-7 fallback is the fragmentation bug, not intentional indented code).
101801
+ let isBlockWrapperClaim = false;
101672
101802
  // Leading indent columns of the current plain-claim line, reset per line; ≥4 is
101673
101803
  // where CommonMark would fragment the island as indented code. Tabs advance to the
101674
101804
  // next 4-column stop — the same rule `expandIndentToColumns`
@@ -101914,16 +102044,11 @@ function createTokenize(mode) {
101914
102044
  }
101915
102045
  // End of opening tag
101916
102046
  if (code === codes.greaterThan) {
101917
- if (requiresBraceAttr && !sawBraceAttr) {
101918
- // Plain lowercase block tags stay claimable in flow, gated per line by
101919
- // `plainClaimLineStart`; everything else falls through to CommonMark.
101920
- if (!isFlow || !plainBlockClaimTagNames.has(tagName))
101921
- return nok(code);
101922
- isPlainBlockClaim = true;
101923
- }
102047
+ if (requiresBraceAttr && !sawBraceAttr && !claimBraceLessTag())
102048
+ return nok(code);
101924
102049
  effects.consume(code);
101925
102050
  onOpenerLine = isFlow;
101926
- return body;
102051
+ return pendingBlockWrapperClaim ? blockWrapperOpenerRest : body;
101927
102052
  }
101928
102053
  // Quoted attribute value
101929
102054
  if (code === codes.quotationMark || code === codes.apostrophe) {
@@ -101978,6 +102103,35 @@ function createTokenize(mode) {
101978
102103
  // `/ ` without `>` is just part of the attribute area
101979
102104
  return afterOpenTagName(code);
101980
102105
  }
102106
+ // Whether a brace-less lowercase flow tag is claimable: type-6 tags immediately,
102107
+ // type-7 tags pending the block-wrapper check; anything else is CommonMark's.
102108
+ function claimBraceLessTag() {
102109
+ if (!isFlow)
102110
+ return false;
102111
+ if (plainBlockClaimTagNames.has(tagName)) {
102112
+ isPlainBlockClaim = true;
102113
+ return true;
102114
+ }
102115
+ if (isBlockWrapperClaimTagName(tagName)) {
102116
+ pendingBlockWrapperClaim = true;
102117
+ return true;
102118
+ }
102119
+ return false;
102120
+ }
102121
+ // A type-7 tag is claimed only as a block wrapper: opener alone on its line
102122
+ // (trailing spaces ok). Inline content after the opener bails to CommonMark.
102123
+ function blockWrapperOpenerRest(code) {
102124
+ if (markdownSpace(code)) {
102125
+ effects.consume(code);
102126
+ return blockWrapperOpenerRest;
102127
+ }
102128
+ if (!markdownLineEnding(code))
102129
+ return nok(code);
102130
+ pendingBlockWrapperClaim = false;
102131
+ isPlainBlockClaim = true;
102132
+ isBlockWrapperClaim = true;
102133
+ return body(code);
102134
+ }
101981
102135
  // Continuation for multi-line opening tags
101982
102136
  function openTagContinuationStart(code) {
101983
102137
  return effects.check(continuation_checks_nonLazyContinuationStart, openTagContinuationNonLazy, continuationAfter)(code);
@@ -102373,10 +102527,16 @@ function createTokenize(mode) {
102373
102527
  // continue on a tag line (`<…`); any markdown island (`**bold**`, `[block:…]`, a
102374
102528
  // fence) refuses so CommonMark html-flow reparses it exactly as it does today.
102375
102529
  function plainClaimLineStart(code) {
102376
- // Leading whitespace only → treat as a blank line, matching CommonMark.
102377
- if (code === codes.space || code === codes.horizontalTab) {
102378
- plainClaimIndentColumns +=
102379
- code === codes.horizontalTab ? TAB_STOP_WIDTH - (plainClaimIndentColumns % TAB_STOP_WIDTH) : 1;
102530
+ // Leading whitespace only → treat as a blank line, matching CommonMark. A tab
102531
+ // advances to the next stop; its trailing `virtualSpace` fillers add nothing
102532
+ // but must still be consumed or they'd read as line content below.
102533
+ if (markdownSpace(code)) {
102534
+ if (code === codes.horizontalTab) {
102535
+ plainClaimIndentColumns += TAB_STOP_WIDTH - (plainClaimIndentColumns % TAB_STOP_WIDTH);
102536
+ }
102537
+ else if (code === codes.space) {
102538
+ plainClaimIndentColumns += 1;
102539
+ }
102380
102540
  effects.consume(code);
102381
102541
  return plainClaimLineStart;
102382
102542
  }
@@ -102388,10 +102548,11 @@ function createTokenize(mode) {
102388
102548
  if (pendingBlankLine) {
102389
102549
  // A 4+ col island nested under other tags is cosmetic nesting indent, not code:
102390
102550
  // keep claiming so promotion dedents + re-parses it as markdown (RM-17560).
102391
- // Tags whose bodies stay raw are excludeda claimed island there would never
102392
- // be re-parsed and would leak as literal text.
102551
+ // Block-wrapper claims extend this to top-of-body islandstheir CommonMark
102552
+ // fallback is the fragmentation bug, not intentional indented code. Tags whose
102553
+ // bodies stay raw are excluded: a claimed island there would leak as literal text.
102393
102554
  if (plainClaimIndentColumns >= INDENTED_CODE_MIN_COLUMNS &&
102394
- sawPlainBlockBodyContent &&
102555
+ (sawPlainBlockBodyContent || isBlockWrapperClaim) &&
102395
102556
  !NON_REPARSED_BODY_TAGS.has(tagName)) {
102396
102557
  return plainClaimContinue(code);
102397
102558
  }
@@ -102470,6 +102631,7 @@ function mdxComponent() {
102470
102631
 
102471
102632
 
102472
102633
 
102634
+
102473
102635
 
102474
102636
 
102475
102637
  const buildInlineMdProcessor = (safeMode) => {
@@ -102477,7 +102639,7 @@ const buildInlineMdProcessor = (safeMode) => {
102477
102639
  // body (e.g. a `<Callout>`) is captured as one html node. Without it, blank
102478
102640
  // lines between rows let CommonMark HTML block type 6 fragment the table and
102479
102641
  // its rows spill out as text / indented code blocks (CX-3705).
102480
- const micromarkExts = [jsxTable(), mdxComponent(), syntax_gemoji(), legacyVariable(), magicBlock()];
102642
+ const micromarkExts = [disableIndentedCode, jsxTable(), mdxComponent(), syntax_gemoji(), legacyVariable(), magicBlock()];
102481
102643
  const fromMarkdownExts = [
102482
102644
  jsxTableFromMarkdown(),
102483
102645
  mdxComponentFromMarkdown(),
@@ -103788,71 +103950,6 @@ const generateSlugForHeadings = () => (tree) => {
103788
103950
  // EXTERNAL MODULE: external "@readme/variable"
103789
103951
  var variable_ = __webpack_require__(8167);
103790
103952
  var variable_default = /*#__PURE__*/__webpack_require__.n(variable_);
103791
- ;// ./node_modules/rehype-parse/lib/index.js
103792
- /**
103793
- * @import {Root} from 'hast'
103794
- * @import {Options as FromHtmlOptions} from 'hast-util-from-html'
103795
- * @import {Parser, Processor} from 'unified'
103796
- */
103797
-
103798
- /**
103799
- * @typedef {Omit<FromHtmlOptions, 'onerror'> & RehypeParseFields} Options
103800
- * Configuration.
103801
- *
103802
- * @typedef RehypeParseFields
103803
- * Extra fields.
103804
- * @property {boolean | null | undefined} [emitParseErrors=false]
103805
- * Whether to emit parse errors while parsing (default: `false`).
103806
- *
103807
- * > 👉 **Note**: parse errors are currently being added to HTML.
103808
- * > Not all errors emitted by parse5 (or us) are specced yet.
103809
- * > Some documentation may still be missing.
103810
- */
103811
-
103812
-
103813
-
103814
- /**
103815
- * Plugin to add support for parsing from HTML.
103816
- *
103817
- * > 👉 **Note**: this is not an XML parser.
103818
- * > It supports SVG as embedded in HTML.
103819
- * > It does not support the features available in XML.
103820
- * > Passing SVG files might break but fragments of modern SVG should be fine.
103821
- * > Use [`xast-util-from-xml`][xast-util-from-xml] to parse XML.
103822
- *
103823
- * @param {Options | null | undefined} [options]
103824
- * Configuration (optional).
103825
- * @returns {undefined}
103826
- * Nothing.
103827
- */
103828
- function rehypeParse(options) {
103829
- /** @type {Processor<Root>} */
103830
- // @ts-expect-error: TS in JSDoc generates wrong types if `this` is typed regularly.
103831
- const self = this
103832
- const {emitParseErrors, ...settings} = {...self.data('settings'), ...options}
103833
-
103834
- self.parser = parser
103835
-
103836
- /**
103837
- * @type {Parser<Root>}
103838
- */
103839
- function parser(document, file) {
103840
- return fromHtml(document, {
103841
- ...settings,
103842
- onerror: emitParseErrors
103843
- ? function (message) {
103844
- if (file.path) {
103845
- message.name = file.path + ':' + message.name
103846
- message.file = file.path
103847
- }
103848
-
103849
- file.messages.push(message)
103850
- }
103851
- : undefined
103852
- })
103853
- }
103854
- }
103855
-
103856
103953
  ;// ./lib/micromark/loose-html-entities/syntax.ts
103857
103954
 
103858
103955
 
@@ -106778,6 +106875,7 @@ function mdxishAstProcessor(mdContent, opts = {}) {
106778
106875
  // Parser extension for MDX expressions {}
106779
106876
  const mdxExprTextOnly = mdxExpressionLenient();
106780
106877
  const micromarkExts = [
106878
+ disableIndentedCode,
106781
106879
  jsxTable(),
106782
106880
  magicBlock(),
106783
106881
  mdxComponent(),
@@ -106880,7 +106978,7 @@ function mdxishMdastToMd(mdast) {
106880
106978
  * Processes markdown content with MDX syntax support and returns a HAST.
106881
106979
  * Detects and renders custom component tags from the components hash.
106882
106980
  *
106883
- * @see {@link https://github.com/readmeio/rmdx/blob/main/docs/mdxish-flow.md}
106981
+ * @see .claude/context/MDXish/Processor Overview.md
106884
106982
  */
106885
106983
  function mdxish(mdContent, opts = {}) {
106886
106984
  const { components: userComponents = {}, safeMode = false, variables } = opts;
@@ -107220,7 +107318,7 @@ function buildRMDXModule(content, headings, tocHast, opts) {
107220
107318
  * @param opts - The options for the render
107221
107319
  * @returns The React component
107222
107320
  *
107223
- * @see {@link https://github.com/readmeio/rmdx/blob/main/docs/mdxish-flow.md}
107321
+ * @see .claude/context/MDXish/Processor Overview.md
107224
107322
  */
107225
107323
  const renderMdxish = (tree, opts = {}) => {
107226
107324
  const { components: userComponents = {}, variables, ...contextOpts } = opts;
@@ -107562,6 +107660,7 @@ async function stripComments(doc, { mdx, mdxish } = {}) {
107562
107660
 
107563
107661
 
107564
107662
 
107663
+
107565
107664
  ;// ./index.tsx
107566
107665
 
107567
107666