@wdprlib/parser 5.1.6 → 5.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/dist/index.cjs +655 -435
  2. package/dist/index.d.cts +11 -4
  3. package/dist/index.d.ts +11 -4
  4. package/dist/index.js +653 -435
  5. package/package.json +2 -2
  6. package/src/build-info.generated.ts +11 -0
  7. package/src/index.ts +2 -0
  8. package/src/lexer/lexer.ts +6 -4
  9. package/src/lexer/punctuation.ts +2 -1
  10. package/src/lexer/spacing-actions.ts +15 -0
  11. package/src/lexer/state.ts +30 -4
  12. package/src/lexer/token-factory.ts +15 -2
  13. package/src/lexer/tokens.ts +4 -3
  14. package/src/parser/rules/block/blockquote/build.ts +81 -37
  15. package/src/parser/rules/block/blockquote/index.ts +5 -6
  16. package/src/parser/rules/block/blockquote/line.ts +11 -10
  17. package/src/parser/rules/block/blockquote/lines.ts +102 -4
  18. package/src/parser/rules/block/code/content.ts +0 -3
  19. package/src/parser/rules/block/code/index.ts +14 -10
  20. package/src/parser/rules/block/definition-list/index.ts +4 -10
  21. package/src/parser/rules/block/definition-list/item-value.ts +2 -11
  22. package/src/parser/rules/block/definition-list/items.ts +1 -2
  23. package/src/parser/rules/block/embed-block/index.ts +30 -30
  24. package/src/parser/rules/block/heading/index.ts +7 -0
  25. package/src/parser/rules/block/paragraph/index.ts +41 -10
  26. package/src/parser/rules/block/parsing/content.ts +18 -1
  27. package/src/parser/rules/block/table/pipe/cell.ts +36 -1
  28. package/src/parser/rules/block/table/pipe/row.ts +21 -1
  29. package/src/parser/rules/block/toc/element.ts +2 -2
  30. package/src/parser/rules/block/toc/index.ts +2 -2
  31. package/src/parser/rules/block/toc/open.ts +5 -18
  32. package/src/parser/rules/contracts/scope.ts +4 -0
  33. package/src/parser/rules/inline/bold.ts +5 -5
  34. package/src/parser/rules/inline/color/syntax.ts +5 -8
  35. package/src/parser/rules/inline/formatting/close.ts +39 -0
  36. package/src/parser/rules/inline/formatting/container.ts +7 -4
  37. package/src/parser/rules/inline/index.ts +2 -0
  38. package/src/parser/rules/inline/italic.ts +5 -5
  39. package/src/parser/rules/inline/monospace.ts +5 -5
  40. package/src/parser/rules/inline/parsing/block-start-predicates.ts +2 -0
  41. package/src/parser/rules/inline/parsing/inline-content.ts +58 -4
  42. package/src/parser/rules/inline/raw/end.ts +28 -0
  43. package/src/parser/rules/inline/span/content.ts +32 -1
  44. package/src/parser/rules/inline/strikethrough/index.ts +1 -1
  45. package/src/parser/rules/inline/strikethrough/parse.ts +2 -9
  46. package/src/parser/rules/inline/strikethrough/syntax.ts +3 -20
  47. package/src/parser/rules/inline/subscript.ts +5 -5
  48. package/src/parser/rules/inline/superscript.ts +5 -5
  49. package/src/parser/rules/inline/underline/index.ts +5 -78
  50. package/src/parser/rules/tokens.ts +6 -15
  51. package/src/parser/rules/inline/underline/child.ts +0 -26
  52. package/src/parser/rules/inline/underline/content.ts +0 -29
package/dist/index.js CHANGED
@@ -1,3 +1,10 @@
1
+ // packages/parser/src/build-info.generated.ts
2
+ var buildInfo = Object.freeze({
3
+ version: "5.2.0",
4
+ sha: "cc290b0d882de3ed9ea33ec060ddfc8a7b9da59a",
5
+ dirty: false
6
+ });
7
+
1
8
  // packages/parser/src/index.ts
2
9
  import {
3
10
  createPoint,
@@ -21,49 +28,6 @@ import { createSettings, DEFAULT_SETTINGS as DEFAULT_SETTINGS3 } from "@wdprlib/
21
28
  function createToken(type, value, position, lineStart = false) {
22
29
  return { type, value, position, lineStart };
23
30
  }
24
- // packages/parser/src/lexer/token-factory.ts
25
- var ZERO_POSITION = {
26
- start: { line: 0, column: 0, offset: 0 },
27
- end: { line: 0, column: 0, offset: 0 }
28
- };
29
- function createLexerToken(state, type, value, trackPositions) {
30
- return {
31
- type,
32
- value,
33
- position: trackPositions ? currentTokenPosition(state, value) : ZERO_POSITION,
34
- lineStart: isTokenAtLineStart(state)
35
- };
36
- }
37
- function updateLastNonWhitespaceType(current, type) {
38
- return type === "WHITESPACE" ? current : type;
39
- }
40
- function nextBlockOpenerDepth(current, type) {
41
- if (type === "BLOCK_OPEN" || type === "BLOCK_END_OPEN") {
42
- return current + 1;
43
- }
44
- if (type === "BLOCK_CLOSE" && current > 0) {
45
- return current - 1;
46
- }
47
- return current;
48
- }
49
- function currentTokenPosition(state, value) {
50
- return {
51
- start: {
52
- line: state.line,
53
- column: state.column - value.length,
54
- offset: state.pos - value.length
55
- },
56
- end: {
57
- line: state.line,
58
- column: state.column,
59
- offset: state.pos
60
- }
61
- };
62
- }
63
- function isTokenAtLineStart(state) {
64
- return state.tokens.length === 0 || state.tokens[state.tokens.length - 1]?.type === "NEWLINE";
65
- }
66
-
67
31
  // packages/parser/src/lexer/state.ts
68
32
  function createInitialLexerState(source) {
69
33
  return {
@@ -72,9 +36,16 @@ function createInitialLexerState(source) {
72
36
  line: 1,
73
37
  column: 1,
74
38
  lineStart: true,
39
+ quoteContentStart: false,
75
40
  tokens: []
76
41
  };
77
42
  }
43
+ function isSyntaxLineStart(state) {
44
+ return state.lineStart || state.quoteContentStart;
45
+ }
46
+ function isLineStartQuoteMarker(token) {
47
+ return token?.type === "BLOCKQUOTE_MARKER" && token.lineStart;
48
+ }
78
49
  function isAtEnd(state) {
79
50
  return state.pos >= state.source.length;
80
51
  }
@@ -88,18 +59,25 @@ function advance(state, n = 1) {
88
59
  updatePosition(state, start, end);
89
60
  return value;
90
61
  }
91
- function advanceByToken(state, type, length) {
62
+ function advanceByToken(state, type, length, value = "") {
63
+ const afterQuoteMarker = isLineStartQuoteMarker(state.tokens[state.tokens.length - 1]);
92
64
  state.pos += length;
93
65
  if (type === "NEWLINE") {
94
66
  state.line++;
95
67
  state.column = 1;
96
68
  state.lineStart = true;
69
+ state.quoteContentStart = false;
97
70
  return;
98
71
  }
99
72
  state.column += length;
100
- if (type !== "WHITESPACE") {
101
- state.lineStart = false;
73
+ if (type === "WHITESPACE") {
74
+ if (afterQuoteMarker && value === " ") {
75
+ state.quoteContentStart = true;
76
+ }
77
+ return;
102
78
  }
79
+ state.lineStart = false;
80
+ state.quoteContentStart = false;
103
81
  }
104
82
  function updatePosition(state, start, end) {
105
83
  state.pos = end;
@@ -110,8 +88,9 @@ function updatePositionFromValue(state, value) {
110
88
  `);
111
89
  if (firstNewline === -1) {
112
90
  state.column += value.length;
113
- if (state.lineStart && hasNonLineStartSpacing(value, 0)) {
91
+ if (hasNonLineStartSpacing(value, 0)) {
114
92
  state.lineStart = false;
93
+ state.quoteContentStart = false;
115
94
  }
116
95
  return;
117
96
  }
@@ -130,6 +109,7 @@ function updatePositionFromValue(state, value) {
130
109
  state.line += newlineCount;
131
110
  state.column = value.length - lastNewline;
132
111
  state.lineStart = !hasNonLineStartSpacing(value, lastNewline + 1);
112
+ state.quoteContentStart = false;
133
113
  }
134
114
  function hasNonLineStartSpacing(value, start) {
135
115
  for (let i = start;i < value.length; i++) {
@@ -141,6 +121,56 @@ function hasNonLineStartSpacing(value, start) {
141
121
  return false;
142
122
  }
143
123
 
124
+ // packages/parser/src/lexer/token-factory.ts
125
+ var ZERO_POSITION = {
126
+ start: { line: 0, column: 0, offset: 0 },
127
+ end: { line: 0, column: 0, offset: 0 }
128
+ };
129
+ function createLexerToken(state, type, value, trackPositions) {
130
+ return {
131
+ type,
132
+ value,
133
+ position: trackPositions ? currentTokenPosition(state, value) : ZERO_POSITION,
134
+ lineStart: isTokenAtLineStart(state)
135
+ };
136
+ }
137
+ function updateLastNonWhitespaceType(current2, type) {
138
+ return type === "WHITESPACE" ? current2 : type;
139
+ }
140
+ function nextBlockOpenerDepth(current2, type) {
141
+ if (type === "BLOCK_OPEN" || type === "BLOCK_END_OPEN") {
142
+ return current2 + 1;
143
+ }
144
+ if (type === "BLOCK_CLOSE" && current2 > 0) {
145
+ return current2 - 1;
146
+ }
147
+ return current2;
148
+ }
149
+ function currentTokenPosition(state, value) {
150
+ return {
151
+ start: {
152
+ line: state.line,
153
+ column: state.column - value.length,
154
+ offset: state.pos - value.length
155
+ },
156
+ end: {
157
+ line: state.line,
158
+ column: state.column,
159
+ offset: state.pos
160
+ }
161
+ };
162
+ }
163
+ function isTokenAtLineStart(state) {
164
+ if (state.tokens.length === 0) {
165
+ return true;
166
+ }
167
+ const last = state.tokens[state.tokens.length - 1];
168
+ if (last?.type === "NEWLINE") {
169
+ return true;
170
+ }
171
+ return last?.type === "WHITESPACE" && last.value === " " && isLineStartQuoteMarker(state.tokens[state.tokens.length - 2]);
172
+ }
173
+
144
174
  // packages/parser/src/lexer/anchor.ts
145
175
  function findInvalidAnchorNameEnd(src, pos) {
146
176
  if (src[pos] !== "[" || src[pos + 1] !== "[" || src[pos + 2] !== "#") {
@@ -457,7 +487,7 @@ function scanPunctuationToken(input) {
457
487
  case "@":
458
488
  return { handled: true, actions: scanAtToken(source, pos) };
459
489
  case ">":
460
- return { handled: true, actions: scanGreaterToken(source, pos, lineStart) };
490
+ return { handled: true, actions: scanGreaterToken(source, pos, input.physicalLineStart) };
461
491
  case "-":
462
492
  return { handled: true, actions: scanDashToken(source, pos, lineStart) };
463
493
  case "~": {
@@ -499,6 +529,15 @@ function runToken3(src, pos, end, type) {
499
529
  }
500
530
 
501
531
  // packages/parser/src/lexer/spacing-actions.ts
532
+ function limitBlockquotePrefixSpace(action, previous) {
533
+ if (!isLineStartQuoteMarker(previous) || action.type !== "WHITESPACE") {
534
+ return action;
535
+ }
536
+ if (action.length <= 1 || !action.value.startsWith(" ")) {
537
+ return action;
538
+ }
539
+ return { type: "WHITESPACE", value: " ", length: 1 };
540
+ }
502
541
  function scanSpacingToken(src, pos) {
503
542
  const char = src[pos];
504
543
  if (char === `
@@ -560,7 +599,7 @@ class Lexer {
560
599
  this.blockOpenerDepth = nextBlockOpenerDepth(this.blockOpenerDepth, type);
561
600
  }
562
601
  emitTokenAction(action) {
563
- advanceByToken(this.state, action.type, action.length);
602
+ advanceByToken(this.state, action.type, action.length, action.value);
564
603
  this.addToken(action.type, action.value);
565
604
  }
566
605
  emitTokenActions(actions) {
@@ -574,11 +613,11 @@ class Lexer {
574
613
  }
575
614
  scanToken() {
576
615
  const char = this.current();
577
- const isLineStart = this.state.lineStart;
616
+ const isLineStart = isSyntaxLineStart(this.state);
578
617
  const src = this.state.source;
579
618
  const spacingAction = scanSpacingToken(src, this.state.pos);
580
619
  if (spacingAction) {
581
- this.emitTokenAction(spacingAction);
620
+ this.emitTokenAction(limitBlockquotePrefixSpace(spacingAction, this.state.tokens.at(-1)));
582
621
  return;
583
622
  }
584
623
  const punctuation = scanPunctuationToken({
@@ -586,6 +625,7 @@ class Lexer {
586
625
  source: src,
587
626
  pos: this.state.pos,
588
627
  lineStart: isLineStart,
628
+ physicalLineStart: this.state.lineStart,
589
629
  splitBlockClose: this.splitBlockClosePositions.has(this.state.pos),
590
630
  findInvalidAnchorNameEnd: () => this.findInvalidAnchorNameEnd()
591
631
  });
@@ -802,7 +842,7 @@ function parseBlocksUntil(ctx, closeCondition, options) {
802
842
  const elements = [];
803
843
  let consumed = 0;
804
844
  let pos = ctx.pos;
805
- const excluded = options?.excludedBlockNames;
845
+ const excluded = mergeExcludedBlockNames(ctx.scope.excludedBlockNames, options?.excludedBlockNames);
806
846
  const blockRules = excluded ? getExcludedBlockRules(ctx.blockRules, excluded) : ctx.blockRules;
807
847
  const blockScope = {
808
848
  ...ctx.scope,
@@ -844,6 +884,13 @@ function parseBlocksUntil(ctx, closeCondition, options) {
844
884
  }
845
885
  return { elements, consumed };
846
886
  }
887
+ function mergeExcludedBlockNames(inherited, added) {
888
+ if (!inherited?.size)
889
+ return added;
890
+ if (!added?.size)
891
+ return inherited;
892
+ return new Set([...inherited, ...added]);
893
+ }
847
894
  function getExcludedBlockRules(blockRules, excluded) {
848
895
  let byExcluded = excludedBlockRulesCache.get(blockRules);
849
896
  if (!byExcluded) {
@@ -880,6 +927,31 @@ function getCandidateInlineRules(inlineRules, tokenType) {
880
927
  byType.set(tokenType, candidates);
881
928
  return candidates;
882
929
  }
930
+ // packages/parser/src/parser/rules/inline/raw/end.ts
931
+ function rawRegionEnd(tokens, start, end) {
932
+ const type = tokens[start]?.type;
933
+ const close = type === "RAW_OPEN" ? "RAW_OPEN" : type === "RAW_BLOCK_OPEN" ? "RAW_BLOCK_CLOSE" : null;
934
+ if (!close)
935
+ return start;
936
+ for (let pos = start + 1;pos < end; pos++) {
937
+ if (tokens[pos]?.type === "NEWLINE" || tokens[pos]?.type === "EOF")
938
+ break;
939
+ if (tokens[pos]?.type === close)
940
+ return pos + 1;
941
+ }
942
+ return start;
943
+ }
944
+ function protectedInlineRegionEnd(tokens, start, end) {
945
+ const rawEnd = rawRegionEnd(tokens, start, end);
946
+ if (rawEnd > start || tokens[start]?.type !== "COMMENT_OPEN")
947
+ return rawEnd;
948
+ for (let pos = start + 1;pos < end; pos++) {
949
+ if (tokens[pos]?.type === "COMMENT_CLOSE")
950
+ return pos + 1;
951
+ }
952
+ return start;
953
+ }
954
+
883
955
  // packages/parser/src/parser/rules/inline/parsing/plain-text.ts
884
956
  var MIN_INLINE_TEXT_RUN_LENGTH = 32;
885
957
  var MIN_INLINE_TEXT_RUN_DOCUMENT_TOKENS = 1e5;
@@ -922,6 +994,135 @@ function isPlainTextRunToken(ctx, pos) {
922
994
  return token5.value !== "(";
923
995
  }
924
996
 
997
+ // packages/parser/src/parser/rules/inline/image/attributes.ts
998
+ function parseImageAttributes(ctx, startPos) {
999
+ const result = parseAttributesRaw(ctx, startPos, false);
1000
+ const link = result.attrs.link ?? null;
1001
+ const { link: _link, ...htmlAttributes } = result.attrs;
1002
+ return {
1003
+ attributes: filterUnsafeAttributes(htmlAttributes),
1004
+ link,
1005
+ consumed: result.consumed
1006
+ };
1007
+ }
1008
+
1009
+ // packages/parser/src/parser/rules/inline/image/body.ts
1010
+ function parseImageSourceText(ctx, startPos) {
1011
+ let pos = startPos;
1012
+ let consumed = 0;
1013
+ while (ctx.tokens[pos]?.type === "WHITESPACE") {
1014
+ pos++;
1015
+ consumed++;
1016
+ }
1017
+ let sourceText = "";
1018
+ while (pos < ctx.tokens.length) {
1019
+ const token5 = ctx.tokens[pos];
1020
+ if (!token5 || token5.type === "WHITESPACE" || token5.type === "BLOCK_CLOSE" || token5.type === "NEWLINE" || token5.type === "EOF") {
1021
+ break;
1022
+ }
1023
+ sourceText += token5.value;
1024
+ pos++;
1025
+ consumed++;
1026
+ }
1027
+ return { sourceText, consumed };
1028
+ }
1029
+
1030
+ // packages/parser/src/parser/rules/inline/image/syntax.ts
1031
+ var IMAGE_BLOCK_NAMES = new Set([
1032
+ "image",
1033
+ "=image",
1034
+ "<image",
1035
+ ">image",
1036
+ "f<image",
1037
+ "f>image",
1038
+ "f=image"
1039
+ ]);
1040
+ function parseImageBlockName(ctx, startPos) {
1041
+ let pos = startPos;
1042
+ let consumed = 0;
1043
+ while (ctx.tokens[pos]?.type === "WHITESPACE") {
1044
+ pos++;
1045
+ consumed++;
1046
+ }
1047
+ const prefixResult = parseImagePrefix(ctx, pos);
1048
+ const prefix = prefixResult.prefix;
1049
+ pos += prefixResult.consumed;
1050
+ consumed += prefixResult.consumed;
1051
+ const nameToken = ctx.tokens[pos];
1052
+ if (!nameToken || nameToken.type !== "TEXT" && nameToken.type !== "IDENTIFIER") {
1053
+ return null;
1054
+ }
1055
+ return { name: prefix + nameToken.value.toLowerCase(), consumed: consumed + 1 };
1056
+ }
1057
+ function isImageBlockName(blockName) {
1058
+ return IMAGE_BLOCK_NAMES.has(blockName);
1059
+ }
1060
+ function parseImagePrefix(ctx, pos) {
1061
+ const token5 = ctx.tokens[pos];
1062
+ if (token5?.type === "EQUALS") {
1063
+ return { prefix: "=", consumed: 1 };
1064
+ }
1065
+ if (token5?.type === "TEXT" && token5.value === "<") {
1066
+ return { prefix: "<", consumed: 1 };
1067
+ }
1068
+ if ((token5?.type === "TEXT" || token5?.type === "BLOCKQUOTE_MARKER") && token5.value === ">") {
1069
+ return { prefix: ">", consumed: 1 };
1070
+ }
1071
+ if (token5?.type === "IDENTIFIER" && token5.value.toLowerCase() === "f") {
1072
+ return parseFloatPrefix(ctx, pos + 1);
1073
+ }
1074
+ return { prefix: "", consumed: 0 };
1075
+ }
1076
+ function parseFloatPrefix(ctx, pos) {
1077
+ const token5 = ctx.tokens[pos];
1078
+ if (token5?.type === "TEXT" && token5.value === "<") {
1079
+ return { prefix: "f<", consumed: 2 };
1080
+ }
1081
+ if ((token5?.type === "TEXT" || token5?.type === "BLOCKQUOTE_MARKER") && token5.value === ">") {
1082
+ return { prefix: "f>", consumed: 2 };
1083
+ }
1084
+ if (token5?.type === "EQUALS") {
1085
+ return { prefix: "f=", consumed: 2 };
1086
+ }
1087
+ return { prefix: "", consumed: 0 };
1088
+ }
1089
+
1090
+ // packages/parser/src/parser/rules/inline/image/open.ts
1091
+ function parseImageOpen(ctx) {
1092
+ if (ctx.tokens[ctx.pos]?.type !== "BLOCK_OPEN") {
1093
+ return null;
1094
+ }
1095
+ let pos = ctx.pos + 1;
1096
+ let consumed = 1;
1097
+ const nameResult = parseImageBlockName(ctx, pos);
1098
+ if (!nameResult || !isImageBlockName(nameResult.name)) {
1099
+ return null;
1100
+ }
1101
+ pos += nameResult.consumed;
1102
+ consumed += nameResult.consumed;
1103
+ const sourceText = parseImageSourceText(ctx, pos);
1104
+ pos += sourceText.consumed;
1105
+ consumed += sourceText.consumed;
1106
+ const attrs = parseImageAttributes(ctx, pos);
1107
+ pos += attrs.consumed;
1108
+ consumed += attrs.consumed;
1109
+ if (ctx.tokens[pos]?.type !== "BLOCK_CLOSE") {
1110
+ return null;
1111
+ }
1112
+ pos++;
1113
+ consumed++;
1114
+ if (!sourceText.sourceText) {
1115
+ return null;
1116
+ }
1117
+ return {
1118
+ blockName: nameResult.name,
1119
+ sourceText: sourceText.sourceText,
1120
+ link: attrs.link,
1121
+ attributes: attrs.attributes,
1122
+ consumed
1123
+ };
1124
+ }
1125
+
925
1126
  // packages/parser/src/parser/constants.ts
926
1127
  var BLOCK_START_TOKENS = [
927
1128
  "BLOCKQUOTE_MARKER",
@@ -1052,7 +1253,7 @@ function isParagraphBreakingBlockStart(ctx, newlinePos, lookAhead) {
1052
1253
  if (!nextMeaningfulToken.lineStart && !isIndentedBlockOpener) {
1053
1254
  return false;
1054
1255
  }
1055
- return !isOrphanCloseSpan(ctx, nextPos) && !isAnchorName(ctx, nextPos) && !isInvalidBlockOpen(ctx, nextPos) && !isInvalidHeading(ctx, nextPos) && !isExcludedBlockStart(ctx, nextPos) && !isUnknownBlockStart(ctx, nextPos);
1256
+ return !parseImageOpen({ ...ctx, pos: nextPos }) && !isOrphanCloseSpan(ctx, nextPos) && !isAnchorName(ctx, nextPos) && !isInvalidBlockOpen(ctx, nextPos) && !isInvalidHeading(ctx, nextPos) && !isExcludedBlockStart(ctx, nextPos) && !isUnknownBlockStart(ctx, nextPos);
1056
1257
  }
1057
1258
  function isOrphanCloseSpan(ctx, blockEndOpenPos) {
1058
1259
  const token5 = ctx.tokens[blockEndOpenPos];
@@ -1162,27 +1363,45 @@ function parseInlineUntil(ctx, endType) {
1162
1363
  let consumed = 0;
1163
1364
  let pos = ctx.pos;
1164
1365
  const paragraphMode = endType === "PARAGRAPH_BREAK";
1366
+ const multiline = paragraphMode || FORMATTING_CLOSE_TOKENS.has(endType);
1367
+ let inlineEnd = ctx.scope.inlineEnd ?? ctx.tokens.length;
1368
+ if (!multiline) {
1369
+ for (let end = ctx.pos;end < inlineEnd; end++) {
1370
+ const protectedEnd = protectedInlineRegionEnd(ctx.tokens, end, inlineEnd);
1371
+ if (protectedEnd > end) {
1372
+ end = protectedEnd - 1;
1373
+ continue;
1374
+ }
1375
+ if (ctx.tokens[end]?.type === "NEWLINE" && ctx.tokens[end - 1]?.type === "UNDERSCORE" && ctx.tokens[end - 2]?.type === "WHITESPACE")
1376
+ continue;
1377
+ if (ctx.tokens[end]?.type === "NEWLINE" || ctx.tokens[end]?.type === endType) {
1378
+ inlineEnd = end;
1379
+ break;
1380
+ }
1381
+ }
1382
+ }
1165
1383
  const { inlineRules } = ctx;
1166
1384
  const inlineCtx = {
1167
1385
  ...ctx,
1168
- pos
1386
+ pos,
1387
+ scope: { ...ctx.scope, inlineEnd }
1169
1388
  };
1170
1389
  const canCollectLongPlainTextRuns = ctx.tokens.length >= MIN_INLINE_TEXT_RUN_DOCUMENT_TOKENS;
1171
- while (pos < ctx.tokens.length) {
1390
+ while (pos < inlineEnd) {
1172
1391
  const token5 = ctx.tokens[pos];
1173
1392
  if (!token5 || token5.type === "EOF") {
1174
1393
  break;
1175
1394
  }
1176
- if (paragraphMode && ctx.scope.blockCloseCondition) {
1395
+ if (ctx.scope.blockCloseCondition) {
1177
1396
  const checkCtx = { ...ctx, pos };
1178
1397
  if (ctx.scope.blockCloseCondition(checkCtx)) {
1179
1398
  break;
1180
1399
  }
1181
1400
  }
1182
- if (!paragraphMode && token5.type === "NEWLINE") {
1401
+ if (!multiline && token5.type === "NEWLINE") {
1183
1402
  break;
1184
1403
  }
1185
- if (paragraphMode && token5.type === "NEWLINE") {
1404
+ if (multiline && token5.type === "NEWLINE" && !ctx.scope.tableFormatting) {
1186
1405
  const boundary = getParagraphNewlineBoundary(ctx, pos, nodes.length > 0);
1187
1406
  if (boundary.shouldBreak) {
1188
1407
  if (boundary.preservePrecedingLineBreak) {
@@ -1192,6 +1411,11 @@ function parseInlineUntil(ctx, endType) {
1192
1411
  break;
1193
1412
  }
1194
1413
  }
1414
+ if (ctx.scope.tableFormatting?.suppressedClosers.has(pos)) {
1415
+ pos++;
1416
+ consumed++;
1417
+ continue;
1418
+ }
1195
1419
  if (token5.type === endType) {
1196
1420
  break;
1197
1421
  }
@@ -1216,6 +1440,24 @@ function parseInlineUntil(ctx, endType) {
1216
1440
  for (const rule of getCandidateInlineRules(inlineRules, token5.type)) {
1217
1441
  const result = rule.parse(inlineCtx);
1218
1442
  if (result.success) {
1443
+ if (rule.name === "comment") {
1444
+ let after = pos + result.consumed;
1445
+ while (ctx.tokens[after]?.type === "WHITESPACE")
1446
+ after++;
1447
+ if (ctx.tokens[after]?.type === "NEWLINE" || ctx.tokens[after]?.type === "EOF") {
1448
+ while (nodes.at(-1)?.element === "text") {
1449
+ const last = nodes.at(-1);
1450
+ if (last.element !== "text")
1451
+ break;
1452
+ last.data = last.data.trimEnd();
1453
+ if (last.data)
1454
+ break;
1455
+ nodes.pop();
1456
+ }
1457
+ if (nodes.at(-1)?.element === "line-break")
1458
+ nodes.pop();
1459
+ }
1460
+ }
1219
1461
  nodes.push(...result.elements);
1220
1462
  consumed += result.consumed;
1221
1463
  pos += result.consumed;
@@ -1231,6 +1473,16 @@ function parseInlineUntil(ctx, endType) {
1231
1473
  }
1232
1474
  return { elements: nodes, consumed };
1233
1475
  }
1476
+ var FORMATTING_CLOSE_TOKENS = new Set([
1477
+ "BOLD_MARKER",
1478
+ "ITALIC_MARKER",
1479
+ "UNDERLINE_MARKER",
1480
+ "STRIKE_MARKER",
1481
+ "SUPER_MARKER",
1482
+ "SUB_MARKER",
1483
+ "MONO_CLOSE",
1484
+ "COLOR_MARKER"
1485
+ ]);
1234
1486
  // packages/parser/src/parser/rules/block/parsing/attributes/names.ts
1235
1487
  function consumeAttributeName(ctx, startPos, startConsumed, startName, options) {
1236
1488
  if (startName === "_" && isAttributeWordToken(ctx.tokens[startPos])) {
@@ -1406,7 +1658,7 @@ function eofToken() {
1406
1658
  }
1407
1659
  function hasClosingMarkerBeforeNewline(ctx, markerType, markerValue) {
1408
1660
  let pos = ctx.pos;
1409
- while (pos < ctx.tokens.length) {
1661
+ while (pos < (ctx.scope.inlineEnd ?? ctx.tokens.length)) {
1410
1662
  const token5 = ctx.tokens[pos];
1411
1663
  if (!token5 || token5.type === "NEWLINE" || token5.type === "EOF") {
1412
1664
  return false;
@@ -1420,31 +1672,6 @@ function hasClosingMarkerBeforeNewline(ctx, markerType, markerValue) {
1420
1672
  }
1421
1673
  return false;
1422
1674
  }
1423
- function hasClosingMarkerBeforeParagraphBreak(ctx, markerType, markerValue) {
1424
- let pos = ctx.pos;
1425
- while (pos < ctx.tokens.length) {
1426
- const token5 = ctx.tokens[pos];
1427
- if (!token5 || token5.type === "EOF") {
1428
- return false;
1429
- }
1430
- if (token5.type === "NEWLINE") {
1431
- let lookAhead = 1;
1432
- while (ctx.tokens[pos + lookAhead]?.type === "WHITESPACE") {
1433
- lookAhead++;
1434
- }
1435
- if (ctx.tokens[pos + lookAhead]?.type === "NEWLINE" || ctx.tokens[pos + lookAhead]?.type === "EOF" || !ctx.tokens[pos + lookAhead]) {
1436
- return false;
1437
- }
1438
- }
1439
- if (token5.type === markerType) {
1440
- if (markerValue === undefined || token5.value === markerValue) {
1441
- return true;
1442
- }
1443
- }
1444
- pos++;
1445
- }
1446
- return false;
1447
- }
1448
1675
  // packages/parser/src/parser/rules/block/heading/open.ts
1449
1676
  function parseHeadingOpen(ctx) {
1450
1677
  const marker = ctx.tokens[ctx.pos];
@@ -1511,6 +1738,15 @@ var headingRule = {
1511
1738
  const inlineCtx = { ...ctx, pos };
1512
1739
  const inlineResult = parseInlineUntil(inlineCtx, "NEWLINE");
1513
1740
  const children = inlineResult.elements;
1741
+ while (children.at(-1)?.element === "text") {
1742
+ const last = children.at(-1);
1743
+ if (last.element !== "text")
1744
+ break;
1745
+ last.data = last.data.trimEnd();
1746
+ if (last.data)
1747
+ break;
1748
+ children.pop();
1749
+ }
1514
1750
  consumed += inlineResult.consumed;
1515
1751
  pos += inlineResult.consumed;
1516
1752
  if (ctx.tokens[pos]?.type === "NEWLINE") {
@@ -2310,17 +2546,15 @@ function parseBlockquoteLine(ctx, startPos) {
2310
2546
  if (ctx.tokens[pos]?.type !== "WHITESPACE") {
2311
2547
  return { kind: "skipped", consumed: consumeLineRemainder(ctx, pos) + consumed };
2312
2548
  }
2313
- while (ctx.tokens[pos]?.type === "WHITESPACE") {
2549
+ pos++;
2550
+ consumed++;
2551
+ const contentStart = pos;
2552
+ while (pos < ctx.tokens.length && ctx.tokens[pos]?.type !== "NEWLINE" && ctx.tokens[pos]?.type !== "EOF") {
2314
2553
  pos++;
2315
2554
  consumed++;
2316
2555
  }
2317
- const inlineCtx = { ...ctx, pos };
2318
- const inlineResult = parseInlineUntil(inlineCtx, "NEWLINE");
2319
- consumed += inlineResult.consumed;
2320
- pos += inlineResult.consumed;
2321
- let hasLineBreak = false;
2322
2556
  if (ctx.tokens[pos]?.type === "NEWLINE") {
2323
- hasLineBreak = true;
2557
+ pos++;
2324
2558
  consumed++;
2325
2559
  }
2326
2560
  return {
@@ -2328,7 +2562,7 @@ function parseBlockquoteLine(ctx, startPos) {
2328
2562
  line: {
2329
2563
  depth: depth - 1,
2330
2564
  ltype: null,
2331
- value: { elements: inlineResult.elements, hasLineBreak }
2565
+ value: { start: contentStart, end: pos }
2332
2566
  },
2333
2567
  consumed
2334
2568
  };
@@ -2347,47 +2581,43 @@ function consumeLineRemainder(ctx, startPos) {
2347
2581
  }
2348
2582
 
2349
2583
  // packages/parser/src/parser/rules/block/blockquote/build.ts
2350
- function buildBlockquoteElements(lines) {
2584
+ var EXCLUDED_BLOCK_NAMES = new Set([
2585
+ "bibliography",
2586
+ "code",
2587
+ "html",
2588
+ "include",
2589
+ "math",
2590
+ "module"
2591
+ ]);
2592
+ var NEVER_CLOSES = () => false;
2593
+ function buildBlockquoteElements(ctx, lines) {
2351
2594
  const depthTrees = processDepths(null, lines);
2352
- return depthTrees.map(({ list }) => buildBlockquoteElement(list));
2595
+ return depthTrees.map(({ list }) => buildBlockquoteElement(ctx, list)).filter((element) => element !== null);
2353
2596
  }
2354
- function buildBlockquoteElement(list) {
2597
+ function buildBlockquoteElement(ctx, list) {
2355
2598
  const children = [];
2356
- let currentParagraphChildren = [];
2357
- function flushParagraph() {
2358
- if (currentParagraphChildren.length > 0) {
2359
- while (currentParagraphChildren.length > 0 && currentParagraphChildren[currentParagraphChildren.length - 1]?.element === "line-break") {
2360
- currentParagraphChildren.pop();
2361
- }
2362
- if (currentParagraphChildren.length > 0) {
2363
- children.push({
2364
- element: "container",
2365
- data: {
2366
- type: "paragraph",
2367
- attributes: {},
2368
- elements: currentParagraphChildren
2369
- }
2370
- });
2371
- }
2372
- currentParagraphChildren = [];
2373
- }
2599
+ let pending = [];
2600
+ function flushPending() {
2601
+ if (pending.length === 0)
2602
+ return;
2603
+ children.push(...parseLines(ctx, pending));
2604
+ pending = [];
2374
2605
  }
2375
2606
  for (const item of list) {
2376
2607
  if (item.kind === "item") {
2377
- if (item.value.elements.length === 0) {
2378
- flushParagraph();
2379
- continue;
2380
- }
2381
- currentParagraphChildren.push(...item.value.elements);
2382
- if (item.value.hasLineBreak) {
2383
- currentParagraphChildren.push({ element: "line-break" });
2384
- }
2385
- } else {
2386
- flushParagraph();
2387
- children.push(buildBlockquoteElement(item.children));
2608
+ pending.push(item.value);
2609
+ continue;
2388
2610
  }
2611
+ flushPending();
2612
+ const nested = buildBlockquoteElement(ctx, item.children);
2613
+ if (nested) {
2614
+ children.push(nested);
2615
+ }
2616
+ }
2617
+ flushPending();
2618
+ if (children.length === 0) {
2619
+ return null;
2389
2620
  }
2390
- flushParagraph();
2391
2621
  return {
2392
2622
  element: "container",
2393
2623
  data: {
@@ -2397,6 +2627,31 @@ function buildBlockquoteElement(list) {
2397
2627
  }
2398
2628
  };
2399
2629
  }
2630
+ function parseLines(ctx, lines) {
2631
+ const tokens = sliceLineTokens(ctx, lines);
2632
+ const lineCtx = { ...ctx, tokens, pos: 0 };
2633
+ return parseBlocksUntil(lineCtx, NEVER_CLOSES, {
2634
+ excludedBlockNames: EXCLUDED_BLOCK_NAMES
2635
+ }).elements;
2636
+ }
2637
+ function sliceLineTokens(ctx, lines) {
2638
+ const tokens = [];
2639
+ for (const { start, end } of lines) {
2640
+ for (let pos = start;pos < end; pos++) {
2641
+ const token5 = ctx.tokens[pos];
2642
+ if (token5) {
2643
+ tokens.push(token5);
2644
+ }
2645
+ }
2646
+ }
2647
+ const last = tokens[tokens.length - 1];
2648
+ tokens.push(createToken("EOF", "", last?.position ?? ZERO_POSITION2));
2649
+ return tokens;
2650
+ }
2651
+ var ZERO_POSITION2 = {
2652
+ start: { line: 0, column: 0, offset: 0 },
2653
+ end: { line: 0, column: 0, offset: 0 }
2654
+ };
2400
2655
 
2401
2656
  // packages/parser/src/parser/rules/block/blockquote/lines.ts
2402
2657
  function collectBlockquoteLines(ctx) {
@@ -2405,16 +2660,90 @@ function collectBlockquoteLines(ctx) {
2405
2660
  let consumed = 0;
2406
2661
  while (pos < ctx.tokens.length) {
2407
2662
  const result = parseBlockquoteLine(ctx, pos);
2408
- if (result.kind === "stop")
2409
- break;
2663
+ if (result.kind === "stop") {
2664
+ const resumed = extendToCommentClose(ctx, lines, pos);
2665
+ if (resumed === pos)
2666
+ break;
2667
+ consumed += resumed - pos;
2668
+ pos = resumed;
2669
+ continue;
2670
+ }
2410
2671
  pos += result.consumed;
2411
2672
  consumed += result.consumed;
2412
2673
  if (result.kind === "parsed") {
2413
2674
  lines.push(result.line);
2414
2675
  }
2415
2676
  }
2677
+ blankCommentOnlyLines(ctx, lines);
2416
2678
  return { lines, consumed };
2417
2679
  }
2680
+ function extendToCommentClose(ctx, lines, stopPos) {
2681
+ const last = lines[lines.length - 1];
2682
+ if (!last || !endsInsideComment(ctx, lines)) {
2683
+ return stopPos;
2684
+ }
2685
+ let pos = stopPos;
2686
+ while (pos < ctx.tokens.length && ctx.tokens[pos]?.type !== "COMMENT_CLOSE") {
2687
+ if (ctx.tokens[pos]?.type === "EOF")
2688
+ return stopPos;
2689
+ pos++;
2690
+ }
2691
+ while (pos < ctx.tokens.length && ctx.tokens[pos]?.type !== "EOF") {
2692
+ pos++;
2693
+ if (ctx.tokens[pos - 1]?.type === "NEWLINE")
2694
+ break;
2695
+ }
2696
+ last.value.end = pos;
2697
+ return pos;
2698
+ }
2699
+ function endsInsideComment(ctx, lines) {
2700
+ let open = false;
2701
+ for (const { value } of lines) {
2702
+ for (let pos = value.start;pos < value.end; pos++) {
2703
+ const type = ctx.tokens[pos]?.type;
2704
+ if (type === "COMMENT_OPEN")
2705
+ open = true;
2706
+ else if (type === "COMMENT_CLOSE")
2707
+ open = false;
2708
+ }
2709
+ }
2710
+ return open;
2711
+ }
2712
+ function blankCommentOnlyLines(ctx, lines) {
2713
+ const positions = [];
2714
+ lines.forEach((line, index) => {
2715
+ for (let pos = line.value.start;pos < line.value.end; pos++) {
2716
+ if (ctx.tokens[pos]?.type !== "NEWLINE") {
2717
+ positions.push({ line: index, pos });
2718
+ }
2719
+ }
2720
+ });
2721
+ const commented = Array.from({ length: positions.length }, () => false);
2722
+ for (let open = 0;open < positions.length; open++) {
2723
+ if (ctx.tokens[positions[open].pos]?.type !== "COMMENT_OPEN")
2724
+ continue;
2725
+ let close = open + 1;
2726
+ while (close < positions.length && ctx.tokens[positions[close].pos]?.type !== "COMMENT_CLOSE") {
2727
+ close++;
2728
+ }
2729
+ if (close === positions.length)
2730
+ break;
2731
+ commented.fill(true, open, close + 1);
2732
+ open = close;
2733
+ }
2734
+ const hasContent = Array.from({ length: lines.length }, () => false);
2735
+ positions.forEach(({ line, pos }, index) => {
2736
+ if (commented[index] || ctx.tokens[pos]?.type === "WHITESPACE")
2737
+ return;
2738
+ hasContent[line] = true;
2739
+ });
2740
+ lines.forEach((line, index) => {
2741
+ if (hasContent[index])
2742
+ return;
2743
+ const { end } = line.value;
2744
+ line.value.start = ctx.tokens[end - 1]?.type === "NEWLINE" ? end - 1 : end;
2745
+ });
2746
+ }
2418
2747
 
2419
2748
  // packages/parser/src/parser/rules/block/blockquote/index.ts
2420
2749
  var blockquoteRule = {
@@ -2433,9 +2762,9 @@ var blockquoteRule = {
2433
2762
  }
2434
2763
  return { success: false };
2435
2764
  }
2436
- const blockquotes = buildBlockquoteElements(blockquoteLines.lines);
2765
+ const blockquotes = buildBlockquoteElements(ctx, blockquoteLines.lines);
2437
2766
  if (blockquotes.length === 0) {
2438
- return { success: false };
2767
+ return { success: true, elements: [], consumed: blockquoteLines.consumed };
2439
2768
  }
2440
2769
  return {
2441
2770
  success: true,
@@ -2530,17 +2859,8 @@ function parseDefinitionItemValue(ctx, startPos) {
2530
2859
  break;
2531
2860
  }
2532
2861
  if (token5.type === "NEWLINE") {
2533
- const nextToken = ctx.tokens[pos + 1];
2534
- if (nextToken?.type === "COLON" && nextToken.lineStart) {
2535
- pos++;
2536
- consumed++;
2537
- break;
2538
- }
2539
- if (nextToken?.type === "NEWLINE" || !nextToken || nextToken.type === "EOF") {
2540
- pos++;
2541
- consumed++;
2542
- break;
2543
- }
2862
+ consumed++;
2863
+ break;
2544
2864
  }
2545
2865
  const inlineCtx = { ...ctx, pos };
2546
2866
  const result = parseInlineUntil(inlineCtx, "NEWLINE");
@@ -2618,14 +2938,10 @@ var definitionListRule = {
2618
2938
  if (result.items.length === 0) {
2619
2939
  return { success: false };
2620
2940
  }
2941
+ const items = toDefinitionListItems(result.items.filter((item) => item.value.length > 0));
2621
2942
  return {
2622
2943
  success: true,
2623
- elements: [
2624
- {
2625
- element: "definition-list",
2626
- data: toDefinitionListItems(result.items)
2627
- }
2628
- ],
2944
+ elements: items.length > 0 ? [{ element: "definition-list", data: items }] : [],
2629
2945
  consumed: result.consumed
2630
2946
  };
2631
2947
  }
@@ -2730,20 +3046,49 @@ var paragraphRule = {
2730
3046
  }
2731
3047
  return {
2732
3048
  success: true,
2733
- elements: [
2734
- {
2735
- element: "container",
2736
- data: {
2737
- type: "paragraph",
2738
- attributes: {},
2739
- elements
2740
- }
2741
- }
2742
- ],
3049
+ elements: wrapParagraphElements(elements),
2743
3050
  consumed: result.consumed
2744
3051
  };
2745
3052
  }
2746
3053
  };
3054
+ function wrapParagraphElements(elements) {
3055
+ const output = [];
3056
+ let group = [];
3057
+ let bare = false;
3058
+ const flush = (trimBreaks = false) => {
3059
+ const content = trimBreaks ? normalizeParagraphElements(group) : group;
3060
+ while (content[0]?.element === "line-break")
3061
+ content.shift();
3062
+ while (content.length) {
3063
+ const last = content.at(-1);
3064
+ if (last.element !== "text" || last.data.trim() !== "")
3065
+ break;
3066
+ content.pop();
3067
+ }
3068
+ while (content[0]?.element === "text" && content[0].data.trim() === "")
3069
+ content.shift();
3070
+ if (content[0]?.element === "text")
3071
+ content[0] = { element: "text", data: content[0].data.trimStart() };
3072
+ if (content.length)
3073
+ output.push(...bare || content.some((el) => el.element === "image") ? content : [
3074
+ {
3075
+ element: "container",
3076
+ data: { type: "paragraph", attributes: {}, elements: content }
3077
+ }
3078
+ ]);
3079
+ group = [];
3080
+ };
3081
+ for (const el of elements) {
3082
+ if (el.element === "image" && el.data.alignment !== null || el.element === "embed-block") {
3083
+ flush(el.element === "image");
3084
+ output.push(el);
3085
+ bare = el.element === "embed-block";
3086
+ } else
3087
+ group.push(el);
3088
+ }
3089
+ flush();
3090
+ return output;
3091
+ }
2747
3092
 
2748
3093
  // packages/parser/src/parser/rules/block/div/close.ts
2749
3094
  function isDivClose(ctx) {
@@ -3109,9 +3454,6 @@ function consumeCodeClose(ctx, startPos, closeNameConsumed) {
3109
3454
  pos++;
3110
3455
  consumed++;
3111
3456
  }
3112
- if (ctx.tokens[pos]?.type === "NEWLINE") {
3113
- consumed++;
3114
- }
3115
3457
  return consumed;
3116
3458
  }
3117
3459
 
@@ -3168,16 +3510,13 @@ var codeBlockRule = {
3168
3510
  name: attrResult.attrs.name ?? null
3169
3511
  };
3170
3512
  ctx.codeBlocks.push(codeBlockData);
3171
- return {
3172
- success: true,
3173
- elements: [
3174
- {
3175
- element: "code",
3176
- data: codeBlockData
3177
- }
3178
- ],
3179
- consumed
3180
- };
3513
+ const elements = [{ element: "code", data: codeBlockData }];
3514
+ if (ctx.tokens[pos]?.type === "NEWLINE" && !getParagraphNewlineBoundary(ctx, pos, false).shouldBreak && !ctx.scope.blockCloseCondition?.({ ...ctx, pos: pos + 1 })) {
3515
+ const after = parseInlineUntil({ ...ctx, pos: pos + 1 }, "PARAGRAPH_BREAK");
3516
+ elements.push({ element: "line-break" }, ...normalizeParagraphElements(after.elements));
3517
+ consumed += 1 + after.consumed;
3518
+ }
3519
+ return { success: true, elements, consumed };
3181
3520
  }
3182
3521
  };
3183
3522
 
@@ -3556,7 +3895,30 @@ function parseTableCell(ctx, startPos, cellStart) {
3556
3895
  consumed++;
3557
3896
  }
3558
3897
  const { inlineRules } = ctx;
3559
- const inlineCtx = { ...ctx, pos };
3898
+ let inlineEnd = pos;
3899
+ while (inlineEnd < ctx.tokens.length) {
3900
+ const rawEnd = protectedInlineRegionEnd(ctx.tokens, inlineEnd, ctx.tokens.length);
3901
+ if (rawEnd > inlineEnd) {
3902
+ inlineEnd = rawEnd;
3903
+ continue;
3904
+ }
3905
+ const token5 = ctx.tokens[inlineEnd];
3906
+ if (!token5 || token5.type === "EOF" || token5.type === "NEWLINE" || isPipeTableToken(token5.type))
3907
+ break;
3908
+ if (token5.type === "WHITESPACE" && ctx.tokens[inlineEnd + 1]?.type === "UNDERSCORE" && ctx.tokens[inlineEnd + 2]?.type === "NEWLINE")
3909
+ inlineEnd += 3;
3910
+ else
3911
+ inlineEnd++;
3912
+ }
3913
+ const inlineCtx = {
3914
+ ...ctx,
3915
+ pos,
3916
+ scope: {
3917
+ ...ctx.scope,
3918
+ inlineEnd,
3919
+ tableFormatting: isPipeTableToken(ctx.tokens[inlineEnd]?.type ?? "EOF") ? ctx.scope.tableFormatting : undefined
3920
+ }
3921
+ };
3560
3922
  while (pos < ctx.tokens.length) {
3561
3923
  const token5 = ctx.tokens[pos];
3562
3924
  if (!token5 || token5.type === "NEWLINE" || token5.type === "EOF") {
@@ -3565,6 +3927,11 @@ function parseTableCell(ctx, startPos, cellStart) {
3565
3927
  if (isPipeTableToken(token5.type)) {
3566
3928
  break;
3567
3929
  }
3930
+ if (ctx.scope.tableFormatting?.suppressedClosers.has(pos)) {
3931
+ pos++;
3932
+ consumed++;
3933
+ continue;
3934
+ }
3568
3935
  if (tryConsumeUnderscoreLineBreak(ctx, pos, children)) {
3569
3936
  pos += 3;
3570
3937
  consumed += 3;
@@ -3624,6 +3991,21 @@ function tryConsumeUnderscoreLineBreak(ctx, pos, children) {
3624
3991
 
3625
3992
  // packages/parser/src/parser/rules/block/table/pipe/row.ts
3626
3993
  function parsePipeTableRows(ctx, startPos) {
3994
+ let end = startPos;
3995
+ while (end < ctx.tokens.length && ctx.tokens[end]?.type !== "EOF") {
3996
+ const protectedEnd = protectedInlineRegionEnd(ctx.tokens, end, ctx.tokens.length);
3997
+ if (protectedEnd > end) {
3998
+ end = protectedEnd;
3999
+ continue;
4000
+ }
4001
+ if (ctx.tokens[end]?.type === "NEWLINE" && !isPipeTableToken(ctx.tokens[end + 1]?.type ?? "EOF") && !(ctx.tokens[end - 1]?.type === "UNDERSCORE" && ctx.tokens[end - 2]?.type === "WHITESPACE"))
4002
+ break;
4003
+ end++;
4004
+ }
4005
+ const tableCtx = {
4006
+ ...ctx,
4007
+ scope: { ...ctx.scope, tableFormatting: { end, suppressedClosers: new Set } }
4008
+ };
3627
4009
  const rows = [];
3628
4010
  let pos = startPos;
3629
4011
  let consumed = 0;
@@ -3632,7 +4014,7 @@ function parsePipeTableRows(ctx, startPos) {
3632
4014
  if (!token5 || !token5.lineStart || !isPipeTableToken(token5.type)) {
3633
4015
  break;
3634
4016
  }
3635
- const rowResult = parseTableRow(ctx, pos);
4017
+ const rowResult = parseTableRow(tableCtx, pos);
3636
4018
  rows.push(rowResult.row);
3637
4019
  pos += rowResult.consumed;
3638
4020
  consumed += rowResult.consumed;
@@ -9063,6 +9445,8 @@ var embedBlockRule = {
9063
9445
  name: "embed-block",
9064
9446
  startTokens: ["BLOCK_OPEN"],
9065
9447
  requiresLineStart: false,
9448
+ preservesPrecedingLineBreak: true,
9449
+ isStartPattern: (ctx, pos) => parseEmbedBlockOpen(ctx, pos) !== null,
9066
9450
  parse(ctx) {
9067
9451
  const openToken = currentToken(ctx);
9068
9452
  if (openToken.type !== "BLOCK_OPEN") {
@@ -9078,38 +9462,30 @@ var embedBlockRule = {
9078
9462
  pos += contentResult.consumed;
9079
9463
  consumed += contentResult.consumed;
9080
9464
  if (!contentResult.foundClose) {
9081
- ctx.diagnostics.push({
9082
- severity: "warning",
9083
- code: "unclosed-block",
9084
- message: `Missing closing tag [[/${openResult.blockName}]] for [[${openResult.blockName}]]`,
9085
- position: openToken.position
9086
- });
9465
+ if (!ctx.diagnostics.some((d) => d.code === "unclosed-block" && d.position === openToken.position))
9466
+ ctx.diagnostics.push({
9467
+ severity: "warning",
9468
+ code: "unclosed-block",
9469
+ message: `Missing closing tag [[/${openResult.blockName}]] for [[${openResult.blockName}]]`,
9470
+ position: openToken.position
9471
+ });
9087
9472
  return { success: false };
9088
9473
  }
9089
9474
  const closeConsumed = consumeEmbedClose(ctx, pos);
9090
9475
  pos += closeConsumed;
9091
9476
  consumed += closeConsumed;
9092
- return {
9093
- success: true,
9094
- elements: [
9095
- {
9096
- element: "container",
9097
- data: {
9098
- type: "paragraph",
9099
- attributes: {},
9100
- elements: [
9101
- {
9102
- element: "embed-block",
9103
- data: {
9104
- contents: contentResult.contents.trim()
9105
- }
9106
- }
9107
- ]
9108
- }
9109
- }
9110
- ],
9111
- consumed
9112
- };
9477
+ const elements = [
9478
+ { element: "embed-block", data: { contents: contentResult.contents.trim() } }
9479
+ ];
9480
+ if (ctx.scope.inlineEnd === undefined && ctx.tokens[pos]?.type !== "NEWLINE" && ctx.tokens[pos]?.type !== "EOF") {
9481
+ const after = parseInlineUntil({ ...ctx, pos }, "PARAGRAPH_BREAK");
9482
+ const tail = normalizeParagraphElements(after.elements);
9483
+ if (tail[0]?.element === "text")
9484
+ tail[0].data = tail[0].data.trimStart();
9485
+ elements.push(...tail);
9486
+ consumed += after.consumed;
9487
+ }
9488
+ return { success: true, elements, consumed };
9113
9489
  }
9114
9490
  };
9115
9491
 
@@ -9423,11 +9799,11 @@ var iftagsRule = {
9423
9799
  };
9424
9800
 
9425
9801
  // packages/parser/src/parser/rules/block/toc/element.ts
9426
- function createTocElement(align) {
9802
+ function createTocElement(align, title) {
9427
9803
  return {
9428
9804
  element: "table-of-contents",
9429
9805
  data: {
9430
- attributes: {},
9806
+ attributes: title === undefined ? {} : { title },
9431
9807
  align
9432
9808
  }
9433
9809
  };
@@ -9470,26 +9846,17 @@ function parseTocOpen(ctx, startPos) {
9470
9846
  } else {
9471
9847
  return null;
9472
9848
  }
9473
- pos = skipUntilClose(ctx, pos);
9849
+ const attributes = parseAttributes(ctx, pos);
9850
+ pos += attributes.consumed;
9474
9851
  if (ctx.tokens[pos]?.type !== "BLOCK_CLOSE") {
9475
9852
  return null;
9476
9853
  }
9477
9854
  return {
9478
9855
  align,
9856
+ title: attributes.attrs.title,
9479
9857
  consumed: pos + 1 - startPos
9480
9858
  };
9481
9859
  }
9482
- function skipUntilClose(ctx, startPos) {
9483
- let pos = startPos;
9484
- while (pos < ctx.tokens.length) {
9485
- const token5 = ctx.tokens[pos];
9486
- if (!token5 || token5.type === "BLOCK_CLOSE" || token5.type === "NEWLINE" || token5.type === "EOF") {
9487
- break;
9488
- }
9489
- pos++;
9490
- }
9491
- return pos;
9492
- }
9493
9860
  function isNameToken(token5) {
9494
9861
  return token5?.type === "TEXT" || token5?.type === "IDENTIFIER";
9495
9862
  }
@@ -9513,7 +9880,7 @@ var tocRule = {
9513
9880
  }
9514
9881
  return {
9515
9882
  success: true,
9516
- elements: [createTocElement(openResult.align)],
9883
+ elements: [createTocElement(openResult.align, openResult.title)],
9517
9884
  consumed: openResult.consumed
9518
9885
  };
9519
9886
  }
@@ -10114,6 +10481,31 @@ var blockRules = [
10114
10481
  galleryRule,
10115
10482
  divRule
10116
10483
  ];
10484
+ // packages/parser/src/parser/rules/inline/formatting/close.ts
10485
+ function findFormattingClose(ctx, start, marker) {
10486
+ const table = ctx.scope.tableFormatting;
10487
+ const end = table?.end ?? ctx.scope.inlineEnd ?? ctx.tokens.length;
10488
+ for (let pos = start;pos < end; pos++) {
10489
+ const token5 = ctx.tokens[pos];
10490
+ if (!token5 || token5.type === "EOF" || ctx.scope.blockCloseCondition?.({ ...ctx, pos }))
10491
+ return null;
10492
+ if (!table && token5.type === "NEWLINE" && getParagraphNewlineBoundary(ctx, pos, true).shouldBreak)
10493
+ return null;
10494
+ if (token5.type === marker && !table?.suppressedClosers.has(pos))
10495
+ return pos;
10496
+ const protectedEnd = protectedInlineRegionEnd(ctx.tokens, pos, end);
10497
+ if (protectedEnd > pos)
10498
+ pos = protectedEnd - 1;
10499
+ }
10500
+ return null;
10501
+ }
10502
+ function consumeFormattingClose(ctx, close, contentEnd) {
10503
+ if (close === contentEnd)
10504
+ return 1;
10505
+ ctx.scope.tableFormatting?.suppressedClosers.add(close);
10506
+ return 0;
10507
+ }
10508
+
10117
10509
  // packages/parser/src/parser/rules/inline/formatting/container.ts
10118
10510
  function createInlineContainer(type, elements) {
10119
10511
  return {
@@ -10125,9 +10517,10 @@ function createInlineContainer(type, elements) {
10125
10517
  }
10126
10518
  };
10127
10519
  }
10128
- function parseSameLineDelimitedContainer(ctx, closeToken, type, options = {}) {
10520
+ function parseDelimitedContainer(ctx, closeToken, type, options = {}) {
10129
10521
  const startToken = currentToken(ctx);
10130
- if (!hasClosingMarkerBeforeNewline({ ...ctx, pos: ctx.pos + 1 }, closeToken)) {
10522
+ const close = findFormattingClose(ctx, ctx.pos + 1, closeToken);
10523
+ if (close === null) {
10131
10524
  return {
10132
10525
  success: true,
10133
10526
  elements: [{ element: "text", data: startToken.value }],
@@ -10135,7 +10528,7 @@ function parseSameLineDelimitedContainer(ctx, closeToken, type, options = {}) {
10135
10528
  };
10136
10529
  }
10137
10530
  const result = parseInlineUntil({ ...ctx, pos: ctx.pos + 1 }, closeToken);
10138
- const consumed = 1 + result.consumed + 1;
10531
+ const consumed = 1 + result.consumed + consumeFormattingClose(ctx, close, ctx.pos + 1 + result.consumed);
10139
10532
  if (options.discardEmpty === true && result.elements.length === 0) {
10140
10533
  return {
10141
10534
  success: true,
@@ -10155,7 +10548,7 @@ var boldRule = {
10155
10548
  name: "bold",
10156
10549
  startTokens: ["BOLD_MARKER"],
10157
10550
  parse(ctx) {
10158
- return parseSameLineDelimitedContainer(ctx, "BOLD_MARKER", "bold", { discardEmpty: true });
10551
+ return parseDelimitedContainer(ctx, "BOLD_MARKER", "bold", { discardEmpty: true });
10159
10552
  }
10160
10553
  };
10161
10554
 
@@ -10164,102 +10557,28 @@ var italicRule = {
10164
10557
  name: "italic",
10165
10558
  startTokens: ["ITALIC_MARKER"],
10166
10559
  parse(ctx) {
10167
- return parseSameLineDelimitedContainer(ctx, "ITALIC_MARKER", "italics");
10560
+ return parseDelimitedContainer(ctx, "ITALIC_MARKER", "italics");
10168
10561
  }
10169
10562
  };
10170
10563
 
10171
- // packages/parser/src/parser/rules/inline/underline/child.ts
10172
- function parseUnderlineChild(ctx, pos) {
10173
- const token5 = ctx.tokens[pos];
10174
- if (!token5) {
10175
- return { elements: [], consumed: 0 };
10176
- }
10177
- if (token5.type === "NEWLINE") {
10178
- return { elements: [{ element: "line-break" }], consumed: 1 };
10179
- }
10180
- const result = parseInlineUntil({ ...ctx, pos }, "UNDERLINE_MARKER");
10181
- if (result.elements.length > 0) {
10182
- return { elements: result.elements, consumed: result.consumed };
10183
- }
10184
- return { elements: [{ element: "text", data: token5.value }], consumed: 1 };
10185
- }
10186
-
10187
- // packages/parser/src/parser/rules/inline/underline/content.ts
10188
- function parseUnderlineContent(ctx, startPos) {
10189
- const children = [];
10190
- let pos = startPos;
10191
- let consumed = 1;
10192
- while (pos < ctx.tokens.length) {
10193
- const token5 = ctx.tokens[pos];
10194
- if (!token5 || token5.type === "EOF")
10195
- break;
10196
- if (token5.type === "UNDERLINE_MARKER") {
10197
- consumed++;
10198
- break;
10199
- }
10200
- const child = parseUnderlineChild(ctx, pos);
10201
- children.push(...child.elements);
10202
- pos += child.consumed;
10203
- consumed += child.consumed;
10204
- }
10205
- return { children, consumed };
10206
- }
10207
-
10208
10564
  // packages/parser/src/parser/rules/inline/underline/index.ts
10209
10565
  var underlineRule = {
10210
10566
  name: "underline",
10211
10567
  startTokens: ["UNDERLINE_MARKER"],
10212
10568
  parse(ctx) {
10213
- const startToken = currentToken(ctx);
10214
- if (!hasClosingMarkerBeforeParagraphBreak({ ...ctx, pos: ctx.pos + 1 }, "UNDERLINE_MARKER")) {
10215
- return {
10216
- success: true,
10217
- elements: [{ element: "text", data: startToken.value }],
10218
- consumed: 1
10219
- };
10220
- }
10221
- const { children, consumed } = parseUnderlineContent(ctx, ctx.pos + 1);
10222
- if (children.length === 0) {
10223
- return {
10224
- success: true,
10225
- elements: [],
10226
- consumed
10227
- };
10228
- }
10229
- return {
10230
- success: true,
10231
- elements: [createInlineContainer("underline", children)],
10232
- consumed
10233
- };
10569
+ return parseDelimitedContainer(ctx, "UNDERLINE_MARKER", "underline", { discardEmpty: true });
10234
10570
  }
10235
10571
  };
10236
10572
 
10237
10573
  // packages/parser/src/parser/rules/inline/strikethrough/parse.ts
10238
10574
  function parseStrikethroughContent(ctx) {
10239
- const result = parseInlineUntil({ ...ctx, pos: ctx.pos + 1 }, "STRIKE_MARKER");
10240
- return {
10241
- success: true,
10242
- elements: [createInlineContainer("strikethrough", result.elements)],
10243
- consumed: 1 + result.consumed + 1
10244
- };
10575
+ return parseDelimitedContainer(ctx, "STRIKE_MARKER", "strikethrough");
10245
10576
  }
10246
10577
 
10247
10578
  // packages/parser/src/parser/rules/inline/strikethrough/syntax.ts
10248
10579
  function hasValidStrikethroughClose(ctx) {
10249
- let pos = ctx.pos + 1;
10250
- let prevWasWhitespace = false;
10251
- while (pos < ctx.tokens.length) {
10252
- const token5 = ctx.tokens[pos];
10253
- if (!token5 || token5.type === "NEWLINE" || token5.type === "EOF") {
10254
- return false;
10255
- }
10256
- if (token5.type === "STRIKE_MARKER") {
10257
- return !prevWasWhitespace;
10258
- }
10259
- prevWasWhitespace = token5.type === "WHITESPACE";
10260
- pos++;
10261
- }
10262
- return false;
10580
+ const close = findFormattingClose(ctx, ctx.pos + 1, "STRIKE_MARKER");
10581
+ return close !== null && close > ctx.pos + 1 && ctx.tokens[close - 1]?.type !== "WHITESPACE";
10263
10582
  }
10264
10583
 
10265
10584
  // packages/parser/src/parser/rules/inline/strikethrough/index.ts
@@ -10283,7 +10602,7 @@ var superscriptRule = {
10283
10602
  name: "superscript",
10284
10603
  startTokens: ["SUPER_MARKER"],
10285
10604
  parse(ctx) {
10286
- return parseSameLineDelimitedContainer(ctx, "SUPER_MARKER", "superscript", {
10605
+ return parseDelimitedContainer(ctx, "SUPER_MARKER", "superscript", {
10287
10606
  discardEmpty: true
10288
10607
  });
10289
10608
  }
@@ -10294,7 +10613,7 @@ var subscriptRule = {
10294
10613
  name: "subscript",
10295
10614
  startTokens: ["SUB_MARKER"],
10296
10615
  parse(ctx) {
10297
- return parseSameLineDelimitedContainer(ctx, "SUB_MARKER", "subscript", { discardEmpty: true });
10616
+ return parseDelimitedContainer(ctx, "SUB_MARKER", "subscript", { discardEmpty: true });
10298
10617
  }
10299
10618
  };
10300
10619
 
@@ -10303,7 +10622,7 @@ var monospaceRule = {
10303
10622
  name: "monospace",
10304
10623
  startTokens: ["MONO_MARKER"],
10305
10624
  parse(ctx) {
10306
- return parseSameLineDelimitedContainer(ctx, "MONO_CLOSE", "monospace");
10625
+ return parseDelimitedContainer(ctx, "MONO_CLOSE", "monospace");
10307
10626
  }
10308
10627
  };
10309
10628
 
@@ -10664,13 +10983,14 @@ var linkStarRule = {
10664
10983
 
10665
10984
  // packages/parser/src/parser/rules/inline/color/syntax.ts
10666
10985
  function parseColorContent(ctx) {
10667
- if (!hasClosingMarkerBeforeNewline({ ...ctx, pos: ctx.pos + 1 }, "COLOR_MARKER")) {
10986
+ const close = findFormattingClose(ctx, ctx.pos + 1, "COLOR_MARKER");
10987
+ if (close === null) {
10668
10988
  return null;
10669
10989
  }
10670
10990
  let pos = ctx.pos + 1;
10671
10991
  let consumed = 1;
10672
10992
  let colorSpec = "";
10673
- while (pos < ctx.tokens.length) {
10993
+ while (pos < (ctx.scope.inlineEnd ?? ctx.tokens.length)) {
10674
10994
  const token5 = ctx.tokens[pos];
10675
10995
  if (!token5 || token5.type === "PIPE" || token5.type === "COLOR_MARKER" || token5.type === "NEWLINE" || token5.type === "EOF") {
10676
10996
  break;
@@ -10687,14 +11007,11 @@ function parseColorContent(ctx) {
10687
11007
  const contentResult = parseInlineUntil({ ...ctx, pos }, "COLOR_MARKER");
10688
11008
  pos += contentResult.consumed;
10689
11009
  consumed += contentResult.consumed;
10690
- if (ctx.tokens[pos]?.type !== "COLOR_MARKER") {
10691
- return null;
10692
- }
10693
- consumed++;
10694
11010
  const color = colorSpec.trim();
10695
11011
  if (color === "" || contentResult.elements.length === 0) {
10696
11012
  return null;
10697
11013
  }
11014
+ consumed += consumeFormattingClose(ctx, close, pos);
10698
11015
  return {
10699
11016
  color: hexifyColor(color),
10700
11017
  elements: contentResult.elements,
@@ -11317,14 +11634,19 @@ function parseSpanContent(ctx, startPos, blockName) {
11317
11634
  const escapedChildren = [];
11318
11635
  const splitSpans = [];
11319
11636
  let foundClose = false;
11637
+ let forcedClose = false;
11320
11638
  let afterBlankLine = false;
11321
11639
  let consumed = 0;
11322
11640
  let pos = startPos;
11323
- while (pos < ctx.tokens.length) {
11641
+ while (pos < (ctx.scope.inlineEnd ?? ctx.tokens.length)) {
11324
11642
  const token5 = ctx.tokens[pos];
11325
11643
  if (!token5 || token5.type === "EOF") {
11326
11644
  break;
11327
11645
  }
11646
+ if (ctx.scope.tableFormatting?.suppressedClosers.has(pos)) {
11647
+ forcedClose = true;
11648
+ break;
11649
+ }
11328
11650
  const close = parseCloseSpan(ctx, pos);
11329
11651
  if (close.success) {
11330
11652
  pos += close.consumed;
@@ -11349,6 +11671,29 @@ function parseSpanContent(ctx, startPos, blockName) {
11349
11671
  pos += parsed.consumed;
11350
11672
  consumed += parsed.consumed;
11351
11673
  }
11674
+ if (!foundClose && ctx.scope.tableFormatting && (pos === ctx.scope.inlineEnd || forcedClose)) {
11675
+ let depth = 0;
11676
+ for (let next = pos;next < ctx.scope.tableFormatting.end; next++) {
11677
+ const rawEnd = rawRegionEnd(ctx.tokens, next, ctx.scope.tableFormatting.end);
11678
+ if (rawEnd > next) {
11679
+ next = rawEnd - 1;
11680
+ continue;
11681
+ }
11682
+ if (ctx.tokens[next]?.type === "BLOCK_OPEN" && /^span_?$/i.test(ctx.tokens[next + 1]?.value ?? ""))
11683
+ depth++;
11684
+ const close = parseCloseSpan(ctx, next);
11685
+ if (!close.success)
11686
+ continue;
11687
+ if (depth > 0) {
11688
+ depth--;
11689
+ continue;
11690
+ }
11691
+ for (let offset = 0;offset < close.consumed; offset++)
11692
+ ctx.scope.tableFormatting.suppressedClosers.add(next + offset);
11693
+ foundClose = true;
11694
+ break;
11695
+ }
11696
+ }
11352
11697
  return { children, escapedChildren, splitSpans, consumed, foundClose };
11353
11698
  }
11354
11699
  function parseOneSpanChild(ctx, pos, targetChildren) {
@@ -11760,135 +12105,6 @@ var footnoteRule = {
11760
12105
  }
11761
12106
  };
11762
12107
 
11763
- // packages/parser/src/parser/rules/inline/image/attributes.ts
11764
- function parseImageAttributes(ctx, startPos) {
11765
- const result = parseAttributesRaw(ctx, startPos, false);
11766
- const link = result.attrs.link ?? null;
11767
- const { link: _link, ...htmlAttributes } = result.attrs;
11768
- return {
11769
- attributes: filterUnsafeAttributes(htmlAttributes),
11770
- link,
11771
- consumed: result.consumed
11772
- };
11773
- }
11774
-
11775
- // packages/parser/src/parser/rules/inline/image/body.ts
11776
- function parseImageSourceText(ctx, startPos) {
11777
- let pos = startPos;
11778
- let consumed = 0;
11779
- while (ctx.tokens[pos]?.type === "WHITESPACE") {
11780
- pos++;
11781
- consumed++;
11782
- }
11783
- let sourceText = "";
11784
- while (pos < ctx.tokens.length) {
11785
- const token5 = ctx.tokens[pos];
11786
- if (!token5 || token5.type === "WHITESPACE" || token5.type === "BLOCK_CLOSE" || token5.type === "NEWLINE" || token5.type === "EOF") {
11787
- break;
11788
- }
11789
- sourceText += token5.value;
11790
- pos++;
11791
- consumed++;
11792
- }
11793
- return { sourceText, consumed };
11794
- }
11795
-
11796
- // packages/parser/src/parser/rules/inline/image/syntax.ts
11797
- var IMAGE_BLOCK_NAMES = new Set([
11798
- "image",
11799
- "=image",
11800
- "<image",
11801
- ">image",
11802
- "f<image",
11803
- "f>image",
11804
- "f=image"
11805
- ]);
11806
- function parseImageBlockName(ctx, startPos) {
11807
- let pos = startPos;
11808
- let consumed = 0;
11809
- while (ctx.tokens[pos]?.type === "WHITESPACE") {
11810
- pos++;
11811
- consumed++;
11812
- }
11813
- const prefixResult = parseImagePrefix(ctx, pos);
11814
- const prefix = prefixResult.prefix;
11815
- pos += prefixResult.consumed;
11816
- consumed += prefixResult.consumed;
11817
- const nameToken = ctx.tokens[pos];
11818
- if (!nameToken || nameToken.type !== "TEXT" && nameToken.type !== "IDENTIFIER") {
11819
- return null;
11820
- }
11821
- return { name: prefix + nameToken.value.toLowerCase(), consumed: consumed + 1 };
11822
- }
11823
- function isImageBlockName(blockName) {
11824
- return IMAGE_BLOCK_NAMES.has(blockName);
11825
- }
11826
- function parseImagePrefix(ctx, pos) {
11827
- const token5 = ctx.tokens[pos];
11828
- if (token5?.type === "EQUALS") {
11829
- return { prefix: "=", consumed: 1 };
11830
- }
11831
- if (token5?.type === "TEXT" && token5.value === "<") {
11832
- return { prefix: "<", consumed: 1 };
11833
- }
11834
- if ((token5?.type === "TEXT" || token5?.type === "BLOCKQUOTE_MARKER") && token5.value === ">") {
11835
- return { prefix: ">", consumed: 1 };
11836
- }
11837
- if (token5?.type === "IDENTIFIER" && token5.value.toLowerCase() === "f") {
11838
- return parseFloatPrefix(ctx, pos + 1);
11839
- }
11840
- return { prefix: "", consumed: 0 };
11841
- }
11842
- function parseFloatPrefix(ctx, pos) {
11843
- const token5 = ctx.tokens[pos];
11844
- if (token5?.type === "TEXT" && token5.value === "<") {
11845
- return { prefix: "f<", consumed: 2 };
11846
- }
11847
- if ((token5?.type === "TEXT" || token5?.type === "BLOCKQUOTE_MARKER") && token5.value === ">") {
11848
- return { prefix: "f>", consumed: 2 };
11849
- }
11850
- if (token5?.type === "EQUALS") {
11851
- return { prefix: "f=", consumed: 2 };
11852
- }
11853
- return { prefix: "", consumed: 0 };
11854
- }
11855
-
11856
- // packages/parser/src/parser/rules/inline/image/open.ts
11857
- function parseImageOpen(ctx) {
11858
- if (ctx.tokens[ctx.pos]?.type !== "BLOCK_OPEN") {
11859
- return null;
11860
- }
11861
- let pos = ctx.pos + 1;
11862
- let consumed = 1;
11863
- const nameResult = parseImageBlockName(ctx, pos);
11864
- if (!nameResult || !isImageBlockName(nameResult.name)) {
11865
- return null;
11866
- }
11867
- pos += nameResult.consumed;
11868
- consumed += nameResult.consumed;
11869
- const sourceText = parseImageSourceText(ctx, pos);
11870
- pos += sourceText.consumed;
11871
- consumed += sourceText.consumed;
11872
- const attrs = parseImageAttributes(ctx, pos);
11873
- pos += attrs.consumed;
11874
- consumed += attrs.consumed;
11875
- if (ctx.tokens[pos]?.type !== "BLOCK_CLOSE") {
11876
- return null;
11877
- }
11878
- pos++;
11879
- consumed++;
11880
- if (!sourceText.sourceText) {
11881
- return null;
11882
- }
11883
- return {
11884
- blockName: nameResult.name,
11885
- sourceText: sourceText.sourceText,
11886
- link: attrs.link,
11887
- attributes: attrs.attributes,
11888
- consumed
11889
- };
11890
- }
11891
-
11892
12108
  // packages/parser/src/parser/rules/inline/image/source.ts
11893
12109
  function parseImageSource(src) {
11894
12110
  if (src.startsWith("http://") || src.startsWith("https://") || src.startsWith("/")) {
@@ -12939,6 +13155,7 @@ var inlineRules = [
12939
13155
  htmlInlineRule,
12940
13156
  rawRule,
12941
13157
  imageRule,
13158
+ embedBlockRule,
12942
13159
  sizeRule,
12943
13160
  footnoteRule,
12944
13161
  spanRule,
@@ -14431,6 +14648,7 @@ export {
14431
14648
  container,
14432
14649
  compileTemplate,
14433
14650
  compileListUsersTemplate,
14651
+ buildInfo,
14434
14652
  bold,
14435
14653
  STYLE_SLOT_PREFIX2 as STYLE_SLOT_PREFIX,
14436
14654
  Parser,