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