@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.node.js CHANGED
@@ -19286,6 +19286,7 @@ __webpack_require__.d(__webpack_exports__, {
19286
19286
  extractToc: () => (/* reexport */ lib_extractToc),
19287
19287
  gemojiRegex: () => (/* reexport */ gemoji_regex),
19288
19288
  hast: () => (/* reexport */ lib_hast),
19289
+ htmlToMarkdown: () => (/* reexport */ htmlToMarkdown),
19289
19290
  mdast: () => (/* reexport */ lib_mdast),
19290
19291
  mdastV6: () => (/* reexport */ lib_mdastV6),
19291
19292
  mdx: () => (/* reexport */ lib_mdx),
@@ -25271,6 +25272,10 @@ const tailwindPrefix = 'readme-tailwind';
25271
25272
 
25272
25273
 
25273
25274
  const TailwindRoot = ({ children, flow }) => {
25275
+ // `styles/gfm.scss` spaces the wrapped block children through this element and
25276
+ // relies on their margins collapsing through it. Keep it a plain block — no
25277
+ // border, padding, or block formatting context (overflow, display: flow-root/
25278
+ // flex/grid) — or the spacing breaks.
25274
25279
  const Tag = flow ? 'div' : 'span';
25275
25280
  return external_react_default().createElement(Tag, { className: tailwindPrefix }, children);
25276
25281
  };
@@ -74730,6 +74735,13 @@ const mdast = (text, opts = {}) => {
74730
74735
  * to parse expressions containing JSX.
74731
74736
  */
74732
74737
  const jsxAcornParser = Parser.extend(acorn_jsx_default()());
74738
+ /**
74739
+ * Disables CommonMark's indented-code-block construct (4+ spaces)
74740
+ * The micromark tokenizers use follow the CommonMark specification: https://spec.commonmark.org/0.28/#indented-code-blocks
74741
+ * So any lines indented 4+ spaces are considered as a code block,
74742
+ * which is unexpected from users that used MDX before.
74743
+ */
74744
+ const disableIndentedCode = { disable: { null: ['codeIndented'] } };
74733
74745
  /**
74734
74746
  * Evaluate a JavaScript expression source and return its value.
74735
74747
  *
@@ -112714,185 +112726,70 @@ const hast = (text, opts = {}) => {
112714
112726
  };
112715
112727
  /* harmony default export */ const lib_hast = (hast);
112716
112728
 
112717
- ;// ./processor/migration/emphasis.ts
112718
-
112719
- const emphasis_strongTest = (node) => ['emphasis', 'strong'].includes(node.type);
112720
- const addSpaceBefore = (index, parent) => {
112721
- if (!(index > 0 && parent.children[index - 1]))
112722
- return;
112723
- const prev = parent.children[index - 1];
112724
- if (!('value' in prev) || prev.value.endsWith(' ') || prev.type === 'escape')
112725
- return;
112726
- parent.children.splice(index, 0, { type: 'text', value: ' ' });
112727
- };
112728
- const addSpaceAfter = (index, parent) => {
112729
- if (!(index < parent.children.length - 1 && parent.children[index + 1]))
112730
- return;
112731
- const nextChild = parent.children[index + 1];
112732
- if (!('value' in nextChild) || nextChild.value.startsWith(' '))
112733
- return;
112734
- parent.children.splice(index + 1, 0, { type: 'text', value: ' ' });
112735
- };
112736
- const trimEmphasis = (node, index, parent) => {
112737
- let trimmed = false;
112738
- visit(node, 'text', (child) => {
112739
- const newValue = child.value.trimStart();
112740
- if (newValue !== child.value) {
112741
- trimmed = true;
112742
- child.value = newValue;
112743
- }
112744
- return EXIT;
112745
- });
112746
- visit(node, 'text', (child) => {
112747
- const newValue = child.value.trimEnd();
112748
- if (newValue !== child.value) {
112749
- trimmed = true;
112750
- child.value = newValue;
112751
- }
112752
- return EXIT;
112753
- }, true);
112754
- if (trimmed) {
112755
- addSpaceBefore(index, parent);
112756
- addSpaceAfter(index, parent);
112757
- }
112758
- };
112759
- const emphasisTransfomer = () => (tree) => {
112760
- visit(tree, emphasis_strongTest, trimEmphasis);
112761
- return tree;
112762
- };
112763
- /* harmony default export */ const migration_emphasis = (emphasisTransfomer);
112729
+ ;// ./node_modules/rehype-parse/lib/index.js
112730
+ /**
112731
+ * @import {Root} from 'hast'
112732
+ * @import {Options as FromHtmlOptions} from 'hast-util-from-html'
112733
+ * @import {Parser, Processor} from 'unified'
112734
+ */
112764
112735
 
112765
- ;// ./processor/migration/images.ts
112736
+ /**
112737
+ * @typedef {Omit<FromHtmlOptions, 'onerror'> & RehypeParseFields} Options
112738
+ * Configuration.
112739
+ *
112740
+ * @typedef RehypeParseFields
112741
+ * Extra fields.
112742
+ * @property {boolean | null | undefined} [emitParseErrors=false]
112743
+ * Whether to emit parse errors while parsing (default: `false`).
112744
+ *
112745
+ * > 👉 **Note**: parse errors are currently being added to HTML.
112746
+ * > Not all errors emitted by parse5 (or us) are specced yet.
112747
+ * > Some documentation may still be missing.
112748
+ */
112766
112749
 
112767
- const images_imageTransformer = () => tree => {
112768
- visit(tree, 'image', (image) => {
112769
- if (image.data?.hProperties?.className === 'border') {
112770
- image.data.hProperties.border = true;
112771
- }
112772
- });
112773
- };
112774
- /* harmony default export */ const migration_images = (images_imageTransformer);
112775
112750
 
112776
- ;// ./processor/migration/linkReference.ts
112777
112751
 
112778
- const linkReferenceTransformer = () => (tree) => {
112779
- visit(tree, 'linkReference', (node, index, parent) => {
112780
- const definitions = {};
112781
- visit(tree, 'definition', (def) => {
112782
- definitions[def.identifier] = def;
112783
- });
112784
- if (node.label === node.identifier && parent) {
112785
- if (!(node.identifier in definitions)) {
112786
- parent.children[index] = {
112787
- type: 'text',
112788
- value: `[${node.label}]`,
112789
- position: node.position,
112790
- };
112791
- }
112792
- }
112793
- });
112794
- return tree;
112795
- };
112796
- /* harmony default export */ const migration_linkReference = (linkReferenceTransformer);
112752
+ /**
112753
+ * Plugin to add support for parsing from HTML.
112754
+ *
112755
+ * > 👉 **Note**: this is not an XML parser.
112756
+ * > It supports SVG as embedded in HTML.
112757
+ * > It does not support the features available in XML.
112758
+ * > Passing SVG files might break but fragments of modern SVG should be fine.
112759
+ * > Use [`xast-util-from-xml`][xast-util-from-xml] to parse XML.
112760
+ *
112761
+ * @param {Options | null | undefined} [options]
112762
+ * Configuration (optional).
112763
+ * @returns {undefined}
112764
+ * Nothing.
112765
+ */
112766
+ function rehypeParse(options) {
112767
+ /** @type {Processor<Root>} */
112768
+ // @ts-expect-error: TS in JSDoc generates wrong types if `this` is typed regularly.
112769
+ const self = this
112770
+ const {emitParseErrors, ...settings} = {...self.data('settings'), ...options}
112797
112771
 
112798
- ;// ./processor/migration/table-cell.ts
112772
+ self.parser = parser
112799
112773
 
112800
- const magicIndex = (i, j) => `${i === 0 ? 'h' : `${i - 1}`}-${j}`;
112801
- const isInlineHtml = node => node.type === 'html' && !node.block;
112802
- // @note: This regex is detect malformed lists that were created by the
112803
- // markdown editor. Consider the following markdown:
112804
- //
112805
- // ```
112806
- // * item 1
112807
- // * item 2
112808
- // * item 3
112809
- // ```
112810
- //
112811
- // This is a perfectly valid list. But when you put that text into a table
112812
- // cell, the editor does **bad** things. After a save and load cycle, it gets
112813
- // converted to this:
112814
- //
112815
- // ```
112816
- // \_ item 1
112817
- // \_ item 2
112818
- // \* item 3
112819
- // ```
112820
- //
112821
- // The following regex attempts to detect this pattern, and we'll convert it to
112822
- // something more standard.
112823
- const psuedoListRegex = /^(?![ \t]*([*_]+).*\1[ \t]*$)(?<ws>[ \t]*)\\?([*_])\s*(?<item>.*)$/gm;
112824
- const migrateTableCells = (vfile, rdmd) => (table) => {
112825
- let json;
112826
- try {
112827
- const { position } = table;
112828
- if (position) {
112829
- json = JSON.parse(vfile
112830
- .toString()
112831
- .slice(position.start.offset, position.end.offset)
112832
- .replace(/.*\[block:parameters\](.*)\[\/block\].*/s, '$1'));
112833
- }
112834
- }
112835
- catch (err) {
112836
- /**
112837
- * This failure case is already handled by the following logic. Plus,
112838
- * because it's being handled internally, there's no way for our
112839
- * migration script to catch the error or keep track of it, and it just
112840
- * ends up blowing up the output logs.
112841
- */
112842
- // console.error(err);
112843
- }
112844
- visit(table, 'tableRow', (row, i) => {
112845
- visit(row, 'tableCell', (cell, j) => {
112846
- let children = cell.children;
112847
- if (json && json.data[magicIndex(i, j)]) {
112848
- const string = json.data[magicIndex(i, j)].replace(psuedoListRegex, '$<ws>- $<item>');
112849
- children = rdmd.mdast(string).children;
112774
+ /**
112775
+ * @type {Parser<Root>}
112776
+ */
112777
+ function parser(document, file) {
112778
+ return fromHtml(document, {
112779
+ ...settings,
112780
+ onerror: emitParseErrors
112781
+ ? function (message) {
112782
+ if (file.path) {
112783
+ message.name = file.path + ':' + message.name
112784
+ message.file = file.path
112850
112785
  }
112851
- cell.children =
112852
- children.length > 1 && !children.some(isInlineHtml)
112853
- ? children
112854
- : [{ type: 'paragraph', children }];
112855
- return SKIP;
112856
- });
112857
- return SKIP;
112858
- });
112859
- visit(table, 'inlineCode', (code) => {
112860
- if (code.value.includes('\n')) {
112861
- code.type = 'code';
112862
- }
112863
- });
112864
- };
112865
- function tableCellTransformer() {
112866
- const rdmd = this.data('rdmd');
112867
- return (tree, vfile) => {
112868
- visit(tree, 'table', migrateTableCells(vfile, rdmd));
112869
- return tree;
112870
- };
112871
- }
112872
- /* harmony default export */ const table_cell = (tableCellTransformer);
112873
-
112874
- ;// ./processor/migration/index.ts
112875
-
112876
-
112877
-
112878
-
112879
- const transformers = [migration_emphasis, migration_images, migration_linkReference, table_cell];
112880
- /* harmony default export */ const migration = (transformers);
112881
112786
 
112882
- ;// ./lib/mdastV6.ts
112883
-
112884
- const migrationNormalize = (doc) => {
112885
- return doc.replaceAll(/^(<!--.*?)\\-->$/gms, '$1-->');
112886
- };
112887
- const mdastV6 = (doc, { rdmd }) => {
112888
- const [_normalizedDoc] = rdmd.setup(doc);
112889
- const normalizedDoc = migrationNormalize(_normalizedDoc);
112890
- const proc = rdmd.processor().use(migration).data('rdmd', rdmd);
112891
- const tree = proc.parse(normalizedDoc);
112892
- proc.runSync(tree, normalizedDoc);
112893
- return tree;
112894
- };
112895
- /* harmony default export */ const lib_mdastV6 = (mdastV6);
112787
+ file.messages.push(message)
112788
+ }
112789
+ : undefined
112790
+ })
112791
+ }
112792
+ }
112896
112793
 
112897
112794
  ;// ./node_modules/hast-util-is-element/lib/index.js
112898
112795
  /**
@@ -117419,6 +117316,227 @@ function rehypeRemark(destination, options) {
117419
117316
  }
117420
117317
  }
117421
117318
 
117319
+ ;// ./lib/htmlToMarkdown.ts
117320
+
117321
+
117322
+
117323
+
117324
+
117325
+ /**
117326
+ * Converts an HTML fragment to GitHub-flavored Markdown.
117327
+ *
117328
+ * `remark-gfm` is load-bearing: without it, `<table>` and `<del>` input throws
117329
+ * at serialization. `iframe` (default: becomes a link) and `noscript` (default:
117330
+ * keeps its text) are dropped by the handlers so raw markup never leaks;
117331
+ * `script`, `style`, and `template` already drop by default and are overridden
117332
+ * defensively. HTML comments are dropped via `nodeHandlers`.
117333
+ */
117334
+ const processor = unified()
117335
+ .use(rehypeParse, { fragment: true })
117336
+ .use(rehypeRemark, {
117337
+ // A comment is a `comment` node, not an element, so it goes in
117338
+ // `nodeHandlers` rather than `handlers`.
117339
+ handlers: {
117340
+ iframe: () => undefined,
117341
+ noscript: () => undefined,
117342
+ script: () => undefined,
117343
+ style: () => undefined,
117344
+ template: () => undefined,
117345
+ },
117346
+ nodeHandlers: { comment: () => undefined },
117347
+ })
117348
+ .use(remarkGfm)
117349
+ .use(remarkStringify, { bullet: '-', emphasis: '_', fences: true });
117350
+ /**
117351
+ * Returns the Markdown form of `html`, or an empty string when there is no
117352
+ * usable input. Synchronous, so it can run inside non-async serializers.
117353
+ */
117354
+ function htmlToMarkdown(html) {
117355
+ if (typeof html !== 'string' || !html.trim())
117356
+ return '';
117357
+ return processor.processSync(html).toString().trim();
117358
+ }
117359
+
117360
+ ;// ./processor/migration/emphasis.ts
117361
+
117362
+ const emphasis_strongTest = (node) => ['emphasis', 'strong'].includes(node.type);
117363
+ const addSpaceBefore = (index, parent) => {
117364
+ if (!(index > 0 && parent.children[index - 1]))
117365
+ return;
117366
+ const prev = parent.children[index - 1];
117367
+ if (!('value' in prev) || prev.value.endsWith(' ') || prev.type === 'escape')
117368
+ return;
117369
+ parent.children.splice(index, 0, { type: 'text', value: ' ' });
117370
+ };
117371
+ const addSpaceAfter = (index, parent) => {
117372
+ if (!(index < parent.children.length - 1 && parent.children[index + 1]))
117373
+ return;
117374
+ const nextChild = parent.children[index + 1];
117375
+ if (!('value' in nextChild) || nextChild.value.startsWith(' '))
117376
+ return;
117377
+ parent.children.splice(index + 1, 0, { type: 'text', value: ' ' });
117378
+ };
117379
+ const trimEmphasis = (node, index, parent) => {
117380
+ let trimmed = false;
117381
+ visit(node, 'text', (child) => {
117382
+ const newValue = child.value.trimStart();
117383
+ if (newValue !== child.value) {
117384
+ trimmed = true;
117385
+ child.value = newValue;
117386
+ }
117387
+ return EXIT;
117388
+ });
117389
+ visit(node, 'text', (child) => {
117390
+ const newValue = child.value.trimEnd();
117391
+ if (newValue !== child.value) {
117392
+ trimmed = true;
117393
+ child.value = newValue;
117394
+ }
117395
+ return EXIT;
117396
+ }, true);
117397
+ if (trimmed) {
117398
+ addSpaceBefore(index, parent);
117399
+ addSpaceAfter(index, parent);
117400
+ }
117401
+ };
117402
+ const emphasisTransfomer = () => (tree) => {
117403
+ visit(tree, emphasis_strongTest, trimEmphasis);
117404
+ return tree;
117405
+ };
117406
+ /* harmony default export */ const migration_emphasis = (emphasisTransfomer);
117407
+
117408
+ ;// ./processor/migration/images.ts
117409
+
117410
+ const images_imageTransformer = () => tree => {
117411
+ visit(tree, 'image', (image) => {
117412
+ if (image.data?.hProperties?.className === 'border') {
117413
+ image.data.hProperties.border = true;
117414
+ }
117415
+ });
117416
+ };
117417
+ /* harmony default export */ const migration_images = (images_imageTransformer);
117418
+
117419
+ ;// ./processor/migration/linkReference.ts
117420
+
117421
+ const linkReferenceTransformer = () => (tree) => {
117422
+ visit(tree, 'linkReference', (node, index, parent) => {
117423
+ const definitions = {};
117424
+ visit(tree, 'definition', (def) => {
117425
+ definitions[def.identifier] = def;
117426
+ });
117427
+ if (node.label === node.identifier && parent) {
117428
+ if (!(node.identifier in definitions)) {
117429
+ parent.children[index] = {
117430
+ type: 'text',
117431
+ value: `[${node.label}]`,
117432
+ position: node.position,
117433
+ };
117434
+ }
117435
+ }
117436
+ });
117437
+ return tree;
117438
+ };
117439
+ /* harmony default export */ const migration_linkReference = (linkReferenceTransformer);
117440
+
117441
+ ;// ./processor/migration/table-cell.ts
117442
+
117443
+ const magicIndex = (i, j) => `${i === 0 ? 'h' : `${i - 1}`}-${j}`;
117444
+ const isInlineHtml = node => node.type === 'html' && !node.block;
117445
+ // @note: This regex is detect malformed lists that were created by the
117446
+ // markdown editor. Consider the following markdown:
117447
+ //
117448
+ // ```
117449
+ // * item 1
117450
+ // * item 2
117451
+ // * item 3
117452
+ // ```
117453
+ //
117454
+ // This is a perfectly valid list. But when you put that text into a table
117455
+ // cell, the editor does **bad** things. After a save and load cycle, it gets
117456
+ // converted to this:
117457
+ //
117458
+ // ```
117459
+ // \_ item 1
117460
+ // \_ item 2
117461
+ // \* item 3
117462
+ // ```
117463
+ //
117464
+ // The following regex attempts to detect this pattern, and we'll convert it to
117465
+ // something more standard.
117466
+ const psuedoListRegex = /^(?![ \t]*([*_]+).*\1[ \t]*$)(?<ws>[ \t]*)\\?([*_])\s*(?<item>.*)$/gm;
117467
+ const migrateTableCells = (vfile, rdmd) => (table) => {
117468
+ let json;
117469
+ try {
117470
+ const { position } = table;
117471
+ if (position) {
117472
+ json = JSON.parse(vfile
117473
+ .toString()
117474
+ .slice(position.start.offset, position.end.offset)
117475
+ .replace(/.*\[block:parameters\](.*)\[\/block\].*/s, '$1'));
117476
+ }
117477
+ }
117478
+ catch (err) {
117479
+ /**
117480
+ * This failure case is already handled by the following logic. Plus,
117481
+ * because it's being handled internally, there's no way for our
117482
+ * migration script to catch the error or keep track of it, and it just
117483
+ * ends up blowing up the output logs.
117484
+ */
117485
+ // console.error(err);
117486
+ }
117487
+ visit(table, 'tableRow', (row, i) => {
117488
+ visit(row, 'tableCell', (cell, j) => {
117489
+ let children = cell.children;
117490
+ if (json && json.data[magicIndex(i, j)]) {
117491
+ const string = json.data[magicIndex(i, j)].replace(psuedoListRegex, '$<ws>- $<item>');
117492
+ children = rdmd.mdast(string).children;
117493
+ }
117494
+ cell.children =
117495
+ children.length > 1 && !children.some(isInlineHtml)
117496
+ ? children
117497
+ : [{ type: 'paragraph', children }];
117498
+ return SKIP;
117499
+ });
117500
+ return SKIP;
117501
+ });
117502
+ visit(table, 'inlineCode', (code) => {
117503
+ if (code.value.includes('\n')) {
117504
+ code.type = 'code';
117505
+ }
117506
+ });
117507
+ };
117508
+ function tableCellTransformer() {
117509
+ const rdmd = this.data('rdmd');
117510
+ return (tree, vfile) => {
117511
+ visit(tree, 'table', migrateTableCells(vfile, rdmd));
117512
+ return tree;
117513
+ };
117514
+ }
117515
+ /* harmony default export */ const table_cell = (tableCellTransformer);
117516
+
117517
+ ;// ./processor/migration/index.ts
117518
+
117519
+
117520
+
117521
+
117522
+ const transformers = [migration_emphasis, migration_images, migration_linkReference, table_cell];
117523
+ /* harmony default export */ const migration = (transformers);
117524
+
117525
+ ;// ./lib/mdastV6.ts
117526
+
117527
+ const migrationNormalize = (doc) => {
117528
+ return doc.replaceAll(/^(<!--.*?)\\-->$/gms, '$1-->');
117529
+ };
117530
+ const mdastV6 = (doc, { rdmd }) => {
117531
+ const [_normalizedDoc] = rdmd.setup(doc);
117532
+ const normalizedDoc = migrationNormalize(_normalizedDoc);
117533
+ const proc = rdmd.processor().use(migration).data('rdmd', rdmd);
117534
+ const tree = proc.parse(normalizedDoc);
117535
+ proc.runSync(tree, normalizedDoc);
117536
+ return tree;
117537
+ };
117538
+ /* harmony default export */ const lib_mdastV6 = (mdastV6);
117539
+
117422
117540
  ;// ./processor/compile/anchor.ts
117423
117541
 
117424
117542
 
@@ -119331,7 +119449,7 @@ function normalizeProperties(node) {
119331
119449
  * Identifies custom MDX components and recursively parses markdown children.
119332
119450
  * Replaces tagName with PascalCase component name for React component resolution.
119333
119451
  *
119334
- * @see {@link https://github.com/readmeio/rmdx/blob/main/docs/mdxish-flow.md}
119452
+ * @see .claude/context/MDXish/Processor Overview.md
119335
119453
  * @param {Options} options - Configuration options
119336
119454
  * @param {CustomComponents} options.components - Available custom components
119337
119455
  * @param {Function} options.processMarkdown - Function to process markdown content
@@ -121829,6 +121947,13 @@ const htmlFlowTagNames = new Set([...htmlRawNames, ...htmlBlockNames]);
121829
121947
  // blank lines between nested JSX siblings don't fragment the block. Excludes table
121830
121948
  // tags (mdxishTables owns their blank lines) and voids (never close).
121831
121949
  const plainBlockClaimTagNames = new Set([...htmlBlockNames].filter(tag => !HTML_TABLE_STRUCTURE_TAGS.has(tag) && !HTML_VOID_ELEMENTS.has(tag)));
121950
+ const foreignContentTags = new Set(FOREIGN_CONTENT_TAGS);
121951
+ // Type-7 lowercase tags (a, span, button, and unknown names): CommonMark ends their
121952
+ // block at a blank line, fragmenting 4+ column children into indented code. Claimable
121953
+ // only in block-wrapper shape (see `blockWrapperOpenerRest`); lookalike openers
121954
+ // (`<https://…>`) never find a closer, so their claim retreats cleanly to CommonMark.
121955
+ // Voids never close and raw/foreign-content bodies have dedicated owners.
121956
+ const isBlockWrapperClaimTagName = (tag) => !htmlFlowTagNames.has(tag) && !HTML_VOID_ELEMENTS.has(tag) && !foreignContentTags.has(tag);
121832
121957
  // Both are 4 columns per CommonMark, but they mean different things: a tab advances
121833
121958
  // to the next multiple of TAB_STOP_WIDTH, and INDENTED_CODE_MIN_COLUMNS is the depth
121834
121959
  // at which a line would fragment into indented code. Named separately so the two
@@ -121893,6 +122018,11 @@ function createTokenize(mode) {
121893
122018
  // `plainClaimLineStart`: after a blank line it may only continue on a tag line.
121894
122019
  let isPlainBlockClaim = false;
121895
122020
  let pendingBlankLine = false;
122021
+ // Type-7 tag claimed pending the block-wrapper (opener alone on its line) check.
122022
+ let pendingBlockWrapperClaim = false;
122023
+ // True once a block-wrapper claim is confirmed; relaxes the top-of-body island gate
122024
+ // below (type-7 fallback is the fragmentation bug, not intentional indented code).
122025
+ let isBlockWrapperClaim = false;
121896
122026
  // Leading indent columns of the current plain-claim line, reset per line; ≥4 is
121897
122027
  // where CommonMark would fragment the island as indented code. Tabs advance to the
121898
122028
  // next 4-column stop — the same rule `expandIndentToColumns`
@@ -122138,16 +122268,11 @@ function createTokenize(mode) {
122138
122268
  }
122139
122269
  // End of opening tag
122140
122270
  if (code === codes.greaterThan) {
122141
- if (requiresBraceAttr && !sawBraceAttr) {
122142
- // Plain lowercase block tags stay claimable in flow, gated per line by
122143
- // `plainClaimLineStart`; everything else falls through to CommonMark.
122144
- if (!isFlow || !plainBlockClaimTagNames.has(tagName))
122145
- return nok(code);
122146
- isPlainBlockClaim = true;
122147
- }
122271
+ if (requiresBraceAttr && !sawBraceAttr && !claimBraceLessTag())
122272
+ return nok(code);
122148
122273
  effects.consume(code);
122149
122274
  onOpenerLine = isFlow;
122150
- return body;
122275
+ return pendingBlockWrapperClaim ? blockWrapperOpenerRest : body;
122151
122276
  }
122152
122277
  // Quoted attribute value
122153
122278
  if (code === codes.quotationMark || code === codes.apostrophe) {
@@ -122202,6 +122327,35 @@ function createTokenize(mode) {
122202
122327
  // `/ ` without `>` is just part of the attribute area
122203
122328
  return afterOpenTagName(code);
122204
122329
  }
122330
+ // Whether a brace-less lowercase flow tag is claimable: type-6 tags immediately,
122331
+ // type-7 tags pending the block-wrapper check; anything else is CommonMark's.
122332
+ function claimBraceLessTag() {
122333
+ if (!isFlow)
122334
+ return false;
122335
+ if (plainBlockClaimTagNames.has(tagName)) {
122336
+ isPlainBlockClaim = true;
122337
+ return true;
122338
+ }
122339
+ if (isBlockWrapperClaimTagName(tagName)) {
122340
+ pendingBlockWrapperClaim = true;
122341
+ return true;
122342
+ }
122343
+ return false;
122344
+ }
122345
+ // A type-7 tag is claimed only as a block wrapper: opener alone on its line
122346
+ // (trailing spaces ok). Inline content after the opener bails to CommonMark.
122347
+ function blockWrapperOpenerRest(code) {
122348
+ if (markdownSpace(code)) {
122349
+ effects.consume(code);
122350
+ return blockWrapperOpenerRest;
122351
+ }
122352
+ if (!markdownLineEnding(code))
122353
+ return nok(code);
122354
+ pendingBlockWrapperClaim = false;
122355
+ isPlainBlockClaim = true;
122356
+ isBlockWrapperClaim = true;
122357
+ return body(code);
122358
+ }
122205
122359
  // Continuation for multi-line opening tags
122206
122360
  function openTagContinuationStart(code) {
122207
122361
  return effects.check(continuation_checks_nonLazyContinuationStart, openTagContinuationNonLazy, continuationAfter)(code);
@@ -122597,10 +122751,16 @@ function createTokenize(mode) {
122597
122751
  // continue on a tag line (`<…`); any markdown island (`**bold**`, `[block:…]`, a
122598
122752
  // fence) refuses so CommonMark html-flow reparses it exactly as it does today.
122599
122753
  function plainClaimLineStart(code) {
122600
- // Leading whitespace only → treat as a blank line, matching CommonMark.
122601
- if (code === codes.space || code === codes.horizontalTab) {
122602
- plainClaimIndentColumns +=
122603
- code === codes.horizontalTab ? TAB_STOP_WIDTH - (plainClaimIndentColumns % TAB_STOP_WIDTH) : 1;
122754
+ // Leading whitespace only → treat as a blank line, matching CommonMark. A tab
122755
+ // advances to the next stop; its trailing `virtualSpace` fillers add nothing
122756
+ // but must still be consumed or they'd read as line content below.
122757
+ if (markdownSpace(code)) {
122758
+ if (code === codes.horizontalTab) {
122759
+ plainClaimIndentColumns += TAB_STOP_WIDTH - (plainClaimIndentColumns % TAB_STOP_WIDTH);
122760
+ }
122761
+ else if (code === codes.space) {
122762
+ plainClaimIndentColumns += 1;
122763
+ }
122604
122764
  effects.consume(code);
122605
122765
  return plainClaimLineStart;
122606
122766
  }
@@ -122612,10 +122772,11 @@ function createTokenize(mode) {
122612
122772
  if (pendingBlankLine) {
122613
122773
  // A 4+ col island nested under other tags is cosmetic nesting indent, not code:
122614
122774
  // keep claiming so promotion dedents + re-parses it as markdown (RM-17560).
122615
- // Tags whose bodies stay raw are excludeda claimed island there would never
122616
- // be re-parsed and would leak as literal text.
122775
+ // Block-wrapper claims extend this to top-of-body islandstheir CommonMark
122776
+ // fallback is the fragmentation bug, not intentional indented code. Tags whose
122777
+ // bodies stay raw are excluded: a claimed island there would leak as literal text.
122617
122778
  if (plainClaimIndentColumns >= INDENTED_CODE_MIN_COLUMNS &&
122618
- sawPlainBlockBodyContent &&
122779
+ (sawPlainBlockBodyContent || isBlockWrapperClaim) &&
122619
122780
  !NON_REPARSED_BODY_TAGS.has(tagName)) {
122620
122781
  return plainClaimContinue(code);
122621
122782
  }
@@ -122694,6 +122855,7 @@ function mdxComponent() {
122694
122855
 
122695
122856
 
122696
122857
 
122858
+
122697
122859
 
122698
122860
 
122699
122861
  const buildInlineMdProcessor = (safeMode) => {
@@ -122701,7 +122863,7 @@ const buildInlineMdProcessor = (safeMode) => {
122701
122863
  // body (e.g. a `<Callout>`) is captured as one html node. Without it, blank
122702
122864
  // lines between rows let CommonMark HTML block type 6 fragment the table and
122703
122865
  // its rows spill out as text / indented code blocks (CX-3705).
122704
- const micromarkExts = [jsxTable(), mdxComponent(), syntax_gemoji(), legacyVariable(), magicBlock()];
122866
+ const micromarkExts = [disableIndentedCode, jsxTable(), mdxComponent(), syntax_gemoji(), legacyVariable(), magicBlock()];
122705
122867
  const fromMarkdownExts = [
122706
122868
  jsxTableFromMarkdown(),
122707
122869
  mdxComponentFromMarkdown(),
@@ -124012,71 +124174,6 @@ const generateSlugForHeadings = () => (tree) => {
124012
124174
  // EXTERNAL MODULE: ./node_modules/@readme/variable/dist/index.js
124013
124175
  var variable_dist = __webpack_require__(4355);
124014
124176
  var variable_dist_default = /*#__PURE__*/__webpack_require__.n(variable_dist);
124015
- ;// ./node_modules/rehype-parse/lib/index.js
124016
- /**
124017
- * @import {Root} from 'hast'
124018
- * @import {Options as FromHtmlOptions} from 'hast-util-from-html'
124019
- * @import {Parser, Processor} from 'unified'
124020
- */
124021
-
124022
- /**
124023
- * @typedef {Omit<FromHtmlOptions, 'onerror'> & RehypeParseFields} Options
124024
- * Configuration.
124025
- *
124026
- * @typedef RehypeParseFields
124027
- * Extra fields.
124028
- * @property {boolean | null | undefined} [emitParseErrors=false]
124029
- * Whether to emit parse errors while parsing (default: `false`).
124030
- *
124031
- * > 👉 **Note**: parse errors are currently being added to HTML.
124032
- * > Not all errors emitted by parse5 (or us) are specced yet.
124033
- * > Some documentation may still be missing.
124034
- */
124035
-
124036
-
124037
-
124038
- /**
124039
- * Plugin to add support for parsing from HTML.
124040
- *
124041
- * > 👉 **Note**: this is not an XML parser.
124042
- * > It supports SVG as embedded in HTML.
124043
- * > It does not support the features available in XML.
124044
- * > Passing SVG files might break but fragments of modern SVG should be fine.
124045
- * > Use [`xast-util-from-xml`][xast-util-from-xml] to parse XML.
124046
- *
124047
- * @param {Options | null | undefined} [options]
124048
- * Configuration (optional).
124049
- * @returns {undefined}
124050
- * Nothing.
124051
- */
124052
- function rehypeParse(options) {
124053
- /** @type {Processor<Root>} */
124054
- // @ts-expect-error: TS in JSDoc generates wrong types if `this` is typed regularly.
124055
- const self = this
124056
- const {emitParseErrors, ...settings} = {...self.data('settings'), ...options}
124057
-
124058
- self.parser = parser
124059
-
124060
- /**
124061
- * @type {Parser<Root>}
124062
- */
124063
- function parser(document, file) {
124064
- return fromHtml(document, {
124065
- ...settings,
124066
- onerror: emitParseErrors
124067
- ? function (message) {
124068
- if (file.path) {
124069
- message.name = file.path + ':' + message.name
124070
- message.file = file.path
124071
- }
124072
-
124073
- file.messages.push(message)
124074
- }
124075
- : undefined
124076
- })
124077
- }
124078
- }
124079
-
124080
124177
  ;// ./lib/micromark/loose-html-entities/syntax.ts
124081
124178
 
124082
124179
 
@@ -127002,6 +127099,7 @@ function mdxishAstProcessor(mdContent, opts = {}) {
127002
127099
  // Parser extension for MDX expressions {}
127003
127100
  const mdxExprTextOnly = mdxExpressionLenient();
127004
127101
  const micromarkExts = [
127102
+ disableIndentedCode,
127005
127103
  jsxTable(),
127006
127104
  magicBlock(),
127007
127105
  mdxComponent(),
@@ -127104,7 +127202,7 @@ function mdxishMdastToMd(mdast) {
127104
127202
  * Processes markdown content with MDX syntax support and returns a HAST.
127105
127203
  * Detects and renders custom component tags from the components hash.
127106
127204
  *
127107
- * @see {@link https://github.com/readmeio/rmdx/blob/main/docs/mdxish-flow.md}
127205
+ * @see .claude/context/MDXish/Processor Overview.md
127108
127206
  */
127109
127207
  function mdxish(mdContent, opts = {}) {
127110
127208
  const { components: userComponents = {}, safeMode = false, variables } = opts;
@@ -127444,7 +127542,7 @@ function buildRMDXModule(content, headings, tocHast, opts) {
127444
127542
  * @param opts - The options for the render
127445
127543
  * @returns The React component
127446
127544
  *
127447
- * @see {@link https://github.com/readmeio/rmdx/blob/main/docs/mdxish-flow.md}
127545
+ * @see .claude/context/MDXish/Processor Overview.md
127448
127546
  */
127449
127547
  const renderMdxish = (tree, opts = {}) => {
127450
127548
  const { components: userComponents = {}, variables, ...contextOpts } = opts;
@@ -127786,6 +127884,7 @@ async function stripComments(doc, { mdx, mdxish } = {}) {
127786
127884
 
127787
127885
 
127788
127886
 
127887
+
127789
127888
  ;// ./index.tsx
127790
127889
 
127791
127890