@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.node.js CHANGED
@@ -96525,6 +96525,15 @@ const HTML_TABLE_STRUCTURE_TAGS = new Set([
96525
96525
  'caption',
96526
96526
  'colgroup',
96527
96527
  ]);
96528
+ /**
96529
+ * Tags whose bodies a later mdxish transform keeps raw and never re-parses as
96530
+ * markdown. Both layers depend on this property, not on the tags being figures:
96531
+ * the transformer treats them as non-promotable, and the tokenizer must not claim
96532
+ * markdown islands inside them (a claimed island would never be re-parsed and would
96533
+ * leak as literal text). Currently just the figure tags, whose bodies are owned by
96534
+ * the figure reassembly transform (`mdxishJsxToMdast`).
96535
+ */
96536
+ const NON_REPARSED_BODY_TAGS = new Set(['figure', 'figcaption']);
96528
96537
  /**
96529
96538
  * The two HTML "foreign content" namespaces: SVG and MathML. Their descendants
96530
96539
  * (`<path>`, `<mrow>`, …) are namespaced XML, not HTML tags or components. A closed
@@ -121722,12 +121731,95 @@ function tokenizeMagicBlockText(effects, ok, nok) {
121722
121731
  */
121723
121732
 
121724
121733
 
121734
+ ;// ./lib/micromark/mdx-component/continuation-checks.ts
121735
+
121736
+
121737
+ /**
121738
+ * Partial constructs the `mdxComponent` tokenizer runs via `effects.check` to
121739
+ * decide whether the next line continues the block. They live here (not in
121740
+ * `syntax.ts`) because they hold none of `createTokenize`'s closure state — each
121741
+ * is a self-contained, single-line lookahead.
121742
+ */
121743
+ function continuation_checks_tokenizeNonLazyContinuationStart(effects, ok, nok) {
121744
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
121745
+ const self = this;
121746
+ return start;
121747
+ function start(code) {
121748
+ if (markdownLineEnding(code)) {
121749
+ effects.enter(types_types.lineEnding);
121750
+ effects.consume(code);
121751
+ effects.exit(types_types.lineEnding);
121752
+ return after;
121753
+ }
121754
+ return nok(code);
121755
+ }
121756
+ function after(code) {
121757
+ if (self.parser.lazy[self.now().line]) {
121758
+ return nok(code);
121759
+ }
121760
+ return ok(code);
121761
+ }
121762
+ }
121763
+ // A markup-only line opens with a tag (`<x`/`</x`) and ends (ignoring trailing
121764
+ // spaces) at a `>`. That distinguishes a structural continuation like
121765
+ // `<span>b</span></div>` from a paragraph like `<b>Note:</b> read *this*`.
121766
+ function tokenizeMarkupOnlyContinuation(effects, ok, nok) {
121767
+ let lastNonSpace = null;
121768
+ return start;
121769
+ function start(code) {
121770
+ // Caller guarantees we are at `<` at the (already de-indented) line start.
121771
+ effects.enter(types_types.data);
121772
+ effects.consume(code);
121773
+ return afterLessThan;
121774
+ }
121775
+ function afterLessThan(code) {
121776
+ if (code === codes.slash) {
121777
+ effects.consume(code);
121778
+ return afterSlash;
121779
+ }
121780
+ return afterSlash(code);
121781
+ }
121782
+ // The `<` (or `</`) must introduce a real tag, not a stray `<` in prose.
121783
+ function afterSlash(code) {
121784
+ if (asciiAlpha(code)) {
121785
+ lastNonSpace = code;
121786
+ effects.consume(code);
121787
+ return scanToLineEnd;
121788
+ }
121789
+ effects.exit(types_types.data);
121790
+ return nok(code);
121791
+ }
121792
+ function scanToLineEnd(code) {
121793
+ if (code === null || markdownLineEnding(code)) {
121794
+ effects.exit(types_types.data);
121795
+ return lastNonSpace === codes.greaterThan ? ok(code) : nok(code);
121796
+ }
121797
+ if (!markdownSpace(code))
121798
+ lastNonSpace = code;
121799
+ effects.consume(code);
121800
+ return scanToLineEnd;
121801
+ }
121802
+ }
121803
+ // A line ending whose next line isn't a lazy paragraph continuation. Checked so a
121804
+ // component body's blank/continuation lines aren't stolen by an interrupted paragraph.
121805
+ const continuation_checks_nonLazyContinuationStart = {
121806
+ tokenize: continuation_checks_tokenizeNonLazyContinuationStart,
121807
+ partial: true,
121808
+ };
121809
+ // Lookahead for `plainClaimLineStart`: is this line markup-only, or a paragraph
121810
+ // that merely starts with a tag? Run via `effects.check` so it never consumes.
121811
+ const markupOnlyContinuation = {
121812
+ tokenize: tokenizeMarkupOnlyContinuation,
121813
+ partial: true,
121814
+ };
121815
+
121725
121816
  ;// ./lib/micromark/mdx-component/syntax.ts
121726
121817
 
121727
121818
 
121728
121819
 
121729
121820
 
121730
121821
 
121822
+
121731
121823
  // Raw tags (type-1: pre/script/style/textarea) and block tags (type-6: div,
121732
121824
  // section, …) always start a block, so they stay flow even with trailing
121733
121825
  // content. Other lowercase tags (i, span, …) follow the type-7 rule and only
@@ -121737,16 +121829,12 @@ const htmlFlowTagNames = new Set([...htmlRawNames, ...htmlBlockNames]);
121737
121829
  // blank lines between nested JSX siblings don't fragment the block. Excludes table
121738
121830
  // tags (mdxishTables owns their blank lines) and voids (never close).
121739
121831
  const plainBlockClaimTagNames = new Set([...htmlBlockNames].filter(tag => !HTML_TABLE_STRUCTURE_TAGS.has(tag) && !HTML_VOID_ELEMENTS.has(tag)));
121740
- const mdx_component_syntax_nonLazyContinuationStart = {
121741
- tokenize: mdx_component_syntax_tokenizeNonLazyContinuationStart,
121742
- partial: true,
121743
- };
121744
- // Lookahead for `plainClaimLineStart`: is this line markup-only, or a paragraph
121745
- // that merely starts with a tag? Run via `effects.check` so it never consumes.
121746
- const markupOnlyContinuation = {
121747
- tokenize: tokenizeMarkupOnlyContinuation,
121748
- partial: true,
121749
- };
121832
+ // Both are 4 columns per CommonMark, but they mean different things: a tab advances
121833
+ // to the next multiple of TAB_STOP_WIDTH, and INDENTED_CODE_MIN_COLUMNS is the depth
121834
+ // at which a line would fragment into indented code. Named separately so the two
121835
+ // concepts don't read as one incidental literal.
121836
+ const TAB_STOP_WIDTH = 4;
121837
+ const INDENTED_CODE_MIN_COLUMNS = 4;
121750
121838
  function resolveToMdxComponent(events) {
121751
121839
  let index = events.length;
121752
121840
  while (index > 0) {
@@ -121805,6 +121893,18 @@ function createTokenize(mode) {
121805
121893
  // `plainClaimLineStart`: after a blank line it may only continue on a tag line.
121806
121894
  let isPlainBlockClaim = false;
121807
121895
  let pendingBlankLine = false;
121896
+ // Leading indent columns of the current plain-claim line, reset per line; ≥4 is
121897
+ // where CommonMark would fragment the island as indented code. Tabs advance to the
121898
+ // next 4-column stop — the same rule `expandIndentToColumns`
121899
+ // (processor/transform/mdxish/indentation.ts) applies, kept in sync by hand since
121900
+ // this side works on a `Code` stream, not a string. NB: do NOT swap this for
121901
+ // `self.now().column`; micromark bumps the point column by 1 per `horizontalTab`
121902
+ // code (the trailing `virtualSpace` codes don't move it), so it measures a tab as
121903
+ // 1 column, reviving the tab-under-measurement bug this math exists to avoid.
121904
+ let plainClaimIndentColumns = 0;
121905
+ // True once a non-blank line follows the opener: a deep island below it is nested
121906
+ // (cosmetic indent), not top-of-body indented code.
121907
+ let sawPlainBlockBodyContent = false;
121808
121908
  // Code span tracking
121809
121909
  let codeSpanOpenSize = 0;
121810
121910
  let codeSpanCloseSize = 0;
@@ -122104,7 +122204,7 @@ function createTokenize(mode) {
122104
122204
  }
122105
122205
  // Continuation for multi-line opening tags
122106
122206
  function openTagContinuationStart(code) {
122107
- return effects.check(mdx_component_syntax_nonLazyContinuationStart, openTagContinuationNonLazy, continuationAfter)(code);
122207
+ return effects.check(continuation_checks_nonLazyContinuationStart, openTagContinuationNonLazy, continuationAfter)(code);
122108
122208
  }
122109
122209
  function openTagContinuationNonLazy(code) {
122110
122210
  sawLineEnding = true;
@@ -122149,6 +122249,9 @@ function createTokenize(mode) {
122149
122249
  }
122150
122250
  if (code !== codes.space && code !== codes.horizontalTab) {
122151
122251
  openerLineHasContent = true;
122252
+ // Continuation content marks a later deep island as nested, not indented code.
122253
+ if (!onOpenerLine)
122254
+ sawPlainBlockBodyContent = true;
122152
122255
  }
122153
122256
  if (code === codes.backslash) {
122154
122257
  effects.consume(code);
@@ -122229,7 +122332,7 @@ function createTokenize(mode) {
122229
122332
  return inFencedCode;
122230
122333
  }
122231
122334
  function fencedCodeContinuationStart(code) {
122232
- return effects.check(mdx_component_syntax_nonLazyContinuationStart, fencedCodeContinuationNonLazy, continuationAfter)(code);
122335
+ return effects.check(continuation_checks_nonLazyContinuationStart, fencedCodeContinuationNonLazy, continuationAfter)(code);
122233
122336
  }
122234
122337
  function fencedCodeContinuationNonLazy(code) {
122235
122338
  sawLineEnding = true;
@@ -122437,7 +122540,7 @@ function createTokenize(mode) {
122437
122540
  }
122438
122541
  // ── Body continuation (line endings) ───────────────────────────────────
122439
122542
  function bodyContinuationStart(code) {
122440
- return effects.check(mdx_component_syntax_nonLazyContinuationStart, bodyContinuationNonLazy, continuationAfter)(code);
122543
+ return effects.check(continuation_checks_nonLazyContinuationStart, bodyContinuationNonLazy, continuationAfter)(code);
122441
122544
  }
122442
122545
  function bodyContinuationNonLazy(code) {
122443
122546
  sawLineEnding = true;
@@ -122463,8 +122566,10 @@ function createTokenize(mode) {
122463
122566
  return inBodyBraceString(code);
122464
122567
  return inBodyBraceExpr(code);
122465
122568
  }
122466
- if (isPlainBlockClaim)
122569
+ if (isPlainBlockClaim) {
122570
+ plainClaimIndentColumns = 0;
122467
122571
  return plainClaimLineStart(code);
122572
+ }
122468
122573
  return bodyLineStart(code);
122469
122574
  }
122470
122575
  // Dispatch a non-blank continuation line: fenced code at line start, else body.
@@ -122494,6 +122599,8 @@ function createTokenize(mode) {
122494
122599
  function plainClaimLineStart(code) {
122495
122600
  // Leading whitespace only → treat as a blank line, matching CommonMark.
122496
122601
  if (code === codes.space || code === codes.horizontalTab) {
122602
+ plainClaimIndentColumns +=
122603
+ code === codes.horizontalTab ? TAB_STOP_WIDTH - (plainClaimIndentColumns % TAB_STOP_WIDTH) : 1;
122497
122604
  effects.consume(code);
122498
122605
  return plainClaimLineStart;
122499
122606
  }
@@ -122502,10 +122609,18 @@ function createTokenize(mode) {
122502
122609
  effects.exit('mdxComponentData');
122503
122610
  return bodyContinuationStart(code);
122504
122611
  }
122505
- // Across a blank line the block only continues onto a markup-only line; a
122506
- // paragraph that merely starts with a tag must fall back so its markdown
122507
- // parses and rehype-raw re-nests it into the wrapper.
122508
122612
  if (pendingBlankLine) {
122613
+ // A 4+ col island nested under other tags is cosmetic nesting indent, not code:
122614
+ // keep claiming so promotion dedents + re-parses it as markdown (RM-17560).
122615
+ // Tags whose bodies stay raw are excluded — a claimed island there would never
122616
+ // be re-parsed and would leak as literal text.
122617
+ if (plainClaimIndentColumns >= INDENTED_CODE_MIN_COLUMNS &&
122618
+ sawPlainBlockBodyContent &&
122619
+ !NON_REPARSED_BODY_TAGS.has(tagName)) {
122620
+ return plainClaimContinue(code);
122621
+ }
122622
+ // Otherwise only a markup-only tag line continues; markdown/prose falls back to
122623
+ // CommonMark so it parses and rehype-raw re-nests it into the wrapper.
122509
122624
  if (code !== codes.lessThan)
122510
122625
  return nok(code);
122511
122626
  return effects.check(markupOnlyContinuation, plainClaimContinue, nok)(code);
@@ -122526,66 +122641,6 @@ function createTokenize(mode) {
122526
122641
  }
122527
122642
  };
122528
122643
  }
122529
- function mdx_component_syntax_tokenizeNonLazyContinuationStart(effects, ok, nok) {
122530
- // eslint-disable-next-line @typescript-eslint/no-this-alias
122531
- const self = this;
122532
- return start;
122533
- function start(code) {
122534
- if (markdownLineEnding(code)) {
122535
- effects.enter(types_types.lineEnding);
122536
- effects.consume(code);
122537
- effects.exit(types_types.lineEnding);
122538
- return after;
122539
- }
122540
- return nok(code);
122541
- }
122542
- function after(code) {
122543
- if (self.parser.lazy[self.now().line]) {
122544
- return nok(code);
122545
- }
122546
- return ok(code);
122547
- }
122548
- }
122549
- // A markup-only line opens with a tag (`<x`/`</x`) and ends (ignoring trailing
122550
- // spaces) at a `>`. That distinguishes a structural continuation like
122551
- // `<span>b</span></div>` from a paragraph like `<b>Note:</b> read *this*`.
122552
- function tokenizeMarkupOnlyContinuation(effects, ok, nok) {
122553
- let lastNonSpace = null;
122554
- return start;
122555
- function start(code) {
122556
- // Caller guarantees we are at `<` at the (already de-indented) line start.
122557
- effects.enter(types_types.data);
122558
- effects.consume(code);
122559
- return afterLessThan;
122560
- }
122561
- function afterLessThan(code) {
122562
- if (code === codes.slash) {
122563
- effects.consume(code);
122564
- return afterSlash;
122565
- }
122566
- return afterSlash(code);
122567
- }
122568
- // The `<` (or `</`) must introduce a real tag, not a stray `<` in prose.
122569
- function afterSlash(code) {
122570
- if (asciiAlpha(code)) {
122571
- lastNonSpace = code;
122572
- effects.consume(code);
122573
- return scanToLineEnd;
122574
- }
122575
- effects.exit(types_types.data);
122576
- return nok(code);
122577
- }
122578
- function scanToLineEnd(code) {
122579
- if (code === null || markdownLineEnding(code)) {
122580
- effects.exit(types_types.data);
122581
- return lastNonSpace === codes.greaterThan ? ok(code) : nok(code);
122582
- }
122583
- if (!markdownSpace(code))
122584
- lastNonSpace = code;
122585
- effects.consume(code);
122586
- return scanToLineEnd;
122587
- }
122588
- }
122589
122644
  /**
122590
122645
  * Micromark extension that tokenizes MDX-like components.
122591
122646
  *
@@ -122639,6 +122694,7 @@ function mdxComponent() {
122639
122694
 
122640
122695
 
122641
122696
 
122697
+
122642
122698
 
122643
122699
  const buildInlineMdProcessor = (safeMode) => {
122644
122700
  // `jsxTable` must be present so a `<Table>`/`<table>` nested in a component
@@ -122710,7 +122766,7 @@ const toMdxJsxTextElement = (name, attributes, children, position) => ({
122710
122766
  // Raw-body tags (pre/script/style/textarea) must stay byte-exact; table
122711
122767
  // structure (`table` + `tableTags`) is owned by `mdxishTables` and figures by
122712
122768
  // `mdxishJsxToMdast`, both of which run later on raw html nodes.
122713
- const NON_PROMOTABLE_PLAIN_TAGS = new Set([...htmlRawNames, ...tableTags, 'table', 'figure', 'figcaption']);
122769
+ const NON_PROMOTABLE_PLAIN_TAGS = new Set([...htmlRawNames, ...tableTags, 'table', ...NON_REPARSED_BODY_TAGS]);
122714
122770
  const NESTED_TABLE_RE = /<table[\s>]/i;
122715
122771
  const isMarkdownPromotableHtmlTag = (tag) => !NON_PROMOTABLE_PLAIN_TAGS.has(tag);
122716
122772
  // Expression nodes count as plain so `<div>{1+1}</div>` keeps its current
@@ -123069,15 +123125,22 @@ function safeDeindent(text) {
123069
123125
  */
123070
123126
  const parseMdChildren = (value, safeMode) => {
123071
123127
  const parsed = getInlineMdProcessor({ safeMode }).parse(terminateHtmlFlowBlocks(safeDeindent(value).trim()));
123128
+ // Promote nested wrappers bottom-up so an outer wrapper sees markdown buried in a
123129
+ // child claimed whole (e.g. `<li>` in `<ol>`) before its containsMarkdownConstruct check (RM-17560).
123130
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define -- mutually recursive; hoisted decl, safe at runtime
123131
+ promoteComponentBlocks(parsed, safeMode, null);
123072
123132
  return parsed.children || [];
123073
123133
  };
123074
- // Parses trailing content into sibling nodes and re-queues the parent so any
123075
- // components among them get processed.
123076
- const parseSibling = (stack, parent, index, sibling, safeMode) => {
123134
+ // Splices trailing content in as sibling nodes. parseMdChildren has already
123135
+ // promoted any components nested among them (bottom-up); the main loop's
123136
+ // index-based walk then reaches these spliced siblings and the original children
123137
+ // they shift down, so no parent re-queue is needed. Each spliced subtree is marked
123138
+ // `promoted` so the walk doesn't redundantly re-descend into it (its html is gone).
123139
+ const parseSibling = (parent, index, sibling, safeMode, promoted) => {
123077
123140
  const siblingNodes = parseMdChildren(sibling, safeMode);
123078
123141
  if (siblingNodes.length > 0) {
123079
123142
  parent.children.splice(index + 1, 0, ...siblingNodes);
123080
- stack.push(parent);
123143
+ siblingNodes.forEach(siblingNode => promoted.add(siblingNode));
123081
123144
  }
123082
123145
  };
123083
123146
  // Ends the position at `consumedLength` so the component doesn't claim trailing
@@ -123143,16 +123206,19 @@ const substituteNodeWithMdxNode = (parent, index, mdxNode) => {
123143
123206
  * The opening tag, content, and closing tag are all captured in one HTML node
123144
123207
  * (guaranteed by the mdx-component tokenizer).
123145
123208
  */
123146
- const mdxishMdxComponentBlocks = (opts = {}) => (tree, file) => {
123209
+ function promoteComponentBlocks(tree, safeMode, source) {
123147
123210
  const stack = [tree];
123148
- const safeMode = !!opts.safeMode;
123149
- const source = file?.value ? String(file.value) : null;
123150
123211
  const parseOpts = { preserveExpressionsAsText: safeMode };
123212
+ // Subtrees a nested parseMdChildren already promoted wholesale (spliced siblings):
123213
+ // re-descending them finds no html to promote, so skip them.
123214
+ const promoted = new WeakSet();
123151
123215
  const processChildNode = (parent, index) => {
123152
123216
  const node = parent.children[index];
123153
123217
  if (!node)
123154
123218
  return;
123155
- if ('children' in node && Array.isArray(node.children)) {
123219
+ // Descend into container nodes (lists, blockquotes, …) so their html children
123220
+ // are reached — unless the subtree was already promoted upstream.
123221
+ if ('children' in node && Array.isArray(node.children) && !promoted.has(node)) {
123156
123222
  stack.push(node);
123157
123223
  }
123158
123224
  // Only html nodes can be an unparsed MDX component.
@@ -123207,7 +123273,7 @@ const mdxishMdxComponentBlocks = (opts = {}) => (tree, file) => {
123207
123273
  substituteNodeWithMdxNode(parent, index, componentNode);
123208
123274
  const remainingContent = contentAfterTag.trim();
123209
123275
  if (remainingContent) {
123210
- parseSibling(stack, parent, index, remainingContent, safeMode);
123276
+ parseSibling(parent, index, remainingContent, safeMode, promoted);
123211
123277
  }
123212
123278
  return;
123213
123279
  }
@@ -123234,43 +123300,57 @@ const mdxishMdxComponentBlocks = (opts = {}) => (tree, file) => {
123234
123300
  return;
123235
123301
  // Lowercase tags are usually inline; unwrap a sole paragraph so their
123236
123302
  // phrasing content isn't spuriously block-wrapped.
123303
+ let unwrappedSoleParagraph = false;
123237
123304
  if (!isPascal && parsedChildren.length === 1 && parsedChildren[0].type === 'paragraph') {
123238
123305
  parsedChildren = parsedChildren[0].children;
123306
+ unwrappedSoleParagraph = true;
123307
+ }
123308
+ // Without trailing content the whole node position is correct. With it, end
123309
+ // precisely at the closing tag — preferring source offsets when available (the
123310
+ // node's value strips blockquote/list prefixes), else the consumed span.
123311
+ let endPosition = node.position;
123312
+ if (contentAfterClose) {
123313
+ endPosition = source
123314
+ ? positionEndingAtClosingTagInSource(node.position, closingTagStr, source)
123315
+ : positionEndingAtConsumed(node.position, value, leadingWhitespace + openingTagEnd + closingTagIndex + closingTagStr.length);
123239
123316
  }
123240
123317
  const componentNode = createComponentNode({
123241
123318
  tag,
123242
123319
  attributes,
123243
123320
  children: parsedChildren,
123244
123321
  startPosition: node.position,
123245
- // With trailing content, end precisely at the closing tag. Prefer source
123246
- // offsets when available (the node's value strips blockquote/list
123247
- // prefixes); otherwise fall back to the whole node position.
123248
- endPosition: contentAfterClose
123249
- ? source
123250
- ? positionEndingAtClosingTagInSource(node.position, closingTagStr, source)
123251
- : positionEndingAtConsumed(node.position, value, leadingWhitespace + openingTagEnd + closingTagIndex + closingTagStr.length)
123252
- : node.position,
123322
+ endPosition,
123253
123323
  });
123254
123324
  substituteNodeWithMdxNode(parent, index, componentNode);
123255
- // Re-queue whichever side may hold further components.
123256
- if (contentAfterClose) {
123257
- parseSibling(stack, parent, index, contentAfterClose, safeMode);
123258
- }
123259
- else if (componentNode.children.length > 0) {
123325
+ // The unwrap reparented the children out of their paragraph, so re-walk them
123326
+ // since the children HTML may contain promotable syntax (e.g. `{…}`-attr tags)
123327
+ if (unwrappedSoleParagraph) {
123260
123328
  stack.push(componentNode);
123261
123329
  }
123330
+ // Trailing content after the close becomes siblings; parseMdChildren has
123331
+ // already promoted any components nested inside both sides, so the promoted
123332
+ // subtree itself needs no re-queue.
123333
+ if (contentAfterClose) {
123334
+ parseSibling(parent, index, contentAfterClose, safeMode, promoted);
123335
+ }
123262
123336
  }
123263
123337
  };
123264
- // Depth-first so nodes keep their source order.
123338
+ // Depth-first so nodes keep their source order. Index-based (not forEach) and
123339
+ // re-reading length each step: parseSibling splices siblings in mid-iteration, and
123340
+ // those — plus the original children they shift down — must all stay eligible.
123265
123341
  while (stack.length) {
123266
123342
  const parent = stack.pop();
123267
123343
  if (parent?.children) {
123268
- parent.children.forEach((_child, index) => {
123344
+ for (let index = 0; index < parent.children.length; index += 1) {
123269
123345
  processChildNode(parent, index);
123270
- });
123346
+ }
123271
123347
  }
123272
123348
  }
123273
123349
  return tree;
123350
+ }
123351
+ const mdxishMdxComponentBlocks = (opts = {}) => (tree, file) => {
123352
+ const source = file?.value ? String(file.value) : null;
123353
+ return promoteComponentBlocks(tree, !!opts.safeMode, source);
123274
123354
  };
123275
123355
  /* harmony default export */ const mdx_blocks = (mdxishMdxComponentBlocks);
123276
123356