@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.
- package/dist/index.cjs +655 -435
- package/dist/index.d.cts +11 -4
- package/dist/index.d.ts +11 -4
- package/dist/index.js +653 -435
- package/package.json +2 -2
- package/src/build-info.generated.ts +11 -0
- package/src/index.ts +2 -0
- package/src/lexer/lexer.ts +6 -4
- package/src/lexer/punctuation.ts +2 -1
- package/src/lexer/spacing-actions.ts +15 -0
- package/src/lexer/state.ts +30 -4
- package/src/lexer/token-factory.ts +15 -2
- package/src/lexer/tokens.ts +4 -3
- package/src/parser/rules/block/blockquote/build.ts +81 -37
- package/src/parser/rules/block/blockquote/index.ts +5 -6
- package/src/parser/rules/block/blockquote/line.ts +11 -10
- package/src/parser/rules/block/blockquote/lines.ts +102 -4
- package/src/parser/rules/block/code/content.ts +0 -3
- package/src/parser/rules/block/code/index.ts +14 -10
- package/src/parser/rules/block/definition-list/index.ts +4 -10
- package/src/parser/rules/block/definition-list/item-value.ts +2 -11
- package/src/parser/rules/block/definition-list/items.ts +1 -2
- package/src/parser/rules/block/embed-block/index.ts +30 -30
- package/src/parser/rules/block/heading/index.ts +7 -0
- package/src/parser/rules/block/paragraph/index.ts +41 -10
- package/src/parser/rules/block/parsing/content.ts +18 -1
- package/src/parser/rules/block/table/pipe/cell.ts +36 -1
- package/src/parser/rules/block/table/pipe/row.ts +21 -1
- package/src/parser/rules/block/toc/element.ts +2 -2
- package/src/parser/rules/block/toc/index.ts +2 -2
- package/src/parser/rules/block/toc/open.ts +5 -18
- package/src/parser/rules/contracts/scope.ts +4 -0
- package/src/parser/rules/inline/bold.ts +5 -5
- package/src/parser/rules/inline/color/syntax.ts +5 -8
- package/src/parser/rules/inline/formatting/close.ts +39 -0
- package/src/parser/rules/inline/formatting/container.ts +7 -4
- package/src/parser/rules/inline/index.ts +2 -0
- package/src/parser/rules/inline/italic.ts +5 -5
- package/src/parser/rules/inline/monospace.ts +5 -5
- package/src/parser/rules/inline/parsing/block-start-predicates.ts +2 -0
- package/src/parser/rules/inline/parsing/inline-content.ts +58 -4
- package/src/parser/rules/inline/raw/end.ts +28 -0
- package/src/parser/rules/inline/span/content.ts +32 -1
- package/src/parser/rules/inline/strikethrough/index.ts +1 -1
- package/src/parser/rules/inline/strikethrough/parse.ts +2 -9
- package/src/parser/rules/inline/strikethrough/syntax.ts +3 -20
- package/src/parser/rules/inline/subscript.ts +5 -5
- package/src/parser/rules/inline/superscript.ts +5 -5
- package/src/parser/rules/inline/underline/index.ts +5 -78
- package/src/parser/rules/tokens.ts +6 -15
- package/src/parser/rules/inline/underline/child.ts +0 -26
- package/src/parser/rules/inline/underline/content.ts +0 -29
package/dist/index.cjs
CHANGED
|
@@ -71,6 +71,7 @@ __export(exports_src, {
|
|
|
71
71
|
container: () => import_ast9.container,
|
|
72
72
|
compileTemplate: () => compileTemplate,
|
|
73
73
|
compileListUsersTemplate: () => compileListUsersTemplate,
|
|
74
|
+
buildInfo: () => buildInfo,
|
|
74
75
|
bold: () => import_ast9.bold,
|
|
75
76
|
STYLE_SLOT_PREFIX: () => import_ast4.STYLE_SLOT_PREFIX,
|
|
76
77
|
Parser: () => Parser,
|
|
@@ -78,6 +79,15 @@ __export(exports_src, {
|
|
|
78
79
|
DEFAULT_SETTINGS: () => import_ast10.DEFAULT_SETTINGS
|
|
79
80
|
});
|
|
80
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
|
|
81
91
|
var import_ast9 = require("@wdprlib/ast");
|
|
82
92
|
var import_ast10 = require("@wdprlib/ast");
|
|
83
93
|
|
|
@@ -85,49 +95,6 @@ var import_ast10 = require("@wdprlib/ast");
|
|
|
85
95
|
function createToken(type, value, position, lineStart = false) {
|
|
86
96
|
return { type, value, position, lineStart };
|
|
87
97
|
}
|
|
88
|
-
// packages/parser/src/lexer/token-factory.ts
|
|
89
|
-
var ZERO_POSITION = {
|
|
90
|
-
start: { line: 0, column: 0, offset: 0 },
|
|
91
|
-
end: { line: 0, column: 0, offset: 0 }
|
|
92
|
-
};
|
|
93
|
-
function createLexerToken(state, type, value, trackPositions) {
|
|
94
|
-
return {
|
|
95
|
-
type,
|
|
96
|
-
value,
|
|
97
|
-
position: trackPositions ? currentTokenPosition(state, value) : ZERO_POSITION,
|
|
98
|
-
lineStart: isTokenAtLineStart(state)
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
function updateLastNonWhitespaceType(current, type) {
|
|
102
|
-
return type === "WHITESPACE" ? current : type;
|
|
103
|
-
}
|
|
104
|
-
function nextBlockOpenerDepth(current, type) {
|
|
105
|
-
if (type === "BLOCK_OPEN" || type === "BLOCK_END_OPEN") {
|
|
106
|
-
return current + 1;
|
|
107
|
-
}
|
|
108
|
-
if (type === "BLOCK_CLOSE" && current > 0) {
|
|
109
|
-
return current - 1;
|
|
110
|
-
}
|
|
111
|
-
return current;
|
|
112
|
-
}
|
|
113
|
-
function currentTokenPosition(state, value) {
|
|
114
|
-
return {
|
|
115
|
-
start: {
|
|
116
|
-
line: state.line,
|
|
117
|
-
column: state.column - value.length,
|
|
118
|
-
offset: state.pos - value.length
|
|
119
|
-
},
|
|
120
|
-
end: {
|
|
121
|
-
line: state.line,
|
|
122
|
-
column: state.column,
|
|
123
|
-
offset: state.pos
|
|
124
|
-
}
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
function isTokenAtLineStart(state) {
|
|
128
|
-
return state.tokens.length === 0 || state.tokens[state.tokens.length - 1]?.type === "NEWLINE";
|
|
129
|
-
}
|
|
130
|
-
|
|
131
98
|
// packages/parser/src/lexer/state.ts
|
|
132
99
|
function createInitialLexerState(source) {
|
|
133
100
|
return {
|
|
@@ -136,9 +103,16 @@ function createInitialLexerState(source) {
|
|
|
136
103
|
line: 1,
|
|
137
104
|
column: 1,
|
|
138
105
|
lineStart: true,
|
|
106
|
+
quoteContentStart: false,
|
|
139
107
|
tokens: []
|
|
140
108
|
};
|
|
141
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
|
+
}
|
|
142
116
|
function isAtEnd(state) {
|
|
143
117
|
return state.pos >= state.source.length;
|
|
144
118
|
}
|
|
@@ -152,18 +126,25 @@ function advance(state, n = 1) {
|
|
|
152
126
|
updatePosition(state, start, end);
|
|
153
127
|
return value;
|
|
154
128
|
}
|
|
155
|
-
function advanceByToken(state, type, length) {
|
|
129
|
+
function advanceByToken(state, type, length, value = "") {
|
|
130
|
+
const afterQuoteMarker = isLineStartQuoteMarker(state.tokens[state.tokens.length - 1]);
|
|
156
131
|
state.pos += length;
|
|
157
132
|
if (type === "NEWLINE") {
|
|
158
133
|
state.line++;
|
|
159
134
|
state.column = 1;
|
|
160
135
|
state.lineStart = true;
|
|
136
|
+
state.quoteContentStart = false;
|
|
161
137
|
return;
|
|
162
138
|
}
|
|
163
139
|
state.column += length;
|
|
164
|
-
if (type
|
|
165
|
-
|
|
140
|
+
if (type === "WHITESPACE") {
|
|
141
|
+
if (afterQuoteMarker && value === " ") {
|
|
142
|
+
state.quoteContentStart = true;
|
|
143
|
+
}
|
|
144
|
+
return;
|
|
166
145
|
}
|
|
146
|
+
state.lineStart = false;
|
|
147
|
+
state.quoteContentStart = false;
|
|
167
148
|
}
|
|
168
149
|
function updatePosition(state, start, end) {
|
|
169
150
|
state.pos = end;
|
|
@@ -174,8 +155,9 @@ function updatePositionFromValue(state, value) {
|
|
|
174
155
|
`);
|
|
175
156
|
if (firstNewline === -1) {
|
|
176
157
|
state.column += value.length;
|
|
177
|
-
if (
|
|
158
|
+
if (hasNonLineStartSpacing(value, 0)) {
|
|
178
159
|
state.lineStart = false;
|
|
160
|
+
state.quoteContentStart = false;
|
|
179
161
|
}
|
|
180
162
|
return;
|
|
181
163
|
}
|
|
@@ -194,6 +176,7 @@ function updatePositionFromValue(state, value) {
|
|
|
194
176
|
state.line += newlineCount;
|
|
195
177
|
state.column = value.length - lastNewline;
|
|
196
178
|
state.lineStart = !hasNonLineStartSpacing(value, lastNewline + 1);
|
|
179
|
+
state.quoteContentStart = false;
|
|
197
180
|
}
|
|
198
181
|
function hasNonLineStartSpacing(value, start) {
|
|
199
182
|
for (let i = start;i < value.length; i++) {
|
|
@@ -205,6 +188,56 @@ function hasNonLineStartSpacing(value, start) {
|
|
|
205
188
|
return false;
|
|
206
189
|
}
|
|
207
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
|
+
|
|
208
241
|
// packages/parser/src/lexer/anchor.ts
|
|
209
242
|
function findInvalidAnchorNameEnd(src, pos) {
|
|
210
243
|
if (src[pos] !== "[" || src[pos + 1] !== "[" || src[pos + 2] !== "#") {
|
|
@@ -521,7 +554,7 @@ function scanPunctuationToken(input) {
|
|
|
521
554
|
case "@":
|
|
522
555
|
return { handled: true, actions: scanAtToken(source, pos) };
|
|
523
556
|
case ">":
|
|
524
|
-
return { handled: true, actions: scanGreaterToken(source, pos,
|
|
557
|
+
return { handled: true, actions: scanGreaterToken(source, pos, input.physicalLineStart) };
|
|
525
558
|
case "-":
|
|
526
559
|
return { handled: true, actions: scanDashToken(source, pos, lineStart) };
|
|
527
560
|
case "~": {
|
|
@@ -563,6 +596,15 @@ function runToken3(src, pos, end, type) {
|
|
|
563
596
|
}
|
|
564
597
|
|
|
565
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
|
+
}
|
|
566
608
|
function scanSpacingToken(src, pos) {
|
|
567
609
|
const char = src[pos];
|
|
568
610
|
if (char === `
|
|
@@ -624,7 +666,7 @@ class Lexer {
|
|
|
624
666
|
this.blockOpenerDepth = nextBlockOpenerDepth(this.blockOpenerDepth, type);
|
|
625
667
|
}
|
|
626
668
|
emitTokenAction(action) {
|
|
627
|
-
advanceByToken(this.state, action.type, action.length);
|
|
669
|
+
advanceByToken(this.state, action.type, action.length, action.value);
|
|
628
670
|
this.addToken(action.type, action.value);
|
|
629
671
|
}
|
|
630
672
|
emitTokenActions(actions) {
|
|
@@ -638,11 +680,11 @@ class Lexer {
|
|
|
638
680
|
}
|
|
639
681
|
scanToken() {
|
|
640
682
|
const char = this.current();
|
|
641
|
-
const isLineStart = this.state
|
|
683
|
+
const isLineStart = isSyntaxLineStart(this.state);
|
|
642
684
|
const src = this.state.source;
|
|
643
685
|
const spacingAction = scanSpacingToken(src, this.state.pos);
|
|
644
686
|
if (spacingAction) {
|
|
645
|
-
this.emitTokenAction(spacingAction);
|
|
687
|
+
this.emitTokenAction(limitBlockquotePrefixSpace(spacingAction, this.state.tokens.at(-1)));
|
|
646
688
|
return;
|
|
647
689
|
}
|
|
648
690
|
const punctuation = scanPunctuationToken({
|
|
@@ -650,6 +692,7 @@ class Lexer {
|
|
|
650
692
|
source: src,
|
|
651
693
|
pos: this.state.pos,
|
|
652
694
|
lineStart: isLineStart,
|
|
695
|
+
physicalLineStart: this.state.lineStart,
|
|
653
696
|
splitBlockClose: this.splitBlockClosePositions.has(this.state.pos),
|
|
654
697
|
findInvalidAnchorNameEnd: () => this.findInvalidAnchorNameEnd()
|
|
655
698
|
});
|
|
@@ -866,7 +909,7 @@ function parseBlocksUntil(ctx, closeCondition, options) {
|
|
|
866
909
|
const elements = [];
|
|
867
910
|
let consumed = 0;
|
|
868
911
|
let pos = ctx.pos;
|
|
869
|
-
const excluded = options?.excludedBlockNames;
|
|
912
|
+
const excluded = mergeExcludedBlockNames(ctx.scope.excludedBlockNames, options?.excludedBlockNames);
|
|
870
913
|
const blockRules = excluded ? getExcludedBlockRules(ctx.blockRules, excluded) : ctx.blockRules;
|
|
871
914
|
const blockScope = {
|
|
872
915
|
...ctx.scope,
|
|
@@ -908,6 +951,13 @@ function parseBlocksUntil(ctx, closeCondition, options) {
|
|
|
908
951
|
}
|
|
909
952
|
return { elements, consumed };
|
|
910
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
|
+
}
|
|
911
961
|
function getExcludedBlockRules(blockRules, excluded) {
|
|
912
962
|
let byExcluded = excludedBlockRulesCache.get(blockRules);
|
|
913
963
|
if (!byExcluded) {
|
|
@@ -944,6 +994,31 @@ function getCandidateInlineRules(inlineRules, tokenType) {
|
|
|
944
994
|
byType.set(tokenType, candidates);
|
|
945
995
|
return candidates;
|
|
946
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
|
+
|
|
947
1022
|
// packages/parser/src/parser/rules/inline/parsing/plain-text.ts
|
|
948
1023
|
var MIN_INLINE_TEXT_RUN_LENGTH = 32;
|
|
949
1024
|
var MIN_INLINE_TEXT_RUN_DOCUMENT_TOKENS = 1e5;
|
|
@@ -986,6 +1061,135 @@ function isPlainTextRunToken(ctx, pos) {
|
|
|
986
1061
|
return token5.value !== "(";
|
|
987
1062
|
}
|
|
988
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
|
+
|
|
989
1193
|
// packages/parser/src/parser/constants.ts
|
|
990
1194
|
var BLOCK_START_TOKENS = [
|
|
991
1195
|
"BLOCKQUOTE_MARKER",
|
|
@@ -1116,7 +1320,7 @@ function isParagraphBreakingBlockStart(ctx, newlinePos, lookAhead) {
|
|
|
1116
1320
|
if (!nextMeaningfulToken.lineStart && !isIndentedBlockOpener) {
|
|
1117
1321
|
return false;
|
|
1118
1322
|
}
|
|
1119
|
-
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);
|
|
1120
1324
|
}
|
|
1121
1325
|
function isOrphanCloseSpan(ctx, blockEndOpenPos) {
|
|
1122
1326
|
const token5 = ctx.tokens[blockEndOpenPos];
|
|
@@ -1226,27 +1430,45 @@ function parseInlineUntil(ctx, endType) {
|
|
|
1226
1430
|
let consumed = 0;
|
|
1227
1431
|
let pos = ctx.pos;
|
|
1228
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
|
+
}
|
|
1229
1450
|
const { inlineRules } = ctx;
|
|
1230
1451
|
const inlineCtx = {
|
|
1231
1452
|
...ctx,
|
|
1232
|
-
pos
|
|
1453
|
+
pos,
|
|
1454
|
+
scope: { ...ctx.scope, inlineEnd }
|
|
1233
1455
|
};
|
|
1234
1456
|
const canCollectLongPlainTextRuns = ctx.tokens.length >= MIN_INLINE_TEXT_RUN_DOCUMENT_TOKENS;
|
|
1235
|
-
while (pos <
|
|
1457
|
+
while (pos < inlineEnd) {
|
|
1236
1458
|
const token5 = ctx.tokens[pos];
|
|
1237
1459
|
if (!token5 || token5.type === "EOF") {
|
|
1238
1460
|
break;
|
|
1239
1461
|
}
|
|
1240
|
-
if (
|
|
1462
|
+
if (ctx.scope.blockCloseCondition) {
|
|
1241
1463
|
const checkCtx = { ...ctx, pos };
|
|
1242
1464
|
if (ctx.scope.blockCloseCondition(checkCtx)) {
|
|
1243
1465
|
break;
|
|
1244
1466
|
}
|
|
1245
1467
|
}
|
|
1246
|
-
if (!
|
|
1468
|
+
if (!multiline && token5.type === "NEWLINE") {
|
|
1247
1469
|
break;
|
|
1248
1470
|
}
|
|
1249
|
-
if (
|
|
1471
|
+
if (multiline && token5.type === "NEWLINE" && !ctx.scope.tableFormatting) {
|
|
1250
1472
|
const boundary = getParagraphNewlineBoundary(ctx, pos, nodes.length > 0);
|
|
1251
1473
|
if (boundary.shouldBreak) {
|
|
1252
1474
|
if (boundary.preservePrecedingLineBreak) {
|
|
@@ -1256,6 +1478,11 @@ function parseInlineUntil(ctx, endType) {
|
|
|
1256
1478
|
break;
|
|
1257
1479
|
}
|
|
1258
1480
|
}
|
|
1481
|
+
if (ctx.scope.tableFormatting?.suppressedClosers.has(pos)) {
|
|
1482
|
+
pos++;
|
|
1483
|
+
consumed++;
|
|
1484
|
+
continue;
|
|
1485
|
+
}
|
|
1259
1486
|
if (token5.type === endType) {
|
|
1260
1487
|
break;
|
|
1261
1488
|
}
|
|
@@ -1280,6 +1507,24 @@ function parseInlineUntil(ctx, endType) {
|
|
|
1280
1507
|
for (const rule of getCandidateInlineRules(inlineRules, token5.type)) {
|
|
1281
1508
|
const result = rule.parse(inlineCtx);
|
|
1282
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
|
+
}
|
|
1283
1528
|
nodes.push(...result.elements);
|
|
1284
1529
|
consumed += result.consumed;
|
|
1285
1530
|
pos += result.consumed;
|
|
@@ -1295,6 +1540,16 @@ function parseInlineUntil(ctx, endType) {
|
|
|
1295
1540
|
}
|
|
1296
1541
|
return { elements: nodes, consumed };
|
|
1297
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
|
+
]);
|
|
1298
1553
|
// packages/parser/src/parser/rules/block/parsing/attributes/names.ts
|
|
1299
1554
|
function consumeAttributeName(ctx, startPos, startConsumed, startName, options) {
|
|
1300
1555
|
if (startName === "_" && isAttributeWordToken(ctx.tokens[startPos])) {
|
|
@@ -1470,7 +1725,7 @@ function eofToken() {
|
|
|
1470
1725
|
}
|
|
1471
1726
|
function hasClosingMarkerBeforeNewline(ctx, markerType, markerValue) {
|
|
1472
1727
|
let pos = ctx.pos;
|
|
1473
|
-
while (pos < ctx.tokens.length) {
|
|
1728
|
+
while (pos < (ctx.scope.inlineEnd ?? ctx.tokens.length)) {
|
|
1474
1729
|
const token5 = ctx.tokens[pos];
|
|
1475
1730
|
if (!token5 || token5.type === "NEWLINE" || token5.type === "EOF") {
|
|
1476
1731
|
return false;
|
|
@@ -1484,31 +1739,6 @@ function hasClosingMarkerBeforeNewline(ctx, markerType, markerValue) {
|
|
|
1484
1739
|
}
|
|
1485
1740
|
return false;
|
|
1486
1741
|
}
|
|
1487
|
-
function hasClosingMarkerBeforeParagraphBreak(ctx, markerType, markerValue) {
|
|
1488
|
-
let pos = ctx.pos;
|
|
1489
|
-
while (pos < ctx.tokens.length) {
|
|
1490
|
-
const token5 = ctx.tokens[pos];
|
|
1491
|
-
if (!token5 || token5.type === "EOF") {
|
|
1492
|
-
return false;
|
|
1493
|
-
}
|
|
1494
|
-
if (token5.type === "NEWLINE") {
|
|
1495
|
-
let lookAhead = 1;
|
|
1496
|
-
while (ctx.tokens[pos + lookAhead]?.type === "WHITESPACE") {
|
|
1497
|
-
lookAhead++;
|
|
1498
|
-
}
|
|
1499
|
-
if (ctx.tokens[pos + lookAhead]?.type === "NEWLINE" || ctx.tokens[pos + lookAhead]?.type === "EOF" || !ctx.tokens[pos + lookAhead]) {
|
|
1500
|
-
return false;
|
|
1501
|
-
}
|
|
1502
|
-
}
|
|
1503
|
-
if (token5.type === markerType) {
|
|
1504
|
-
if (markerValue === undefined || token5.value === markerValue) {
|
|
1505
|
-
return true;
|
|
1506
|
-
}
|
|
1507
|
-
}
|
|
1508
|
-
pos++;
|
|
1509
|
-
}
|
|
1510
|
-
return false;
|
|
1511
|
-
}
|
|
1512
1742
|
// packages/parser/src/parser/rules/block/heading/open.ts
|
|
1513
1743
|
function parseHeadingOpen(ctx) {
|
|
1514
1744
|
const marker = ctx.tokens[ctx.pos];
|
|
@@ -1575,6 +1805,15 @@ var headingRule = {
|
|
|
1575
1805
|
const inlineCtx = { ...ctx, pos };
|
|
1576
1806
|
const inlineResult = parseInlineUntil(inlineCtx, "NEWLINE");
|
|
1577
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
|
+
}
|
|
1578
1817
|
consumed += inlineResult.consumed;
|
|
1579
1818
|
pos += inlineResult.consumed;
|
|
1580
1819
|
if (ctx.tokens[pos]?.type === "NEWLINE") {
|
|
@@ -2374,17 +2613,15 @@ function parseBlockquoteLine(ctx, startPos) {
|
|
|
2374
2613
|
if (ctx.tokens[pos]?.type !== "WHITESPACE") {
|
|
2375
2614
|
return { kind: "skipped", consumed: consumeLineRemainder(ctx, pos) + consumed };
|
|
2376
2615
|
}
|
|
2377
|
-
|
|
2616
|
+
pos++;
|
|
2617
|
+
consumed++;
|
|
2618
|
+
const contentStart = pos;
|
|
2619
|
+
while (pos < ctx.tokens.length && ctx.tokens[pos]?.type !== "NEWLINE" && ctx.tokens[pos]?.type !== "EOF") {
|
|
2378
2620
|
pos++;
|
|
2379
2621
|
consumed++;
|
|
2380
2622
|
}
|
|
2381
|
-
const inlineCtx = { ...ctx, pos };
|
|
2382
|
-
const inlineResult = parseInlineUntil(inlineCtx, "NEWLINE");
|
|
2383
|
-
consumed += inlineResult.consumed;
|
|
2384
|
-
pos += inlineResult.consumed;
|
|
2385
|
-
let hasLineBreak = false;
|
|
2386
2623
|
if (ctx.tokens[pos]?.type === "NEWLINE") {
|
|
2387
|
-
|
|
2624
|
+
pos++;
|
|
2388
2625
|
consumed++;
|
|
2389
2626
|
}
|
|
2390
2627
|
return {
|
|
@@ -2392,7 +2629,7 @@ function parseBlockquoteLine(ctx, startPos) {
|
|
|
2392
2629
|
line: {
|
|
2393
2630
|
depth: depth - 1,
|
|
2394
2631
|
ltype: null,
|
|
2395
|
-
value: {
|
|
2632
|
+
value: { start: contentStart, end: pos }
|
|
2396
2633
|
},
|
|
2397
2634
|
consumed
|
|
2398
2635
|
};
|
|
@@ -2411,47 +2648,43 @@ function consumeLineRemainder(ctx, startPos) {
|
|
|
2411
2648
|
}
|
|
2412
2649
|
|
|
2413
2650
|
// packages/parser/src/parser/rules/block/blockquote/build.ts
|
|
2414
|
-
|
|
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) {
|
|
2415
2661
|
const depthTrees = processDepths(null, lines);
|
|
2416
|
-
return depthTrees.map(({ list }) => buildBlockquoteElement(list));
|
|
2662
|
+
return depthTrees.map(({ list }) => buildBlockquoteElement(ctx, list)).filter((element) => element !== null);
|
|
2417
2663
|
}
|
|
2418
|
-
function buildBlockquoteElement(list) {
|
|
2664
|
+
function buildBlockquoteElement(ctx, list) {
|
|
2419
2665
|
const children = [];
|
|
2420
|
-
let
|
|
2421
|
-
function
|
|
2422
|
-
if (
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
if (currentParagraphChildren.length > 0) {
|
|
2427
|
-
children.push({
|
|
2428
|
-
element: "container",
|
|
2429
|
-
data: {
|
|
2430
|
-
type: "paragraph",
|
|
2431
|
-
attributes: {},
|
|
2432
|
-
elements: currentParagraphChildren
|
|
2433
|
-
}
|
|
2434
|
-
});
|
|
2435
|
-
}
|
|
2436
|
-
currentParagraphChildren = [];
|
|
2437
|
-
}
|
|
2666
|
+
let pending = [];
|
|
2667
|
+
function flushPending() {
|
|
2668
|
+
if (pending.length === 0)
|
|
2669
|
+
return;
|
|
2670
|
+
children.push(...parseLines(ctx, pending));
|
|
2671
|
+
pending = [];
|
|
2438
2672
|
}
|
|
2439
2673
|
for (const item of list) {
|
|
2440
2674
|
if (item.kind === "item") {
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
continue;
|
|
2444
|
-
}
|
|
2445
|
-
currentParagraphChildren.push(...item.value.elements);
|
|
2446
|
-
if (item.value.hasLineBreak) {
|
|
2447
|
-
currentParagraphChildren.push({ element: "line-break" });
|
|
2448
|
-
}
|
|
2449
|
-
} else {
|
|
2450
|
-
flushParagraph();
|
|
2451
|
-
children.push(buildBlockquoteElement(item.children));
|
|
2675
|
+
pending.push(item.value);
|
|
2676
|
+
continue;
|
|
2452
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;
|
|
2453
2687
|
}
|
|
2454
|
-
flushParagraph();
|
|
2455
2688
|
return {
|
|
2456
2689
|
element: "container",
|
|
2457
2690
|
data: {
|
|
@@ -2461,6 +2694,31 @@ function buildBlockquoteElement(list) {
|
|
|
2461
2694
|
}
|
|
2462
2695
|
};
|
|
2463
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
|
+
};
|
|
2464
2722
|
|
|
2465
2723
|
// packages/parser/src/parser/rules/block/blockquote/lines.ts
|
|
2466
2724
|
function collectBlockquoteLines(ctx) {
|
|
@@ -2469,16 +2727,90 @@ function collectBlockquoteLines(ctx) {
|
|
|
2469
2727
|
let consumed = 0;
|
|
2470
2728
|
while (pos < ctx.tokens.length) {
|
|
2471
2729
|
const result = parseBlockquoteLine(ctx, pos);
|
|
2472
|
-
if (result.kind === "stop")
|
|
2473
|
-
|
|
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
|
+
}
|
|
2474
2738
|
pos += result.consumed;
|
|
2475
2739
|
consumed += result.consumed;
|
|
2476
2740
|
if (result.kind === "parsed") {
|
|
2477
2741
|
lines.push(result.line);
|
|
2478
2742
|
}
|
|
2479
2743
|
}
|
|
2744
|
+
blankCommentOnlyLines(ctx, lines);
|
|
2480
2745
|
return { lines, consumed };
|
|
2481
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
|
+
}
|
|
2482
2814
|
|
|
2483
2815
|
// packages/parser/src/parser/rules/block/blockquote/index.ts
|
|
2484
2816
|
var blockquoteRule = {
|
|
@@ -2497,9 +2829,9 @@ var blockquoteRule = {
|
|
|
2497
2829
|
}
|
|
2498
2830
|
return { success: false };
|
|
2499
2831
|
}
|
|
2500
|
-
const blockquotes = buildBlockquoteElements(blockquoteLines.lines);
|
|
2832
|
+
const blockquotes = buildBlockquoteElements(ctx, blockquoteLines.lines);
|
|
2501
2833
|
if (blockquotes.length === 0) {
|
|
2502
|
-
return { success:
|
|
2834
|
+
return { success: true, elements: [], consumed: blockquoteLines.consumed };
|
|
2503
2835
|
}
|
|
2504
2836
|
return {
|
|
2505
2837
|
success: true,
|
|
@@ -2594,17 +2926,8 @@ function parseDefinitionItemValue(ctx, startPos) {
|
|
|
2594
2926
|
break;
|
|
2595
2927
|
}
|
|
2596
2928
|
if (token5.type === "NEWLINE") {
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
pos++;
|
|
2600
|
-
consumed++;
|
|
2601
|
-
break;
|
|
2602
|
-
}
|
|
2603
|
-
if (nextToken?.type === "NEWLINE" || !nextToken || nextToken.type === "EOF") {
|
|
2604
|
-
pos++;
|
|
2605
|
-
consumed++;
|
|
2606
|
-
break;
|
|
2607
|
-
}
|
|
2929
|
+
consumed++;
|
|
2930
|
+
break;
|
|
2608
2931
|
}
|
|
2609
2932
|
const inlineCtx = { ...ctx, pos };
|
|
2610
2933
|
const result = parseInlineUntil(inlineCtx, "NEWLINE");
|
|
@@ -2682,14 +3005,10 @@ var definitionListRule = {
|
|
|
2682
3005
|
if (result.items.length === 0) {
|
|
2683
3006
|
return { success: false };
|
|
2684
3007
|
}
|
|
3008
|
+
const items = toDefinitionListItems(result.items.filter((item) => item.value.length > 0));
|
|
2685
3009
|
return {
|
|
2686
3010
|
success: true,
|
|
2687
|
-
elements: [
|
|
2688
|
-
{
|
|
2689
|
-
element: "definition-list",
|
|
2690
|
-
data: toDefinitionListItems(result.items)
|
|
2691
|
-
}
|
|
2692
|
-
],
|
|
3011
|
+
elements: items.length > 0 ? [{ element: "definition-list", data: items }] : [],
|
|
2693
3012
|
consumed: result.consumed
|
|
2694
3013
|
};
|
|
2695
3014
|
}
|
|
@@ -2794,20 +3113,49 @@ var paragraphRule = {
|
|
|
2794
3113
|
}
|
|
2795
3114
|
return {
|
|
2796
3115
|
success: true,
|
|
2797
|
-
elements:
|
|
2798
|
-
{
|
|
2799
|
-
element: "container",
|
|
2800
|
-
data: {
|
|
2801
|
-
type: "paragraph",
|
|
2802
|
-
attributes: {},
|
|
2803
|
-
elements
|
|
2804
|
-
}
|
|
2805
|
-
}
|
|
2806
|
-
],
|
|
3116
|
+
elements: wrapParagraphElements(elements),
|
|
2807
3117
|
consumed: result.consumed
|
|
2808
3118
|
};
|
|
2809
3119
|
}
|
|
2810
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
|
+
}
|
|
2811
3159
|
|
|
2812
3160
|
// packages/parser/src/parser/rules/block/div/close.ts
|
|
2813
3161
|
function isDivClose(ctx) {
|
|
@@ -3173,9 +3521,6 @@ function consumeCodeClose(ctx, startPos, closeNameConsumed) {
|
|
|
3173
3521
|
pos++;
|
|
3174
3522
|
consumed++;
|
|
3175
3523
|
}
|
|
3176
|
-
if (ctx.tokens[pos]?.type === "NEWLINE") {
|
|
3177
|
-
consumed++;
|
|
3178
|
-
}
|
|
3179
3524
|
return consumed;
|
|
3180
3525
|
}
|
|
3181
3526
|
|
|
@@ -3232,16 +3577,13 @@ var codeBlockRule = {
|
|
|
3232
3577
|
name: attrResult.attrs.name ?? null
|
|
3233
3578
|
};
|
|
3234
3579
|
ctx.codeBlocks.push(codeBlockData);
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
],
|
|
3243
|
-
consumed
|
|
3244
|
-
};
|
|
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 };
|
|
3245
3587
|
}
|
|
3246
3588
|
};
|
|
3247
3589
|
|
|
@@ -3620,7 +3962,30 @@ function parseTableCell(ctx, startPos, cellStart) {
|
|
|
3620
3962
|
consumed++;
|
|
3621
3963
|
}
|
|
3622
3964
|
const { inlineRules } = ctx;
|
|
3623
|
-
|
|
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
|
+
};
|
|
3624
3989
|
while (pos < ctx.tokens.length) {
|
|
3625
3990
|
const token5 = ctx.tokens[pos];
|
|
3626
3991
|
if (!token5 || token5.type === "NEWLINE" || token5.type === "EOF") {
|
|
@@ -3629,6 +3994,11 @@ function parseTableCell(ctx, startPos, cellStart) {
|
|
|
3629
3994
|
if (isPipeTableToken(token5.type)) {
|
|
3630
3995
|
break;
|
|
3631
3996
|
}
|
|
3997
|
+
if (ctx.scope.tableFormatting?.suppressedClosers.has(pos)) {
|
|
3998
|
+
pos++;
|
|
3999
|
+
consumed++;
|
|
4000
|
+
continue;
|
|
4001
|
+
}
|
|
3632
4002
|
if (tryConsumeUnderscoreLineBreak(ctx, pos, children)) {
|
|
3633
4003
|
pos += 3;
|
|
3634
4004
|
consumed += 3;
|
|
@@ -3688,6 +4058,21 @@ function tryConsumeUnderscoreLineBreak(ctx, pos, children) {
|
|
|
3688
4058
|
|
|
3689
4059
|
// packages/parser/src/parser/rules/block/table/pipe/row.ts
|
|
3690
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
|
+
};
|
|
3691
4076
|
const rows = [];
|
|
3692
4077
|
let pos = startPos;
|
|
3693
4078
|
let consumed = 0;
|
|
@@ -3696,7 +4081,7 @@ function parsePipeTableRows(ctx, startPos) {
|
|
|
3696
4081
|
if (!token5 || !token5.lineStart || !isPipeTableToken(token5.type)) {
|
|
3697
4082
|
break;
|
|
3698
4083
|
}
|
|
3699
|
-
const rowResult = parseTableRow(
|
|
4084
|
+
const rowResult = parseTableRow(tableCtx, pos);
|
|
3700
4085
|
rows.push(rowResult.row);
|
|
3701
4086
|
pos += rowResult.consumed;
|
|
3702
4087
|
consumed += rowResult.consumed;
|
|
@@ -9124,6 +9509,8 @@ var embedBlockRule = {
|
|
|
9124
9509
|
name: "embed-block",
|
|
9125
9510
|
startTokens: ["BLOCK_OPEN"],
|
|
9126
9511
|
requiresLineStart: false,
|
|
9512
|
+
preservesPrecedingLineBreak: true,
|
|
9513
|
+
isStartPattern: (ctx, pos) => parseEmbedBlockOpen(ctx, pos) !== null,
|
|
9127
9514
|
parse(ctx) {
|
|
9128
9515
|
const openToken = currentToken(ctx);
|
|
9129
9516
|
if (openToken.type !== "BLOCK_OPEN") {
|
|
@@ -9139,38 +9526,30 @@ var embedBlockRule = {
|
|
|
9139
9526
|
pos += contentResult.consumed;
|
|
9140
9527
|
consumed += contentResult.consumed;
|
|
9141
9528
|
if (!contentResult.foundClose) {
|
|
9142
|
-
ctx.diagnostics.
|
|
9143
|
-
|
|
9144
|
-
|
|
9145
|
-
|
|
9146
|
-
|
|
9147
|
-
|
|
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
|
+
});
|
|
9148
9536
|
return { success: false };
|
|
9149
9537
|
}
|
|
9150
9538
|
const closeConsumed = consumeEmbedClose(ctx, pos);
|
|
9151
9539
|
pos += closeConsumed;
|
|
9152
9540
|
consumed += closeConsumed;
|
|
9153
|
-
|
|
9154
|
-
|
|
9155
|
-
|
|
9156
|
-
|
|
9157
|
-
|
|
9158
|
-
|
|
9159
|
-
|
|
9160
|
-
|
|
9161
|
-
|
|
9162
|
-
|
|
9163
|
-
|
|
9164
|
-
|
|
9165
|
-
contents: contentResult.contents.trim()
|
|
9166
|
-
}
|
|
9167
|
-
}
|
|
9168
|
-
]
|
|
9169
|
-
}
|
|
9170
|
-
}
|
|
9171
|
-
],
|
|
9172
|
-
consumed
|
|
9173
|
-
};
|
|
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 };
|
|
9174
9553
|
}
|
|
9175
9554
|
};
|
|
9176
9555
|
|
|
@@ -9484,11 +9863,11 @@ var iftagsRule = {
|
|
|
9484
9863
|
};
|
|
9485
9864
|
|
|
9486
9865
|
// packages/parser/src/parser/rules/block/toc/element.ts
|
|
9487
|
-
function createTocElement(align) {
|
|
9866
|
+
function createTocElement(align, title) {
|
|
9488
9867
|
return {
|
|
9489
9868
|
element: "table-of-contents",
|
|
9490
9869
|
data: {
|
|
9491
|
-
attributes: {},
|
|
9870
|
+
attributes: title === undefined ? {} : { title },
|
|
9492
9871
|
align
|
|
9493
9872
|
}
|
|
9494
9873
|
};
|
|
@@ -9531,26 +9910,17 @@ function parseTocOpen(ctx, startPos) {
|
|
|
9531
9910
|
} else {
|
|
9532
9911
|
return null;
|
|
9533
9912
|
}
|
|
9534
|
-
|
|
9913
|
+
const attributes = parseAttributes(ctx, pos);
|
|
9914
|
+
pos += attributes.consumed;
|
|
9535
9915
|
if (ctx.tokens[pos]?.type !== "BLOCK_CLOSE") {
|
|
9536
9916
|
return null;
|
|
9537
9917
|
}
|
|
9538
9918
|
return {
|
|
9539
9919
|
align,
|
|
9920
|
+
title: attributes.attrs.title,
|
|
9540
9921
|
consumed: pos + 1 - startPos
|
|
9541
9922
|
};
|
|
9542
9923
|
}
|
|
9543
|
-
function skipUntilClose(ctx, startPos) {
|
|
9544
|
-
let pos = startPos;
|
|
9545
|
-
while (pos < ctx.tokens.length) {
|
|
9546
|
-
const token5 = ctx.tokens[pos];
|
|
9547
|
-
if (!token5 || token5.type === "BLOCK_CLOSE" || token5.type === "NEWLINE" || token5.type === "EOF") {
|
|
9548
|
-
break;
|
|
9549
|
-
}
|
|
9550
|
-
pos++;
|
|
9551
|
-
}
|
|
9552
|
-
return pos;
|
|
9553
|
-
}
|
|
9554
9924
|
function isNameToken(token5) {
|
|
9555
9925
|
return token5?.type === "TEXT" || token5?.type === "IDENTIFIER";
|
|
9556
9926
|
}
|
|
@@ -9574,7 +9944,7 @@ var tocRule = {
|
|
|
9574
9944
|
}
|
|
9575
9945
|
return {
|
|
9576
9946
|
success: true,
|
|
9577
|
-
elements: [createTocElement(openResult.align)],
|
|
9947
|
+
elements: [createTocElement(openResult.align, openResult.title)],
|
|
9578
9948
|
consumed: openResult.consumed
|
|
9579
9949
|
};
|
|
9580
9950
|
}
|
|
@@ -10175,6 +10545,31 @@ var blockRules = [
|
|
|
10175
10545
|
galleryRule,
|
|
10176
10546
|
divRule
|
|
10177
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
|
+
|
|
10178
10573
|
// packages/parser/src/parser/rules/inline/formatting/container.ts
|
|
10179
10574
|
function createInlineContainer(type, elements) {
|
|
10180
10575
|
return {
|
|
@@ -10186,9 +10581,10 @@ function createInlineContainer(type, elements) {
|
|
|
10186
10581
|
}
|
|
10187
10582
|
};
|
|
10188
10583
|
}
|
|
10189
|
-
function
|
|
10584
|
+
function parseDelimitedContainer(ctx, closeToken, type, options = {}) {
|
|
10190
10585
|
const startToken = currentToken(ctx);
|
|
10191
|
-
|
|
10586
|
+
const close = findFormattingClose(ctx, ctx.pos + 1, closeToken);
|
|
10587
|
+
if (close === null) {
|
|
10192
10588
|
return {
|
|
10193
10589
|
success: true,
|
|
10194
10590
|
elements: [{ element: "text", data: startToken.value }],
|
|
@@ -10196,7 +10592,7 @@ function parseSameLineDelimitedContainer(ctx, closeToken, type, options = {}) {
|
|
|
10196
10592
|
};
|
|
10197
10593
|
}
|
|
10198
10594
|
const result = parseInlineUntil({ ...ctx, pos: ctx.pos + 1 }, closeToken);
|
|
10199
|
-
const consumed = 1 + result.consumed + 1;
|
|
10595
|
+
const consumed = 1 + result.consumed + consumeFormattingClose(ctx, close, ctx.pos + 1 + result.consumed);
|
|
10200
10596
|
if (options.discardEmpty === true && result.elements.length === 0) {
|
|
10201
10597
|
return {
|
|
10202
10598
|
success: true,
|
|
@@ -10216,7 +10612,7 @@ var boldRule = {
|
|
|
10216
10612
|
name: "bold",
|
|
10217
10613
|
startTokens: ["BOLD_MARKER"],
|
|
10218
10614
|
parse(ctx) {
|
|
10219
|
-
return
|
|
10615
|
+
return parseDelimitedContainer(ctx, "BOLD_MARKER", "bold", { discardEmpty: true });
|
|
10220
10616
|
}
|
|
10221
10617
|
};
|
|
10222
10618
|
|
|
@@ -10225,102 +10621,28 @@ var italicRule = {
|
|
|
10225
10621
|
name: "italic",
|
|
10226
10622
|
startTokens: ["ITALIC_MARKER"],
|
|
10227
10623
|
parse(ctx) {
|
|
10228
|
-
return
|
|
10624
|
+
return parseDelimitedContainer(ctx, "ITALIC_MARKER", "italics");
|
|
10229
10625
|
}
|
|
10230
10626
|
};
|
|
10231
10627
|
|
|
10232
|
-
// packages/parser/src/parser/rules/inline/underline/child.ts
|
|
10233
|
-
function parseUnderlineChild(ctx, pos) {
|
|
10234
|
-
const token5 = ctx.tokens[pos];
|
|
10235
|
-
if (!token5) {
|
|
10236
|
-
return { elements: [], consumed: 0 };
|
|
10237
|
-
}
|
|
10238
|
-
if (token5.type === "NEWLINE") {
|
|
10239
|
-
return { elements: [{ element: "line-break" }], consumed: 1 };
|
|
10240
|
-
}
|
|
10241
|
-
const result = parseInlineUntil({ ...ctx, pos }, "UNDERLINE_MARKER");
|
|
10242
|
-
if (result.elements.length > 0) {
|
|
10243
|
-
return { elements: result.elements, consumed: result.consumed };
|
|
10244
|
-
}
|
|
10245
|
-
return { elements: [{ element: "text", data: token5.value }], consumed: 1 };
|
|
10246
|
-
}
|
|
10247
|
-
|
|
10248
|
-
// packages/parser/src/parser/rules/inline/underline/content.ts
|
|
10249
|
-
function parseUnderlineContent(ctx, startPos) {
|
|
10250
|
-
const children = [];
|
|
10251
|
-
let pos = startPos;
|
|
10252
|
-
let consumed = 1;
|
|
10253
|
-
while (pos < ctx.tokens.length) {
|
|
10254
|
-
const token5 = ctx.tokens[pos];
|
|
10255
|
-
if (!token5 || token5.type === "EOF")
|
|
10256
|
-
break;
|
|
10257
|
-
if (token5.type === "UNDERLINE_MARKER") {
|
|
10258
|
-
consumed++;
|
|
10259
|
-
break;
|
|
10260
|
-
}
|
|
10261
|
-
const child = parseUnderlineChild(ctx, pos);
|
|
10262
|
-
children.push(...child.elements);
|
|
10263
|
-
pos += child.consumed;
|
|
10264
|
-
consumed += child.consumed;
|
|
10265
|
-
}
|
|
10266
|
-
return { children, consumed };
|
|
10267
|
-
}
|
|
10268
|
-
|
|
10269
10628
|
// packages/parser/src/parser/rules/inline/underline/index.ts
|
|
10270
10629
|
var underlineRule = {
|
|
10271
10630
|
name: "underline",
|
|
10272
10631
|
startTokens: ["UNDERLINE_MARKER"],
|
|
10273
10632
|
parse(ctx) {
|
|
10274
|
-
|
|
10275
|
-
if (!hasClosingMarkerBeforeParagraphBreak({ ...ctx, pos: ctx.pos + 1 }, "UNDERLINE_MARKER")) {
|
|
10276
|
-
return {
|
|
10277
|
-
success: true,
|
|
10278
|
-
elements: [{ element: "text", data: startToken.value }],
|
|
10279
|
-
consumed: 1
|
|
10280
|
-
};
|
|
10281
|
-
}
|
|
10282
|
-
const { children, consumed } = parseUnderlineContent(ctx, ctx.pos + 1);
|
|
10283
|
-
if (children.length === 0) {
|
|
10284
|
-
return {
|
|
10285
|
-
success: true,
|
|
10286
|
-
elements: [],
|
|
10287
|
-
consumed
|
|
10288
|
-
};
|
|
10289
|
-
}
|
|
10290
|
-
return {
|
|
10291
|
-
success: true,
|
|
10292
|
-
elements: [createInlineContainer("underline", children)],
|
|
10293
|
-
consumed
|
|
10294
|
-
};
|
|
10633
|
+
return parseDelimitedContainer(ctx, "UNDERLINE_MARKER", "underline", { discardEmpty: true });
|
|
10295
10634
|
}
|
|
10296
10635
|
};
|
|
10297
10636
|
|
|
10298
10637
|
// packages/parser/src/parser/rules/inline/strikethrough/parse.ts
|
|
10299
10638
|
function parseStrikethroughContent(ctx) {
|
|
10300
|
-
|
|
10301
|
-
return {
|
|
10302
|
-
success: true,
|
|
10303
|
-
elements: [createInlineContainer("strikethrough", result.elements)],
|
|
10304
|
-
consumed: 1 + result.consumed + 1
|
|
10305
|
-
};
|
|
10639
|
+
return parseDelimitedContainer(ctx, "STRIKE_MARKER", "strikethrough");
|
|
10306
10640
|
}
|
|
10307
10641
|
|
|
10308
10642
|
// packages/parser/src/parser/rules/inline/strikethrough/syntax.ts
|
|
10309
10643
|
function hasValidStrikethroughClose(ctx) {
|
|
10310
|
-
|
|
10311
|
-
|
|
10312
|
-
while (pos < ctx.tokens.length) {
|
|
10313
|
-
const token5 = ctx.tokens[pos];
|
|
10314
|
-
if (!token5 || token5.type === "NEWLINE" || token5.type === "EOF") {
|
|
10315
|
-
return false;
|
|
10316
|
-
}
|
|
10317
|
-
if (token5.type === "STRIKE_MARKER") {
|
|
10318
|
-
return !prevWasWhitespace;
|
|
10319
|
-
}
|
|
10320
|
-
prevWasWhitespace = token5.type === "WHITESPACE";
|
|
10321
|
-
pos++;
|
|
10322
|
-
}
|
|
10323
|
-
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";
|
|
10324
10646
|
}
|
|
10325
10647
|
|
|
10326
10648
|
// packages/parser/src/parser/rules/inline/strikethrough/index.ts
|
|
@@ -10344,7 +10666,7 @@ var superscriptRule = {
|
|
|
10344
10666
|
name: "superscript",
|
|
10345
10667
|
startTokens: ["SUPER_MARKER"],
|
|
10346
10668
|
parse(ctx) {
|
|
10347
|
-
return
|
|
10669
|
+
return parseDelimitedContainer(ctx, "SUPER_MARKER", "superscript", {
|
|
10348
10670
|
discardEmpty: true
|
|
10349
10671
|
});
|
|
10350
10672
|
}
|
|
@@ -10355,7 +10677,7 @@ var subscriptRule = {
|
|
|
10355
10677
|
name: "subscript",
|
|
10356
10678
|
startTokens: ["SUB_MARKER"],
|
|
10357
10679
|
parse(ctx) {
|
|
10358
|
-
return
|
|
10680
|
+
return parseDelimitedContainer(ctx, "SUB_MARKER", "subscript", { discardEmpty: true });
|
|
10359
10681
|
}
|
|
10360
10682
|
};
|
|
10361
10683
|
|
|
@@ -10364,7 +10686,7 @@ var monospaceRule = {
|
|
|
10364
10686
|
name: "monospace",
|
|
10365
10687
|
startTokens: ["MONO_MARKER"],
|
|
10366
10688
|
parse(ctx) {
|
|
10367
|
-
return
|
|
10689
|
+
return parseDelimitedContainer(ctx, "MONO_CLOSE", "monospace");
|
|
10368
10690
|
}
|
|
10369
10691
|
};
|
|
10370
10692
|
|
|
@@ -10725,13 +11047,14 @@ var linkStarRule = {
|
|
|
10725
11047
|
|
|
10726
11048
|
// packages/parser/src/parser/rules/inline/color/syntax.ts
|
|
10727
11049
|
function parseColorContent(ctx) {
|
|
10728
|
-
|
|
11050
|
+
const close = findFormattingClose(ctx, ctx.pos + 1, "COLOR_MARKER");
|
|
11051
|
+
if (close === null) {
|
|
10729
11052
|
return null;
|
|
10730
11053
|
}
|
|
10731
11054
|
let pos = ctx.pos + 1;
|
|
10732
11055
|
let consumed = 1;
|
|
10733
11056
|
let colorSpec = "";
|
|
10734
|
-
while (pos < ctx.tokens.length) {
|
|
11057
|
+
while (pos < (ctx.scope.inlineEnd ?? ctx.tokens.length)) {
|
|
10735
11058
|
const token5 = ctx.tokens[pos];
|
|
10736
11059
|
if (!token5 || token5.type === "PIPE" || token5.type === "COLOR_MARKER" || token5.type === "NEWLINE" || token5.type === "EOF") {
|
|
10737
11060
|
break;
|
|
@@ -10748,14 +11071,11 @@ function parseColorContent(ctx) {
|
|
|
10748
11071
|
const contentResult = parseInlineUntil({ ...ctx, pos }, "COLOR_MARKER");
|
|
10749
11072
|
pos += contentResult.consumed;
|
|
10750
11073
|
consumed += contentResult.consumed;
|
|
10751
|
-
if (ctx.tokens[pos]?.type !== "COLOR_MARKER") {
|
|
10752
|
-
return null;
|
|
10753
|
-
}
|
|
10754
|
-
consumed++;
|
|
10755
11074
|
const color = colorSpec.trim();
|
|
10756
11075
|
if (color === "" || contentResult.elements.length === 0) {
|
|
10757
11076
|
return null;
|
|
10758
11077
|
}
|
|
11078
|
+
consumed += consumeFormattingClose(ctx, close, pos);
|
|
10759
11079
|
return {
|
|
10760
11080
|
color: hexifyColor(color),
|
|
10761
11081
|
elements: contentResult.elements,
|
|
@@ -11378,14 +11698,19 @@ function parseSpanContent(ctx, startPos, blockName) {
|
|
|
11378
11698
|
const escapedChildren = [];
|
|
11379
11699
|
const splitSpans = [];
|
|
11380
11700
|
let foundClose = false;
|
|
11701
|
+
let forcedClose = false;
|
|
11381
11702
|
let afterBlankLine = false;
|
|
11382
11703
|
let consumed = 0;
|
|
11383
11704
|
let pos = startPos;
|
|
11384
|
-
while (pos < ctx.tokens.length) {
|
|
11705
|
+
while (pos < (ctx.scope.inlineEnd ?? ctx.tokens.length)) {
|
|
11385
11706
|
const token5 = ctx.tokens[pos];
|
|
11386
11707
|
if (!token5 || token5.type === "EOF") {
|
|
11387
11708
|
break;
|
|
11388
11709
|
}
|
|
11710
|
+
if (ctx.scope.tableFormatting?.suppressedClosers.has(pos)) {
|
|
11711
|
+
forcedClose = true;
|
|
11712
|
+
break;
|
|
11713
|
+
}
|
|
11389
11714
|
const close = parseCloseSpan(ctx, pos);
|
|
11390
11715
|
if (close.success) {
|
|
11391
11716
|
pos += close.consumed;
|
|
@@ -11410,6 +11735,29 @@ function parseSpanContent(ctx, startPos, blockName) {
|
|
|
11410
11735
|
pos += parsed.consumed;
|
|
11411
11736
|
consumed += parsed.consumed;
|
|
11412
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
|
+
}
|
|
11413
11761
|
return { children, escapedChildren, splitSpans, consumed, foundClose };
|
|
11414
11762
|
}
|
|
11415
11763
|
function parseOneSpanChild(ctx, pos, targetChildren) {
|
|
@@ -11821,135 +12169,6 @@ var footnoteRule = {
|
|
|
11821
12169
|
}
|
|
11822
12170
|
};
|
|
11823
12171
|
|
|
11824
|
-
// packages/parser/src/parser/rules/inline/image/attributes.ts
|
|
11825
|
-
function parseImageAttributes(ctx, startPos) {
|
|
11826
|
-
const result = parseAttributesRaw(ctx, startPos, false);
|
|
11827
|
-
const link = result.attrs.link ?? null;
|
|
11828
|
-
const { link: _link, ...htmlAttributes } = result.attrs;
|
|
11829
|
-
return {
|
|
11830
|
-
attributes: filterUnsafeAttributes(htmlAttributes),
|
|
11831
|
-
link,
|
|
11832
|
-
consumed: result.consumed
|
|
11833
|
-
};
|
|
11834
|
-
}
|
|
11835
|
-
|
|
11836
|
-
// packages/parser/src/parser/rules/inline/image/body.ts
|
|
11837
|
-
function parseImageSourceText(ctx, startPos) {
|
|
11838
|
-
let pos = startPos;
|
|
11839
|
-
let consumed = 0;
|
|
11840
|
-
while (ctx.tokens[pos]?.type === "WHITESPACE") {
|
|
11841
|
-
pos++;
|
|
11842
|
-
consumed++;
|
|
11843
|
-
}
|
|
11844
|
-
let sourceText = "";
|
|
11845
|
-
while (pos < ctx.tokens.length) {
|
|
11846
|
-
const token5 = ctx.tokens[pos];
|
|
11847
|
-
if (!token5 || token5.type === "WHITESPACE" || token5.type === "BLOCK_CLOSE" || token5.type === "NEWLINE" || token5.type === "EOF") {
|
|
11848
|
-
break;
|
|
11849
|
-
}
|
|
11850
|
-
sourceText += token5.value;
|
|
11851
|
-
pos++;
|
|
11852
|
-
consumed++;
|
|
11853
|
-
}
|
|
11854
|
-
return { sourceText, consumed };
|
|
11855
|
-
}
|
|
11856
|
-
|
|
11857
|
-
// packages/parser/src/parser/rules/inline/image/syntax.ts
|
|
11858
|
-
var IMAGE_BLOCK_NAMES = new Set([
|
|
11859
|
-
"image",
|
|
11860
|
-
"=image",
|
|
11861
|
-
"<image",
|
|
11862
|
-
">image",
|
|
11863
|
-
"f<image",
|
|
11864
|
-
"f>image",
|
|
11865
|
-
"f=image"
|
|
11866
|
-
]);
|
|
11867
|
-
function parseImageBlockName(ctx, startPos) {
|
|
11868
|
-
let pos = startPos;
|
|
11869
|
-
let consumed = 0;
|
|
11870
|
-
while (ctx.tokens[pos]?.type === "WHITESPACE") {
|
|
11871
|
-
pos++;
|
|
11872
|
-
consumed++;
|
|
11873
|
-
}
|
|
11874
|
-
const prefixResult = parseImagePrefix(ctx, pos);
|
|
11875
|
-
const prefix = prefixResult.prefix;
|
|
11876
|
-
pos += prefixResult.consumed;
|
|
11877
|
-
consumed += prefixResult.consumed;
|
|
11878
|
-
const nameToken = ctx.tokens[pos];
|
|
11879
|
-
if (!nameToken || nameToken.type !== "TEXT" && nameToken.type !== "IDENTIFIER") {
|
|
11880
|
-
return null;
|
|
11881
|
-
}
|
|
11882
|
-
return { name: prefix + nameToken.value.toLowerCase(), consumed: consumed + 1 };
|
|
11883
|
-
}
|
|
11884
|
-
function isImageBlockName(blockName) {
|
|
11885
|
-
return IMAGE_BLOCK_NAMES.has(blockName);
|
|
11886
|
-
}
|
|
11887
|
-
function parseImagePrefix(ctx, pos) {
|
|
11888
|
-
const token5 = ctx.tokens[pos];
|
|
11889
|
-
if (token5?.type === "EQUALS") {
|
|
11890
|
-
return { prefix: "=", consumed: 1 };
|
|
11891
|
-
}
|
|
11892
|
-
if (token5?.type === "TEXT" && token5.value === "<") {
|
|
11893
|
-
return { prefix: "<", consumed: 1 };
|
|
11894
|
-
}
|
|
11895
|
-
if ((token5?.type === "TEXT" || token5?.type === "BLOCKQUOTE_MARKER") && token5.value === ">") {
|
|
11896
|
-
return { prefix: ">", consumed: 1 };
|
|
11897
|
-
}
|
|
11898
|
-
if (token5?.type === "IDENTIFIER" && token5.value.toLowerCase() === "f") {
|
|
11899
|
-
return parseFloatPrefix(ctx, pos + 1);
|
|
11900
|
-
}
|
|
11901
|
-
return { prefix: "", consumed: 0 };
|
|
11902
|
-
}
|
|
11903
|
-
function parseFloatPrefix(ctx, pos) {
|
|
11904
|
-
const token5 = ctx.tokens[pos];
|
|
11905
|
-
if (token5?.type === "TEXT" && token5.value === "<") {
|
|
11906
|
-
return { prefix: "f<", consumed: 2 };
|
|
11907
|
-
}
|
|
11908
|
-
if ((token5?.type === "TEXT" || token5?.type === "BLOCKQUOTE_MARKER") && token5.value === ">") {
|
|
11909
|
-
return { prefix: "f>", consumed: 2 };
|
|
11910
|
-
}
|
|
11911
|
-
if (token5?.type === "EQUALS") {
|
|
11912
|
-
return { prefix: "f=", consumed: 2 };
|
|
11913
|
-
}
|
|
11914
|
-
return { prefix: "", consumed: 0 };
|
|
11915
|
-
}
|
|
11916
|
-
|
|
11917
|
-
// packages/parser/src/parser/rules/inline/image/open.ts
|
|
11918
|
-
function parseImageOpen(ctx) {
|
|
11919
|
-
if (ctx.tokens[ctx.pos]?.type !== "BLOCK_OPEN") {
|
|
11920
|
-
return null;
|
|
11921
|
-
}
|
|
11922
|
-
let pos = ctx.pos + 1;
|
|
11923
|
-
let consumed = 1;
|
|
11924
|
-
const nameResult = parseImageBlockName(ctx, pos);
|
|
11925
|
-
if (!nameResult || !isImageBlockName(nameResult.name)) {
|
|
11926
|
-
return null;
|
|
11927
|
-
}
|
|
11928
|
-
pos += nameResult.consumed;
|
|
11929
|
-
consumed += nameResult.consumed;
|
|
11930
|
-
const sourceText = parseImageSourceText(ctx, pos);
|
|
11931
|
-
pos += sourceText.consumed;
|
|
11932
|
-
consumed += sourceText.consumed;
|
|
11933
|
-
const attrs = parseImageAttributes(ctx, pos);
|
|
11934
|
-
pos += attrs.consumed;
|
|
11935
|
-
consumed += attrs.consumed;
|
|
11936
|
-
if (ctx.tokens[pos]?.type !== "BLOCK_CLOSE") {
|
|
11937
|
-
return null;
|
|
11938
|
-
}
|
|
11939
|
-
pos++;
|
|
11940
|
-
consumed++;
|
|
11941
|
-
if (!sourceText.sourceText) {
|
|
11942
|
-
return null;
|
|
11943
|
-
}
|
|
11944
|
-
return {
|
|
11945
|
-
blockName: nameResult.name,
|
|
11946
|
-
sourceText: sourceText.sourceText,
|
|
11947
|
-
link: attrs.link,
|
|
11948
|
-
attributes: attrs.attributes,
|
|
11949
|
-
consumed
|
|
11950
|
-
};
|
|
11951
|
-
}
|
|
11952
|
-
|
|
11953
12172
|
// packages/parser/src/parser/rules/inline/image/source.ts
|
|
11954
12173
|
function parseImageSource(src) {
|
|
11955
12174
|
if (src.startsWith("http://") || src.startsWith("https://") || src.startsWith("/")) {
|
|
@@ -13000,6 +13219,7 @@ var inlineRules = [
|
|
|
13000
13219
|
htmlInlineRule,
|
|
13001
13220
|
rawRule,
|
|
13002
13221
|
imageRule,
|
|
13222
|
+
embedBlockRule,
|
|
13003
13223
|
sizeRule,
|
|
13004
13224
|
footnoteRule,
|
|
13005
13225
|
spanRule,
|