@readme/markdown 14.13.0 → 14.13.1

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
@@ -76301,6 +76301,15 @@ const HTML_TABLE_STRUCTURE_TAGS = new Set([
76301
76301
  'caption',
76302
76302
  'colgroup',
76303
76303
  ]);
76304
+ /**
76305
+ * Tags whose bodies a later mdxish transform keeps raw and never re-parses as
76306
+ * markdown. Both layers depend on this property, not on the tags being figures:
76307
+ * the transformer treats them as non-promotable, and the tokenizer must not claim
76308
+ * markdown islands inside them (a claimed island would never be re-parsed and would
76309
+ * leak as literal text). Currently just the figure tags, whose bodies are owned by
76310
+ * the figure reassembly transform (`mdxishJsxToMdast`).
76311
+ */
76312
+ const NON_REPARSED_BODY_TAGS = new Set(['figure', 'figcaption']);
76304
76313
  /**
76305
76314
  * The two HTML "foreign content" namespaces: SVG and MathML. Their descendants
76306
76315
  * (`<path>`, `<mrow>`, …) are namespaced XML, not HTML tags or components. A closed
@@ -101498,12 +101507,95 @@ function tokenizeMagicBlockText(effects, ok, nok) {
101498
101507
  */
101499
101508
 
101500
101509
 
101510
+ ;// ./lib/micromark/mdx-component/continuation-checks.ts
101511
+
101512
+
101513
+ /**
101514
+ * Partial constructs the `mdxComponent` tokenizer runs via `effects.check` to
101515
+ * decide whether the next line continues the block. They live here (not in
101516
+ * `syntax.ts`) because they hold none of `createTokenize`'s closure state — each
101517
+ * is a self-contained, single-line lookahead.
101518
+ */
101519
+ function continuation_checks_tokenizeNonLazyContinuationStart(effects, ok, nok) {
101520
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
101521
+ const self = this;
101522
+ return start;
101523
+ function start(code) {
101524
+ if (markdownLineEnding(code)) {
101525
+ effects.enter(types_types.lineEnding);
101526
+ effects.consume(code);
101527
+ effects.exit(types_types.lineEnding);
101528
+ return after;
101529
+ }
101530
+ return nok(code);
101531
+ }
101532
+ function after(code) {
101533
+ if (self.parser.lazy[self.now().line]) {
101534
+ return nok(code);
101535
+ }
101536
+ return ok(code);
101537
+ }
101538
+ }
101539
+ // A markup-only line opens with a tag (`<x`/`</x`) and ends (ignoring trailing
101540
+ // spaces) at a `>`. That distinguishes a structural continuation like
101541
+ // `<span>b</span></div>` from a paragraph like `<b>Note:</b> read *this*`.
101542
+ function tokenizeMarkupOnlyContinuation(effects, ok, nok) {
101543
+ let lastNonSpace = null;
101544
+ return start;
101545
+ function start(code) {
101546
+ // Caller guarantees we are at `<` at the (already de-indented) line start.
101547
+ effects.enter(types_types.data);
101548
+ effects.consume(code);
101549
+ return afterLessThan;
101550
+ }
101551
+ function afterLessThan(code) {
101552
+ if (code === codes.slash) {
101553
+ effects.consume(code);
101554
+ return afterSlash;
101555
+ }
101556
+ return afterSlash(code);
101557
+ }
101558
+ // The `<` (or `</`) must introduce a real tag, not a stray `<` in prose.
101559
+ function afterSlash(code) {
101560
+ if (asciiAlpha(code)) {
101561
+ lastNonSpace = code;
101562
+ effects.consume(code);
101563
+ return scanToLineEnd;
101564
+ }
101565
+ effects.exit(types_types.data);
101566
+ return nok(code);
101567
+ }
101568
+ function scanToLineEnd(code) {
101569
+ if (code === null || markdownLineEnding(code)) {
101570
+ effects.exit(types_types.data);
101571
+ return lastNonSpace === codes.greaterThan ? ok(code) : nok(code);
101572
+ }
101573
+ if (!markdownSpace(code))
101574
+ lastNonSpace = code;
101575
+ effects.consume(code);
101576
+ return scanToLineEnd;
101577
+ }
101578
+ }
101579
+ // A line ending whose next line isn't a lazy paragraph continuation. Checked so a
101580
+ // component body's blank/continuation lines aren't stolen by an interrupted paragraph.
101581
+ const continuation_checks_nonLazyContinuationStart = {
101582
+ tokenize: continuation_checks_tokenizeNonLazyContinuationStart,
101583
+ partial: true,
101584
+ };
101585
+ // Lookahead for `plainClaimLineStart`: is this line markup-only, or a paragraph
101586
+ // that merely starts with a tag? Run via `effects.check` so it never consumes.
101587
+ const markupOnlyContinuation = {
101588
+ tokenize: tokenizeMarkupOnlyContinuation,
101589
+ partial: true,
101590
+ };
101591
+
101501
101592
  ;// ./lib/micromark/mdx-component/syntax.ts
101502
101593
 
101503
101594
 
101504
101595
 
101505
101596
 
101506
101597
 
101598
+
101507
101599
  // Raw tags (type-1: pre/script/style/textarea) and block tags (type-6: div,
101508
101600
  // section, …) always start a block, so they stay flow even with trailing
101509
101601
  // content. Other lowercase tags (i, span, …) follow the type-7 rule and only
@@ -101513,16 +101605,12 @@ const htmlFlowTagNames = new Set([...htmlRawNames, ...htmlBlockNames]);
101513
101605
  // blank lines between nested JSX siblings don't fragment the block. Excludes table
101514
101606
  // tags (mdxishTables owns their blank lines) and voids (never close).
101515
101607
  const plainBlockClaimTagNames = new Set([...htmlBlockNames].filter(tag => !HTML_TABLE_STRUCTURE_TAGS.has(tag) && !HTML_VOID_ELEMENTS.has(tag)));
101516
- const mdx_component_syntax_nonLazyContinuationStart = {
101517
- tokenize: mdx_component_syntax_tokenizeNonLazyContinuationStart,
101518
- partial: true,
101519
- };
101520
- // Lookahead for `plainClaimLineStart`: is this line markup-only, or a paragraph
101521
- // that merely starts with a tag? Run via `effects.check` so it never consumes.
101522
- const markupOnlyContinuation = {
101523
- tokenize: tokenizeMarkupOnlyContinuation,
101524
- partial: true,
101525
- };
101608
+ // Both are 4 columns per CommonMark, but they mean different things: a tab advances
101609
+ // to the next multiple of TAB_STOP_WIDTH, and INDENTED_CODE_MIN_COLUMNS is the depth
101610
+ // at which a line would fragment into indented code. Named separately so the two
101611
+ // concepts don't read as one incidental literal.
101612
+ const TAB_STOP_WIDTH = 4;
101613
+ const INDENTED_CODE_MIN_COLUMNS = 4;
101526
101614
  function resolveToMdxComponent(events) {
101527
101615
  let index = events.length;
101528
101616
  while (index > 0) {
@@ -101581,6 +101669,18 @@ function createTokenize(mode) {
101581
101669
  // `plainClaimLineStart`: after a blank line it may only continue on a tag line.
101582
101670
  let isPlainBlockClaim = false;
101583
101671
  let pendingBlankLine = false;
101672
+ // Leading indent columns of the current plain-claim line, reset per line; ≥4 is
101673
+ // where CommonMark would fragment the island as indented code. Tabs advance to the
101674
+ // next 4-column stop — the same rule `expandIndentToColumns`
101675
+ // (processor/transform/mdxish/indentation.ts) applies, kept in sync by hand since
101676
+ // this side works on a `Code` stream, not a string. NB: do NOT swap this for
101677
+ // `self.now().column`; micromark bumps the point column by 1 per `horizontalTab`
101678
+ // code (the trailing `virtualSpace` codes don't move it), so it measures a tab as
101679
+ // 1 column, reviving the tab-under-measurement bug this math exists to avoid.
101680
+ let plainClaimIndentColumns = 0;
101681
+ // True once a non-blank line follows the opener: a deep island below it is nested
101682
+ // (cosmetic indent), not top-of-body indented code.
101683
+ let sawPlainBlockBodyContent = false;
101584
101684
  // Code span tracking
101585
101685
  let codeSpanOpenSize = 0;
101586
101686
  let codeSpanCloseSize = 0;
@@ -101880,7 +101980,7 @@ function createTokenize(mode) {
101880
101980
  }
101881
101981
  // Continuation for multi-line opening tags
101882
101982
  function openTagContinuationStart(code) {
101883
- return effects.check(mdx_component_syntax_nonLazyContinuationStart, openTagContinuationNonLazy, continuationAfter)(code);
101983
+ return effects.check(continuation_checks_nonLazyContinuationStart, openTagContinuationNonLazy, continuationAfter)(code);
101884
101984
  }
101885
101985
  function openTagContinuationNonLazy(code) {
101886
101986
  sawLineEnding = true;
@@ -101925,6 +102025,9 @@ function createTokenize(mode) {
101925
102025
  }
101926
102026
  if (code !== codes.space && code !== codes.horizontalTab) {
101927
102027
  openerLineHasContent = true;
102028
+ // Continuation content marks a later deep island as nested, not indented code.
102029
+ if (!onOpenerLine)
102030
+ sawPlainBlockBodyContent = true;
101928
102031
  }
101929
102032
  if (code === codes.backslash) {
101930
102033
  effects.consume(code);
@@ -102005,7 +102108,7 @@ function createTokenize(mode) {
102005
102108
  return inFencedCode;
102006
102109
  }
102007
102110
  function fencedCodeContinuationStart(code) {
102008
- return effects.check(mdx_component_syntax_nonLazyContinuationStart, fencedCodeContinuationNonLazy, continuationAfter)(code);
102111
+ return effects.check(continuation_checks_nonLazyContinuationStart, fencedCodeContinuationNonLazy, continuationAfter)(code);
102009
102112
  }
102010
102113
  function fencedCodeContinuationNonLazy(code) {
102011
102114
  sawLineEnding = true;
@@ -102213,7 +102316,7 @@ function createTokenize(mode) {
102213
102316
  }
102214
102317
  // ── Body continuation (line endings) ───────────────────────────────────
102215
102318
  function bodyContinuationStart(code) {
102216
- return effects.check(mdx_component_syntax_nonLazyContinuationStart, bodyContinuationNonLazy, continuationAfter)(code);
102319
+ return effects.check(continuation_checks_nonLazyContinuationStart, bodyContinuationNonLazy, continuationAfter)(code);
102217
102320
  }
102218
102321
  function bodyContinuationNonLazy(code) {
102219
102322
  sawLineEnding = true;
@@ -102239,8 +102342,10 @@ function createTokenize(mode) {
102239
102342
  return inBodyBraceString(code);
102240
102343
  return inBodyBraceExpr(code);
102241
102344
  }
102242
- if (isPlainBlockClaim)
102345
+ if (isPlainBlockClaim) {
102346
+ plainClaimIndentColumns = 0;
102243
102347
  return plainClaimLineStart(code);
102348
+ }
102244
102349
  return bodyLineStart(code);
102245
102350
  }
102246
102351
  // Dispatch a non-blank continuation line: fenced code at line start, else body.
@@ -102270,6 +102375,8 @@ function createTokenize(mode) {
102270
102375
  function plainClaimLineStart(code) {
102271
102376
  // Leading whitespace only → treat as a blank line, matching CommonMark.
102272
102377
  if (code === codes.space || code === codes.horizontalTab) {
102378
+ plainClaimIndentColumns +=
102379
+ code === codes.horizontalTab ? TAB_STOP_WIDTH - (plainClaimIndentColumns % TAB_STOP_WIDTH) : 1;
102273
102380
  effects.consume(code);
102274
102381
  return plainClaimLineStart;
102275
102382
  }
@@ -102278,10 +102385,18 @@ function createTokenize(mode) {
102278
102385
  effects.exit('mdxComponentData');
102279
102386
  return bodyContinuationStart(code);
102280
102387
  }
102281
- // Across a blank line the block only continues onto a markup-only line; a
102282
- // paragraph that merely starts with a tag must fall back so its markdown
102283
- // parses and rehype-raw re-nests it into the wrapper.
102284
102388
  if (pendingBlankLine) {
102389
+ // A 4+ col island nested under other tags is cosmetic nesting indent, not code:
102390
+ // keep claiming so promotion dedents + re-parses it as markdown (RM-17560).
102391
+ // Tags whose bodies stay raw are excluded — a claimed island there would never
102392
+ // be re-parsed and would leak as literal text.
102393
+ if (plainClaimIndentColumns >= INDENTED_CODE_MIN_COLUMNS &&
102394
+ sawPlainBlockBodyContent &&
102395
+ !NON_REPARSED_BODY_TAGS.has(tagName)) {
102396
+ return plainClaimContinue(code);
102397
+ }
102398
+ // Otherwise only a markup-only tag line continues; markdown/prose falls back to
102399
+ // CommonMark so it parses and rehype-raw re-nests it into the wrapper.
102285
102400
  if (code !== codes.lessThan)
102286
102401
  return nok(code);
102287
102402
  return effects.check(markupOnlyContinuation, plainClaimContinue, nok)(code);
@@ -102302,66 +102417,6 @@ function createTokenize(mode) {
102302
102417
  }
102303
102418
  };
102304
102419
  }
102305
- function mdx_component_syntax_tokenizeNonLazyContinuationStart(effects, ok, nok) {
102306
- // eslint-disable-next-line @typescript-eslint/no-this-alias
102307
- const self = this;
102308
- return start;
102309
- function start(code) {
102310
- if (markdownLineEnding(code)) {
102311
- effects.enter(types_types.lineEnding);
102312
- effects.consume(code);
102313
- effects.exit(types_types.lineEnding);
102314
- return after;
102315
- }
102316
- return nok(code);
102317
- }
102318
- function after(code) {
102319
- if (self.parser.lazy[self.now().line]) {
102320
- return nok(code);
102321
- }
102322
- return ok(code);
102323
- }
102324
- }
102325
- // A markup-only line opens with a tag (`<x`/`</x`) and ends (ignoring trailing
102326
- // spaces) at a `>`. That distinguishes a structural continuation like
102327
- // `<span>b</span></div>` from a paragraph like `<b>Note:</b> read *this*`.
102328
- function tokenizeMarkupOnlyContinuation(effects, ok, nok) {
102329
- let lastNonSpace = null;
102330
- return start;
102331
- function start(code) {
102332
- // Caller guarantees we are at `<` at the (already de-indented) line start.
102333
- effects.enter(types_types.data);
102334
- effects.consume(code);
102335
- return afterLessThan;
102336
- }
102337
- function afterLessThan(code) {
102338
- if (code === codes.slash) {
102339
- effects.consume(code);
102340
- return afterSlash;
102341
- }
102342
- return afterSlash(code);
102343
- }
102344
- // The `<` (or `</`) must introduce a real tag, not a stray `<` in prose.
102345
- function afterSlash(code) {
102346
- if (asciiAlpha(code)) {
102347
- lastNonSpace = code;
102348
- effects.consume(code);
102349
- return scanToLineEnd;
102350
- }
102351
- effects.exit(types_types.data);
102352
- return nok(code);
102353
- }
102354
- function scanToLineEnd(code) {
102355
- if (code === null || markdownLineEnding(code)) {
102356
- effects.exit(types_types.data);
102357
- return lastNonSpace === codes.greaterThan ? ok(code) : nok(code);
102358
- }
102359
- if (!markdownSpace(code))
102360
- lastNonSpace = code;
102361
- effects.consume(code);
102362
- return scanToLineEnd;
102363
- }
102364
- }
102365
102420
  /**
102366
102421
  * Micromark extension that tokenizes MDX-like components.
102367
102422
  *
@@ -102415,6 +102470,7 @@ function mdxComponent() {
102415
102470
 
102416
102471
 
102417
102472
 
102473
+
102418
102474
 
102419
102475
  const buildInlineMdProcessor = (safeMode) => {
102420
102476
  // `jsxTable` must be present so a `<Table>`/`<table>` nested in a component
@@ -102486,7 +102542,7 @@ const toMdxJsxTextElement = (name, attributes, children, position) => ({
102486
102542
  // Raw-body tags (pre/script/style/textarea) must stay byte-exact; table
102487
102543
  // structure (`table` + `tableTags`) is owned by `mdxishTables` and figures by
102488
102544
  // `mdxishJsxToMdast`, both of which run later on raw html nodes.
102489
- const NON_PROMOTABLE_PLAIN_TAGS = new Set([...htmlRawNames, ...tableTags, 'table', 'figure', 'figcaption']);
102545
+ const NON_PROMOTABLE_PLAIN_TAGS = new Set([...htmlRawNames, ...tableTags, 'table', ...NON_REPARSED_BODY_TAGS]);
102490
102546
  const NESTED_TABLE_RE = /<table[\s>]/i;
102491
102547
  const isMarkdownPromotableHtmlTag = (tag) => !NON_PROMOTABLE_PLAIN_TAGS.has(tag);
102492
102548
  // Expression nodes count as plain so `<div>{1+1}</div>` keeps its current
@@ -102845,15 +102901,22 @@ function safeDeindent(text) {
102845
102901
  */
102846
102902
  const parseMdChildren = (value, safeMode) => {
102847
102903
  const parsed = getInlineMdProcessor({ safeMode }).parse(terminateHtmlFlowBlocks(safeDeindent(value).trim()));
102904
+ // Promote nested wrappers bottom-up so an outer wrapper sees markdown buried in a
102905
+ // child claimed whole (e.g. `<li>` in `<ol>`) before its containsMarkdownConstruct check (RM-17560).
102906
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define -- mutually recursive; hoisted decl, safe at runtime
102907
+ promoteComponentBlocks(parsed, safeMode, null);
102848
102908
  return parsed.children || [];
102849
102909
  };
102850
- // Parses trailing content into sibling nodes and re-queues the parent so any
102851
- // components among them get processed.
102852
- const parseSibling = (stack, parent, index, sibling, safeMode) => {
102910
+ // Splices trailing content in as sibling nodes. parseMdChildren has already
102911
+ // promoted any components nested among them (bottom-up); the main loop's
102912
+ // index-based walk then reaches these spliced siblings and the original children
102913
+ // they shift down, so no parent re-queue is needed. Each spliced subtree is marked
102914
+ // `promoted` so the walk doesn't redundantly re-descend into it (its html is gone).
102915
+ const parseSibling = (parent, index, sibling, safeMode, promoted) => {
102853
102916
  const siblingNodes = parseMdChildren(sibling, safeMode);
102854
102917
  if (siblingNodes.length > 0) {
102855
102918
  parent.children.splice(index + 1, 0, ...siblingNodes);
102856
- stack.push(parent);
102919
+ siblingNodes.forEach(siblingNode => promoted.add(siblingNode));
102857
102920
  }
102858
102921
  };
102859
102922
  // Ends the position at `consumedLength` so the component doesn't claim trailing
@@ -102919,16 +102982,19 @@ const substituteNodeWithMdxNode = (parent, index, mdxNode) => {
102919
102982
  * The opening tag, content, and closing tag are all captured in one HTML node
102920
102983
  * (guaranteed by the mdx-component tokenizer).
102921
102984
  */
102922
- const mdxishMdxComponentBlocks = (opts = {}) => (tree, file) => {
102985
+ function promoteComponentBlocks(tree, safeMode, source) {
102923
102986
  const stack = [tree];
102924
- const safeMode = !!opts.safeMode;
102925
- const source = file?.value ? String(file.value) : null;
102926
102987
  const parseOpts = { preserveExpressionsAsText: safeMode };
102988
+ // Subtrees a nested parseMdChildren already promoted wholesale (spliced siblings):
102989
+ // re-descending them finds no html to promote, so skip them.
102990
+ const promoted = new WeakSet();
102927
102991
  const processChildNode = (parent, index) => {
102928
102992
  const node = parent.children[index];
102929
102993
  if (!node)
102930
102994
  return;
102931
- if ('children' in node && Array.isArray(node.children)) {
102995
+ // Descend into container nodes (lists, blockquotes, …) so their html children
102996
+ // are reached — unless the subtree was already promoted upstream.
102997
+ if ('children' in node && Array.isArray(node.children) && !promoted.has(node)) {
102932
102998
  stack.push(node);
102933
102999
  }
102934
103000
  // Only html nodes can be an unparsed MDX component.
@@ -102983,7 +103049,7 @@ const mdxishMdxComponentBlocks = (opts = {}) => (tree, file) => {
102983
103049
  substituteNodeWithMdxNode(parent, index, componentNode);
102984
103050
  const remainingContent = contentAfterTag.trim();
102985
103051
  if (remainingContent) {
102986
- parseSibling(stack, parent, index, remainingContent, safeMode);
103052
+ parseSibling(parent, index, remainingContent, safeMode, promoted);
102987
103053
  }
102988
103054
  return;
102989
103055
  }
@@ -103010,43 +103076,57 @@ const mdxishMdxComponentBlocks = (opts = {}) => (tree, file) => {
103010
103076
  return;
103011
103077
  // Lowercase tags are usually inline; unwrap a sole paragraph so their
103012
103078
  // phrasing content isn't spuriously block-wrapped.
103079
+ let unwrappedSoleParagraph = false;
103013
103080
  if (!isPascal && parsedChildren.length === 1 && parsedChildren[0].type === 'paragraph') {
103014
103081
  parsedChildren = parsedChildren[0].children;
103082
+ unwrappedSoleParagraph = true;
103083
+ }
103084
+ // Without trailing content the whole node position is correct. With it, end
103085
+ // precisely at the closing tag — preferring source offsets when available (the
103086
+ // node's value strips blockquote/list prefixes), else the consumed span.
103087
+ let endPosition = node.position;
103088
+ if (contentAfterClose) {
103089
+ endPosition = source
103090
+ ? positionEndingAtClosingTagInSource(node.position, closingTagStr, source)
103091
+ : positionEndingAtConsumed(node.position, value, leadingWhitespace + openingTagEnd + closingTagIndex + closingTagStr.length);
103015
103092
  }
103016
103093
  const componentNode = createComponentNode({
103017
103094
  tag,
103018
103095
  attributes,
103019
103096
  children: parsedChildren,
103020
103097
  startPosition: node.position,
103021
- // With trailing content, end precisely at the closing tag. Prefer source
103022
- // offsets when available (the node's value strips blockquote/list
103023
- // prefixes); otherwise fall back to the whole node position.
103024
- endPosition: contentAfterClose
103025
- ? source
103026
- ? positionEndingAtClosingTagInSource(node.position, closingTagStr, source)
103027
- : positionEndingAtConsumed(node.position, value, leadingWhitespace + openingTagEnd + closingTagIndex + closingTagStr.length)
103028
- : node.position,
103098
+ endPosition,
103029
103099
  });
103030
103100
  substituteNodeWithMdxNode(parent, index, componentNode);
103031
- // Re-queue whichever side may hold further components.
103032
- if (contentAfterClose) {
103033
- parseSibling(stack, parent, index, contentAfterClose, safeMode);
103034
- }
103035
- else if (componentNode.children.length > 0) {
103101
+ // The unwrap reparented the children out of their paragraph, so re-walk them
103102
+ // since the children HTML may contain promotable syntax (e.g. `{…}`-attr tags)
103103
+ if (unwrappedSoleParagraph) {
103036
103104
  stack.push(componentNode);
103037
103105
  }
103106
+ // Trailing content after the close becomes siblings; parseMdChildren has
103107
+ // already promoted any components nested inside both sides, so the promoted
103108
+ // subtree itself needs no re-queue.
103109
+ if (contentAfterClose) {
103110
+ parseSibling(parent, index, contentAfterClose, safeMode, promoted);
103111
+ }
103038
103112
  }
103039
103113
  };
103040
- // Depth-first so nodes keep their source order.
103114
+ // Depth-first so nodes keep their source order. Index-based (not forEach) and
103115
+ // re-reading length each step: parseSibling splices siblings in mid-iteration, and
103116
+ // those — plus the original children they shift down — must all stay eligible.
103041
103117
  while (stack.length) {
103042
103118
  const parent = stack.pop();
103043
103119
  if (parent?.children) {
103044
- parent.children.forEach((_child, index) => {
103120
+ for (let index = 0; index < parent.children.length; index += 1) {
103045
103121
  processChildNode(parent, index);
103046
- });
103122
+ }
103047
103123
  }
103048
103124
  }
103049
103125
  return tree;
103126
+ }
103127
+ const mdxishMdxComponentBlocks = (opts = {}) => (tree, file) => {
103128
+ const source = file?.value ? String(file.value) : null;
103129
+ return promoteComponentBlocks(tree, !!opts.safeMode, source);
103050
103130
  };
103051
103131
  /* harmony default export */ const mdx_blocks = (mdxishMdxComponentBlocks);
103052
103132