@readme/markdown 11.14.1 → 11.15.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/index.d.ts CHANGED
@@ -6,7 +6,7 @@ declare const utils: {
6
6
  getHref: typeof getHref;
7
7
  calloutIcons: {};
8
8
  };
9
- export { compile, exports, hast, run, mdast, mdastV6, mdx, mdxish, mdxishAstProcessor, mdxishMdastToMd, mdxishTags, migrate, mix, plain, renderMdxish, remarkPlugins, stripComments, tags, isPlainText, } from './lib';
9
+ export { compile, exports, hast, run, mdast, mdastV6, mdx, mdxish, mdxishAstProcessor, mdxishMdastToMd, mdxishTags, migrate, mix, plain, renderMdxish, remarkPlugins, stripComments, tags, } from './lib';
10
10
  export { default as Owlmoji } from './lib/owlmoji';
11
11
  export { Components, utils };
12
12
  export { tailwindCompiler } from './utils/tailwind-compiler';
@@ -17,4 +17,3 @@ export { default as run } from './run';
17
17
  export { default as tags } from './tags';
18
18
  export { default as mdxishTags } from './mdxishTags';
19
19
  export { default as stripComments } from './stripComments';
20
- export { default as isPlainText } from './utils/isPlainText';
package/dist/main.js CHANGED
@@ -11362,7 +11362,6 @@ __webpack_require__.d(__webpack_exports__, {
11362
11362
  exports: () => (/* reexport */ lib_exports),
11363
11363
  gemojiRegex: () => (/* reexport */ gemoji_regex),
11364
11364
  hast: () => (/* reexport */ lib_hast),
11365
- isPlainText: () => (/* reexport */ isPlainText),
11366
11365
  mdast: () => (/* reexport */ lib_mdast),
11367
11366
  mdastV6: () => (/* reexport */ lib_mdastV6),
11368
11367
  mdx: () => (/* reexport */ lib_mdx),
@@ -70621,10 +70620,13 @@ const tagAttributePattern = /([a-zA-Z_:][-a-zA-Z0-9_:.]*)(?:\s*=\s*("[^"]*"|'[^'
70621
70620
  const MAX_LOOKAHEAD = 30;
70622
70621
  /**
70623
70622
  * Tags that have dedicated transformers and should NOT be handled by this plugin.
70624
- * These components have special parsing requirements that the generic component
70625
- * block transformer cannot handle correctly.
70623
+ * These components either have special parsing requirements that the generic component
70624
+ * block transformer cannot handle correctly, or are inline components that we don't
70625
+ * want to convert to mdxJsxFlowElement which is a block level element.
70626
+ *
70627
+ * Glossary and Anchor are inline components.
70626
70628
  */
70627
- const EXCLUDED_TAGS = new Set(['HTMLBlock', 'Table']);
70629
+ const EXCLUDED_TAGS = new Set(['HTMLBlock', 'Table', 'Glossary', 'Anchor']);
70628
70630
  const inlineMdProcessor = unified().use(remarkParse);
70629
70631
  const isClosingTag = (value, tag) => value.trim() === `</${tag}>`;
70630
70632
  /**
@@ -94414,6 +94416,92 @@ const normalizeEmphasisAST = () => (tree) => {
94414
94416
  };
94415
94417
  /* harmony default export */ const normalize_malformed_md_syntax = (normalizeEmphasisAST);
94416
94418
 
94419
+ ;// ./processor/transform/mdxish/normalize-table-separator.ts
94420
+ /**
94421
+ * Preprocessor to normalize malformed GFM table separator syntax.
94422
+ *
94423
+ * Fixes the common mistake where the alignment colon is placed after the pipe
94424
+ * instead of before the dashes:
94425
+ *
94426
+ * Invalid: `|: ---` or `|:---` (colon after pipe)
94427
+ * Valid: `| :---` (colon before dashes)
94428
+ *
94429
+ * Also handles right alignment:
94430
+ * Invalid: `| ---:| ` with space before pipe
94431
+ * Valid: `| ---:|` (no space before closing pipe)
94432
+ *
94433
+ * This runs before remark-parse to ensure the table is recognized as a valid GFM table.
94434
+ */
94435
+ /**
94436
+ * Pattern to match a table separator row.
94437
+ * A separator row consists of cells that contain only dashes, colons (for alignment), and spaces.
94438
+ *
94439
+ * Valid GFM separator formats:
94440
+ * - `---` or `----` (no alignment, defaults to left)
94441
+ * - `:---` (left aligned)
94442
+ * - `---:` (right aligned)
94443
+ * - `:---:` (center aligned)
94444
+ *
94445
+ * Invalid formats this fixes:
94446
+ * - `|: ---` → `| :---` (colon wrongly placed after pipe)
94447
+ * - `|:---` → `| :---` (colon directly after pipe, missing space)
94448
+ * - `|::---` or `| ::---` → `| :---` (double colon typo)
94449
+ */
94450
+ // Match a line that looks like a table separator row
94451
+ // This regex captures the whole line if it contains only pipe-separated cells with dashes/colons
94452
+ const TABLE_SEPARATOR_LINE_REGEX = /^(\|[:\s-]+)+\|?\s*$/;
94453
+ // Match malformed left-alignment: `|: ` or `|:` followed by dashes
94454
+ // Captures: group 1 = pipe, group 2 = spaces after colon, group 3 = dashes
94455
+ const MALFORMED_LEFT_ALIGN_REGEX = /\|:(\s*)(-+)/g;
94456
+ // Match malformed double colon: `|::---` or `| ::---` → `| :---`
94457
+ const MALFORMED_DOUBLE_COLON_REGEX = /\|\s*::(\s*)(-+)/g;
94458
+ // Match malformed patterns with spaces before closing colons: `| --- : |` → `| ---: |`
94459
+ const MALFORMED_RIGHT_ALIGN_SPACE_REGEX = /(-+)\s+:(\s*\|)/g;
94460
+ // Match malformed center alignment with spaces: `| : --- : |` → `| :---: |`
94461
+ const MALFORMED_CENTER_ALIGN_REGEX = /\|:(\s+)(-+)(\s+):/g;
94462
+ /**
94463
+ * Normalizes a single table separator line.
94464
+ */
94465
+ function normalizeTableSeparatorLine(line) {
94466
+ // Check if this line looks like a table separator
94467
+ if (!TABLE_SEPARATOR_LINE_REGEX.test(line)) {
94468
+ return line;
94469
+ }
94470
+ let normalized = line;
94471
+ // Fix `|::---` → `| :---` (double colon typo)
94472
+ // Must run before single colon fix to avoid partial replacement
94473
+ normalized = normalized.replace(MALFORMED_DOUBLE_COLON_REGEX, '| :$2');
94474
+ // Fix `|: ---` or `|:---` → `| :---`
94475
+ // The colon should be adjacent to the dashes, not the pipe
94476
+ normalized = normalized.replace(MALFORMED_LEFT_ALIGN_REGEX, '| :$2');
94477
+ // Fix `| --- : |` → `| ---: |`
94478
+ // Remove space before right-alignment colon
94479
+ normalized = normalized.replace(MALFORMED_RIGHT_ALIGN_SPACE_REGEX, '$1:$2');
94480
+ // Fix `| : --- : |` → `| :---: |`
94481
+ // Remove spaces around center-aligned dashes
94482
+ normalized = normalized.replace(MALFORMED_CENTER_ALIGN_REGEX, '| :$2:');
94483
+ return normalized;
94484
+ }
94485
+ /**
94486
+ * Preprocesses markdown content to normalize malformed table separator syntax.
94487
+ *
94488
+ * @param content - The raw markdown content
94489
+ * @returns The content with normalized table separators
94490
+ */
94491
+ function normalizeTableSeparator(content) {
94492
+ const lines = content.split('\n');
94493
+ const normalizedLines = lines.map((line, index) => {
94494
+ const prevLine = index > 0 ? lines[index - 1] : '';
94495
+ const isPrevLineTableRow = prevLine.trim().startsWith('|');
94496
+ if (isPrevLineTableRow) {
94497
+ return normalizeTableSeparatorLine(line);
94498
+ }
94499
+ return line;
94500
+ });
94501
+ return normalizedLines.join('\n');
94502
+ }
94503
+ /* harmony default export */ const normalize_table_separator = ((/* unused pure expression or super */ null && (normalizeTableSeparator)));
94504
+
94417
94505
  ;// ./processor/transform/mdxish/restore-snake-case-component-name.ts
94418
94506
 
94419
94507
 
@@ -94677,6 +94765,7 @@ function loadComponents() {
94677
94765
 
94678
94766
 
94679
94767
 
94768
+
94680
94769
 
94681
94770
 
94682
94771
  const defaultTransformers = [callouts, code_tabs, gemoji_, transform_embeds];
@@ -94689,9 +94778,11 @@ function mdxishAstProcessor(mdContent, opts = {}) {
94689
94778
  // Preprocessing pipeline: Transform content to be parser-ready
94690
94779
  // Step 1: Extract legacy magic blocks
94691
94780
  const { replaced: contentAfterMagicBlocks, blocks } = extractMagicBlocks(mdContent);
94692
- // Step 2: Evaluate JSX expressions in attributes
94693
- const contentAfterJSXEvaluation = preprocessJSXExpressions(contentAfterMagicBlocks, jsxContext);
94694
- // Step 3: Replace snake_case component names with parser-safe placeholders
94781
+ // Step 2: Normalize malformed table separator syntax (e.g., `|: ---` → `| :---`)
94782
+ const contentAfterTableNormalization = normalizeTableSeparator(contentAfterMagicBlocks);
94783
+ // Step 3: Evaluate JSX expressions in attributes
94784
+ const contentAfterJSXEvaluation = preprocessJSXExpressions(contentAfterTableNormalization, jsxContext);
94785
+ // Step 4: Replace snake_case component names with parser-safe placeholders
94695
94786
  // (e.g., <Snake_case /> → <MDXishSnakeCase0 /> which will be restored after parsing)
94696
94787
  const { content: parserReadyContent, mapping: snakeCaseMapping } = processSnakeCaseComponent(contentAfterJSXEvaluation);
94697
94788
  // Create string map for tailwind transformer
@@ -95295,89 +95386,6 @@ async function stripComments(doc, { mdx } = {}) {
95295
95386
  }
95296
95387
  /* harmony default export */ const lib_stripComments = (stripComments);
95297
95388
 
95298
- ;// ./lib/utils/isPlainText.ts
95299
-
95300
- /**
95301
- * Detects if content contains HTML, magic blocks, or MDX syntax.
95302
- *
95303
- * We can use this in some pipelines to determine if we should have to parse content through
95304
- * `.plain() or if it is already plain text and it should be able to detect everything that would
95305
- * be stripped or sanitized by `.plain()`.
95306
- *
95307
- */
95308
- function isPlainText(content) {
95309
- if (!content || typeof content !== 'string') {
95310
- return true;
95311
- }
95312
- // Exclude markdown code blocks and inline code to avoid false positives
95313
- // Match code blocks with optional language identifier: ```lang\n...\n```
95314
- const codeBlockRegex = /```[^\n]*\n[\s\S]*?```/g;
95315
- // Match inline code: `code` (but not escaped backticks)
95316
- const inlineCodeRegex = /`[^`\n]+`/g;
95317
- // Remove code blocks and inline code to avoid false positives
95318
- let contentWithoutCode = structuredClone(content);
95319
- contentWithoutCode = contentWithoutCode.replace(codeBlockRegex, '');
95320
- contentWithoutCode = contentWithoutCode.replace(inlineCodeRegex, '');
95321
- // Check for magic blocks: `[block:TYPE]...[/block]`
95322
- // Only check after removing code blocks to avoid detecting magic blocks in code
95323
- if (contentWithoutCode.match(MAGIC_BLOCK_REGEX) !== null) {
95324
- return false;
95325
- }
95326
- // Check for markdown links: [text](url) or [text][reference]
95327
- // Pattern matches inline links and reference-style links
95328
- // Exclude images which start with ! before the bracket
95329
- // Only check after removing code blocks
95330
- const markdownLinkPattern = /(?<!!)\[([^\]]+)\]\(([^)]+)\)|(?<!!)\[([^\]]+)\]\[([^\]]*)\]/;
95331
- if (markdownLinkPattern.test(contentWithoutCode)) {
95332
- return false;
95333
- }
95334
- // Check for JSX elements (PascalCase components) in the original content
95335
- // This includes code blocks since JSX code examples should be detected
95336
- // Pattern matches:
95337
- // - Self-closing: <Component /> or <Component/>
95338
- // - With attributes: <Component prop="value" />
95339
- // - With children: <Component>...</Component>
95340
- // Use simpler, safer patterns to avoid ReDoS from backtracking
95341
- // Match self-closing tags with bounded attribute length to prevent excessive backtracking
95342
- const jsxSelfClosingPattern = /<[A-Z][a-zA-Z0-9]*(?:\s[^>]{0,50})?\/>/;
95343
- if (jsxSelfClosingPattern.test(content)) {
95344
- return false;
95345
- }
95346
- // For components with children, use a safer pattern that limits backtracking
95347
- // Match opening tag with bounded attributes, then look for closing tag with same name
95348
- const jsxWithChildrenPattern = /<([A-Z][a-zA-Z0-9]*)(?:\s[^>]{0,50})?>[\s\S]{0,50}<\/\1>/;
95349
- if (jsxWithChildrenPattern.test(content)) {
95350
- return false;
95351
- }
95352
- // Check for MDX expressions and HTML tags in the original content
95353
- // HTML/JSX/MDX in code blocks should be detected (as per test requirements)
95354
- // But exclude inline code that contains magic block patterns to avoid false positives
95355
- let contentForHtmlMdx = content;
95356
- // Find inline code blocks and check if they contain [block: pattern
95357
- // Exclude these from HTML/MDX detection to avoid false positives
95358
- const inlineCodePattern = /`[^`\n]+`/g;
95359
- let inlineCodeMatch;
95360
- inlineCodePattern.lastIndex = 0;
95361
- while ((inlineCodeMatch = inlineCodePattern.exec(content)) !== null) {
95362
- if (inlineCodeMatch[0].includes('[block:')) {
95363
- contentForHtmlMdx = contentForHtmlMdx.replace(inlineCodeMatch[0], '');
95364
- }
95365
- }
95366
- // Match simple MDX variable expressions like {variable}, {user.name}, {getValue()}, {}
95367
- // Use bounded quantifier to prevent ReDoS - limit to reasonable variable name length
95368
- // Allow empty braces {} to be detected as well
95369
- const jsxExpressionPattern = /\{[^}"]{0,50}\}/;
95370
- if (jsxExpressionPattern.test(contentForHtmlMdx)) {
95371
- return false;
95372
- }
95373
- // Match HTML tags with bounded attribute length to prevent ReDoS
95374
- const htmlTagPattern = /<[a-z][a-z0-9]*(?:\s[^>]{0,50})?(?:\/>|>)/i;
95375
- if (htmlTagPattern.test(contentForHtmlMdx)) {
95376
- return false;
95377
- }
95378
- return true;
95379
- }
95380
-
95381
95389
  ;// ./lib/index.ts
95382
95390
 
95383
95391
 
@@ -95396,7 +95404,6 @@ function isPlainText(content) {
95396
95404
 
95397
95405
 
95398
95406
 
95399
-
95400
95407
  ;// ./index.tsx
95401
95408
 
95402
95409
 
package/dist/main.node.js CHANGED
@@ -19024,7 +19024,6 @@ __webpack_require__.d(__webpack_exports__, {
19024
19024
  exports: () => (/* reexport */ lib_exports),
19025
19025
  gemojiRegex: () => (/* reexport */ gemoji_regex),
19026
19026
  hast: () => (/* reexport */ lib_hast),
19027
- isPlainText: () => (/* reexport */ isPlainText),
19028
19027
  mdast: () => (/* reexport */ lib_mdast),
19029
19028
  mdastV6: () => (/* reexport */ lib_mdastV6),
19030
19029
  mdx: () => (/* reexport */ lib_mdx),
@@ -90825,10 +90824,13 @@ const tagAttributePattern = /([a-zA-Z_:][-a-zA-Z0-9_:.]*)(?:\s*=\s*("[^"]*"|'[^'
90825
90824
  const MAX_LOOKAHEAD = 30;
90826
90825
  /**
90827
90826
  * Tags that have dedicated transformers and should NOT be handled by this plugin.
90828
- * These components have special parsing requirements that the generic component
90829
- * block transformer cannot handle correctly.
90827
+ * These components either have special parsing requirements that the generic component
90828
+ * block transformer cannot handle correctly, or are inline components that we don't
90829
+ * want to convert to mdxJsxFlowElement which is a block level element.
90830
+ *
90831
+ * Glossary and Anchor are inline components.
90830
90832
  */
90831
- const EXCLUDED_TAGS = new Set(['HTMLBlock', 'Table']);
90833
+ const EXCLUDED_TAGS = new Set(['HTMLBlock', 'Table', 'Glossary', 'Anchor']);
90832
90834
  const inlineMdProcessor = unified().use(remarkParse);
90833
90835
  const isClosingTag = (value, tag) => value.trim() === `</${tag}>`;
90834
90836
  /**
@@ -114618,6 +114620,92 @@ const normalizeEmphasisAST = () => (tree) => {
114618
114620
  };
114619
114621
  /* harmony default export */ const normalize_malformed_md_syntax = (normalizeEmphasisAST);
114620
114622
 
114623
+ ;// ./processor/transform/mdxish/normalize-table-separator.ts
114624
+ /**
114625
+ * Preprocessor to normalize malformed GFM table separator syntax.
114626
+ *
114627
+ * Fixes the common mistake where the alignment colon is placed after the pipe
114628
+ * instead of before the dashes:
114629
+ *
114630
+ * Invalid: `|: ---` or `|:---` (colon after pipe)
114631
+ * Valid: `| :---` (colon before dashes)
114632
+ *
114633
+ * Also handles right alignment:
114634
+ * Invalid: `| ---:| ` with space before pipe
114635
+ * Valid: `| ---:|` (no space before closing pipe)
114636
+ *
114637
+ * This runs before remark-parse to ensure the table is recognized as a valid GFM table.
114638
+ */
114639
+ /**
114640
+ * Pattern to match a table separator row.
114641
+ * A separator row consists of cells that contain only dashes, colons (for alignment), and spaces.
114642
+ *
114643
+ * Valid GFM separator formats:
114644
+ * - `---` or `----` (no alignment, defaults to left)
114645
+ * - `:---` (left aligned)
114646
+ * - `---:` (right aligned)
114647
+ * - `:---:` (center aligned)
114648
+ *
114649
+ * Invalid formats this fixes:
114650
+ * - `|: ---` → `| :---` (colon wrongly placed after pipe)
114651
+ * - `|:---` → `| :---` (colon directly after pipe, missing space)
114652
+ * - `|::---` or `| ::---` → `| :---` (double colon typo)
114653
+ */
114654
+ // Match a line that looks like a table separator row
114655
+ // This regex captures the whole line if it contains only pipe-separated cells with dashes/colons
114656
+ const TABLE_SEPARATOR_LINE_REGEX = /^(\|[:\s-]+)+\|?\s*$/;
114657
+ // Match malformed left-alignment: `|: ` or `|:` followed by dashes
114658
+ // Captures: group 1 = pipe, group 2 = spaces after colon, group 3 = dashes
114659
+ const MALFORMED_LEFT_ALIGN_REGEX = /\|:(\s*)(-+)/g;
114660
+ // Match malformed double colon: `|::---` or `| ::---` → `| :---`
114661
+ const MALFORMED_DOUBLE_COLON_REGEX = /\|\s*::(\s*)(-+)/g;
114662
+ // Match malformed patterns with spaces before closing colons: `| --- : |` → `| ---: |`
114663
+ const MALFORMED_RIGHT_ALIGN_SPACE_REGEX = /(-+)\s+:(\s*\|)/g;
114664
+ // Match malformed center alignment with spaces: `| : --- : |` → `| :---: |`
114665
+ const MALFORMED_CENTER_ALIGN_REGEX = /\|:(\s+)(-+)(\s+):/g;
114666
+ /**
114667
+ * Normalizes a single table separator line.
114668
+ */
114669
+ function normalizeTableSeparatorLine(line) {
114670
+ // Check if this line looks like a table separator
114671
+ if (!TABLE_SEPARATOR_LINE_REGEX.test(line)) {
114672
+ return line;
114673
+ }
114674
+ let normalized = line;
114675
+ // Fix `|::---` → `| :---` (double colon typo)
114676
+ // Must run before single colon fix to avoid partial replacement
114677
+ normalized = normalized.replace(MALFORMED_DOUBLE_COLON_REGEX, '| :$2');
114678
+ // Fix `|: ---` or `|:---` → `| :---`
114679
+ // The colon should be adjacent to the dashes, not the pipe
114680
+ normalized = normalized.replace(MALFORMED_LEFT_ALIGN_REGEX, '| :$2');
114681
+ // Fix `| --- : |` → `| ---: |`
114682
+ // Remove space before right-alignment colon
114683
+ normalized = normalized.replace(MALFORMED_RIGHT_ALIGN_SPACE_REGEX, '$1:$2');
114684
+ // Fix `| : --- : |` → `| :---: |`
114685
+ // Remove spaces around center-aligned dashes
114686
+ normalized = normalized.replace(MALFORMED_CENTER_ALIGN_REGEX, '| :$2:');
114687
+ return normalized;
114688
+ }
114689
+ /**
114690
+ * Preprocesses markdown content to normalize malformed table separator syntax.
114691
+ *
114692
+ * @param content - The raw markdown content
114693
+ * @returns The content with normalized table separators
114694
+ */
114695
+ function normalizeTableSeparator(content) {
114696
+ const lines = content.split('\n');
114697
+ const normalizedLines = lines.map((line, index) => {
114698
+ const prevLine = index > 0 ? lines[index - 1] : '';
114699
+ const isPrevLineTableRow = prevLine.trim().startsWith('|');
114700
+ if (isPrevLineTableRow) {
114701
+ return normalizeTableSeparatorLine(line);
114702
+ }
114703
+ return line;
114704
+ });
114705
+ return normalizedLines.join('\n');
114706
+ }
114707
+ /* harmony default export */ const normalize_table_separator = ((/* unused pure expression or super */ null && (normalizeTableSeparator)));
114708
+
114621
114709
  ;// ./processor/transform/mdxish/restore-snake-case-component-name.ts
114622
114710
 
114623
114711
 
@@ -114881,6 +114969,7 @@ function loadComponents() {
114881
114969
 
114882
114970
 
114883
114971
 
114972
+
114884
114973
 
114885
114974
 
114886
114975
  const defaultTransformers = [callouts, code_tabs, gemoji_, transform_embeds];
@@ -114893,9 +114982,11 @@ function mdxishAstProcessor(mdContent, opts = {}) {
114893
114982
  // Preprocessing pipeline: Transform content to be parser-ready
114894
114983
  // Step 1: Extract legacy magic blocks
114895
114984
  const { replaced: contentAfterMagicBlocks, blocks } = extractMagicBlocks(mdContent);
114896
- // Step 2: Evaluate JSX expressions in attributes
114897
- const contentAfterJSXEvaluation = preprocessJSXExpressions(contentAfterMagicBlocks, jsxContext);
114898
- // Step 3: Replace snake_case component names with parser-safe placeholders
114985
+ // Step 2: Normalize malformed table separator syntax (e.g., `|: ---` → `| :---`)
114986
+ const contentAfterTableNormalization = normalizeTableSeparator(contentAfterMagicBlocks);
114987
+ // Step 3: Evaluate JSX expressions in attributes
114988
+ const contentAfterJSXEvaluation = preprocessJSXExpressions(contentAfterTableNormalization, jsxContext);
114989
+ // Step 4: Replace snake_case component names with parser-safe placeholders
114899
114990
  // (e.g., <Snake_case /> → <MDXishSnakeCase0 /> which will be restored after parsing)
114900
114991
  const { content: parserReadyContent, mapping: snakeCaseMapping } = processSnakeCaseComponent(contentAfterJSXEvaluation);
114901
114992
  // Create string map for tailwind transformer
@@ -115499,89 +115590,6 @@ async function stripComments(doc, { mdx } = {}) {
115499
115590
  }
115500
115591
  /* harmony default export */ const lib_stripComments = (stripComments);
115501
115592
 
115502
- ;// ./lib/utils/isPlainText.ts
115503
-
115504
- /**
115505
- * Detects if content contains HTML, magic blocks, or MDX syntax.
115506
- *
115507
- * We can use this in some pipelines to determine if we should have to parse content through
115508
- * `.plain() or if it is already plain text and it should be able to detect everything that would
115509
- * be stripped or sanitized by `.plain()`.
115510
- *
115511
- */
115512
- function isPlainText(content) {
115513
- if (!content || typeof content !== 'string') {
115514
- return true;
115515
- }
115516
- // Exclude markdown code blocks and inline code to avoid false positives
115517
- // Match code blocks with optional language identifier: ```lang\n...\n```
115518
- const codeBlockRegex = /```[^\n]*\n[\s\S]*?```/g;
115519
- // Match inline code: `code` (but not escaped backticks)
115520
- const inlineCodeRegex = /`[^`\n]+`/g;
115521
- // Remove code blocks and inline code to avoid false positives
115522
- let contentWithoutCode = structuredClone(content);
115523
- contentWithoutCode = contentWithoutCode.replace(codeBlockRegex, '');
115524
- contentWithoutCode = contentWithoutCode.replace(inlineCodeRegex, '');
115525
- // Check for magic blocks: `[block:TYPE]...[/block]`
115526
- // Only check after removing code blocks to avoid detecting magic blocks in code
115527
- if (contentWithoutCode.match(MAGIC_BLOCK_REGEX) !== null) {
115528
- return false;
115529
- }
115530
- // Check for markdown links: [text](url) or [text][reference]
115531
- // Pattern matches inline links and reference-style links
115532
- // Exclude images which start with ! before the bracket
115533
- // Only check after removing code blocks
115534
- const markdownLinkPattern = /(?<!!)\[([^\]]+)\]\(([^)]+)\)|(?<!!)\[([^\]]+)\]\[([^\]]*)\]/;
115535
- if (markdownLinkPattern.test(contentWithoutCode)) {
115536
- return false;
115537
- }
115538
- // Check for JSX elements (PascalCase components) in the original content
115539
- // This includes code blocks since JSX code examples should be detected
115540
- // Pattern matches:
115541
- // - Self-closing: <Component /> or <Component/>
115542
- // - With attributes: <Component prop="value" />
115543
- // - With children: <Component>...</Component>
115544
- // Use simpler, safer patterns to avoid ReDoS from backtracking
115545
- // Match self-closing tags with bounded attribute length to prevent excessive backtracking
115546
- const jsxSelfClosingPattern = /<[A-Z][a-zA-Z0-9]*(?:\s[^>]{0,50})?\/>/;
115547
- if (jsxSelfClosingPattern.test(content)) {
115548
- return false;
115549
- }
115550
- // For components with children, use a safer pattern that limits backtracking
115551
- // Match opening tag with bounded attributes, then look for closing tag with same name
115552
- const jsxWithChildrenPattern = /<([A-Z][a-zA-Z0-9]*)(?:\s[^>]{0,50})?>[\s\S]{0,50}<\/\1>/;
115553
- if (jsxWithChildrenPattern.test(content)) {
115554
- return false;
115555
- }
115556
- // Check for MDX expressions and HTML tags in the original content
115557
- // HTML/JSX/MDX in code blocks should be detected (as per test requirements)
115558
- // But exclude inline code that contains magic block patterns to avoid false positives
115559
- let contentForHtmlMdx = content;
115560
- // Find inline code blocks and check if they contain [block: pattern
115561
- // Exclude these from HTML/MDX detection to avoid false positives
115562
- const inlineCodePattern = /`[^`\n]+`/g;
115563
- let inlineCodeMatch;
115564
- inlineCodePattern.lastIndex = 0;
115565
- while ((inlineCodeMatch = inlineCodePattern.exec(content)) !== null) {
115566
- if (inlineCodeMatch[0].includes('[block:')) {
115567
- contentForHtmlMdx = contentForHtmlMdx.replace(inlineCodeMatch[0], '');
115568
- }
115569
- }
115570
- // Match simple MDX variable expressions like {variable}, {user.name}, {getValue()}, {}
115571
- // Use bounded quantifier to prevent ReDoS - limit to reasonable variable name length
115572
- // Allow empty braces {} to be detected as well
115573
- const jsxExpressionPattern = /\{[^}"]{0,50}\}/;
115574
- if (jsxExpressionPattern.test(contentForHtmlMdx)) {
115575
- return false;
115576
- }
115577
- // Match HTML tags with bounded attribute length to prevent ReDoS
115578
- const htmlTagPattern = /<[a-z][a-z0-9]*(?:\s[^>]{0,50})?(?:\/>|>)/i;
115579
- if (htmlTagPattern.test(contentForHtmlMdx)) {
115580
- return false;
115581
- }
115582
- return true;
115583
- }
115584
-
115585
115593
  ;// ./lib/index.ts
115586
115594
 
115587
115595
 
@@ -115600,7 +115608,6 @@ function isPlainText(content) {
115600
115608
 
115601
115609
 
115602
115610
 
115603
-
115604
115611
  ;// ./index.tsx
115605
115612
 
115606
115613