@readme/markdown 15.0.0 → 15.0.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
@@ -27250,72 +27250,319 @@ function push(list, items) {
27250
27250
  return items
27251
27251
  }
27252
27252
 
27253
+ ;// ./node_modules/micromark-util-subtokenize/lib/splice-buffer.js
27254
+ /**
27255
+ * Some of the internal operations of micromark do lots of editing
27256
+ * operations on very large arrays. This runs into problems with two
27257
+ * properties of most circa-2020 JavaScript interpreters:
27258
+ *
27259
+ * - Array-length modifications at the high end of an array (push/pop) are
27260
+ * expected to be common and are implemented in (amortized) time
27261
+ * proportional to the number of elements added or removed, whereas
27262
+ * other operations (shift/unshift and splice) are much less efficient.
27263
+ * - Function arguments are passed on the stack, so adding tens of thousands
27264
+ * of elements to an array with `arr.push(...newElements)` will frequently
27265
+ * cause stack overflows. (see <https://stackoverflow.com/questions/22123769/rangeerror-maximum-call-stack-size-exceeded-why>)
27266
+ *
27267
+ * SpliceBuffers are an implementation of gap buffers, which are a
27268
+ * generalization of the "queue made of two stacks" idea. The splice buffer
27269
+ * maintains a cursor, and moving the cursor has cost proportional to the
27270
+ * distance the cursor moves, but inserting, deleting, or splicing in
27271
+ * new information at the cursor is as efficient as the push/pop operation.
27272
+ * This allows for an efficient sequence of splices (or pushes, pops, shifts,
27273
+ * or unshifts) as long such edits happen at the same part of the array or
27274
+ * generally sweep through the array from the beginning to the end.
27275
+ *
27276
+ * The interface for splice buffers also supports large numbers of inputs by
27277
+ * passing a single array argument rather passing multiple arguments on the
27278
+ * function call stack.
27279
+ *
27280
+ * @template T
27281
+ * Item type.
27282
+ */
27283
+ class SpliceBuffer {
27284
+ /**
27285
+ * @param {ReadonlyArray<T> | null | undefined} [initial]
27286
+ * Initial items (optional).
27287
+ * @returns
27288
+ * Splice buffer.
27289
+ */
27290
+ constructor(initial) {
27291
+ /** @type {Array<T>} */
27292
+ this.left = initial ? [...initial] : [];
27293
+ /** @type {Array<T>} */
27294
+ this.right = [];
27295
+ }
27296
+
27297
+ /**
27298
+ * Array access;
27299
+ * does not move the cursor.
27300
+ *
27301
+ * @param {number} index
27302
+ * Index.
27303
+ * @return {T}
27304
+ * Item.
27305
+ */
27306
+ get(index) {
27307
+ if (index < 0 || index >= this.left.length + this.right.length) {
27308
+ throw new RangeError('Cannot access index `' + index + '` in a splice buffer of size `' + (this.left.length + this.right.length) + '`');
27309
+ }
27310
+ if (index < this.left.length) return this.left[index];
27311
+ return this.right[this.right.length - index + this.left.length - 1];
27312
+ }
27313
+
27314
+ /**
27315
+ * The length of the splice buffer, one greater than the largest index in the
27316
+ * array.
27317
+ */
27318
+ get length() {
27319
+ return this.left.length + this.right.length;
27320
+ }
27321
+
27322
+ /**
27323
+ * Remove and return `list[0]`;
27324
+ * moves the cursor to `0`.
27325
+ *
27326
+ * @returns {T | undefined}
27327
+ * Item, optional.
27328
+ */
27329
+ shift() {
27330
+ this.setCursor(0);
27331
+ return this.right.pop();
27332
+ }
27333
+
27334
+ /**
27335
+ * Slice the buffer to get an array;
27336
+ * does not move the cursor.
27337
+ *
27338
+ * @param {number} start
27339
+ * Start.
27340
+ * @param {number | null | undefined} [end]
27341
+ * End (optional).
27342
+ * @returns {Array<T>}
27343
+ * Array of items.
27344
+ */
27345
+ slice(start, end) {
27346
+ /** @type {number} */
27347
+ const stop = end === null || end === undefined ? Number.POSITIVE_INFINITY : end;
27348
+ if (stop < this.left.length) {
27349
+ return this.left.slice(start, stop);
27350
+ }
27351
+ if (start > this.left.length) {
27352
+ return this.right.slice(this.right.length - stop + this.left.length, this.right.length - start + this.left.length).reverse();
27353
+ }
27354
+ return this.left.slice(start).concat(this.right.slice(this.right.length - stop + this.left.length).reverse());
27355
+ }
27356
+
27357
+ /**
27358
+ * Mimics the behavior of Array.prototype.splice() except for the change of
27359
+ * interface necessary to avoid segfaults when patching in very large arrays.
27360
+ *
27361
+ * This operation moves cursor is moved to `start` and results in the cursor
27362
+ * placed after any inserted items.
27363
+ *
27364
+ * @param {number} start
27365
+ * Start;
27366
+ * zero-based index at which to start changing the array;
27367
+ * negative numbers count backwards from the end of the array and values
27368
+ * that are out-of bounds are clamped to the appropriate end of the array.
27369
+ * @param {number | null | undefined} [deleteCount=0]
27370
+ * Delete count (default: `0`);
27371
+ * maximum number of elements to delete, starting from start.
27372
+ * @param {Array<T> | null | undefined} [items=[]]
27373
+ * Items to include in place of the deleted items (default: `[]`).
27374
+ * @return {Array<T>}
27375
+ * Any removed items.
27376
+ */
27377
+ splice(start, deleteCount, items) {
27378
+ /** @type {number} */
27379
+ const count = deleteCount || 0;
27380
+ this.setCursor(Math.trunc(start));
27381
+ const removed = this.right.splice(this.right.length - count, Number.POSITIVE_INFINITY);
27382
+ if (items) chunkedPush(this.left, items);
27383
+ return removed.reverse();
27384
+ }
27385
+
27386
+ /**
27387
+ * Remove and return the highest-numbered item in the array, so
27388
+ * `list[list.length - 1]`;
27389
+ * Moves the cursor to `length`.
27390
+ *
27391
+ * @returns {T | undefined}
27392
+ * Item, optional.
27393
+ */
27394
+ pop() {
27395
+ this.setCursor(Number.POSITIVE_INFINITY);
27396
+ return this.left.pop();
27397
+ }
27398
+
27399
+ /**
27400
+ * Inserts a single item to the high-numbered side of the array;
27401
+ * moves the cursor to `length`.
27402
+ *
27403
+ * @param {T} item
27404
+ * Item.
27405
+ * @returns {undefined}
27406
+ * Nothing.
27407
+ */
27408
+ push(item) {
27409
+ this.setCursor(Number.POSITIVE_INFINITY);
27410
+ this.left.push(item);
27411
+ }
27412
+
27413
+ /**
27414
+ * Inserts many items to the high-numbered side of the array.
27415
+ * Moves the cursor to `length`.
27416
+ *
27417
+ * @param {Array<T>} items
27418
+ * Items.
27419
+ * @returns {undefined}
27420
+ * Nothing.
27421
+ */
27422
+ pushMany(items) {
27423
+ this.setCursor(Number.POSITIVE_INFINITY);
27424
+ chunkedPush(this.left, items);
27425
+ }
27426
+
27427
+ /**
27428
+ * Inserts a single item to the low-numbered side of the array;
27429
+ * Moves the cursor to `0`.
27430
+ *
27431
+ * @param {T} item
27432
+ * Item.
27433
+ * @returns {undefined}
27434
+ * Nothing.
27435
+ */
27436
+ unshift(item) {
27437
+ this.setCursor(0);
27438
+ this.right.push(item);
27439
+ }
27440
+
27441
+ /**
27442
+ * Inserts many items to the low-numbered side of the array;
27443
+ * moves the cursor to `0`.
27444
+ *
27445
+ * @param {Array<T>} items
27446
+ * Items.
27447
+ * @returns {undefined}
27448
+ * Nothing.
27449
+ */
27450
+ unshiftMany(items) {
27451
+ this.setCursor(0);
27452
+ chunkedPush(this.right, items.reverse());
27453
+ }
27454
+
27455
+ /**
27456
+ * Move the cursor to a specific position in the array. Requires
27457
+ * time proportional to the distance moved.
27458
+ *
27459
+ * If `n < 0`, the cursor will end up at the beginning.
27460
+ * If `n > length`, the cursor will end up at the end.
27461
+ *
27462
+ * @param {number} n
27463
+ * Position.
27464
+ * @return {undefined}
27465
+ * Nothing.
27466
+ */
27467
+ setCursor(n) {
27468
+ if (n === this.left.length || n > this.left.length && this.right.length === 0 || n < 0 && this.left.length === 0) return;
27469
+ if (n < this.left.length) {
27470
+ // Move cursor to the this.left
27471
+ const removed = this.left.splice(n, Number.POSITIVE_INFINITY);
27472
+ chunkedPush(this.right, removed.reverse());
27473
+ } else {
27474
+ // Move cursor to the this.right
27475
+ const removed = this.right.splice(this.left.length + this.right.length - n, Number.POSITIVE_INFINITY);
27476
+ chunkedPush(this.left, removed.reverse());
27477
+ }
27478
+ }
27479
+ }
27480
+
27481
+ /**
27482
+ * Avoid stack overflow by pushing items onto the stack in segments
27483
+ *
27484
+ * @template T
27485
+ * Item type.
27486
+ * @param {Array<T>} list
27487
+ * List to inject into.
27488
+ * @param {ReadonlyArray<T>} right
27489
+ * Items to inject.
27490
+ * @return {undefined}
27491
+ * Nothing.
27492
+ */
27493
+ function chunkedPush(list, right) {
27494
+ /** @type {number} */
27495
+ let chunkStart = 0;
27496
+ if (right.length < 10000) {
27497
+ list.push(...right);
27498
+ } else {
27499
+ while (chunkStart < right.length) {
27500
+ list.push(...right.slice(chunkStart, chunkStart + 10000));
27501
+ chunkStart += 10000;
27502
+ }
27503
+ }
27504
+ }
27253
27505
  ;// ./node_modules/micromark-util-subtokenize/index.js
27254
27506
  /**
27255
- * @typedef {import('micromark-util-types').Chunk} Chunk
27256
- * @typedef {import('micromark-util-types').Event} Event
27257
- * @typedef {import('micromark-util-types').Token} Token
27507
+ * @import {Chunk, Event, Token} from 'micromark-util-types'
27258
27508
  */
27259
27509
 
27260
27510
 
27511
+
27512
+
27513
+ // Hidden API exposed for testing.
27514
+
27515
+
27261
27516
  /**
27262
27517
  * Tokenize subcontent.
27263
27518
  *
27264
- * @param {Array<Event>} events
27519
+ * @param {Array<Event>} eventsArray
27265
27520
  * List of events.
27266
27521
  * @returns {boolean}
27267
27522
  * Whether subtokens were found.
27268
- */ // eslint-disable-next-line complexity
27269
- function subtokenize(events) {
27523
+ */
27524
+ // eslint-disable-next-line complexity
27525
+ function subtokenize(eventsArray) {
27270
27526
  /** @type {Record<string, number>} */
27271
- const jumps = {}
27272
- let index = -1
27527
+ const jumps = {};
27528
+ let index = -1;
27273
27529
  /** @type {Event} */
27274
- let event
27530
+ let event;
27275
27531
  /** @type {number | undefined} */
27276
- let lineIndex
27532
+ let lineIndex;
27277
27533
  /** @type {number} */
27278
- let otherIndex
27534
+ let otherIndex;
27279
27535
  /** @type {Event} */
27280
- let otherEvent
27536
+ let otherEvent;
27281
27537
  /** @type {Array<Event>} */
27282
- let parameters
27538
+ let parameters;
27283
27539
  /** @type {Array<Event>} */
27284
- let subevents
27540
+ let subevents;
27285
27541
  /** @type {boolean | undefined} */
27286
- let more
27542
+ let more;
27543
+ const events = new SpliceBuffer(eventsArray);
27287
27544
  while (++index < events.length) {
27288
27545
  while (index in jumps) {
27289
- index = jumps[index]
27546
+ index = jumps[index];
27290
27547
  }
27291
- event = events[index]
27548
+ event = events.get(index);
27292
27549
 
27293
27550
  // Add a hook for the GFM tasklist extension, which needs to know if text
27294
27551
  // is in the first content of a list item.
27295
- if (
27296
- index &&
27297
- event[1].type === 'chunkFlow' &&
27298
- events[index - 1][1].type === 'listItemPrefix'
27299
- ) {
27300
- subevents = event[1]._tokenizer.events
27301
- otherIndex = 0
27302
- if (
27303
- otherIndex < subevents.length &&
27304
- subevents[otherIndex][1].type === 'lineEndingBlank'
27305
- ) {
27306
- otherIndex += 2
27552
+ if (index && event[1].type === "chunkFlow" && events.get(index - 1)[1].type === "listItemPrefix") {
27553
+ subevents = event[1]._tokenizer.events;
27554
+ otherIndex = 0;
27555
+ if (otherIndex < subevents.length && subevents[otherIndex][1].type === "lineEndingBlank") {
27556
+ otherIndex += 2;
27307
27557
  }
27308
- if (
27309
- otherIndex < subevents.length &&
27310
- subevents[otherIndex][1].type === 'content'
27311
- ) {
27558
+ if (otherIndex < subevents.length && subevents[otherIndex][1].type === "content") {
27312
27559
  while (++otherIndex < subevents.length) {
27313
- if (subevents[otherIndex][1].type === 'content') {
27314
- break
27560
+ if (subevents[otherIndex][1].type === "content") {
27561
+ break;
27315
27562
  }
27316
- if (subevents[otherIndex][1].type === 'chunkText') {
27317
- subevents[otherIndex][1]._isInFirstContentOfListItem = true
27318
- otherIndex++
27563
+ if (subevents[otherIndex][1].type === "chunkText") {
27564
+ subevents[otherIndex][1]._isInFirstContentOfListItem = true;
27565
+ otherIndex++;
27319
27566
  }
27320
27567
  }
27321
27568
  }
@@ -27324,158 +27571,160 @@ function subtokenize(events) {
27324
27571
  // Enter.
27325
27572
  if (event[0] === 'enter') {
27326
27573
  if (event[1].contentType) {
27327
- Object.assign(jumps, subcontent(events, index))
27328
- index = jumps[index]
27329
- more = true
27574
+ Object.assign(jumps, subcontent(events, index));
27575
+ index = jumps[index];
27576
+ more = true;
27330
27577
  }
27331
27578
  }
27332
27579
  // Exit.
27333
27580
  else if (event[1]._container) {
27334
- otherIndex = index
27335
- lineIndex = undefined
27581
+ otherIndex = index;
27582
+ lineIndex = undefined;
27336
27583
  while (otherIndex--) {
27337
- otherEvent = events[otherIndex]
27338
- if (
27339
- otherEvent[1].type === 'lineEnding' ||
27340
- otherEvent[1].type === 'lineEndingBlank'
27341
- ) {
27584
+ otherEvent = events.get(otherIndex);
27585
+ if (otherEvent[1].type === "lineEnding" || otherEvent[1].type === "lineEndingBlank") {
27342
27586
  if (otherEvent[0] === 'enter') {
27343
27587
  if (lineIndex) {
27344
- events[lineIndex][1].type = 'lineEndingBlank'
27588
+ events.get(lineIndex)[1].type = "lineEndingBlank";
27345
27589
  }
27346
- otherEvent[1].type = 'lineEnding'
27347
- lineIndex = otherIndex
27590
+ otherEvent[1].type = "lineEnding";
27591
+ lineIndex = otherIndex;
27348
27592
  }
27593
+ } else if (otherEvent[1].type === "linePrefix") {
27594
+ // Move past.
27349
27595
  } else {
27350
- break
27596
+ break;
27351
27597
  }
27352
27598
  }
27353
27599
  if (lineIndex) {
27354
27600
  // Fix position.
27355
- event[1].end = Object.assign({}, events[lineIndex][1].start)
27601
+ event[1].end = {
27602
+ ...events.get(lineIndex)[1].start
27603
+ };
27356
27604
 
27357
27605
  // Switch container exit w/ line endings.
27358
- parameters = events.slice(lineIndex, index)
27359
- parameters.unshift(event)
27360
- splice(events, lineIndex, index - lineIndex + 1, parameters)
27606
+ parameters = events.slice(lineIndex, index);
27607
+ parameters.unshift(event);
27608
+ events.splice(lineIndex, index - lineIndex + 1, parameters);
27361
27609
  }
27362
27610
  }
27363
27611
  }
27364
- return !more
27612
+
27613
+ // The changes to the `events` buffer must be copied back into the eventsArray
27614
+ splice(eventsArray, 0, Number.POSITIVE_INFINITY, events.slice(0));
27615
+ return !more;
27365
27616
  }
27366
27617
 
27367
27618
  /**
27368
27619
  * Tokenize embedded tokens.
27369
27620
  *
27370
- * @param {Array<Event>} events
27621
+ * @param {SpliceBuffer<Event>} events
27622
+ * Events.
27371
27623
  * @param {number} eventIndex
27624
+ * Index.
27372
27625
  * @returns {Record<string, number>}
27626
+ * Gaps.
27373
27627
  */
27374
27628
  function subcontent(events, eventIndex) {
27375
- const token = events[eventIndex][1]
27376
- const context = events[eventIndex][2]
27377
- let startPosition = eventIndex - 1
27629
+ const token = events.get(eventIndex)[1];
27630
+ const context = events.get(eventIndex)[2];
27631
+ let startPosition = eventIndex - 1;
27378
27632
  /** @type {Array<number>} */
27379
- const startPositions = []
27380
- const tokenizer =
27381
- token._tokenizer || context.parser[token.contentType](token.start)
27382
- const childEvents = tokenizer.events
27633
+ const startPositions = [];
27634
+ const tokenizer = token._tokenizer || context.parser[token.contentType](token.start);
27635
+ const childEvents = tokenizer.events;
27383
27636
  /** @type {Array<[number, number]>} */
27384
- const jumps = []
27637
+ const jumps = [];
27385
27638
  /** @type {Record<string, number>} */
27386
- const gaps = {}
27639
+ const gaps = {};
27387
27640
  /** @type {Array<Chunk>} */
27388
- let stream
27641
+ let stream;
27389
27642
  /** @type {Token | undefined} */
27390
- let previous
27391
- let index = -1
27643
+ let previous;
27644
+ let index = -1;
27392
27645
  /** @type {Token | undefined} */
27393
- let current = token
27394
- let adjust = 0
27395
- let start = 0
27396
- const breaks = [start]
27646
+ let current = token;
27647
+ let adjust = 0;
27648
+ let start = 0;
27649
+ const breaks = [start];
27397
27650
 
27398
27651
  // Loop forward through the linked tokens to pass them in order to the
27399
27652
  // subtokenizer.
27400
27653
  while (current) {
27401
27654
  // Find the position of the event for this token.
27402
- while (events[++startPosition][1] !== current) {
27655
+ while (events.get(++startPosition)[1] !== current) {
27403
27656
  // Empty.
27404
27657
  }
27405
- startPositions.push(startPosition)
27658
+ startPositions.push(startPosition);
27406
27659
  if (!current._tokenizer) {
27407
- stream = context.sliceStream(current)
27660
+ stream = context.sliceStream(current);
27408
27661
  if (!current.next) {
27409
- stream.push(null)
27662
+ stream.push(null);
27410
27663
  }
27411
27664
  if (previous) {
27412
- tokenizer.defineSkip(current.start)
27665
+ tokenizer.defineSkip(current.start);
27413
27666
  }
27414
27667
  if (current._isInFirstContentOfListItem) {
27415
- tokenizer._gfmTasklistFirstContentOfListItem = true
27668
+ tokenizer._gfmTasklistFirstContentOfListItem = true;
27416
27669
  }
27417
- tokenizer.write(stream)
27670
+ tokenizer.write(stream);
27418
27671
  if (current._isInFirstContentOfListItem) {
27419
- tokenizer._gfmTasklistFirstContentOfListItem = undefined
27672
+ tokenizer._gfmTasklistFirstContentOfListItem = undefined;
27420
27673
  }
27421
27674
  }
27422
27675
 
27423
27676
  // Unravel the next token.
27424
- previous = current
27425
- current = current.next
27677
+ previous = current;
27678
+ current = current.next;
27426
27679
  }
27427
27680
 
27428
27681
  // Now, loop back through all events (and linked tokens), to figure out which
27429
27682
  // parts belong where.
27430
- current = token
27683
+ current = token;
27431
27684
  while (++index < childEvents.length) {
27432
27685
  if (
27433
- // Find a void token that includes a break.
27434
- childEvents[index][0] === 'exit' &&
27435
- childEvents[index - 1][0] === 'enter' &&
27436
- childEvents[index][1].type === childEvents[index - 1][1].type &&
27437
- childEvents[index][1].start.line !== childEvents[index][1].end.line
27438
- ) {
27439
- start = index + 1
27440
- breaks.push(start)
27686
+ // Find a void token that includes a break.
27687
+ childEvents[index][0] === 'exit' && childEvents[index - 1][0] === 'enter' && childEvents[index][1].type === childEvents[index - 1][1].type && childEvents[index][1].start.line !== childEvents[index][1].end.line) {
27688
+ start = index + 1;
27689
+ breaks.push(start);
27441
27690
  // Help GC.
27442
- current._tokenizer = undefined
27443
- current.previous = undefined
27444
- current = current.next
27691
+ current._tokenizer = undefined;
27692
+ current.previous = undefined;
27693
+ current = current.next;
27445
27694
  }
27446
27695
  }
27447
27696
 
27448
27697
  // Help GC.
27449
- tokenizer.events = []
27698
+ tokenizer.events = [];
27450
27699
 
27451
27700
  // If there’s one more token (which is the cases for lines that end in an
27452
27701
  // EOF), that’s perfect: the last point we found starts it.
27453
27702
  // If there isn’t then make sure any remaining content is added to it.
27454
27703
  if (current) {
27455
27704
  // Help GC.
27456
- current._tokenizer = undefined
27457
- current.previous = undefined
27705
+ current._tokenizer = undefined;
27706
+ current.previous = undefined;
27458
27707
  } else {
27459
- breaks.pop()
27708
+ breaks.pop();
27460
27709
  }
27461
27710
 
27462
27711
  // Now splice the events from the subtokenizer into the current events,
27463
27712
  // moving back to front so that splice indices aren’t affected.
27464
- index = breaks.length
27713
+ index = breaks.length;
27465
27714
  while (index--) {
27466
- const slice = childEvents.slice(breaks[index], breaks[index + 1])
27467
- const start = startPositions.pop()
27468
- jumps.unshift([start, start + slice.length - 1])
27469
- splice(events, start, 2, slice)
27715
+ const slice = childEvents.slice(breaks[index], breaks[index + 1]);
27716
+ const start = startPositions.pop();
27717
+ jumps.push([start, start + slice.length - 1]);
27718
+ events.splice(start, 2, slice);
27470
27719
  }
27471
- index = -1
27720
+ jumps.reverse();
27721
+ index = -1;
27472
27722
  while (++index < jumps.length) {
27473
- gaps[adjust + jumps[index][0]] = adjust + jumps[index][1]
27474
- adjust += jumps[index][1] - jumps[index][0] - 1
27723
+ gaps[adjust + jumps[index][0]] = adjust + jumps[index][1];
27724
+ adjust += jumps[index][1] - jumps[index][0] - 1;
27475
27725
  }
27476
- return gaps
27726
+ return gaps;
27477
27727
  }
27478
-
27479
27728
  ;// ./node_modules/micromark/lib/postprocess.js
27480
27729
  /**
27481
27730
  * @typedef {import('micromark-util-types').Event} Event
@@ -113491,7 +113740,9 @@ class MdxSyntaxError extends SyntaxError {
113491
113740
  * as `\r<br>`. Treating both characters as hard breaks doubles the spacing.
113492
113741
  */
113493
113742
  const hardBreaks = () => tree => {
113494
- findAndReplace(tree, [/\r?\n/g, () => ({ type: 'break' })]);
113743
+ // Skip `html-block`: its opaque payload is rendered verbatim, so turning its newlines
113744
+ // into `break` nodes is unnecessary and costly on large blocks.
113745
+ findAndReplace(tree, [/\r?\n/g, () => ({ type: 'break' })], { ignore: ['html-block'] });
113495
113746
  };
113496
113747
  /* harmony default export */ const hard_breaks = (hardBreaks);
113497
113748
 
@@ -123960,6 +124211,10 @@ const NESTED_ATTR_EXPRESSION_RE = /[\w-]+\s*=\s*\{/;
123960
124211
  // Name shape mirrors `componentTagPattern`; the lookbehind skips the inner tag
123961
124212
  // of a legacy `<<VARIABLE>>`.
123962
124213
  const NESTED_COMPONENT_TAG_RE = /(?<!<)<([A-Z][A-Za-z0-9_]*)[\s/>]/g;
124214
+ // Whole blank lines at a component body's edges. `\n` sits inside each group so a
124215
+ // match can only ever span complete lines, never part of a content line.
124216
+ const LEADING_BLANK_LINES_RE = /^(?:[ \t]*\n)+/;
124217
+ const TRAILING_BLANK_LINES_RE = /(?:\n[ \t]*)+$/;
123963
124218
  // Excludes tags with dedicated transformers (`Table`, `HTMLBlock`, inline
123964
124219
  // components), which expect their wrapper to stay raw.
123965
124220
  const hasNestedGenericComponentTag = (content) => [...content.matchAll(NESTED_COMPONENT_TAG_RE)].some(match => !GENERIC_MDX_COMPONENT_EXCLUDED_TAGS.has(match[1]));
@@ -123993,13 +124248,21 @@ function safeDeindent(text) {
123993
124248
  })
123994
124249
  .join('\n');
123995
124250
  }
124251
+ /**
124252
+ * Drop the blank lines at a component body's edges, keeping the first content line's
124253
+ * indent: `.trim()` stripped that line alone, so a uniformly indented body reparsed
124254
+ * lopsided and every list item after the first nested. The trailing pattern
124255
+ * takes the last content line's newline but leaves its spaces, which are code content
124256
+ * when a fence runs into the end tag.
124257
+ */
124258
+ const trimBlankEdges = (text) => text.replace(LEADING_BLANK_LINES_RE, '').replace(TRAILING_BLANK_LINES_RE, '');
123996
124259
  /**
123997
124260
  * Parse component-body markdown into mdast children. Dedenting shifts columns and
123998
124261
  * stales the top-level `terminateHtmlFlowBlocks` decisions, so that one preprocessor
123999
124262
  * re-runs here; other column-anchored fixups (compact headings, tables) do not.
124000
124263
  */
124001
124264
  const parseMdChildren = (value, safeMode) => {
124002
- const reparseSource = terminateHtmlFlowBlocks(safeDeindent(value).trim());
124265
+ const reparseSource = terminateHtmlFlowBlocks(trimBlankEdges(safeDeindent(value)));
124003
124266
  const parsed = getInlineMdProcessor({ safeMode }).parse(reparseSource);
124004
124267
  // Promote nested wrappers bottom-up so an outer wrapper sees markdown buried in a
124005
124268
  // child claimed whole (e.g. `<li>` in `<ol>`) before its containsMarkdownConstruct check (RM-17560).
@@ -124164,7 +124427,8 @@ function promoteComponentBlocks(tree, safeMode, source) {
124164
124427
  // Case 2: Self-contained block (closing tag in content)
124165
124428
  const closingTagIndex = isPlainLowercaseHtml ? plainClosingTagIndex : contentAfterTag.lastIndexOf(closingTagStr);
124166
124429
  if (closingTagIndex >= 0) {
124167
- // Untrimmed so parseMdChildren can dedent before trimming.
124430
+ // Left as authored: parseMdChildren needs the original columns to dedent by, and
124431
+ // it clears the blank edges itself.
124168
124432
  const componentInnerContent = contentAfterTag.substring(0, closingTagIndex);
124169
124433
  const contentAfterClose = contentAfterTag.substring(closingTagIndex + closingTagStr.length).trim();
124170
124434
  let parsedChildren = [];