@wdprlib/parser 5.1.5 → 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 (56) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +1 -1
  3. package/THIRD-PARTY-LICENSES.md +23 -0
  4. package/dist/index.cjs +655 -436
  5. package/dist/index.d.cts +11 -4
  6. package/dist/index.d.ts +11 -4
  7. package/dist/index.js +653 -435
  8. package/licenses/LGPL-2.1.txt +501 -0
  9. package/package.json +6 -3
  10. package/src/build-info.generated.ts +11 -0
  11. package/src/index.ts +2 -0
  12. package/src/lexer/lexer.ts +6 -4
  13. package/src/lexer/punctuation.ts +2 -1
  14. package/src/lexer/spacing-actions.ts +15 -0
  15. package/src/lexer/state.ts +30 -4
  16. package/src/lexer/token-factory.ts +15 -2
  17. package/src/lexer/tokens.ts +4 -3
  18. package/src/parser/rules/block/blockquote/build.ts +81 -37
  19. package/src/parser/rules/block/blockquote/index.ts +5 -6
  20. package/src/parser/rules/block/blockquote/line.ts +11 -10
  21. package/src/parser/rules/block/blockquote/lines.ts +102 -4
  22. package/src/parser/rules/block/code/content.ts +0 -3
  23. package/src/parser/rules/block/code/index.ts +14 -10
  24. package/src/parser/rules/block/definition-list/index.ts +4 -10
  25. package/src/parser/rules/block/definition-list/item-value.ts +2 -11
  26. package/src/parser/rules/block/definition-list/items.ts +1 -2
  27. package/src/parser/rules/block/embed-block/index.ts +30 -30
  28. package/src/parser/rules/block/heading/index.ts +7 -0
  29. package/src/parser/rules/block/paragraph/index.ts +41 -10
  30. package/src/parser/rules/block/parsing/content.ts +18 -1
  31. package/src/parser/rules/block/table/pipe/cell.ts +36 -1
  32. package/src/parser/rules/block/table/pipe/row.ts +21 -1
  33. package/src/parser/rules/block/toc/element.ts +2 -2
  34. package/src/parser/rules/block/toc/index.ts +2 -2
  35. package/src/parser/rules/block/toc/open.ts +5 -18
  36. package/src/parser/rules/contracts/scope.ts +4 -0
  37. package/src/parser/rules/inline/bold.ts +5 -5
  38. package/src/parser/rules/inline/color/syntax.ts +5 -8
  39. package/src/parser/rules/inline/formatting/close.ts +39 -0
  40. package/src/parser/rules/inline/formatting/container.ts +7 -4
  41. package/src/parser/rules/inline/index.ts +2 -0
  42. package/src/parser/rules/inline/italic.ts +5 -5
  43. package/src/parser/rules/inline/monospace.ts +5 -5
  44. package/src/parser/rules/inline/parsing/block-start-predicates.ts +2 -0
  45. package/src/parser/rules/inline/parsing/inline-content.ts +58 -4
  46. package/src/parser/rules/inline/raw/end.ts +28 -0
  47. package/src/parser/rules/inline/span/content.ts +32 -1
  48. package/src/parser/rules/inline/strikethrough/index.ts +1 -1
  49. package/src/parser/rules/inline/strikethrough/parse.ts +2 -9
  50. package/src/parser/rules/inline/strikethrough/syntax.ts +3 -20
  51. package/src/parser/rules/inline/subscript.ts +5 -5
  52. package/src/parser/rules/inline/superscript.ts +5 -5
  53. package/src/parser/rules/inline/underline/index.ts +5 -78
  54. package/src/parser/rules/tokens.ts +6 -15
  55. package/src/parser/rules/inline/underline/child.ts +0 -26
  56. package/src/parser/rules/inline/underline/content.ts +0 -29
package/dist/index.cjs CHANGED
@@ -1,4 +1,3 @@
1
- var import_node_module = require("node:module");
2
1
  var __defProp = Object.defineProperty;
3
2
  var __getOwnPropNames = Object.getOwnPropertyNames;
4
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -72,6 +71,7 @@ __export(exports_src, {
72
71
  container: () => import_ast9.container,
73
72
  compileTemplate: () => compileTemplate,
74
73
  compileListUsersTemplate: () => compileListUsersTemplate,
74
+ buildInfo: () => buildInfo,
75
75
  bold: () => import_ast9.bold,
76
76
  STYLE_SLOT_PREFIX: () => import_ast4.STYLE_SLOT_PREFIX,
77
77
  Parser: () => Parser,
@@ -79,6 +79,15 @@ __export(exports_src, {
79
79
  DEFAULT_SETTINGS: () => import_ast10.DEFAULT_SETTINGS
80
80
  });
81
81
  module.exports = __toCommonJS(exports_src);
82
+
83
+ // packages/parser/src/build-info.generated.ts
84
+ var buildInfo = Object.freeze({
85
+ version: "5.2.0",
86
+ sha: "cc290b0d882de3ed9ea33ec060ddfc8a7b9da59a",
87
+ dirty: false
88
+ });
89
+
90
+ // packages/parser/src/index.ts
82
91
  var import_ast9 = require("@wdprlib/ast");
83
92
  var import_ast10 = require("@wdprlib/ast");
84
93
 
@@ -86,49 +95,6 @@ var import_ast10 = require("@wdprlib/ast");
86
95
  function createToken(type, value, position, lineStart = false) {
87
96
  return { type, value, position, lineStart };
88
97
  }
89
- // packages/parser/src/lexer/token-factory.ts
90
- var ZERO_POSITION = {
91
- start: { line: 0, column: 0, offset: 0 },
92
- end: { line: 0, column: 0, offset: 0 }
93
- };
94
- function createLexerToken(state, type, value, trackPositions) {
95
- return {
96
- type,
97
- value,
98
- position: trackPositions ? currentTokenPosition(state, value) : ZERO_POSITION,
99
- lineStart: isTokenAtLineStart(state)
100
- };
101
- }
102
- function updateLastNonWhitespaceType(current, type) {
103
- return type === "WHITESPACE" ? current : type;
104
- }
105
- function nextBlockOpenerDepth(current, type) {
106
- if (type === "BLOCK_OPEN" || type === "BLOCK_END_OPEN") {
107
- return current + 1;
108
- }
109
- if (type === "BLOCK_CLOSE" && current > 0) {
110
- return current - 1;
111
- }
112
- return current;
113
- }
114
- function currentTokenPosition(state, value) {
115
- return {
116
- start: {
117
- line: state.line,
118
- column: state.column - value.length,
119
- offset: state.pos - value.length
120
- },
121
- end: {
122
- line: state.line,
123
- column: state.column,
124
- offset: state.pos
125
- }
126
- };
127
- }
128
- function isTokenAtLineStart(state) {
129
- return state.tokens.length === 0 || state.tokens[state.tokens.length - 1]?.type === "NEWLINE";
130
- }
131
-
132
98
  // packages/parser/src/lexer/state.ts
133
99
  function createInitialLexerState(source) {
134
100
  return {
@@ -137,9 +103,16 @@ function createInitialLexerState(source) {
137
103
  line: 1,
138
104
  column: 1,
139
105
  lineStart: true,
106
+ quoteContentStart: false,
140
107
  tokens: []
141
108
  };
142
109
  }
110
+ function isSyntaxLineStart(state) {
111
+ return state.lineStart || state.quoteContentStart;
112
+ }
113
+ function isLineStartQuoteMarker(token) {
114
+ return token?.type === "BLOCKQUOTE_MARKER" && token.lineStart;
115
+ }
143
116
  function isAtEnd(state) {
144
117
  return state.pos >= state.source.length;
145
118
  }
@@ -153,18 +126,25 @@ function advance(state, n = 1) {
153
126
  updatePosition(state, start, end);
154
127
  return value;
155
128
  }
156
- function advanceByToken(state, type, length) {
129
+ function advanceByToken(state, type, length, value = "") {
130
+ const afterQuoteMarker = isLineStartQuoteMarker(state.tokens[state.tokens.length - 1]);
157
131
  state.pos += length;
158
132
  if (type === "NEWLINE") {
159
133
  state.line++;
160
134
  state.column = 1;
161
135
  state.lineStart = true;
136
+ state.quoteContentStart = false;
162
137
  return;
163
138
  }
164
139
  state.column += length;
165
- if (type !== "WHITESPACE") {
166
- state.lineStart = false;
140
+ if (type === "WHITESPACE") {
141
+ if (afterQuoteMarker && value === " ") {
142
+ state.quoteContentStart = true;
143
+ }
144
+ return;
167
145
  }
146
+ state.lineStart = false;
147
+ state.quoteContentStart = false;
168
148
  }
169
149
  function updatePosition(state, start, end) {
170
150
  state.pos = end;
@@ -175,8 +155,9 @@ function updatePositionFromValue(state, value) {
175
155
  `);
176
156
  if (firstNewline === -1) {
177
157
  state.column += value.length;
178
- if (state.lineStart && hasNonLineStartSpacing(value, 0)) {
158
+ if (hasNonLineStartSpacing(value, 0)) {
179
159
  state.lineStart = false;
160
+ state.quoteContentStart = false;
180
161
  }
181
162
  return;
182
163
  }
@@ -195,6 +176,7 @@ function updatePositionFromValue(state, value) {
195
176
  state.line += newlineCount;
196
177
  state.column = value.length - lastNewline;
197
178
  state.lineStart = !hasNonLineStartSpacing(value, lastNewline + 1);
179
+ state.quoteContentStart = false;
198
180
  }
199
181
  function hasNonLineStartSpacing(value, start) {
200
182
  for (let i = start;i < value.length; i++) {
@@ -206,6 +188,56 @@ function hasNonLineStartSpacing(value, start) {
206
188
  return false;
207
189
  }
208
190
 
191
+ // packages/parser/src/lexer/token-factory.ts
192
+ var ZERO_POSITION = {
193
+ start: { line: 0, column: 0, offset: 0 },
194
+ end: { line: 0, column: 0, offset: 0 }
195
+ };
196
+ function createLexerToken(state, type, value, trackPositions) {
197
+ return {
198
+ type,
199
+ value,
200
+ position: trackPositions ? currentTokenPosition(state, value) : ZERO_POSITION,
201
+ lineStart: isTokenAtLineStart(state)
202
+ };
203
+ }
204
+ function updateLastNonWhitespaceType(current2, type) {
205
+ return type === "WHITESPACE" ? current2 : type;
206
+ }
207
+ function nextBlockOpenerDepth(current2, type) {
208
+ if (type === "BLOCK_OPEN" || type === "BLOCK_END_OPEN") {
209
+ return current2 + 1;
210
+ }
211
+ if (type === "BLOCK_CLOSE" && current2 > 0) {
212
+ return current2 - 1;
213
+ }
214
+ return current2;
215
+ }
216
+ function currentTokenPosition(state, value) {
217
+ return {
218
+ start: {
219
+ line: state.line,
220
+ column: state.column - value.length,
221
+ offset: state.pos - value.length
222
+ },
223
+ end: {
224
+ line: state.line,
225
+ column: state.column,
226
+ offset: state.pos
227
+ }
228
+ };
229
+ }
230
+ function isTokenAtLineStart(state) {
231
+ if (state.tokens.length === 0) {
232
+ return true;
233
+ }
234
+ const last = state.tokens[state.tokens.length - 1];
235
+ if (last?.type === "NEWLINE") {
236
+ return true;
237
+ }
238
+ return last?.type === "WHITESPACE" && last.value === " " && isLineStartQuoteMarker(state.tokens[state.tokens.length - 2]);
239
+ }
240
+
209
241
  // packages/parser/src/lexer/anchor.ts
210
242
  function findInvalidAnchorNameEnd(src, pos) {
211
243
  if (src[pos] !== "[" || src[pos + 1] !== "[" || src[pos + 2] !== "#") {
@@ -522,7 +554,7 @@ function scanPunctuationToken(input) {
522
554
  case "@":
523
555
  return { handled: true, actions: scanAtToken(source, pos) };
524
556
  case ">":
525
- return { handled: true, actions: scanGreaterToken(source, pos, lineStart) };
557
+ return { handled: true, actions: scanGreaterToken(source, pos, input.physicalLineStart) };
526
558
  case "-":
527
559
  return { handled: true, actions: scanDashToken(source, pos, lineStart) };
528
560
  case "~": {
@@ -564,6 +596,15 @@ function runToken3(src, pos, end, type) {
564
596
  }
565
597
 
566
598
  // packages/parser/src/lexer/spacing-actions.ts
599
+ function limitBlockquotePrefixSpace(action, previous) {
600
+ if (!isLineStartQuoteMarker(previous) || action.type !== "WHITESPACE") {
601
+ return action;
602
+ }
603
+ if (action.length <= 1 || !action.value.startsWith(" ")) {
604
+ return action;
605
+ }
606
+ return { type: "WHITESPACE", value: " ", length: 1 };
607
+ }
567
608
  function scanSpacingToken(src, pos) {
568
609
  const char = src[pos];
569
610
  if (char === `
@@ -625,7 +666,7 @@ class Lexer {
625
666
  this.blockOpenerDepth = nextBlockOpenerDepth(this.blockOpenerDepth, type);
626
667
  }
627
668
  emitTokenAction(action) {
628
- advanceByToken(this.state, action.type, action.length);
669
+ advanceByToken(this.state, action.type, action.length, action.value);
629
670
  this.addToken(action.type, action.value);
630
671
  }
631
672
  emitTokenActions(actions) {
@@ -639,11 +680,11 @@ class Lexer {
639
680
  }
640
681
  scanToken() {
641
682
  const char = this.current();
642
- const isLineStart = this.state.lineStart;
683
+ const isLineStart = isSyntaxLineStart(this.state);
643
684
  const src = this.state.source;
644
685
  const spacingAction = scanSpacingToken(src, this.state.pos);
645
686
  if (spacingAction) {
646
- this.emitTokenAction(spacingAction);
687
+ this.emitTokenAction(limitBlockquotePrefixSpace(spacingAction, this.state.tokens.at(-1)));
647
688
  return;
648
689
  }
649
690
  const punctuation = scanPunctuationToken({
@@ -651,6 +692,7 @@ class Lexer {
651
692
  source: src,
652
693
  pos: this.state.pos,
653
694
  lineStart: isLineStart,
695
+ physicalLineStart: this.state.lineStart,
654
696
  splitBlockClose: this.splitBlockClosePositions.has(this.state.pos),
655
697
  findInvalidAnchorNameEnd: () => this.findInvalidAnchorNameEnd()
656
698
  });
@@ -867,7 +909,7 @@ function parseBlocksUntil(ctx, closeCondition, options) {
867
909
  const elements = [];
868
910
  let consumed = 0;
869
911
  let pos = ctx.pos;
870
- const excluded = options?.excludedBlockNames;
912
+ const excluded = mergeExcludedBlockNames(ctx.scope.excludedBlockNames, options?.excludedBlockNames);
871
913
  const blockRules = excluded ? getExcludedBlockRules(ctx.blockRules, excluded) : ctx.blockRules;
872
914
  const blockScope = {
873
915
  ...ctx.scope,
@@ -909,6 +951,13 @@ function parseBlocksUntil(ctx, closeCondition, options) {
909
951
  }
910
952
  return { elements, consumed };
911
953
  }
954
+ function mergeExcludedBlockNames(inherited, added) {
955
+ if (!inherited?.size)
956
+ return added;
957
+ if (!added?.size)
958
+ return inherited;
959
+ return new Set([...inherited, ...added]);
960
+ }
912
961
  function getExcludedBlockRules(blockRules, excluded) {
913
962
  let byExcluded = excludedBlockRulesCache.get(blockRules);
914
963
  if (!byExcluded) {
@@ -945,6 +994,31 @@ function getCandidateInlineRules(inlineRules, tokenType) {
945
994
  byType.set(tokenType, candidates);
946
995
  return candidates;
947
996
  }
997
+ // packages/parser/src/parser/rules/inline/raw/end.ts
998
+ function rawRegionEnd(tokens, start, end) {
999
+ const type = tokens[start]?.type;
1000
+ const close = type === "RAW_OPEN" ? "RAW_OPEN" : type === "RAW_BLOCK_OPEN" ? "RAW_BLOCK_CLOSE" : null;
1001
+ if (!close)
1002
+ return start;
1003
+ for (let pos = start + 1;pos < end; pos++) {
1004
+ if (tokens[pos]?.type === "NEWLINE" || tokens[pos]?.type === "EOF")
1005
+ break;
1006
+ if (tokens[pos]?.type === close)
1007
+ return pos + 1;
1008
+ }
1009
+ return start;
1010
+ }
1011
+ function protectedInlineRegionEnd(tokens, start, end) {
1012
+ const rawEnd = rawRegionEnd(tokens, start, end);
1013
+ if (rawEnd > start || tokens[start]?.type !== "COMMENT_OPEN")
1014
+ return rawEnd;
1015
+ for (let pos = start + 1;pos < end; pos++) {
1016
+ if (tokens[pos]?.type === "COMMENT_CLOSE")
1017
+ return pos + 1;
1018
+ }
1019
+ return start;
1020
+ }
1021
+
948
1022
  // packages/parser/src/parser/rules/inline/parsing/plain-text.ts
949
1023
  var MIN_INLINE_TEXT_RUN_LENGTH = 32;
950
1024
  var MIN_INLINE_TEXT_RUN_DOCUMENT_TOKENS = 1e5;
@@ -987,6 +1061,135 @@ function isPlainTextRunToken(ctx, pos) {
987
1061
  return token5.value !== "(";
988
1062
  }
989
1063
 
1064
+ // packages/parser/src/parser/rules/inline/image/attributes.ts
1065
+ function parseImageAttributes(ctx, startPos) {
1066
+ const result = parseAttributesRaw(ctx, startPos, false);
1067
+ const link = result.attrs.link ?? null;
1068
+ const { link: _link, ...htmlAttributes } = result.attrs;
1069
+ return {
1070
+ attributes: filterUnsafeAttributes(htmlAttributes),
1071
+ link,
1072
+ consumed: result.consumed
1073
+ };
1074
+ }
1075
+
1076
+ // packages/parser/src/parser/rules/inline/image/body.ts
1077
+ function parseImageSourceText(ctx, startPos) {
1078
+ let pos = startPos;
1079
+ let consumed = 0;
1080
+ while (ctx.tokens[pos]?.type === "WHITESPACE") {
1081
+ pos++;
1082
+ consumed++;
1083
+ }
1084
+ let sourceText = "";
1085
+ while (pos < ctx.tokens.length) {
1086
+ const token5 = ctx.tokens[pos];
1087
+ if (!token5 || token5.type === "WHITESPACE" || token5.type === "BLOCK_CLOSE" || token5.type === "NEWLINE" || token5.type === "EOF") {
1088
+ break;
1089
+ }
1090
+ sourceText += token5.value;
1091
+ pos++;
1092
+ consumed++;
1093
+ }
1094
+ return { sourceText, consumed };
1095
+ }
1096
+
1097
+ // packages/parser/src/parser/rules/inline/image/syntax.ts
1098
+ var IMAGE_BLOCK_NAMES = new Set([
1099
+ "image",
1100
+ "=image",
1101
+ "<image",
1102
+ ">image",
1103
+ "f<image",
1104
+ "f>image",
1105
+ "f=image"
1106
+ ]);
1107
+ function parseImageBlockName(ctx, startPos) {
1108
+ let pos = startPos;
1109
+ let consumed = 0;
1110
+ while (ctx.tokens[pos]?.type === "WHITESPACE") {
1111
+ pos++;
1112
+ consumed++;
1113
+ }
1114
+ const prefixResult = parseImagePrefix(ctx, pos);
1115
+ const prefix = prefixResult.prefix;
1116
+ pos += prefixResult.consumed;
1117
+ consumed += prefixResult.consumed;
1118
+ const nameToken = ctx.tokens[pos];
1119
+ if (!nameToken || nameToken.type !== "TEXT" && nameToken.type !== "IDENTIFIER") {
1120
+ return null;
1121
+ }
1122
+ return { name: prefix + nameToken.value.toLowerCase(), consumed: consumed + 1 };
1123
+ }
1124
+ function isImageBlockName(blockName) {
1125
+ return IMAGE_BLOCK_NAMES.has(blockName);
1126
+ }
1127
+ function parseImagePrefix(ctx, pos) {
1128
+ const token5 = ctx.tokens[pos];
1129
+ if (token5?.type === "EQUALS") {
1130
+ return { prefix: "=", consumed: 1 };
1131
+ }
1132
+ if (token5?.type === "TEXT" && token5.value === "<") {
1133
+ return { prefix: "<", consumed: 1 };
1134
+ }
1135
+ if ((token5?.type === "TEXT" || token5?.type === "BLOCKQUOTE_MARKER") && token5.value === ">") {
1136
+ return { prefix: ">", consumed: 1 };
1137
+ }
1138
+ if (token5?.type === "IDENTIFIER" && token5.value.toLowerCase() === "f") {
1139
+ return parseFloatPrefix(ctx, pos + 1);
1140
+ }
1141
+ return { prefix: "", consumed: 0 };
1142
+ }
1143
+ function parseFloatPrefix(ctx, pos) {
1144
+ const token5 = ctx.tokens[pos];
1145
+ if (token5?.type === "TEXT" && token5.value === "<") {
1146
+ return { prefix: "f<", consumed: 2 };
1147
+ }
1148
+ if ((token5?.type === "TEXT" || token5?.type === "BLOCKQUOTE_MARKER") && token5.value === ">") {
1149
+ return { prefix: "f>", consumed: 2 };
1150
+ }
1151
+ if (token5?.type === "EQUALS") {
1152
+ return { prefix: "f=", consumed: 2 };
1153
+ }
1154
+ return { prefix: "", consumed: 0 };
1155
+ }
1156
+
1157
+ // packages/parser/src/parser/rules/inline/image/open.ts
1158
+ function parseImageOpen(ctx) {
1159
+ if (ctx.tokens[ctx.pos]?.type !== "BLOCK_OPEN") {
1160
+ return null;
1161
+ }
1162
+ let pos = ctx.pos + 1;
1163
+ let consumed = 1;
1164
+ const nameResult = parseImageBlockName(ctx, pos);
1165
+ if (!nameResult || !isImageBlockName(nameResult.name)) {
1166
+ return null;
1167
+ }
1168
+ pos += nameResult.consumed;
1169
+ consumed += nameResult.consumed;
1170
+ const sourceText = parseImageSourceText(ctx, pos);
1171
+ pos += sourceText.consumed;
1172
+ consumed += sourceText.consumed;
1173
+ const attrs = parseImageAttributes(ctx, pos);
1174
+ pos += attrs.consumed;
1175
+ consumed += attrs.consumed;
1176
+ if (ctx.tokens[pos]?.type !== "BLOCK_CLOSE") {
1177
+ return null;
1178
+ }
1179
+ pos++;
1180
+ consumed++;
1181
+ if (!sourceText.sourceText) {
1182
+ return null;
1183
+ }
1184
+ return {
1185
+ blockName: nameResult.name,
1186
+ sourceText: sourceText.sourceText,
1187
+ link: attrs.link,
1188
+ attributes: attrs.attributes,
1189
+ consumed
1190
+ };
1191
+ }
1192
+
990
1193
  // packages/parser/src/parser/constants.ts
991
1194
  var BLOCK_START_TOKENS = [
992
1195
  "BLOCKQUOTE_MARKER",
@@ -1117,7 +1320,7 @@ function isParagraphBreakingBlockStart(ctx, newlinePos, lookAhead) {
1117
1320
  if (!nextMeaningfulToken.lineStart && !isIndentedBlockOpener) {
1118
1321
  return false;
1119
1322
  }
1120
- return !isOrphanCloseSpan(ctx, nextPos) && !isAnchorName(ctx, nextPos) && !isInvalidBlockOpen(ctx, nextPos) && !isInvalidHeading(ctx, nextPos) && !isExcludedBlockStart(ctx, nextPos) && !isUnknownBlockStart(ctx, nextPos);
1323
+ return !parseImageOpen({ ...ctx, pos: nextPos }) && !isOrphanCloseSpan(ctx, nextPos) && !isAnchorName(ctx, nextPos) && !isInvalidBlockOpen(ctx, nextPos) && !isInvalidHeading(ctx, nextPos) && !isExcludedBlockStart(ctx, nextPos) && !isUnknownBlockStart(ctx, nextPos);
1121
1324
  }
1122
1325
  function isOrphanCloseSpan(ctx, blockEndOpenPos) {
1123
1326
  const token5 = ctx.tokens[blockEndOpenPos];
@@ -1227,27 +1430,45 @@ function parseInlineUntil(ctx, endType) {
1227
1430
  let consumed = 0;
1228
1431
  let pos = ctx.pos;
1229
1432
  const paragraphMode = endType === "PARAGRAPH_BREAK";
1433
+ const multiline = paragraphMode || FORMATTING_CLOSE_TOKENS.has(endType);
1434
+ let inlineEnd = ctx.scope.inlineEnd ?? ctx.tokens.length;
1435
+ if (!multiline) {
1436
+ for (let end = ctx.pos;end < inlineEnd; end++) {
1437
+ const protectedEnd = protectedInlineRegionEnd(ctx.tokens, end, inlineEnd);
1438
+ if (protectedEnd > end) {
1439
+ end = protectedEnd - 1;
1440
+ continue;
1441
+ }
1442
+ if (ctx.tokens[end]?.type === "NEWLINE" && ctx.tokens[end - 1]?.type === "UNDERSCORE" && ctx.tokens[end - 2]?.type === "WHITESPACE")
1443
+ continue;
1444
+ if (ctx.tokens[end]?.type === "NEWLINE" || ctx.tokens[end]?.type === endType) {
1445
+ inlineEnd = end;
1446
+ break;
1447
+ }
1448
+ }
1449
+ }
1230
1450
  const { inlineRules } = ctx;
1231
1451
  const inlineCtx = {
1232
1452
  ...ctx,
1233
- pos
1453
+ pos,
1454
+ scope: { ...ctx.scope, inlineEnd }
1234
1455
  };
1235
1456
  const canCollectLongPlainTextRuns = ctx.tokens.length >= MIN_INLINE_TEXT_RUN_DOCUMENT_TOKENS;
1236
- while (pos < ctx.tokens.length) {
1457
+ while (pos < inlineEnd) {
1237
1458
  const token5 = ctx.tokens[pos];
1238
1459
  if (!token5 || token5.type === "EOF") {
1239
1460
  break;
1240
1461
  }
1241
- if (paragraphMode && ctx.scope.blockCloseCondition) {
1462
+ if (ctx.scope.blockCloseCondition) {
1242
1463
  const checkCtx = { ...ctx, pos };
1243
1464
  if (ctx.scope.blockCloseCondition(checkCtx)) {
1244
1465
  break;
1245
1466
  }
1246
1467
  }
1247
- if (!paragraphMode && token5.type === "NEWLINE") {
1468
+ if (!multiline && token5.type === "NEWLINE") {
1248
1469
  break;
1249
1470
  }
1250
- if (paragraphMode && token5.type === "NEWLINE") {
1471
+ if (multiline && token5.type === "NEWLINE" && !ctx.scope.tableFormatting) {
1251
1472
  const boundary = getParagraphNewlineBoundary(ctx, pos, nodes.length > 0);
1252
1473
  if (boundary.shouldBreak) {
1253
1474
  if (boundary.preservePrecedingLineBreak) {
@@ -1257,6 +1478,11 @@ function parseInlineUntil(ctx, endType) {
1257
1478
  break;
1258
1479
  }
1259
1480
  }
1481
+ if (ctx.scope.tableFormatting?.suppressedClosers.has(pos)) {
1482
+ pos++;
1483
+ consumed++;
1484
+ continue;
1485
+ }
1260
1486
  if (token5.type === endType) {
1261
1487
  break;
1262
1488
  }
@@ -1281,6 +1507,24 @@ function parseInlineUntil(ctx, endType) {
1281
1507
  for (const rule of getCandidateInlineRules(inlineRules, token5.type)) {
1282
1508
  const result = rule.parse(inlineCtx);
1283
1509
  if (result.success) {
1510
+ if (rule.name === "comment") {
1511
+ let after = pos + result.consumed;
1512
+ while (ctx.tokens[after]?.type === "WHITESPACE")
1513
+ after++;
1514
+ if (ctx.tokens[after]?.type === "NEWLINE" || ctx.tokens[after]?.type === "EOF") {
1515
+ while (nodes.at(-1)?.element === "text") {
1516
+ const last = nodes.at(-1);
1517
+ if (last.element !== "text")
1518
+ break;
1519
+ last.data = last.data.trimEnd();
1520
+ if (last.data)
1521
+ break;
1522
+ nodes.pop();
1523
+ }
1524
+ if (nodes.at(-1)?.element === "line-break")
1525
+ nodes.pop();
1526
+ }
1527
+ }
1284
1528
  nodes.push(...result.elements);
1285
1529
  consumed += result.consumed;
1286
1530
  pos += result.consumed;
@@ -1296,6 +1540,16 @@ function parseInlineUntil(ctx, endType) {
1296
1540
  }
1297
1541
  return { elements: nodes, consumed };
1298
1542
  }
1543
+ var FORMATTING_CLOSE_TOKENS = new Set([
1544
+ "BOLD_MARKER",
1545
+ "ITALIC_MARKER",
1546
+ "UNDERLINE_MARKER",
1547
+ "STRIKE_MARKER",
1548
+ "SUPER_MARKER",
1549
+ "SUB_MARKER",
1550
+ "MONO_CLOSE",
1551
+ "COLOR_MARKER"
1552
+ ]);
1299
1553
  // packages/parser/src/parser/rules/block/parsing/attributes/names.ts
1300
1554
  function consumeAttributeName(ctx, startPos, startConsumed, startName, options) {
1301
1555
  if (startName === "_" && isAttributeWordToken(ctx.tokens[startPos])) {
@@ -1471,7 +1725,7 @@ function eofToken() {
1471
1725
  }
1472
1726
  function hasClosingMarkerBeforeNewline(ctx, markerType, markerValue) {
1473
1727
  let pos = ctx.pos;
1474
- while (pos < ctx.tokens.length) {
1728
+ while (pos < (ctx.scope.inlineEnd ?? ctx.tokens.length)) {
1475
1729
  const token5 = ctx.tokens[pos];
1476
1730
  if (!token5 || token5.type === "NEWLINE" || token5.type === "EOF") {
1477
1731
  return false;
@@ -1485,31 +1739,6 @@ function hasClosingMarkerBeforeNewline(ctx, markerType, markerValue) {
1485
1739
  }
1486
1740
  return false;
1487
1741
  }
1488
- function hasClosingMarkerBeforeParagraphBreak(ctx, markerType, markerValue) {
1489
- let pos = ctx.pos;
1490
- while (pos < ctx.tokens.length) {
1491
- const token5 = ctx.tokens[pos];
1492
- if (!token5 || token5.type === "EOF") {
1493
- return false;
1494
- }
1495
- if (token5.type === "NEWLINE") {
1496
- let lookAhead = 1;
1497
- while (ctx.tokens[pos + lookAhead]?.type === "WHITESPACE") {
1498
- lookAhead++;
1499
- }
1500
- if (ctx.tokens[pos + lookAhead]?.type === "NEWLINE" || ctx.tokens[pos + lookAhead]?.type === "EOF" || !ctx.tokens[pos + lookAhead]) {
1501
- return false;
1502
- }
1503
- }
1504
- if (token5.type === markerType) {
1505
- if (markerValue === undefined || token5.value === markerValue) {
1506
- return true;
1507
- }
1508
- }
1509
- pos++;
1510
- }
1511
- return false;
1512
- }
1513
1742
  // packages/parser/src/parser/rules/block/heading/open.ts
1514
1743
  function parseHeadingOpen(ctx) {
1515
1744
  const marker = ctx.tokens[ctx.pos];
@@ -1576,6 +1805,15 @@ var headingRule = {
1576
1805
  const inlineCtx = { ...ctx, pos };
1577
1806
  const inlineResult = parseInlineUntil(inlineCtx, "NEWLINE");
1578
1807
  const children = inlineResult.elements;
1808
+ while (children.at(-1)?.element === "text") {
1809
+ const last = children.at(-1);
1810
+ if (last.element !== "text")
1811
+ break;
1812
+ last.data = last.data.trimEnd();
1813
+ if (last.data)
1814
+ break;
1815
+ children.pop();
1816
+ }
1579
1817
  consumed += inlineResult.consumed;
1580
1818
  pos += inlineResult.consumed;
1581
1819
  if (ctx.tokens[pos]?.type === "NEWLINE") {
@@ -2375,17 +2613,15 @@ function parseBlockquoteLine(ctx, startPos) {
2375
2613
  if (ctx.tokens[pos]?.type !== "WHITESPACE") {
2376
2614
  return { kind: "skipped", consumed: consumeLineRemainder(ctx, pos) + consumed };
2377
2615
  }
2378
- while (ctx.tokens[pos]?.type === "WHITESPACE") {
2616
+ pos++;
2617
+ consumed++;
2618
+ const contentStart = pos;
2619
+ while (pos < ctx.tokens.length && ctx.tokens[pos]?.type !== "NEWLINE" && ctx.tokens[pos]?.type !== "EOF") {
2379
2620
  pos++;
2380
2621
  consumed++;
2381
2622
  }
2382
- const inlineCtx = { ...ctx, pos };
2383
- const inlineResult = parseInlineUntil(inlineCtx, "NEWLINE");
2384
- consumed += inlineResult.consumed;
2385
- pos += inlineResult.consumed;
2386
- let hasLineBreak = false;
2387
2623
  if (ctx.tokens[pos]?.type === "NEWLINE") {
2388
- hasLineBreak = true;
2624
+ pos++;
2389
2625
  consumed++;
2390
2626
  }
2391
2627
  return {
@@ -2393,7 +2629,7 @@ function parseBlockquoteLine(ctx, startPos) {
2393
2629
  line: {
2394
2630
  depth: depth - 1,
2395
2631
  ltype: null,
2396
- value: { elements: inlineResult.elements, hasLineBreak }
2632
+ value: { start: contentStart, end: pos }
2397
2633
  },
2398
2634
  consumed
2399
2635
  };
@@ -2412,47 +2648,43 @@ function consumeLineRemainder(ctx, startPos) {
2412
2648
  }
2413
2649
 
2414
2650
  // packages/parser/src/parser/rules/block/blockquote/build.ts
2415
- function buildBlockquoteElements(lines) {
2651
+ var EXCLUDED_BLOCK_NAMES = new Set([
2652
+ "bibliography",
2653
+ "code",
2654
+ "html",
2655
+ "include",
2656
+ "math",
2657
+ "module"
2658
+ ]);
2659
+ var NEVER_CLOSES = () => false;
2660
+ function buildBlockquoteElements(ctx, lines) {
2416
2661
  const depthTrees = processDepths(null, lines);
2417
- return depthTrees.map(({ list }) => buildBlockquoteElement(list));
2662
+ return depthTrees.map(({ list }) => buildBlockquoteElement(ctx, list)).filter((element) => element !== null);
2418
2663
  }
2419
- function buildBlockquoteElement(list) {
2664
+ function buildBlockquoteElement(ctx, list) {
2420
2665
  const children = [];
2421
- let currentParagraphChildren = [];
2422
- function flushParagraph() {
2423
- if (currentParagraphChildren.length > 0) {
2424
- while (currentParagraphChildren.length > 0 && currentParagraphChildren[currentParagraphChildren.length - 1]?.element === "line-break") {
2425
- currentParagraphChildren.pop();
2426
- }
2427
- if (currentParagraphChildren.length > 0) {
2428
- children.push({
2429
- element: "container",
2430
- data: {
2431
- type: "paragraph",
2432
- attributes: {},
2433
- elements: currentParagraphChildren
2434
- }
2435
- });
2436
- }
2437
- currentParagraphChildren = [];
2438
- }
2666
+ let pending = [];
2667
+ function flushPending() {
2668
+ if (pending.length === 0)
2669
+ return;
2670
+ children.push(...parseLines(ctx, pending));
2671
+ pending = [];
2439
2672
  }
2440
2673
  for (const item of list) {
2441
2674
  if (item.kind === "item") {
2442
- if (item.value.elements.length === 0) {
2443
- flushParagraph();
2444
- continue;
2445
- }
2446
- currentParagraphChildren.push(...item.value.elements);
2447
- if (item.value.hasLineBreak) {
2448
- currentParagraphChildren.push({ element: "line-break" });
2449
- }
2450
- } else {
2451
- flushParagraph();
2452
- children.push(buildBlockquoteElement(item.children));
2675
+ pending.push(item.value);
2676
+ continue;
2453
2677
  }
2678
+ flushPending();
2679
+ const nested = buildBlockquoteElement(ctx, item.children);
2680
+ if (nested) {
2681
+ children.push(nested);
2682
+ }
2683
+ }
2684
+ flushPending();
2685
+ if (children.length === 0) {
2686
+ return null;
2454
2687
  }
2455
- flushParagraph();
2456
2688
  return {
2457
2689
  element: "container",
2458
2690
  data: {
@@ -2462,6 +2694,31 @@ function buildBlockquoteElement(list) {
2462
2694
  }
2463
2695
  };
2464
2696
  }
2697
+ function parseLines(ctx, lines) {
2698
+ const tokens = sliceLineTokens(ctx, lines);
2699
+ const lineCtx = { ...ctx, tokens, pos: 0 };
2700
+ return parseBlocksUntil(lineCtx, NEVER_CLOSES, {
2701
+ excludedBlockNames: EXCLUDED_BLOCK_NAMES
2702
+ }).elements;
2703
+ }
2704
+ function sliceLineTokens(ctx, lines) {
2705
+ const tokens = [];
2706
+ for (const { start, end } of lines) {
2707
+ for (let pos = start;pos < end; pos++) {
2708
+ const token5 = ctx.tokens[pos];
2709
+ if (token5) {
2710
+ tokens.push(token5);
2711
+ }
2712
+ }
2713
+ }
2714
+ const last = tokens[tokens.length - 1];
2715
+ tokens.push(createToken("EOF", "", last?.position ?? ZERO_POSITION2));
2716
+ return tokens;
2717
+ }
2718
+ var ZERO_POSITION2 = {
2719
+ start: { line: 0, column: 0, offset: 0 },
2720
+ end: { line: 0, column: 0, offset: 0 }
2721
+ };
2465
2722
 
2466
2723
  // packages/parser/src/parser/rules/block/blockquote/lines.ts
2467
2724
  function collectBlockquoteLines(ctx) {
@@ -2470,16 +2727,90 @@ function collectBlockquoteLines(ctx) {
2470
2727
  let consumed = 0;
2471
2728
  while (pos < ctx.tokens.length) {
2472
2729
  const result = parseBlockquoteLine(ctx, pos);
2473
- if (result.kind === "stop")
2474
- break;
2730
+ if (result.kind === "stop") {
2731
+ const resumed = extendToCommentClose(ctx, lines, pos);
2732
+ if (resumed === pos)
2733
+ break;
2734
+ consumed += resumed - pos;
2735
+ pos = resumed;
2736
+ continue;
2737
+ }
2475
2738
  pos += result.consumed;
2476
2739
  consumed += result.consumed;
2477
2740
  if (result.kind === "parsed") {
2478
2741
  lines.push(result.line);
2479
2742
  }
2480
2743
  }
2744
+ blankCommentOnlyLines(ctx, lines);
2481
2745
  return { lines, consumed };
2482
2746
  }
2747
+ function extendToCommentClose(ctx, lines, stopPos) {
2748
+ const last = lines[lines.length - 1];
2749
+ if (!last || !endsInsideComment(ctx, lines)) {
2750
+ return stopPos;
2751
+ }
2752
+ let pos = stopPos;
2753
+ while (pos < ctx.tokens.length && ctx.tokens[pos]?.type !== "COMMENT_CLOSE") {
2754
+ if (ctx.tokens[pos]?.type === "EOF")
2755
+ return stopPos;
2756
+ pos++;
2757
+ }
2758
+ while (pos < ctx.tokens.length && ctx.tokens[pos]?.type !== "EOF") {
2759
+ pos++;
2760
+ if (ctx.tokens[pos - 1]?.type === "NEWLINE")
2761
+ break;
2762
+ }
2763
+ last.value.end = pos;
2764
+ return pos;
2765
+ }
2766
+ function endsInsideComment(ctx, lines) {
2767
+ let open = false;
2768
+ for (const { value } of lines) {
2769
+ for (let pos = value.start;pos < value.end; pos++) {
2770
+ const type = ctx.tokens[pos]?.type;
2771
+ if (type === "COMMENT_OPEN")
2772
+ open = true;
2773
+ else if (type === "COMMENT_CLOSE")
2774
+ open = false;
2775
+ }
2776
+ }
2777
+ return open;
2778
+ }
2779
+ function blankCommentOnlyLines(ctx, lines) {
2780
+ const positions = [];
2781
+ lines.forEach((line, index) => {
2782
+ for (let pos = line.value.start;pos < line.value.end; pos++) {
2783
+ if (ctx.tokens[pos]?.type !== "NEWLINE") {
2784
+ positions.push({ line: index, pos });
2785
+ }
2786
+ }
2787
+ });
2788
+ const commented = Array.from({ length: positions.length }, () => false);
2789
+ for (let open = 0;open < positions.length; open++) {
2790
+ if (ctx.tokens[positions[open].pos]?.type !== "COMMENT_OPEN")
2791
+ continue;
2792
+ let close = open + 1;
2793
+ while (close < positions.length && ctx.tokens[positions[close].pos]?.type !== "COMMENT_CLOSE") {
2794
+ close++;
2795
+ }
2796
+ if (close === positions.length)
2797
+ break;
2798
+ commented.fill(true, open, close + 1);
2799
+ open = close;
2800
+ }
2801
+ const hasContent = Array.from({ length: lines.length }, () => false);
2802
+ positions.forEach(({ line, pos }, index) => {
2803
+ if (commented[index] || ctx.tokens[pos]?.type === "WHITESPACE")
2804
+ return;
2805
+ hasContent[line] = true;
2806
+ });
2807
+ lines.forEach((line, index) => {
2808
+ if (hasContent[index])
2809
+ return;
2810
+ const { end } = line.value;
2811
+ line.value.start = ctx.tokens[end - 1]?.type === "NEWLINE" ? end - 1 : end;
2812
+ });
2813
+ }
2483
2814
 
2484
2815
  // packages/parser/src/parser/rules/block/blockquote/index.ts
2485
2816
  var blockquoteRule = {
@@ -2498,9 +2829,9 @@ var blockquoteRule = {
2498
2829
  }
2499
2830
  return { success: false };
2500
2831
  }
2501
- const blockquotes = buildBlockquoteElements(blockquoteLines.lines);
2832
+ const blockquotes = buildBlockquoteElements(ctx, blockquoteLines.lines);
2502
2833
  if (blockquotes.length === 0) {
2503
- return { success: false };
2834
+ return { success: true, elements: [], consumed: blockquoteLines.consumed };
2504
2835
  }
2505
2836
  return {
2506
2837
  success: true,
@@ -2595,17 +2926,8 @@ function parseDefinitionItemValue(ctx, startPos) {
2595
2926
  break;
2596
2927
  }
2597
2928
  if (token5.type === "NEWLINE") {
2598
- const nextToken = ctx.tokens[pos + 1];
2599
- if (nextToken?.type === "COLON" && nextToken.lineStart) {
2600
- pos++;
2601
- consumed++;
2602
- break;
2603
- }
2604
- if (nextToken?.type === "NEWLINE" || !nextToken || nextToken.type === "EOF") {
2605
- pos++;
2606
- consumed++;
2607
- break;
2608
- }
2929
+ consumed++;
2930
+ break;
2609
2931
  }
2610
2932
  const inlineCtx = { ...ctx, pos };
2611
2933
  const result = parseInlineUntil(inlineCtx, "NEWLINE");
@@ -2683,14 +3005,10 @@ var definitionListRule = {
2683
3005
  if (result.items.length === 0) {
2684
3006
  return { success: false };
2685
3007
  }
3008
+ const items = toDefinitionListItems(result.items.filter((item) => item.value.length > 0));
2686
3009
  return {
2687
3010
  success: true,
2688
- elements: [
2689
- {
2690
- element: "definition-list",
2691
- data: toDefinitionListItems(result.items)
2692
- }
2693
- ],
3011
+ elements: items.length > 0 ? [{ element: "definition-list", data: items }] : [],
2694
3012
  consumed: result.consumed
2695
3013
  };
2696
3014
  }
@@ -2795,20 +3113,49 @@ var paragraphRule = {
2795
3113
  }
2796
3114
  return {
2797
3115
  success: true,
2798
- elements: [
2799
- {
2800
- element: "container",
2801
- data: {
2802
- type: "paragraph",
2803
- attributes: {},
2804
- elements
2805
- }
2806
- }
2807
- ],
3116
+ elements: wrapParagraphElements(elements),
2808
3117
  consumed: result.consumed
2809
3118
  };
2810
3119
  }
2811
3120
  };
3121
+ function wrapParagraphElements(elements) {
3122
+ const output = [];
3123
+ let group = [];
3124
+ let bare = false;
3125
+ const flush = (trimBreaks = false) => {
3126
+ const content = trimBreaks ? normalizeParagraphElements(group) : group;
3127
+ while (content[0]?.element === "line-break")
3128
+ content.shift();
3129
+ while (content.length) {
3130
+ const last = content.at(-1);
3131
+ if (last.element !== "text" || last.data.trim() !== "")
3132
+ break;
3133
+ content.pop();
3134
+ }
3135
+ while (content[0]?.element === "text" && content[0].data.trim() === "")
3136
+ content.shift();
3137
+ if (content[0]?.element === "text")
3138
+ content[0] = { element: "text", data: content[0].data.trimStart() };
3139
+ if (content.length)
3140
+ output.push(...bare || content.some((el) => el.element === "image") ? content : [
3141
+ {
3142
+ element: "container",
3143
+ data: { type: "paragraph", attributes: {}, elements: content }
3144
+ }
3145
+ ]);
3146
+ group = [];
3147
+ };
3148
+ for (const el of elements) {
3149
+ if (el.element === "image" && el.data.alignment !== null || el.element === "embed-block") {
3150
+ flush(el.element === "image");
3151
+ output.push(el);
3152
+ bare = el.element === "embed-block";
3153
+ } else
3154
+ group.push(el);
3155
+ }
3156
+ flush();
3157
+ return output;
3158
+ }
2812
3159
 
2813
3160
  // packages/parser/src/parser/rules/block/div/close.ts
2814
3161
  function isDivClose(ctx) {
@@ -3174,9 +3521,6 @@ function consumeCodeClose(ctx, startPos, closeNameConsumed) {
3174
3521
  pos++;
3175
3522
  consumed++;
3176
3523
  }
3177
- if (ctx.tokens[pos]?.type === "NEWLINE") {
3178
- consumed++;
3179
- }
3180
3524
  return consumed;
3181
3525
  }
3182
3526
 
@@ -3233,16 +3577,13 @@ var codeBlockRule = {
3233
3577
  name: attrResult.attrs.name ?? null
3234
3578
  };
3235
3579
  ctx.codeBlocks.push(codeBlockData);
3236
- return {
3237
- success: true,
3238
- elements: [
3239
- {
3240
- element: "code",
3241
- data: codeBlockData
3242
- }
3243
- ],
3244
- consumed
3245
- };
3580
+ const elements = [{ element: "code", data: codeBlockData }];
3581
+ if (ctx.tokens[pos]?.type === "NEWLINE" && !getParagraphNewlineBoundary(ctx, pos, false).shouldBreak && !ctx.scope.blockCloseCondition?.({ ...ctx, pos: pos + 1 })) {
3582
+ const after = parseInlineUntil({ ...ctx, pos: pos + 1 }, "PARAGRAPH_BREAK");
3583
+ elements.push({ element: "line-break" }, ...normalizeParagraphElements(after.elements));
3584
+ consumed += 1 + after.consumed;
3585
+ }
3586
+ return { success: true, elements, consumed };
3246
3587
  }
3247
3588
  };
3248
3589
 
@@ -3621,7 +3962,30 @@ function parseTableCell(ctx, startPos, cellStart) {
3621
3962
  consumed++;
3622
3963
  }
3623
3964
  const { inlineRules } = ctx;
3624
- const inlineCtx = { ...ctx, pos };
3965
+ let inlineEnd = pos;
3966
+ while (inlineEnd < ctx.tokens.length) {
3967
+ const rawEnd = protectedInlineRegionEnd(ctx.tokens, inlineEnd, ctx.tokens.length);
3968
+ if (rawEnd > inlineEnd) {
3969
+ inlineEnd = rawEnd;
3970
+ continue;
3971
+ }
3972
+ const token5 = ctx.tokens[inlineEnd];
3973
+ if (!token5 || token5.type === "EOF" || token5.type === "NEWLINE" || isPipeTableToken(token5.type))
3974
+ break;
3975
+ if (token5.type === "WHITESPACE" && ctx.tokens[inlineEnd + 1]?.type === "UNDERSCORE" && ctx.tokens[inlineEnd + 2]?.type === "NEWLINE")
3976
+ inlineEnd += 3;
3977
+ else
3978
+ inlineEnd++;
3979
+ }
3980
+ const inlineCtx = {
3981
+ ...ctx,
3982
+ pos,
3983
+ scope: {
3984
+ ...ctx.scope,
3985
+ inlineEnd,
3986
+ tableFormatting: isPipeTableToken(ctx.tokens[inlineEnd]?.type ?? "EOF") ? ctx.scope.tableFormatting : undefined
3987
+ }
3988
+ };
3625
3989
  while (pos < ctx.tokens.length) {
3626
3990
  const token5 = ctx.tokens[pos];
3627
3991
  if (!token5 || token5.type === "NEWLINE" || token5.type === "EOF") {
@@ -3630,6 +3994,11 @@ function parseTableCell(ctx, startPos, cellStart) {
3630
3994
  if (isPipeTableToken(token5.type)) {
3631
3995
  break;
3632
3996
  }
3997
+ if (ctx.scope.tableFormatting?.suppressedClosers.has(pos)) {
3998
+ pos++;
3999
+ consumed++;
4000
+ continue;
4001
+ }
3633
4002
  if (tryConsumeUnderscoreLineBreak(ctx, pos, children)) {
3634
4003
  pos += 3;
3635
4004
  consumed += 3;
@@ -3689,6 +4058,21 @@ function tryConsumeUnderscoreLineBreak(ctx, pos, children) {
3689
4058
 
3690
4059
  // packages/parser/src/parser/rules/block/table/pipe/row.ts
3691
4060
  function parsePipeTableRows(ctx, startPos) {
4061
+ let end = startPos;
4062
+ while (end < ctx.tokens.length && ctx.tokens[end]?.type !== "EOF") {
4063
+ const protectedEnd = protectedInlineRegionEnd(ctx.tokens, end, ctx.tokens.length);
4064
+ if (protectedEnd > end) {
4065
+ end = protectedEnd;
4066
+ continue;
4067
+ }
4068
+ 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"))
4069
+ break;
4070
+ end++;
4071
+ }
4072
+ const tableCtx = {
4073
+ ...ctx,
4074
+ scope: { ...ctx.scope, tableFormatting: { end, suppressedClosers: new Set } }
4075
+ };
3692
4076
  const rows = [];
3693
4077
  let pos = startPos;
3694
4078
  let consumed = 0;
@@ -3697,7 +4081,7 @@ function parsePipeTableRows(ctx, startPos) {
3697
4081
  if (!token5 || !token5.lineStart || !isPipeTableToken(token5.type)) {
3698
4082
  break;
3699
4083
  }
3700
- const rowResult = parseTableRow(ctx, pos);
4084
+ const rowResult = parseTableRow(tableCtx, pos);
3701
4085
  rows.push(rowResult.row);
3702
4086
  pos += rowResult.consumed;
3703
4087
  consumed += rowResult.consumed;
@@ -9125,6 +9509,8 @@ var embedBlockRule = {
9125
9509
  name: "embed-block",
9126
9510
  startTokens: ["BLOCK_OPEN"],
9127
9511
  requiresLineStart: false,
9512
+ preservesPrecedingLineBreak: true,
9513
+ isStartPattern: (ctx, pos) => parseEmbedBlockOpen(ctx, pos) !== null,
9128
9514
  parse(ctx) {
9129
9515
  const openToken = currentToken(ctx);
9130
9516
  if (openToken.type !== "BLOCK_OPEN") {
@@ -9140,38 +9526,30 @@ var embedBlockRule = {
9140
9526
  pos += contentResult.consumed;
9141
9527
  consumed += contentResult.consumed;
9142
9528
  if (!contentResult.foundClose) {
9143
- ctx.diagnostics.push({
9144
- severity: "warning",
9145
- code: "unclosed-block",
9146
- message: `Missing closing tag [[/${openResult.blockName}]] for [[${openResult.blockName}]]`,
9147
- position: openToken.position
9148
- });
9529
+ if (!ctx.diagnostics.some((d) => d.code === "unclosed-block" && d.position === openToken.position))
9530
+ ctx.diagnostics.push({
9531
+ severity: "warning",
9532
+ code: "unclosed-block",
9533
+ message: `Missing closing tag [[/${openResult.blockName}]] for [[${openResult.blockName}]]`,
9534
+ position: openToken.position
9535
+ });
9149
9536
  return { success: false };
9150
9537
  }
9151
9538
  const closeConsumed = consumeEmbedClose(ctx, pos);
9152
9539
  pos += closeConsumed;
9153
9540
  consumed += closeConsumed;
9154
- return {
9155
- success: true,
9156
- elements: [
9157
- {
9158
- element: "container",
9159
- data: {
9160
- type: "paragraph",
9161
- attributes: {},
9162
- elements: [
9163
- {
9164
- element: "embed-block",
9165
- data: {
9166
- contents: contentResult.contents.trim()
9167
- }
9168
- }
9169
- ]
9170
- }
9171
- }
9172
- ],
9173
- consumed
9174
- };
9541
+ const elements = [
9542
+ { element: "embed-block", data: { contents: contentResult.contents.trim() } }
9543
+ ];
9544
+ if (ctx.scope.inlineEnd === undefined && ctx.tokens[pos]?.type !== "NEWLINE" && ctx.tokens[pos]?.type !== "EOF") {
9545
+ const after = parseInlineUntil({ ...ctx, pos }, "PARAGRAPH_BREAK");
9546
+ const tail = normalizeParagraphElements(after.elements);
9547
+ if (tail[0]?.element === "text")
9548
+ tail[0].data = tail[0].data.trimStart();
9549
+ elements.push(...tail);
9550
+ consumed += after.consumed;
9551
+ }
9552
+ return { success: true, elements, consumed };
9175
9553
  }
9176
9554
  };
9177
9555
 
@@ -9485,11 +9863,11 @@ var iftagsRule = {
9485
9863
  };
9486
9864
 
9487
9865
  // packages/parser/src/parser/rules/block/toc/element.ts
9488
- function createTocElement(align) {
9866
+ function createTocElement(align, title) {
9489
9867
  return {
9490
9868
  element: "table-of-contents",
9491
9869
  data: {
9492
- attributes: {},
9870
+ attributes: title === undefined ? {} : { title },
9493
9871
  align
9494
9872
  }
9495
9873
  };
@@ -9532,26 +9910,17 @@ function parseTocOpen(ctx, startPos) {
9532
9910
  } else {
9533
9911
  return null;
9534
9912
  }
9535
- pos = skipUntilClose(ctx, pos);
9913
+ const attributes = parseAttributes(ctx, pos);
9914
+ pos += attributes.consumed;
9536
9915
  if (ctx.tokens[pos]?.type !== "BLOCK_CLOSE") {
9537
9916
  return null;
9538
9917
  }
9539
9918
  return {
9540
9919
  align,
9920
+ title: attributes.attrs.title,
9541
9921
  consumed: pos + 1 - startPos
9542
9922
  };
9543
9923
  }
9544
- function skipUntilClose(ctx, startPos) {
9545
- let pos = startPos;
9546
- while (pos < ctx.tokens.length) {
9547
- const token5 = ctx.tokens[pos];
9548
- if (!token5 || token5.type === "BLOCK_CLOSE" || token5.type === "NEWLINE" || token5.type === "EOF") {
9549
- break;
9550
- }
9551
- pos++;
9552
- }
9553
- return pos;
9554
- }
9555
9924
  function isNameToken(token5) {
9556
9925
  return token5?.type === "TEXT" || token5?.type === "IDENTIFIER";
9557
9926
  }
@@ -9575,7 +9944,7 @@ var tocRule = {
9575
9944
  }
9576
9945
  return {
9577
9946
  success: true,
9578
- elements: [createTocElement(openResult.align)],
9947
+ elements: [createTocElement(openResult.align, openResult.title)],
9579
9948
  consumed: openResult.consumed
9580
9949
  };
9581
9950
  }
@@ -10176,6 +10545,31 @@ var blockRules = [
10176
10545
  galleryRule,
10177
10546
  divRule
10178
10547
  ];
10548
+ // packages/parser/src/parser/rules/inline/formatting/close.ts
10549
+ function findFormattingClose(ctx, start, marker) {
10550
+ const table = ctx.scope.tableFormatting;
10551
+ const end = table?.end ?? ctx.scope.inlineEnd ?? ctx.tokens.length;
10552
+ for (let pos = start;pos < end; pos++) {
10553
+ const token5 = ctx.tokens[pos];
10554
+ if (!token5 || token5.type === "EOF" || ctx.scope.blockCloseCondition?.({ ...ctx, pos }))
10555
+ return null;
10556
+ if (!table && token5.type === "NEWLINE" && getParagraphNewlineBoundary(ctx, pos, true).shouldBreak)
10557
+ return null;
10558
+ if (token5.type === marker && !table?.suppressedClosers.has(pos))
10559
+ return pos;
10560
+ const protectedEnd = protectedInlineRegionEnd(ctx.tokens, pos, end);
10561
+ if (protectedEnd > pos)
10562
+ pos = protectedEnd - 1;
10563
+ }
10564
+ return null;
10565
+ }
10566
+ function consumeFormattingClose(ctx, close, contentEnd) {
10567
+ if (close === contentEnd)
10568
+ return 1;
10569
+ ctx.scope.tableFormatting?.suppressedClosers.add(close);
10570
+ return 0;
10571
+ }
10572
+
10179
10573
  // packages/parser/src/parser/rules/inline/formatting/container.ts
10180
10574
  function createInlineContainer(type, elements) {
10181
10575
  return {
@@ -10187,9 +10581,10 @@ function createInlineContainer(type, elements) {
10187
10581
  }
10188
10582
  };
10189
10583
  }
10190
- function parseSameLineDelimitedContainer(ctx, closeToken, type, options = {}) {
10584
+ function parseDelimitedContainer(ctx, closeToken, type, options = {}) {
10191
10585
  const startToken = currentToken(ctx);
10192
- if (!hasClosingMarkerBeforeNewline({ ...ctx, pos: ctx.pos + 1 }, closeToken)) {
10586
+ const close = findFormattingClose(ctx, ctx.pos + 1, closeToken);
10587
+ if (close === null) {
10193
10588
  return {
10194
10589
  success: true,
10195
10590
  elements: [{ element: "text", data: startToken.value }],
@@ -10197,7 +10592,7 @@ function parseSameLineDelimitedContainer(ctx, closeToken, type, options = {}) {
10197
10592
  };
10198
10593
  }
10199
10594
  const result = parseInlineUntil({ ...ctx, pos: ctx.pos + 1 }, closeToken);
10200
- const consumed = 1 + result.consumed + 1;
10595
+ const consumed = 1 + result.consumed + consumeFormattingClose(ctx, close, ctx.pos + 1 + result.consumed);
10201
10596
  if (options.discardEmpty === true && result.elements.length === 0) {
10202
10597
  return {
10203
10598
  success: true,
@@ -10217,7 +10612,7 @@ var boldRule = {
10217
10612
  name: "bold",
10218
10613
  startTokens: ["BOLD_MARKER"],
10219
10614
  parse(ctx) {
10220
- return parseSameLineDelimitedContainer(ctx, "BOLD_MARKER", "bold", { discardEmpty: true });
10615
+ return parseDelimitedContainer(ctx, "BOLD_MARKER", "bold", { discardEmpty: true });
10221
10616
  }
10222
10617
  };
10223
10618
 
@@ -10226,102 +10621,28 @@ var italicRule = {
10226
10621
  name: "italic",
10227
10622
  startTokens: ["ITALIC_MARKER"],
10228
10623
  parse(ctx) {
10229
- return parseSameLineDelimitedContainer(ctx, "ITALIC_MARKER", "italics");
10624
+ return parseDelimitedContainer(ctx, "ITALIC_MARKER", "italics");
10230
10625
  }
10231
10626
  };
10232
10627
 
10233
- // packages/parser/src/parser/rules/inline/underline/child.ts
10234
- function parseUnderlineChild(ctx, pos) {
10235
- const token5 = ctx.tokens[pos];
10236
- if (!token5) {
10237
- return { elements: [], consumed: 0 };
10238
- }
10239
- if (token5.type === "NEWLINE") {
10240
- return { elements: [{ element: "line-break" }], consumed: 1 };
10241
- }
10242
- const result = parseInlineUntil({ ...ctx, pos }, "UNDERLINE_MARKER");
10243
- if (result.elements.length > 0) {
10244
- return { elements: result.elements, consumed: result.consumed };
10245
- }
10246
- return { elements: [{ element: "text", data: token5.value }], consumed: 1 };
10247
- }
10248
-
10249
- // packages/parser/src/parser/rules/inline/underline/content.ts
10250
- function parseUnderlineContent(ctx, startPos) {
10251
- const children = [];
10252
- let pos = startPos;
10253
- let consumed = 1;
10254
- while (pos < ctx.tokens.length) {
10255
- const token5 = ctx.tokens[pos];
10256
- if (!token5 || token5.type === "EOF")
10257
- break;
10258
- if (token5.type === "UNDERLINE_MARKER") {
10259
- consumed++;
10260
- break;
10261
- }
10262
- const child = parseUnderlineChild(ctx, pos);
10263
- children.push(...child.elements);
10264
- pos += child.consumed;
10265
- consumed += child.consumed;
10266
- }
10267
- return { children, consumed };
10268
- }
10269
-
10270
10628
  // packages/parser/src/parser/rules/inline/underline/index.ts
10271
10629
  var underlineRule = {
10272
10630
  name: "underline",
10273
10631
  startTokens: ["UNDERLINE_MARKER"],
10274
10632
  parse(ctx) {
10275
- const startToken = currentToken(ctx);
10276
- if (!hasClosingMarkerBeforeParagraphBreak({ ...ctx, pos: ctx.pos + 1 }, "UNDERLINE_MARKER")) {
10277
- return {
10278
- success: true,
10279
- elements: [{ element: "text", data: startToken.value }],
10280
- consumed: 1
10281
- };
10282
- }
10283
- const { children, consumed } = parseUnderlineContent(ctx, ctx.pos + 1);
10284
- if (children.length === 0) {
10285
- return {
10286
- success: true,
10287
- elements: [],
10288
- consumed
10289
- };
10290
- }
10291
- return {
10292
- success: true,
10293
- elements: [createInlineContainer("underline", children)],
10294
- consumed
10295
- };
10633
+ return parseDelimitedContainer(ctx, "UNDERLINE_MARKER", "underline", { discardEmpty: true });
10296
10634
  }
10297
10635
  };
10298
10636
 
10299
10637
  // packages/parser/src/parser/rules/inline/strikethrough/parse.ts
10300
10638
  function parseStrikethroughContent(ctx) {
10301
- const result = parseInlineUntil({ ...ctx, pos: ctx.pos + 1 }, "STRIKE_MARKER");
10302
- return {
10303
- success: true,
10304
- elements: [createInlineContainer("strikethrough", result.elements)],
10305
- consumed: 1 + result.consumed + 1
10306
- };
10639
+ return parseDelimitedContainer(ctx, "STRIKE_MARKER", "strikethrough");
10307
10640
  }
10308
10641
 
10309
10642
  // packages/parser/src/parser/rules/inline/strikethrough/syntax.ts
10310
10643
  function hasValidStrikethroughClose(ctx) {
10311
- let pos = ctx.pos + 1;
10312
- let prevWasWhitespace = false;
10313
- while (pos < ctx.tokens.length) {
10314
- const token5 = ctx.tokens[pos];
10315
- if (!token5 || token5.type === "NEWLINE" || token5.type === "EOF") {
10316
- return false;
10317
- }
10318
- if (token5.type === "STRIKE_MARKER") {
10319
- return !prevWasWhitespace;
10320
- }
10321
- prevWasWhitespace = token5.type === "WHITESPACE";
10322
- pos++;
10323
- }
10324
- return false;
10644
+ const close = findFormattingClose(ctx, ctx.pos + 1, "STRIKE_MARKER");
10645
+ return close !== null && close > ctx.pos + 1 && ctx.tokens[close - 1]?.type !== "WHITESPACE";
10325
10646
  }
10326
10647
 
10327
10648
  // packages/parser/src/parser/rules/inline/strikethrough/index.ts
@@ -10345,7 +10666,7 @@ var superscriptRule = {
10345
10666
  name: "superscript",
10346
10667
  startTokens: ["SUPER_MARKER"],
10347
10668
  parse(ctx) {
10348
- return parseSameLineDelimitedContainer(ctx, "SUPER_MARKER", "superscript", {
10669
+ return parseDelimitedContainer(ctx, "SUPER_MARKER", "superscript", {
10349
10670
  discardEmpty: true
10350
10671
  });
10351
10672
  }
@@ -10356,7 +10677,7 @@ var subscriptRule = {
10356
10677
  name: "subscript",
10357
10678
  startTokens: ["SUB_MARKER"],
10358
10679
  parse(ctx) {
10359
- return parseSameLineDelimitedContainer(ctx, "SUB_MARKER", "subscript", { discardEmpty: true });
10680
+ return parseDelimitedContainer(ctx, "SUB_MARKER", "subscript", { discardEmpty: true });
10360
10681
  }
10361
10682
  };
10362
10683
 
@@ -10365,7 +10686,7 @@ var monospaceRule = {
10365
10686
  name: "monospace",
10366
10687
  startTokens: ["MONO_MARKER"],
10367
10688
  parse(ctx) {
10368
- return parseSameLineDelimitedContainer(ctx, "MONO_CLOSE", "monospace");
10689
+ return parseDelimitedContainer(ctx, "MONO_CLOSE", "monospace");
10369
10690
  }
10370
10691
  };
10371
10692
 
@@ -10726,13 +11047,14 @@ var linkStarRule = {
10726
11047
 
10727
11048
  // packages/parser/src/parser/rules/inline/color/syntax.ts
10728
11049
  function parseColorContent(ctx) {
10729
- if (!hasClosingMarkerBeforeNewline({ ...ctx, pos: ctx.pos + 1 }, "COLOR_MARKER")) {
11050
+ const close = findFormattingClose(ctx, ctx.pos + 1, "COLOR_MARKER");
11051
+ if (close === null) {
10730
11052
  return null;
10731
11053
  }
10732
11054
  let pos = ctx.pos + 1;
10733
11055
  let consumed = 1;
10734
11056
  let colorSpec = "";
10735
- while (pos < ctx.tokens.length) {
11057
+ while (pos < (ctx.scope.inlineEnd ?? ctx.tokens.length)) {
10736
11058
  const token5 = ctx.tokens[pos];
10737
11059
  if (!token5 || token5.type === "PIPE" || token5.type === "COLOR_MARKER" || token5.type === "NEWLINE" || token5.type === "EOF") {
10738
11060
  break;
@@ -10749,14 +11071,11 @@ function parseColorContent(ctx) {
10749
11071
  const contentResult = parseInlineUntil({ ...ctx, pos }, "COLOR_MARKER");
10750
11072
  pos += contentResult.consumed;
10751
11073
  consumed += contentResult.consumed;
10752
- if (ctx.tokens[pos]?.type !== "COLOR_MARKER") {
10753
- return null;
10754
- }
10755
- consumed++;
10756
11074
  const color = colorSpec.trim();
10757
11075
  if (color === "" || contentResult.elements.length === 0) {
10758
11076
  return null;
10759
11077
  }
11078
+ consumed += consumeFormattingClose(ctx, close, pos);
10760
11079
  return {
10761
11080
  color: hexifyColor(color),
10762
11081
  elements: contentResult.elements,
@@ -11379,14 +11698,19 @@ function parseSpanContent(ctx, startPos, blockName) {
11379
11698
  const escapedChildren = [];
11380
11699
  const splitSpans = [];
11381
11700
  let foundClose = false;
11701
+ let forcedClose = false;
11382
11702
  let afterBlankLine = false;
11383
11703
  let consumed = 0;
11384
11704
  let pos = startPos;
11385
- while (pos < ctx.tokens.length) {
11705
+ while (pos < (ctx.scope.inlineEnd ?? ctx.tokens.length)) {
11386
11706
  const token5 = ctx.tokens[pos];
11387
11707
  if (!token5 || token5.type === "EOF") {
11388
11708
  break;
11389
11709
  }
11710
+ if (ctx.scope.tableFormatting?.suppressedClosers.has(pos)) {
11711
+ forcedClose = true;
11712
+ break;
11713
+ }
11390
11714
  const close = parseCloseSpan(ctx, pos);
11391
11715
  if (close.success) {
11392
11716
  pos += close.consumed;
@@ -11411,6 +11735,29 @@ function parseSpanContent(ctx, startPos, blockName) {
11411
11735
  pos += parsed.consumed;
11412
11736
  consumed += parsed.consumed;
11413
11737
  }
11738
+ if (!foundClose && ctx.scope.tableFormatting && (pos === ctx.scope.inlineEnd || forcedClose)) {
11739
+ let depth = 0;
11740
+ for (let next = pos;next < ctx.scope.tableFormatting.end; next++) {
11741
+ const rawEnd = rawRegionEnd(ctx.tokens, next, ctx.scope.tableFormatting.end);
11742
+ if (rawEnd > next) {
11743
+ next = rawEnd - 1;
11744
+ continue;
11745
+ }
11746
+ if (ctx.tokens[next]?.type === "BLOCK_OPEN" && /^span_?$/i.test(ctx.tokens[next + 1]?.value ?? ""))
11747
+ depth++;
11748
+ const close = parseCloseSpan(ctx, next);
11749
+ if (!close.success)
11750
+ continue;
11751
+ if (depth > 0) {
11752
+ depth--;
11753
+ continue;
11754
+ }
11755
+ for (let offset = 0;offset < close.consumed; offset++)
11756
+ ctx.scope.tableFormatting.suppressedClosers.add(next + offset);
11757
+ foundClose = true;
11758
+ break;
11759
+ }
11760
+ }
11414
11761
  return { children, escapedChildren, splitSpans, consumed, foundClose };
11415
11762
  }
11416
11763
  function parseOneSpanChild(ctx, pos, targetChildren) {
@@ -11822,135 +12169,6 @@ var footnoteRule = {
11822
12169
  }
11823
12170
  };
11824
12171
 
11825
- // packages/parser/src/parser/rules/inline/image/attributes.ts
11826
- function parseImageAttributes(ctx, startPos) {
11827
- const result = parseAttributesRaw(ctx, startPos, false);
11828
- const link = result.attrs.link ?? null;
11829
- const { link: _link, ...htmlAttributes } = result.attrs;
11830
- return {
11831
- attributes: filterUnsafeAttributes(htmlAttributes),
11832
- link,
11833
- consumed: result.consumed
11834
- };
11835
- }
11836
-
11837
- // packages/parser/src/parser/rules/inline/image/body.ts
11838
- function parseImageSourceText(ctx, startPos) {
11839
- let pos = startPos;
11840
- let consumed = 0;
11841
- while (ctx.tokens[pos]?.type === "WHITESPACE") {
11842
- pos++;
11843
- consumed++;
11844
- }
11845
- let sourceText = "";
11846
- while (pos < ctx.tokens.length) {
11847
- const token5 = ctx.tokens[pos];
11848
- if (!token5 || token5.type === "WHITESPACE" || token5.type === "BLOCK_CLOSE" || token5.type === "NEWLINE" || token5.type === "EOF") {
11849
- break;
11850
- }
11851
- sourceText += token5.value;
11852
- pos++;
11853
- consumed++;
11854
- }
11855
- return { sourceText, consumed };
11856
- }
11857
-
11858
- // packages/parser/src/parser/rules/inline/image/syntax.ts
11859
- var IMAGE_BLOCK_NAMES = new Set([
11860
- "image",
11861
- "=image",
11862
- "<image",
11863
- ">image",
11864
- "f<image",
11865
- "f>image",
11866
- "f=image"
11867
- ]);
11868
- function parseImageBlockName(ctx, startPos) {
11869
- let pos = startPos;
11870
- let consumed = 0;
11871
- while (ctx.tokens[pos]?.type === "WHITESPACE") {
11872
- pos++;
11873
- consumed++;
11874
- }
11875
- const prefixResult = parseImagePrefix(ctx, pos);
11876
- const prefix = prefixResult.prefix;
11877
- pos += prefixResult.consumed;
11878
- consumed += prefixResult.consumed;
11879
- const nameToken = ctx.tokens[pos];
11880
- if (!nameToken || nameToken.type !== "TEXT" && nameToken.type !== "IDENTIFIER") {
11881
- return null;
11882
- }
11883
- return { name: prefix + nameToken.value.toLowerCase(), consumed: consumed + 1 };
11884
- }
11885
- function isImageBlockName(blockName) {
11886
- return IMAGE_BLOCK_NAMES.has(blockName);
11887
- }
11888
- function parseImagePrefix(ctx, pos) {
11889
- const token5 = ctx.tokens[pos];
11890
- if (token5?.type === "EQUALS") {
11891
- return { prefix: "=", consumed: 1 };
11892
- }
11893
- if (token5?.type === "TEXT" && token5.value === "<") {
11894
- return { prefix: "<", consumed: 1 };
11895
- }
11896
- if ((token5?.type === "TEXT" || token5?.type === "BLOCKQUOTE_MARKER") && token5.value === ">") {
11897
- return { prefix: ">", consumed: 1 };
11898
- }
11899
- if (token5?.type === "IDENTIFIER" && token5.value.toLowerCase() === "f") {
11900
- return parseFloatPrefix(ctx, pos + 1);
11901
- }
11902
- return { prefix: "", consumed: 0 };
11903
- }
11904
- function parseFloatPrefix(ctx, pos) {
11905
- const token5 = ctx.tokens[pos];
11906
- if (token5?.type === "TEXT" && token5.value === "<") {
11907
- return { prefix: "f<", consumed: 2 };
11908
- }
11909
- if ((token5?.type === "TEXT" || token5?.type === "BLOCKQUOTE_MARKER") && token5.value === ">") {
11910
- return { prefix: "f>", consumed: 2 };
11911
- }
11912
- if (token5?.type === "EQUALS") {
11913
- return { prefix: "f=", consumed: 2 };
11914
- }
11915
- return { prefix: "", consumed: 0 };
11916
- }
11917
-
11918
- // packages/parser/src/parser/rules/inline/image/open.ts
11919
- function parseImageOpen(ctx) {
11920
- if (ctx.tokens[ctx.pos]?.type !== "BLOCK_OPEN") {
11921
- return null;
11922
- }
11923
- let pos = ctx.pos + 1;
11924
- let consumed = 1;
11925
- const nameResult = parseImageBlockName(ctx, pos);
11926
- if (!nameResult || !isImageBlockName(nameResult.name)) {
11927
- return null;
11928
- }
11929
- pos += nameResult.consumed;
11930
- consumed += nameResult.consumed;
11931
- const sourceText = parseImageSourceText(ctx, pos);
11932
- pos += sourceText.consumed;
11933
- consumed += sourceText.consumed;
11934
- const attrs = parseImageAttributes(ctx, pos);
11935
- pos += attrs.consumed;
11936
- consumed += attrs.consumed;
11937
- if (ctx.tokens[pos]?.type !== "BLOCK_CLOSE") {
11938
- return null;
11939
- }
11940
- pos++;
11941
- consumed++;
11942
- if (!sourceText.sourceText) {
11943
- return null;
11944
- }
11945
- return {
11946
- blockName: nameResult.name,
11947
- sourceText: sourceText.sourceText,
11948
- link: attrs.link,
11949
- attributes: attrs.attributes,
11950
- consumed
11951
- };
11952
- }
11953
-
11954
12172
  // packages/parser/src/parser/rules/inline/image/source.ts
11955
12173
  function parseImageSource(src) {
11956
12174
  if (src.startsWith("http://") || src.startsWith("https://") || src.startsWith("/")) {
@@ -13001,6 +13219,7 @@ var inlineRules = [
13001
13219
  htmlInlineRule,
13002
13220
  rawRule,
13003
13221
  imageRule,
13222
+ embedBlockRule,
13004
13223
  sizeRule,
13005
13224
  footnoteRule,
13006
13225
  spanRule,