@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.
@@ -20922,72 +20922,319 @@ function push(list, items) {
20922
20922
  return items
20923
20923
  }
20924
20924
 
20925
+ ;// ./node_modules/micromark-util-subtokenize/lib/splice-buffer.js
20926
+ /**
20927
+ * Some of the internal operations of micromark do lots of editing
20928
+ * operations on very large arrays. This runs into problems with two
20929
+ * properties of most circa-2020 JavaScript interpreters:
20930
+ *
20931
+ * - Array-length modifications at the high end of an array (push/pop) are
20932
+ * expected to be common and are implemented in (amortized) time
20933
+ * proportional to the number of elements added or removed, whereas
20934
+ * other operations (shift/unshift and splice) are much less efficient.
20935
+ * - Function arguments are passed on the stack, so adding tens of thousands
20936
+ * of elements to an array with `arr.push(...newElements)` will frequently
20937
+ * cause stack overflows. (see <https://stackoverflow.com/questions/22123769/rangeerror-maximum-call-stack-size-exceeded-why>)
20938
+ *
20939
+ * SpliceBuffers are an implementation of gap buffers, which are a
20940
+ * generalization of the "queue made of two stacks" idea. The splice buffer
20941
+ * maintains a cursor, and moving the cursor has cost proportional to the
20942
+ * distance the cursor moves, but inserting, deleting, or splicing in
20943
+ * new information at the cursor is as efficient as the push/pop operation.
20944
+ * This allows for an efficient sequence of splices (or pushes, pops, shifts,
20945
+ * or unshifts) as long such edits happen at the same part of the array or
20946
+ * generally sweep through the array from the beginning to the end.
20947
+ *
20948
+ * The interface for splice buffers also supports large numbers of inputs by
20949
+ * passing a single array argument rather passing multiple arguments on the
20950
+ * function call stack.
20951
+ *
20952
+ * @template T
20953
+ * Item type.
20954
+ */
20955
+ class SpliceBuffer {
20956
+ /**
20957
+ * @param {ReadonlyArray<T> | null | undefined} [initial]
20958
+ * Initial items (optional).
20959
+ * @returns
20960
+ * Splice buffer.
20961
+ */
20962
+ constructor(initial) {
20963
+ /** @type {Array<T>} */
20964
+ this.left = initial ? [...initial] : [];
20965
+ /** @type {Array<T>} */
20966
+ this.right = [];
20967
+ }
20968
+
20969
+ /**
20970
+ * Array access;
20971
+ * does not move the cursor.
20972
+ *
20973
+ * @param {number} index
20974
+ * Index.
20975
+ * @return {T}
20976
+ * Item.
20977
+ */
20978
+ get(index) {
20979
+ if (index < 0 || index >= this.left.length + this.right.length) {
20980
+ throw new RangeError('Cannot access index `' + index + '` in a splice buffer of size `' + (this.left.length + this.right.length) + '`');
20981
+ }
20982
+ if (index < this.left.length) return this.left[index];
20983
+ return this.right[this.right.length - index + this.left.length - 1];
20984
+ }
20985
+
20986
+ /**
20987
+ * The length of the splice buffer, one greater than the largest index in the
20988
+ * array.
20989
+ */
20990
+ get length() {
20991
+ return this.left.length + this.right.length;
20992
+ }
20993
+
20994
+ /**
20995
+ * Remove and return `list[0]`;
20996
+ * moves the cursor to `0`.
20997
+ *
20998
+ * @returns {T | undefined}
20999
+ * Item, optional.
21000
+ */
21001
+ shift() {
21002
+ this.setCursor(0);
21003
+ return this.right.pop();
21004
+ }
21005
+
21006
+ /**
21007
+ * Slice the buffer to get an array;
21008
+ * does not move the cursor.
21009
+ *
21010
+ * @param {number} start
21011
+ * Start.
21012
+ * @param {number | null | undefined} [end]
21013
+ * End (optional).
21014
+ * @returns {Array<T>}
21015
+ * Array of items.
21016
+ */
21017
+ slice(start, end) {
21018
+ /** @type {number} */
21019
+ const stop = end === null || end === undefined ? Number.POSITIVE_INFINITY : end;
21020
+ if (stop < this.left.length) {
21021
+ return this.left.slice(start, stop);
21022
+ }
21023
+ if (start > this.left.length) {
21024
+ return this.right.slice(this.right.length - stop + this.left.length, this.right.length - start + this.left.length).reverse();
21025
+ }
21026
+ return this.left.slice(start).concat(this.right.slice(this.right.length - stop + this.left.length).reverse());
21027
+ }
21028
+
21029
+ /**
21030
+ * Mimics the behavior of Array.prototype.splice() except for the change of
21031
+ * interface necessary to avoid segfaults when patching in very large arrays.
21032
+ *
21033
+ * This operation moves cursor is moved to `start` and results in the cursor
21034
+ * placed after any inserted items.
21035
+ *
21036
+ * @param {number} start
21037
+ * Start;
21038
+ * zero-based index at which to start changing the array;
21039
+ * negative numbers count backwards from the end of the array and values
21040
+ * that are out-of bounds are clamped to the appropriate end of the array.
21041
+ * @param {number | null | undefined} [deleteCount=0]
21042
+ * Delete count (default: `0`);
21043
+ * maximum number of elements to delete, starting from start.
21044
+ * @param {Array<T> | null | undefined} [items=[]]
21045
+ * Items to include in place of the deleted items (default: `[]`).
21046
+ * @return {Array<T>}
21047
+ * Any removed items.
21048
+ */
21049
+ splice(start, deleteCount, items) {
21050
+ /** @type {number} */
21051
+ const count = deleteCount || 0;
21052
+ this.setCursor(Math.trunc(start));
21053
+ const removed = this.right.splice(this.right.length - count, Number.POSITIVE_INFINITY);
21054
+ if (items) chunkedPush(this.left, items);
21055
+ return removed.reverse();
21056
+ }
21057
+
21058
+ /**
21059
+ * Remove and return the highest-numbered item in the array, so
21060
+ * `list[list.length - 1]`;
21061
+ * Moves the cursor to `length`.
21062
+ *
21063
+ * @returns {T | undefined}
21064
+ * Item, optional.
21065
+ */
21066
+ pop() {
21067
+ this.setCursor(Number.POSITIVE_INFINITY);
21068
+ return this.left.pop();
21069
+ }
21070
+
21071
+ /**
21072
+ * Inserts a single item to the high-numbered side of the array;
21073
+ * moves the cursor to `length`.
21074
+ *
21075
+ * @param {T} item
21076
+ * Item.
21077
+ * @returns {undefined}
21078
+ * Nothing.
21079
+ */
21080
+ push(item) {
21081
+ this.setCursor(Number.POSITIVE_INFINITY);
21082
+ this.left.push(item);
21083
+ }
21084
+
21085
+ /**
21086
+ * Inserts many items to the high-numbered side of the array.
21087
+ * Moves the cursor to `length`.
21088
+ *
21089
+ * @param {Array<T>} items
21090
+ * Items.
21091
+ * @returns {undefined}
21092
+ * Nothing.
21093
+ */
21094
+ pushMany(items) {
21095
+ this.setCursor(Number.POSITIVE_INFINITY);
21096
+ chunkedPush(this.left, items);
21097
+ }
21098
+
21099
+ /**
21100
+ * Inserts a single item to the low-numbered side of the array;
21101
+ * Moves the cursor to `0`.
21102
+ *
21103
+ * @param {T} item
21104
+ * Item.
21105
+ * @returns {undefined}
21106
+ * Nothing.
21107
+ */
21108
+ unshift(item) {
21109
+ this.setCursor(0);
21110
+ this.right.push(item);
21111
+ }
21112
+
21113
+ /**
21114
+ * Inserts many items to the low-numbered side of the array;
21115
+ * moves the cursor to `0`.
21116
+ *
21117
+ * @param {Array<T>} items
21118
+ * Items.
21119
+ * @returns {undefined}
21120
+ * Nothing.
21121
+ */
21122
+ unshiftMany(items) {
21123
+ this.setCursor(0);
21124
+ chunkedPush(this.right, items.reverse());
21125
+ }
21126
+
21127
+ /**
21128
+ * Move the cursor to a specific position in the array. Requires
21129
+ * time proportional to the distance moved.
21130
+ *
21131
+ * If `n < 0`, the cursor will end up at the beginning.
21132
+ * If `n > length`, the cursor will end up at the end.
21133
+ *
21134
+ * @param {number} n
21135
+ * Position.
21136
+ * @return {undefined}
21137
+ * Nothing.
21138
+ */
21139
+ setCursor(n) {
21140
+ if (n === this.left.length || n > this.left.length && this.right.length === 0 || n < 0 && this.left.length === 0) return;
21141
+ if (n < this.left.length) {
21142
+ // Move cursor to the this.left
21143
+ const removed = this.left.splice(n, Number.POSITIVE_INFINITY);
21144
+ chunkedPush(this.right, removed.reverse());
21145
+ } else {
21146
+ // Move cursor to the this.right
21147
+ const removed = this.right.splice(this.left.length + this.right.length - n, Number.POSITIVE_INFINITY);
21148
+ chunkedPush(this.left, removed.reverse());
21149
+ }
21150
+ }
21151
+ }
21152
+
21153
+ /**
21154
+ * Avoid stack overflow by pushing items onto the stack in segments
21155
+ *
21156
+ * @template T
21157
+ * Item type.
21158
+ * @param {Array<T>} list
21159
+ * List to inject into.
21160
+ * @param {ReadonlyArray<T>} right
21161
+ * Items to inject.
21162
+ * @return {undefined}
21163
+ * Nothing.
21164
+ */
21165
+ function chunkedPush(list, right) {
21166
+ /** @type {number} */
21167
+ let chunkStart = 0;
21168
+ if (right.length < 10000) {
21169
+ list.push(...right);
21170
+ } else {
21171
+ while (chunkStart < right.length) {
21172
+ list.push(...right.slice(chunkStart, chunkStart + 10000));
21173
+ chunkStart += 10000;
21174
+ }
21175
+ }
21176
+ }
20925
21177
  ;// ./node_modules/micromark-util-subtokenize/index.js
20926
21178
  /**
20927
- * @typedef {import('micromark-util-types').Chunk} Chunk
20928
- * @typedef {import('micromark-util-types').Event} Event
20929
- * @typedef {import('micromark-util-types').Token} Token
21179
+ * @import {Chunk, Event, Token} from 'micromark-util-types'
20930
21180
  */
20931
21181
 
20932
21182
 
21183
+
21184
+
21185
+ // Hidden API exposed for testing.
21186
+
21187
+
20933
21188
  /**
20934
21189
  * Tokenize subcontent.
20935
21190
  *
20936
- * @param {Array<Event>} events
21191
+ * @param {Array<Event>} eventsArray
20937
21192
  * List of events.
20938
21193
  * @returns {boolean}
20939
21194
  * Whether subtokens were found.
20940
- */ // eslint-disable-next-line complexity
20941
- function subtokenize(events) {
21195
+ */
21196
+ // eslint-disable-next-line complexity
21197
+ function subtokenize(eventsArray) {
20942
21198
  /** @type {Record<string, number>} */
20943
- const jumps = {}
20944
- let index = -1
21199
+ const jumps = {};
21200
+ let index = -1;
20945
21201
  /** @type {Event} */
20946
- let event
21202
+ let event;
20947
21203
  /** @type {number | undefined} */
20948
- let lineIndex
21204
+ let lineIndex;
20949
21205
  /** @type {number} */
20950
- let otherIndex
21206
+ let otherIndex;
20951
21207
  /** @type {Event} */
20952
- let otherEvent
21208
+ let otherEvent;
20953
21209
  /** @type {Array<Event>} */
20954
- let parameters
21210
+ let parameters;
20955
21211
  /** @type {Array<Event>} */
20956
- let subevents
21212
+ let subevents;
20957
21213
  /** @type {boolean | undefined} */
20958
- let more
21214
+ let more;
21215
+ const events = new SpliceBuffer(eventsArray);
20959
21216
  while (++index < events.length) {
20960
21217
  while (index in jumps) {
20961
- index = jumps[index]
21218
+ index = jumps[index];
20962
21219
  }
20963
- event = events[index]
21220
+ event = events.get(index);
20964
21221
 
20965
21222
  // Add a hook for the GFM tasklist extension, which needs to know if text
20966
21223
  // is in the first content of a list item.
20967
- if (
20968
- index &&
20969
- event[1].type === 'chunkFlow' &&
20970
- events[index - 1][1].type === 'listItemPrefix'
20971
- ) {
20972
- subevents = event[1]._tokenizer.events
20973
- otherIndex = 0
20974
- if (
20975
- otherIndex < subevents.length &&
20976
- subevents[otherIndex][1].type === 'lineEndingBlank'
20977
- ) {
20978
- otherIndex += 2
21224
+ if (index && event[1].type === "chunkFlow" && events.get(index - 1)[1].type === "listItemPrefix") {
21225
+ subevents = event[1]._tokenizer.events;
21226
+ otherIndex = 0;
21227
+ if (otherIndex < subevents.length && subevents[otherIndex][1].type === "lineEndingBlank") {
21228
+ otherIndex += 2;
20979
21229
  }
20980
- if (
20981
- otherIndex < subevents.length &&
20982
- subevents[otherIndex][1].type === 'content'
20983
- ) {
21230
+ if (otherIndex < subevents.length && subevents[otherIndex][1].type === "content") {
20984
21231
  while (++otherIndex < subevents.length) {
20985
- if (subevents[otherIndex][1].type === 'content') {
20986
- break
21232
+ if (subevents[otherIndex][1].type === "content") {
21233
+ break;
20987
21234
  }
20988
- if (subevents[otherIndex][1].type === 'chunkText') {
20989
- subevents[otherIndex][1]._isInFirstContentOfListItem = true
20990
- otherIndex++
21235
+ if (subevents[otherIndex][1].type === "chunkText") {
21236
+ subevents[otherIndex][1]._isInFirstContentOfListItem = true;
21237
+ otherIndex++;
20991
21238
  }
20992
21239
  }
20993
21240
  }
@@ -20996,158 +21243,160 @@ function subtokenize(events) {
20996
21243
  // Enter.
20997
21244
  if (event[0] === 'enter') {
20998
21245
  if (event[1].contentType) {
20999
- Object.assign(jumps, subcontent(events, index))
21000
- index = jumps[index]
21001
- more = true
21246
+ Object.assign(jumps, subcontent(events, index));
21247
+ index = jumps[index];
21248
+ more = true;
21002
21249
  }
21003
21250
  }
21004
21251
  // Exit.
21005
21252
  else if (event[1]._container) {
21006
- otherIndex = index
21007
- lineIndex = undefined
21253
+ otherIndex = index;
21254
+ lineIndex = undefined;
21008
21255
  while (otherIndex--) {
21009
- otherEvent = events[otherIndex]
21010
- if (
21011
- otherEvent[1].type === 'lineEnding' ||
21012
- otherEvent[1].type === 'lineEndingBlank'
21013
- ) {
21256
+ otherEvent = events.get(otherIndex);
21257
+ if (otherEvent[1].type === "lineEnding" || otherEvent[1].type === "lineEndingBlank") {
21014
21258
  if (otherEvent[0] === 'enter') {
21015
21259
  if (lineIndex) {
21016
- events[lineIndex][1].type = 'lineEndingBlank'
21260
+ events.get(lineIndex)[1].type = "lineEndingBlank";
21017
21261
  }
21018
- otherEvent[1].type = 'lineEnding'
21019
- lineIndex = otherIndex
21262
+ otherEvent[1].type = "lineEnding";
21263
+ lineIndex = otherIndex;
21020
21264
  }
21265
+ } else if (otherEvent[1].type === "linePrefix") {
21266
+ // Move past.
21021
21267
  } else {
21022
- break
21268
+ break;
21023
21269
  }
21024
21270
  }
21025
21271
  if (lineIndex) {
21026
21272
  // Fix position.
21027
- event[1].end = Object.assign({}, events[lineIndex][1].start)
21273
+ event[1].end = {
21274
+ ...events.get(lineIndex)[1].start
21275
+ };
21028
21276
 
21029
21277
  // Switch container exit w/ line endings.
21030
- parameters = events.slice(lineIndex, index)
21031
- parameters.unshift(event)
21032
- splice(events, lineIndex, index - lineIndex + 1, parameters)
21278
+ parameters = events.slice(lineIndex, index);
21279
+ parameters.unshift(event);
21280
+ events.splice(lineIndex, index - lineIndex + 1, parameters);
21033
21281
  }
21034
21282
  }
21035
21283
  }
21036
- return !more
21284
+
21285
+ // The changes to the `events` buffer must be copied back into the eventsArray
21286
+ splice(eventsArray, 0, Number.POSITIVE_INFINITY, events.slice(0));
21287
+ return !more;
21037
21288
  }
21038
21289
 
21039
21290
  /**
21040
21291
  * Tokenize embedded tokens.
21041
21292
  *
21042
- * @param {Array<Event>} events
21293
+ * @param {SpliceBuffer<Event>} events
21294
+ * Events.
21043
21295
  * @param {number} eventIndex
21296
+ * Index.
21044
21297
  * @returns {Record<string, number>}
21298
+ * Gaps.
21045
21299
  */
21046
21300
  function subcontent(events, eventIndex) {
21047
- const token = events[eventIndex][1]
21048
- const context = events[eventIndex][2]
21049
- let startPosition = eventIndex - 1
21301
+ const token = events.get(eventIndex)[1];
21302
+ const context = events.get(eventIndex)[2];
21303
+ let startPosition = eventIndex - 1;
21050
21304
  /** @type {Array<number>} */
21051
- const startPositions = []
21052
- const tokenizer =
21053
- token._tokenizer || context.parser[token.contentType](token.start)
21054
- const childEvents = tokenizer.events
21305
+ const startPositions = [];
21306
+ const tokenizer = token._tokenizer || context.parser[token.contentType](token.start);
21307
+ const childEvents = tokenizer.events;
21055
21308
  /** @type {Array<[number, number]>} */
21056
- const jumps = []
21309
+ const jumps = [];
21057
21310
  /** @type {Record<string, number>} */
21058
- const gaps = {}
21311
+ const gaps = {};
21059
21312
  /** @type {Array<Chunk>} */
21060
- let stream
21313
+ let stream;
21061
21314
  /** @type {Token | undefined} */
21062
- let previous
21063
- let index = -1
21315
+ let previous;
21316
+ let index = -1;
21064
21317
  /** @type {Token | undefined} */
21065
- let current = token
21066
- let adjust = 0
21067
- let start = 0
21068
- const breaks = [start]
21318
+ let current = token;
21319
+ let adjust = 0;
21320
+ let start = 0;
21321
+ const breaks = [start];
21069
21322
 
21070
21323
  // Loop forward through the linked tokens to pass them in order to the
21071
21324
  // subtokenizer.
21072
21325
  while (current) {
21073
21326
  // Find the position of the event for this token.
21074
- while (events[++startPosition][1] !== current) {
21327
+ while (events.get(++startPosition)[1] !== current) {
21075
21328
  // Empty.
21076
21329
  }
21077
- startPositions.push(startPosition)
21330
+ startPositions.push(startPosition);
21078
21331
  if (!current._tokenizer) {
21079
- stream = context.sliceStream(current)
21332
+ stream = context.sliceStream(current);
21080
21333
  if (!current.next) {
21081
- stream.push(null)
21334
+ stream.push(null);
21082
21335
  }
21083
21336
  if (previous) {
21084
- tokenizer.defineSkip(current.start)
21337
+ tokenizer.defineSkip(current.start);
21085
21338
  }
21086
21339
  if (current._isInFirstContentOfListItem) {
21087
- tokenizer._gfmTasklistFirstContentOfListItem = true
21340
+ tokenizer._gfmTasklistFirstContentOfListItem = true;
21088
21341
  }
21089
- tokenizer.write(stream)
21342
+ tokenizer.write(stream);
21090
21343
  if (current._isInFirstContentOfListItem) {
21091
- tokenizer._gfmTasklistFirstContentOfListItem = undefined
21344
+ tokenizer._gfmTasklistFirstContentOfListItem = undefined;
21092
21345
  }
21093
21346
  }
21094
21347
 
21095
21348
  // Unravel the next token.
21096
- previous = current
21097
- current = current.next
21349
+ previous = current;
21350
+ current = current.next;
21098
21351
  }
21099
21352
 
21100
21353
  // Now, loop back through all events (and linked tokens), to figure out which
21101
21354
  // parts belong where.
21102
- current = token
21355
+ current = token;
21103
21356
  while (++index < childEvents.length) {
21104
21357
  if (
21105
- // Find a void token that includes a break.
21106
- childEvents[index][0] === 'exit' &&
21107
- childEvents[index - 1][0] === 'enter' &&
21108
- childEvents[index][1].type === childEvents[index - 1][1].type &&
21109
- childEvents[index][1].start.line !== childEvents[index][1].end.line
21110
- ) {
21111
- start = index + 1
21112
- breaks.push(start)
21358
+ // Find a void token that includes a break.
21359
+ 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) {
21360
+ start = index + 1;
21361
+ breaks.push(start);
21113
21362
  // Help GC.
21114
- current._tokenizer = undefined
21115
- current.previous = undefined
21116
- current = current.next
21363
+ current._tokenizer = undefined;
21364
+ current.previous = undefined;
21365
+ current = current.next;
21117
21366
  }
21118
21367
  }
21119
21368
 
21120
21369
  // Help GC.
21121
- tokenizer.events = []
21370
+ tokenizer.events = [];
21122
21371
 
21123
21372
  // If there’s one more token (which is the cases for lines that end in an
21124
21373
  // EOF), that’s perfect: the last point we found starts it.
21125
21374
  // If there isn’t then make sure any remaining content is added to it.
21126
21375
  if (current) {
21127
21376
  // Help GC.
21128
- current._tokenizer = undefined
21129
- current.previous = undefined
21377
+ current._tokenizer = undefined;
21378
+ current.previous = undefined;
21130
21379
  } else {
21131
- breaks.pop()
21380
+ breaks.pop();
21132
21381
  }
21133
21382
 
21134
21383
  // Now splice the events from the subtokenizer into the current events,
21135
21384
  // moving back to front so that splice indices aren’t affected.
21136
- index = breaks.length
21385
+ index = breaks.length;
21137
21386
  while (index--) {
21138
- const slice = childEvents.slice(breaks[index], breaks[index + 1])
21139
- const start = startPositions.pop()
21140
- jumps.unshift([start, start + slice.length - 1])
21141
- splice(events, start, 2, slice)
21387
+ const slice = childEvents.slice(breaks[index], breaks[index + 1]);
21388
+ const start = startPositions.pop();
21389
+ jumps.push([start, start + slice.length - 1]);
21390
+ events.splice(start, 2, slice);
21142
21391
  }
21143
- index = -1
21392
+ jumps.reverse();
21393
+ index = -1;
21144
21394
  while (++index < jumps.length) {
21145
- gaps[adjust + jumps[index][0]] = adjust + jumps[index][1]
21146
- adjust += jumps[index][1] - jumps[index][0] - 1
21395
+ gaps[adjust + jumps[index][0]] = adjust + jumps[index][1];
21396
+ adjust += jumps[index][1] - jumps[index][0] - 1;
21147
21397
  }
21148
- return gaps
21398
+ return gaps;
21149
21399
  }
21150
-
21151
21400
  ;// ./node_modules/micromark/lib/postprocess.js
21152
21401
  /**
21153
21402
  * @typedef {import('micromark-util-types').Event} Event
@@ -113441,7 +113690,9 @@ class MdxSyntaxError extends SyntaxError {
113441
113690
  * as `\r<br>`. Treating both characters as hard breaks doubles the spacing.
113442
113691
  */
113443
113692
  const hardBreaks = () => tree => {
113444
- findAndReplace(tree, [/\r?\n/g, () => ({ type: 'break' })]);
113693
+ // Skip `html-block`: its opaque payload is rendered verbatim, so turning its newlines
113694
+ // into `break` nodes is unnecessary and costly on large blocks.
113695
+ findAndReplace(tree, [/\r?\n/g, () => ({ type: 'break' })], { ignore: ['html-block'] });
113445
113696
  };
113446
113697
  /* harmony default export */ const hard_breaks = (hardBreaks);
113447
113698
 
@@ -122490,6 +122741,10 @@ const NESTED_ATTR_EXPRESSION_RE = /[\w-]+\s*=\s*\{/;
122490
122741
  // Name shape mirrors `componentTagPattern`; the lookbehind skips the inner tag
122491
122742
  // of a legacy `<<VARIABLE>>`.
122492
122743
  const NESTED_COMPONENT_TAG_RE = /(?<!<)<([A-Z][A-Za-z0-9_]*)[\s/>]/g;
122744
+ // Whole blank lines at a component body's edges. `\n` sits inside each group so a
122745
+ // match can only ever span complete lines, never part of a content line.
122746
+ const LEADING_BLANK_LINES_RE = /^(?:[ \t]*\n)+/;
122747
+ const TRAILING_BLANK_LINES_RE = /(?:\n[ \t]*)+$/;
122493
122748
  // Excludes tags with dedicated transformers (`Table`, `HTMLBlock`, inline
122494
122749
  // components), which expect their wrapper to stay raw.
122495
122750
  const hasNestedGenericComponentTag = (content) => [...content.matchAll(NESTED_COMPONENT_TAG_RE)].some(match => !GENERIC_MDX_COMPONENT_EXCLUDED_TAGS.has(match[1]));
@@ -122523,13 +122778,21 @@ function safeDeindent(text) {
122523
122778
  })
122524
122779
  .join('\n');
122525
122780
  }
122781
+ /**
122782
+ * Drop the blank lines at a component body's edges, keeping the first content line's
122783
+ * indent: `.trim()` stripped that line alone, so a uniformly indented body reparsed
122784
+ * lopsided and every list item after the first nested. The trailing pattern
122785
+ * takes the last content line's newline but leaves its spaces, which are code content
122786
+ * when a fence runs into the end tag.
122787
+ */
122788
+ const trimBlankEdges = (text) => text.replace(LEADING_BLANK_LINES_RE, '').replace(TRAILING_BLANK_LINES_RE, '');
122526
122789
  /**
122527
122790
  * Parse component-body markdown into mdast children. Dedenting shifts columns and
122528
122791
  * stales the top-level `terminateHtmlFlowBlocks` decisions, so that one preprocessor
122529
122792
  * re-runs here; other column-anchored fixups (compact headings, tables) do not.
122530
122793
  */
122531
122794
  const parseMdChildren = (value, safeMode) => {
122532
- const reparseSource = terminateHtmlFlowBlocks(safeDeindent(value).trim());
122795
+ const reparseSource = terminateHtmlFlowBlocks(trimBlankEdges(safeDeindent(value)));
122533
122796
  const parsed = getInlineMdProcessor({ safeMode }).parse(reparseSource);
122534
122797
  // Promote nested wrappers bottom-up so an outer wrapper sees markdown buried in a
122535
122798
  // child claimed whole (e.g. `<li>` in `<ol>`) before its containsMarkdownConstruct check (RM-17560).
@@ -122694,7 +122957,8 @@ function promoteComponentBlocks(tree, safeMode, source) {
122694
122957
  // Case 2: Self-contained block (closing tag in content)
122695
122958
  const closingTagIndex = isPlainLowercaseHtml ? plainClosingTagIndex : contentAfterTag.lastIndexOf(closingTagStr);
122696
122959
  if (closingTagIndex >= 0) {
122697
- // Untrimmed so parseMdChildren can dedent before trimming.
122960
+ // Left as authored: parseMdChildren needs the original columns to dedent by, and
122961
+ // it clears the blank edges itself.
122698
122962
  const componentInnerContent = contentAfterTag.substring(0, closingTagIndex);
122699
122963
  const contentAfterClose = contentAfterTag.substring(closingTagIndex + closingTagStr.length).trim();
122700
122964
  let parsedChildren = [];