@jianwen-lang/parser 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +95 -0
- package/dist/cli/render.d.ts +1 -0
- package/dist/cli/render.js +300 -0
- package/dist/core/ast.d.ts +286 -0
- package/dist/core/ast.js +2 -0
- package/dist/core/block/rules/heading.d.ts +9 -0
- package/dist/core/block/rules/heading.js +75 -0
- package/dist/core/block/rules/horizontal-rule.d.ts +9 -0
- package/dist/core/block/rules/horizontal-rule.js +87 -0
- package/dist/core/block/rules/include.d.ts +9 -0
- package/dist/core/block/rules/include.js +64 -0
- package/dist/core/block/rules/index.d.ts +2 -0
- package/dist/core/block/rules/index.js +16 -0
- package/dist/core/block/rules/types.d.ts +21 -0
- package/dist/core/block/rules/types.js +2 -0
- package/dist/core/block/types.d.ts +10 -0
- package/dist/core/block/types.js +2 -0
- package/dist/core/block-parser.d.ts +3 -0
- package/dist/core/block-parser.js +1385 -0
- package/dist/core/clone.d.ts +9 -0
- package/dist/core/clone.js +32 -0
- package/dist/core/diagnostics.d.ts +12 -0
- package/dist/core/diagnostics.js +24 -0
- package/dist/core/errors.d.ts +12 -0
- package/dist/core/errors.js +2 -0
- package/dist/core/inline/rules/backtick.d.ts +4 -0
- package/dist/core/inline/rules/backtick.js +90 -0
- package/dist/core/inline/rules/bracket.d.ts +4 -0
- package/dist/core/inline/rules/bracket.js +721 -0
- package/dist/core/inline/rules/disabled.d.ts +2 -0
- package/dist/core/inline/rules/disabled.js +34 -0
- package/dist/core/inline/rules/escape.d.ts +2 -0
- package/dist/core/inline/rules/escape.js +11 -0
- package/dist/core/inline/rules/index.d.ts +2 -0
- package/dist/core/inline/rules/index.js +25 -0
- package/dist/core/inline/rules/marker-highlight.d.ts +4 -0
- package/dist/core/inline/rules/marker-highlight.js +56 -0
- package/dist/core/inline/rules/style.d.ts +4 -0
- package/dist/core/inline/rules/style.js +120 -0
- package/dist/core/inline/rules/types.d.ts +22 -0
- package/dist/core/inline/rules/types.js +2 -0
- package/dist/core/inline/types.d.ts +1 -0
- package/dist/core/inline/types.js +2 -0
- package/dist/core/inline-parser.d.ts +3 -0
- package/dist/core/inline-parser.js +52 -0
- package/dist/core/location.d.ts +9 -0
- package/dist/core/location.js +30 -0
- package/dist/core/parser.d.ts +9 -0
- package/dist/core/parser.js +423 -0
- package/dist/core/traverse.d.ts +7 -0
- package/dist/core/traverse.js +71 -0
- package/dist/html/convert.d.ts +29 -0
- package/dist/html/convert.js +61 -0
- package/dist/html/format.d.ts +1 -0
- package/dist/html/format.js +17 -0
- package/dist/html/render/blocks.d.ts +4 -0
- package/dist/html/render/blocks.js +433 -0
- package/dist/html/render/html.d.ts +8 -0
- package/dist/html/render/html.js +89 -0
- package/dist/html/render/inlines.d.ts +4 -0
- package/dist/html/render/inlines.js +110 -0
- package/dist/html/render/meta.d.ts +3 -0
- package/dist/html/render/meta.js +51 -0
- package/dist/html/render/utils.d.ts +31 -0
- package/dist/html/render/utils.js +213 -0
- package/dist/html/theme/base/css.d.ts +2 -0
- package/dist/html/theme/base/css.js +383 -0
- package/dist/html/theme/dark/css.d.ts +2 -0
- package/dist/html/theme/dark/css.js +108 -0
- package/dist/html/theme/default/colors.d.ts +13 -0
- package/dist/html/theme/default/colors.js +2 -0
- package/dist/html/theme/default/css.d.ts +2 -0
- package/dist/html/theme/default/css.js +6 -0
- package/dist/html/theme/default/runtime.d.ts +0 -0
- package/dist/html/theme/default/runtime.js +31 -0
- package/dist/html/theme/light/css.d.ts +2 -0
- package/dist/html/theme/light/css.js +55 -0
- package/dist/html/theme/preset/colors.d.ts +10 -0
- package/dist/html/theme/preset/colors.js +14 -0
- package/dist/html/theme/runtime.d.ts +0 -0
- package/dist/html/theme/runtime.js +31 -0
- package/dist/html/theme/theme.d.ts +9 -0
- package/dist/html/theme/theme.js +21 -0
- package/dist/lexer/lexer.d.ts +17 -0
- package/dist/lexer/lexer.js +47 -0
- package/dist/parser.d.ts +6 -0
- package/dist/parser.js +22 -0
- package/package.json +50 -0
|
@@ -0,0 +1,721 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.bracketRule = void 0;
|
|
4
|
+
exports.parseBracketExpression = parseBracketExpression;
|
|
5
|
+
const diagnostics_1 = require("../../diagnostics");
|
|
6
|
+
const location_1 = require("../../location");
|
|
7
|
+
const backtick_1 = require("./backtick");
|
|
8
|
+
const marker_highlight_1 = require("./marker-highlight");
|
|
9
|
+
const style_1 = require("./style");
|
|
10
|
+
const INLINE_FONT_STYLE_KEYS = new Set([
|
|
11
|
+
'italic',
|
|
12
|
+
'bold',
|
|
13
|
+
'heavy',
|
|
14
|
+
'slim',
|
|
15
|
+
'serif',
|
|
16
|
+
'mono',
|
|
17
|
+
]);
|
|
18
|
+
const INLINE_FONT_STYLE_ALIASES = {
|
|
19
|
+
i: 'italic',
|
|
20
|
+
b: 'bold',
|
|
21
|
+
bb: 'heavy',
|
|
22
|
+
};
|
|
23
|
+
function splitInlineAttributeParts(inside) {
|
|
24
|
+
return inside
|
|
25
|
+
.split(',')
|
|
26
|
+
.map((p) => p.trim())
|
|
27
|
+
.filter((p) => p.length > 0);
|
|
28
|
+
}
|
|
29
|
+
function normalizeFontStyleKey(part) {
|
|
30
|
+
const alias = INLINE_FONT_STYLE_ALIASES[part];
|
|
31
|
+
if (alias) {
|
|
32
|
+
return alias;
|
|
33
|
+
}
|
|
34
|
+
if (INLINE_FONT_STYLE_KEYS.has(part)) {
|
|
35
|
+
return part;
|
|
36
|
+
}
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
function parseColorAttributeFromToken(token) {
|
|
40
|
+
const value = token.trim();
|
|
41
|
+
if (value.length === 0) {
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
if (/^#[0-9A-Fa-f]{3,8}$/.test(value)) {
|
|
45
|
+
return { kind: 'hex', value };
|
|
46
|
+
}
|
|
47
|
+
if (/^[A-Za-z][A-Za-z0-9_-]*$/.test(value)) {
|
|
48
|
+
return { kind: 'preset', value };
|
|
49
|
+
}
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
function parseShapeAttributeFromToken(token) {
|
|
53
|
+
const value = token.trim();
|
|
54
|
+
if (value === 'square') {
|
|
55
|
+
return { shape: 'square' };
|
|
56
|
+
}
|
|
57
|
+
if (value === 'rounded') {
|
|
58
|
+
return { shape: 'rounded' };
|
|
59
|
+
}
|
|
60
|
+
const roundedMatch = value.match(/^rounded=([0-9.]+)$/);
|
|
61
|
+
if (roundedMatch && roundedMatch[1]) {
|
|
62
|
+
const num = parseFloat(roundedMatch[1]);
|
|
63
|
+
if (!isNaN(num) && num > 0) {
|
|
64
|
+
return { shape: 'rounded', roundedRadius: num };
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
function hasInlineAttributes(attrs) {
|
|
70
|
+
return Boolean(attrs.color ||
|
|
71
|
+
attrs.secondaryColor ||
|
|
72
|
+
attrs.shape ||
|
|
73
|
+
attrs.roundedRadius !== undefined ||
|
|
74
|
+
attrs.fontSize ||
|
|
75
|
+
attrs.fontStyle);
|
|
76
|
+
}
|
|
77
|
+
function isInlineAttributeExpression(inside) {
|
|
78
|
+
const parts = splitInlineAttributeParts(inside);
|
|
79
|
+
if (parts.length === 0) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
for (const part of parts) {
|
|
83
|
+
if (part === '->' || part === '<-' || part === '<->') {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
let hasRecognized = false;
|
|
88
|
+
for (const part of parts) {
|
|
89
|
+
if (part.length === 0) {
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
hasRecognized = true;
|
|
93
|
+
const asNumber = Number(part);
|
|
94
|
+
if (!Number.isNaN(asNumber)) {
|
|
95
|
+
if (asNumber >= 0.5 &&
|
|
96
|
+
asNumber <= 5 &&
|
|
97
|
+
Math.abs(asNumber * 2 - Math.round(asNumber * 2)) < 1e-6) {
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
const styleKey = normalizeFontStyleKey(part);
|
|
103
|
+
if (styleKey) {
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
if (part === 'square' || part === 'rounded' || part.startsWith('rounded=')) {
|
|
107
|
+
if (parseShapeAttributeFromToken(part)) {
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
if (part.startsWith('!')) {
|
|
113
|
+
if (parseColorAttributeFromToken(part.slice(1))) {
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
if (parseColorAttributeFromToken(part)) {
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
return hasRecognized;
|
|
124
|
+
}
|
|
125
|
+
function parseInlineAttributes(inside, errors, line, column) {
|
|
126
|
+
const parts = splitInlineAttributeParts(inside);
|
|
127
|
+
if (parts.length === 0) {
|
|
128
|
+
return undefined;
|
|
129
|
+
}
|
|
130
|
+
const attrs = {};
|
|
131
|
+
const fontStyles = [];
|
|
132
|
+
for (const part of parts) {
|
|
133
|
+
if (part.length === 0) {
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
if (part === '->' || part === '<-' || part === '<->') {
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
const asNumber = Number(part);
|
|
140
|
+
if (!Number.isNaN(asNumber)) {
|
|
141
|
+
const size = asNumber;
|
|
142
|
+
if (size >= 0.5 && size <= 5 && Math.abs(size * 2 - Math.round(size * 2)) < 1e-6) {
|
|
143
|
+
attrs.fontSize = size;
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
(0, diagnostics_1.reportParseWarning)(errors, {
|
|
147
|
+
message: `Invalid fontSize ${part} in inline attributes`,
|
|
148
|
+
line,
|
|
149
|
+
column,
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
const styleKey = normalizeFontStyleKey(part);
|
|
155
|
+
if (styleKey) {
|
|
156
|
+
fontStyles.push(styleKey);
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
if (part === 'square' || part === 'rounded' || part.startsWith('rounded=')) {
|
|
160
|
+
const shapeAttr = parseShapeAttributeFromToken(part);
|
|
161
|
+
if (shapeAttr) {
|
|
162
|
+
attrs.shape = shapeAttr.shape;
|
|
163
|
+
if (shapeAttr.roundedRadius !== undefined) {
|
|
164
|
+
attrs.roundedRadius = shapeAttr.roundedRadius;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
else if (part.startsWith('rounded=')) {
|
|
168
|
+
(0, diagnostics_1.reportParseWarning)(errors, {
|
|
169
|
+
message: `Invalid rounded radius "${part}" in inline attributes`,
|
|
170
|
+
line,
|
|
171
|
+
column,
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
if (part.startsWith('!')) {
|
|
177
|
+
const color = parseColorAttributeFromToken(part.slice(1));
|
|
178
|
+
if (color) {
|
|
179
|
+
attrs.secondaryColor = color;
|
|
180
|
+
}
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
const color = parseColorAttributeFromToken(part);
|
|
184
|
+
if (color) {
|
|
185
|
+
attrs.color = color;
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
if (fontStyles.length > 0) {
|
|
190
|
+
attrs.fontStyle = fontStyles;
|
|
191
|
+
}
|
|
192
|
+
if (!attrs.color &&
|
|
193
|
+
!attrs.secondaryColor &&
|
|
194
|
+
!attrs.shape &&
|
|
195
|
+
attrs.roundedRadius === undefined &&
|
|
196
|
+
!attrs.fontSize &&
|
|
197
|
+
!attrs.fontStyle) {
|
|
198
|
+
return undefined;
|
|
199
|
+
}
|
|
200
|
+
return attrs;
|
|
201
|
+
}
|
|
202
|
+
function mergeInlineAttributes(base, next) {
|
|
203
|
+
const merged = { ...base };
|
|
204
|
+
if (next.color) {
|
|
205
|
+
merged.color = next.color;
|
|
206
|
+
}
|
|
207
|
+
if (next.secondaryColor) {
|
|
208
|
+
merged.secondaryColor = next.secondaryColor;
|
|
209
|
+
}
|
|
210
|
+
if (next.fontSize) {
|
|
211
|
+
merged.fontSize = next.fontSize;
|
|
212
|
+
}
|
|
213
|
+
if (next.fontStyle) {
|
|
214
|
+
const styles = [...(merged.fontStyle ?? [])];
|
|
215
|
+
for (const style of next.fontStyle) {
|
|
216
|
+
if (!styles.includes(style)) {
|
|
217
|
+
styles.push(style);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
merged.fontStyle = styles;
|
|
221
|
+
}
|
|
222
|
+
if (next.shape) {
|
|
223
|
+
merged.shape = next.shape;
|
|
224
|
+
}
|
|
225
|
+
if (next.roundedRadius !== undefined) {
|
|
226
|
+
merged.roundedRadius = next.roundedRadius;
|
|
227
|
+
}
|
|
228
|
+
return merged;
|
|
229
|
+
}
|
|
230
|
+
function isInlineSymbol(ch) {
|
|
231
|
+
return (ch === '`' ||
|
|
232
|
+
ch === '=' ||
|
|
233
|
+
ch === '*' ||
|
|
234
|
+
ch === '/' ||
|
|
235
|
+
ch === '_' ||
|
|
236
|
+
ch === '-' ||
|
|
237
|
+
ch === '~' ||
|
|
238
|
+
ch === '^' ||
|
|
239
|
+
ch === '[');
|
|
240
|
+
}
|
|
241
|
+
function applyHighlightColorsFromAttrs(node, attrs) {
|
|
242
|
+
if (node.type !== 'highlight' || !attrs) {
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
if (attrs.color) {
|
|
246
|
+
node.colorAttr = attrs.color;
|
|
247
|
+
}
|
|
248
|
+
if (attrs.secondaryColor) {
|
|
249
|
+
node.fillColorAttr = attrs.secondaryColor;
|
|
250
|
+
}
|
|
251
|
+
if (attrs.shape) {
|
|
252
|
+
node.shape = attrs.shape;
|
|
253
|
+
}
|
|
254
|
+
if (attrs.roundedRadius !== undefined) {
|
|
255
|
+
node.roundedRadius = attrs.roundedRadius;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
function parseInlineAttrsNode(scanner, ctx, attrs, baseLine, startColumn, rawInside) {
|
|
259
|
+
let segment = '';
|
|
260
|
+
let closedBySlash = false;
|
|
261
|
+
let closedByLineBreak = false;
|
|
262
|
+
let closedByNextAttr = false;
|
|
263
|
+
while (!scanner.eof()) {
|
|
264
|
+
const ch = scanner.peek();
|
|
265
|
+
if (ch === undefined) {
|
|
266
|
+
break;
|
|
267
|
+
}
|
|
268
|
+
if (ch === '\n') {
|
|
269
|
+
closedByLineBreak = true;
|
|
270
|
+
break;
|
|
271
|
+
}
|
|
272
|
+
if (ch === '[') {
|
|
273
|
+
const saveIndex = scanner.index;
|
|
274
|
+
const saveLine = scanner.line;
|
|
275
|
+
const saveColumn = scanner.column;
|
|
276
|
+
scanner.next();
|
|
277
|
+
const next1 = scanner.peek();
|
|
278
|
+
if (next1 === '/') {
|
|
279
|
+
scanner.next();
|
|
280
|
+
const next2 = scanner.peek();
|
|
281
|
+
if (next2 === ']') {
|
|
282
|
+
scanner.next();
|
|
283
|
+
closedBySlash = true;
|
|
284
|
+
break;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
else {
|
|
288
|
+
const rest = scanner.text.slice(scanner.index);
|
|
289
|
+
const closingOffset = rest.indexOf(']');
|
|
290
|
+
if (closingOffset !== -1) {
|
|
291
|
+
const insideCandidate = rest.slice(0, closingOffset);
|
|
292
|
+
if (isInlineAttributeExpression(insideCandidate)) {
|
|
293
|
+
closedByNextAttr = true;
|
|
294
|
+
scanner.index = saveIndex;
|
|
295
|
+
scanner.line = saveLine;
|
|
296
|
+
scanner.column = saveColumn;
|
|
297
|
+
break;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
scanner.index = saveIndex;
|
|
302
|
+
scanner.line = saveLine;
|
|
303
|
+
scanner.column = saveColumn;
|
|
304
|
+
}
|
|
305
|
+
scanner.next();
|
|
306
|
+
segment += ch;
|
|
307
|
+
}
|
|
308
|
+
const endedByEof = scanner.eof();
|
|
309
|
+
if (!closedBySlash && !closedByLineBreak && !closedByNextAttr && !endedByEof) {
|
|
310
|
+
(0, diagnostics_1.reportParseWarning)(ctx.errors, {
|
|
311
|
+
message: 'Missing closing [/] for inline attributes',
|
|
312
|
+
line: baseLine,
|
|
313
|
+
column: startColumn,
|
|
314
|
+
});
|
|
315
|
+
return `[${rawInside}]${segment}`;
|
|
316
|
+
}
|
|
317
|
+
const children = ctx.parseNested(segment, baseLine);
|
|
318
|
+
const node = {
|
|
319
|
+
type: 'inlineAttrs',
|
|
320
|
+
attrs,
|
|
321
|
+
children,
|
|
322
|
+
};
|
|
323
|
+
return node;
|
|
324
|
+
}
|
|
325
|
+
function parseLinkAfterLinkKeyword(scanner, ctx, startLine) {
|
|
326
|
+
let raw = '[link]';
|
|
327
|
+
let linkColor;
|
|
328
|
+
let underlineColor;
|
|
329
|
+
while (!scanner.eof()) {
|
|
330
|
+
const ch = scanner.peek();
|
|
331
|
+
if (ch !== '[') {
|
|
332
|
+
break;
|
|
333
|
+
}
|
|
334
|
+
const saveIndex = scanner.index;
|
|
335
|
+
const saveLine = scanner.line;
|
|
336
|
+
const saveColumn = scanner.column;
|
|
337
|
+
scanner.next();
|
|
338
|
+
let attrInside = '';
|
|
339
|
+
let attrClosed = false;
|
|
340
|
+
while (!scanner.eof()) {
|
|
341
|
+
const c = scanner.peek();
|
|
342
|
+
if (c === undefined) {
|
|
343
|
+
break;
|
|
344
|
+
}
|
|
345
|
+
if (c === ']') {
|
|
346
|
+
scanner.next();
|
|
347
|
+
attrClosed = true;
|
|
348
|
+
break;
|
|
349
|
+
}
|
|
350
|
+
scanner.next();
|
|
351
|
+
attrInside += c;
|
|
352
|
+
}
|
|
353
|
+
if (!attrClosed) {
|
|
354
|
+
(0, diagnostics_1.reportParseWarning)(ctx.errors, {
|
|
355
|
+
message: 'Missing closing ] for link attribute',
|
|
356
|
+
line: saveLine,
|
|
357
|
+
column: saveColumn,
|
|
358
|
+
});
|
|
359
|
+
return `[link][${attrInside}`;
|
|
360
|
+
}
|
|
361
|
+
if (attrInside.length === 0) {
|
|
362
|
+
scanner.index = saveIndex;
|
|
363
|
+
scanner.line = saveLine;
|
|
364
|
+
scanner.column = saveColumn;
|
|
365
|
+
break;
|
|
366
|
+
}
|
|
367
|
+
const parts = attrInside
|
|
368
|
+
.split(',')
|
|
369
|
+
.map((p) => p.trim())
|
|
370
|
+
.filter((p) => p.length > 0);
|
|
371
|
+
let recognizedColor = false;
|
|
372
|
+
for (const part of parts) {
|
|
373
|
+
if (part.startsWith('!')) {
|
|
374
|
+
const color = parseColorAttributeFromToken(part.slice(1));
|
|
375
|
+
if (color) {
|
|
376
|
+
underlineColor = color;
|
|
377
|
+
recognizedColor = true;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
else {
|
|
381
|
+
const color = parseColorAttributeFromToken(part);
|
|
382
|
+
if (color) {
|
|
383
|
+
linkColor = color;
|
|
384
|
+
recognizedColor = true;
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
if (!recognizedColor) {
|
|
389
|
+
scanner.index = saveIndex;
|
|
390
|
+
scanner.line = saveLine;
|
|
391
|
+
scanner.column = saveColumn;
|
|
392
|
+
break;
|
|
393
|
+
}
|
|
394
|
+
raw += `[${attrInside}]`;
|
|
395
|
+
}
|
|
396
|
+
let text = '';
|
|
397
|
+
while (!scanner.eof()) {
|
|
398
|
+
const ch = scanner.peek();
|
|
399
|
+
if (ch === undefined) {
|
|
400
|
+
break;
|
|
401
|
+
}
|
|
402
|
+
if (ch === '(') {
|
|
403
|
+
break;
|
|
404
|
+
}
|
|
405
|
+
scanner.next();
|
|
406
|
+
text += ch;
|
|
407
|
+
}
|
|
408
|
+
const trimmedText = text.trim();
|
|
409
|
+
if (trimmedText.length === 0) {
|
|
410
|
+
return raw + text;
|
|
411
|
+
}
|
|
412
|
+
raw += text;
|
|
413
|
+
const next = scanner.peek();
|
|
414
|
+
if (next !== '(') {
|
|
415
|
+
(0, diagnostics_1.reportParseWarning)(ctx.errors, {
|
|
416
|
+
message: 'Missing (url) after [link]text for inline link',
|
|
417
|
+
line: scanner.line,
|
|
418
|
+
column: scanner.column,
|
|
419
|
+
});
|
|
420
|
+
return raw;
|
|
421
|
+
}
|
|
422
|
+
scanner.next();
|
|
423
|
+
let url = '';
|
|
424
|
+
while (!scanner.eof()) {
|
|
425
|
+
const ch = scanner.peek();
|
|
426
|
+
if (ch === undefined) {
|
|
427
|
+
break;
|
|
428
|
+
}
|
|
429
|
+
if (ch === ')') {
|
|
430
|
+
scanner.next();
|
|
431
|
+
break;
|
|
432
|
+
}
|
|
433
|
+
scanner.next();
|
|
434
|
+
url += ch;
|
|
435
|
+
}
|
|
436
|
+
const href = url.trim();
|
|
437
|
+
if (href.length === 0) {
|
|
438
|
+
(0, diagnostics_1.reportParseWarning)(ctx.errors, {
|
|
439
|
+
message: 'Empty url in inline link',
|
|
440
|
+
line: scanner.line,
|
|
441
|
+
column: scanner.column,
|
|
442
|
+
});
|
|
443
|
+
return `${raw}()`;
|
|
444
|
+
}
|
|
445
|
+
raw += `(${url})`;
|
|
446
|
+
const children = ctx.parseNested(trimmedText, startLine);
|
|
447
|
+
const node = {
|
|
448
|
+
type: 'link',
|
|
449
|
+
href,
|
|
450
|
+
children,
|
|
451
|
+
};
|
|
452
|
+
const linkNode = node;
|
|
453
|
+
if (linkColor) {
|
|
454
|
+
linkNode.colorAttr = linkColor;
|
|
455
|
+
}
|
|
456
|
+
if (underlineColor) {
|
|
457
|
+
linkNode.underlineColorAttr = underlineColor;
|
|
458
|
+
}
|
|
459
|
+
return node;
|
|
460
|
+
}
|
|
461
|
+
function parseBracketExpression(scanner, ctx) {
|
|
462
|
+
const startLine = scanner.line;
|
|
463
|
+
const startColumn = scanner.column;
|
|
464
|
+
const open = scanner.next();
|
|
465
|
+
if (open !== '[') {
|
|
466
|
+
return undefined;
|
|
467
|
+
}
|
|
468
|
+
let inside = '';
|
|
469
|
+
let closed = false;
|
|
470
|
+
while (!scanner.eof()) {
|
|
471
|
+
const ch = scanner.peek();
|
|
472
|
+
if (ch === undefined) {
|
|
473
|
+
break;
|
|
474
|
+
}
|
|
475
|
+
if (ch === ']') {
|
|
476
|
+
scanner.next();
|
|
477
|
+
closed = true;
|
|
478
|
+
break;
|
|
479
|
+
}
|
|
480
|
+
scanner.next();
|
|
481
|
+
inside += ch;
|
|
482
|
+
}
|
|
483
|
+
if (!closed) {
|
|
484
|
+
(0, diagnostics_1.reportParseWarning)(ctx.errors, {
|
|
485
|
+
message: 'Missing closing ] for bracket expression',
|
|
486
|
+
line: startLine,
|
|
487
|
+
column: startColumn,
|
|
488
|
+
});
|
|
489
|
+
return `[${inside}`;
|
|
490
|
+
}
|
|
491
|
+
if (inside.length === 0) {
|
|
492
|
+
return '[]';
|
|
493
|
+
}
|
|
494
|
+
if (inside.startsWith('fn:')) {
|
|
495
|
+
const id = inside.slice(3).trim();
|
|
496
|
+
if (id.length === 0) {
|
|
497
|
+
return `[${inside}]`;
|
|
498
|
+
}
|
|
499
|
+
const node = {
|
|
500
|
+
type: 'footnoteRef',
|
|
501
|
+
id,
|
|
502
|
+
};
|
|
503
|
+
(0, location_1.setNodeLocation)(node, { line: startLine, column: startColumn });
|
|
504
|
+
return node;
|
|
505
|
+
}
|
|
506
|
+
if (inside === 'comment') {
|
|
507
|
+
let content = '';
|
|
508
|
+
while (!scanner.eof()) {
|
|
509
|
+
const ch = scanner.peek();
|
|
510
|
+
if (ch === undefined) {
|
|
511
|
+
break;
|
|
512
|
+
}
|
|
513
|
+
if (ch === '[') {
|
|
514
|
+
const saveIndex = scanner.index;
|
|
515
|
+
const saveLine = scanner.line;
|
|
516
|
+
const saveColumn = scanner.column;
|
|
517
|
+
scanner.next();
|
|
518
|
+
const next1 = scanner.peek();
|
|
519
|
+
if (next1 === '/') {
|
|
520
|
+
scanner.next();
|
|
521
|
+
const next2 = scanner.peek();
|
|
522
|
+
if (next2 === ']') {
|
|
523
|
+
scanner.next();
|
|
524
|
+
const children = ctx.parseNested(content, startLine);
|
|
525
|
+
const node = {
|
|
526
|
+
type: 'commentInline',
|
|
527
|
+
children,
|
|
528
|
+
};
|
|
529
|
+
return node;
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
scanner.index = saveIndex;
|
|
533
|
+
scanner.line = saveLine;
|
|
534
|
+
scanner.column = saveColumn;
|
|
535
|
+
}
|
|
536
|
+
scanner.next();
|
|
537
|
+
content += ch;
|
|
538
|
+
}
|
|
539
|
+
(0, diagnostics_1.reportParseWarning)(ctx.errors, {
|
|
540
|
+
message: 'Missing closing [/] for inline comment',
|
|
541
|
+
line: startLine,
|
|
542
|
+
column: startColumn,
|
|
543
|
+
});
|
|
544
|
+
return `[comment]${content}`;
|
|
545
|
+
}
|
|
546
|
+
if (inside === 'link') {
|
|
547
|
+
const linkNodeOrText = parseLinkAfterLinkKeyword(scanner, ctx, startLine);
|
|
548
|
+
if (linkNodeOrText) {
|
|
549
|
+
return linkNodeOrText;
|
|
550
|
+
}
|
|
551
|
+
return '[link]';
|
|
552
|
+
}
|
|
553
|
+
const attrs = parseInlineAttributes(inside, ctx.errors, startLine, startColumn);
|
|
554
|
+
if (attrs) {
|
|
555
|
+
let mergedAttrs = attrs;
|
|
556
|
+
let mergedRawInside = inside;
|
|
557
|
+
while (true) {
|
|
558
|
+
const nextCh = scanner.peek();
|
|
559
|
+
if (nextCh !== '[') {
|
|
560
|
+
break;
|
|
561
|
+
}
|
|
562
|
+
const saveIndex = scanner.index;
|
|
563
|
+
const saveLine = scanner.line;
|
|
564
|
+
const saveColumn = scanner.column;
|
|
565
|
+
scanner.next();
|
|
566
|
+
let attrInside = '';
|
|
567
|
+
let attrClosed = false;
|
|
568
|
+
while (!scanner.eof()) {
|
|
569
|
+
const ch = scanner.peek();
|
|
570
|
+
if (ch === undefined) {
|
|
571
|
+
break;
|
|
572
|
+
}
|
|
573
|
+
if (ch === ']') {
|
|
574
|
+
scanner.next();
|
|
575
|
+
attrClosed = true;
|
|
576
|
+
break;
|
|
577
|
+
}
|
|
578
|
+
scanner.next();
|
|
579
|
+
attrInside += ch;
|
|
580
|
+
}
|
|
581
|
+
if (!attrClosed) {
|
|
582
|
+
(0, diagnostics_1.reportParseWarning)(ctx.errors, {
|
|
583
|
+
message: 'Missing closing ] for inline attributes',
|
|
584
|
+
line: saveLine,
|
|
585
|
+
column: saveColumn,
|
|
586
|
+
});
|
|
587
|
+
return `[${mergedRawInside}][${attrInside}`;
|
|
588
|
+
}
|
|
589
|
+
if (!isInlineAttributeExpression(attrInside)) {
|
|
590
|
+
scanner.index = saveIndex;
|
|
591
|
+
scanner.line = saveLine;
|
|
592
|
+
scanner.column = saveColumn;
|
|
593
|
+
break;
|
|
594
|
+
}
|
|
595
|
+
const nextAttrs = parseInlineAttributes(attrInside, ctx.errors, saveLine, saveColumn);
|
|
596
|
+
if (!nextAttrs) {
|
|
597
|
+
scanner.index = saveIndex;
|
|
598
|
+
scanner.line = saveLine;
|
|
599
|
+
scanner.column = saveColumn;
|
|
600
|
+
break;
|
|
601
|
+
}
|
|
602
|
+
mergedAttrs = mergeInlineAttributes(mergedAttrs, nextAttrs);
|
|
603
|
+
mergedRawInside += `][${attrInside}`;
|
|
604
|
+
}
|
|
605
|
+
const nextCh = scanner.peek();
|
|
606
|
+
if (nextCh !== undefined && isInlineSymbol(nextCh)) {
|
|
607
|
+
const symbol = nextCh;
|
|
608
|
+
let inner;
|
|
609
|
+
if (symbol === '`') {
|
|
610
|
+
inner = (0, backtick_1.readBacktickSegment)(scanner, ctx);
|
|
611
|
+
}
|
|
612
|
+
else if (symbol === '=') {
|
|
613
|
+
inner = (0, marker_highlight_1.readMarkerHighlight)(scanner, ctx);
|
|
614
|
+
}
|
|
615
|
+
else if (symbol === '*' ||
|
|
616
|
+
symbol === '/' ||
|
|
617
|
+
symbol === '_' ||
|
|
618
|
+
symbol === '-' ||
|
|
619
|
+
symbol === '~' ||
|
|
620
|
+
symbol === '^') {
|
|
621
|
+
inner = (0, style_1.readStyledSegment)(scanner, ctx);
|
|
622
|
+
}
|
|
623
|
+
else if (symbol === '[') {
|
|
624
|
+
inner = parseBracketExpression(scanner, ctx);
|
|
625
|
+
}
|
|
626
|
+
if (!inner) {
|
|
627
|
+
return `[${inside}]`;
|
|
628
|
+
}
|
|
629
|
+
if (typeof inner === 'string') {
|
|
630
|
+
return `[${inside}]${inner}`;
|
|
631
|
+
}
|
|
632
|
+
if (inner.type === 'highlight') {
|
|
633
|
+
applyHighlightColorsFromAttrs(inner, mergedAttrs);
|
|
634
|
+
delete mergedAttrs.color;
|
|
635
|
+
delete mergedAttrs.secondaryColor;
|
|
636
|
+
delete mergedAttrs.shape;
|
|
637
|
+
delete mergedAttrs.roundedRadius;
|
|
638
|
+
}
|
|
639
|
+
if (!hasInlineAttributes(mergedAttrs)) {
|
|
640
|
+
return inner;
|
|
641
|
+
}
|
|
642
|
+
const node = {
|
|
643
|
+
type: 'inlineAttrs',
|
|
644
|
+
attrs: mergedAttrs,
|
|
645
|
+
children: [inner],
|
|
646
|
+
};
|
|
647
|
+
return node;
|
|
648
|
+
}
|
|
649
|
+
const saveIndex = scanner.index;
|
|
650
|
+
const saveLine = scanner.line;
|
|
651
|
+
const saveColumn = scanner.column;
|
|
652
|
+
let linkText = '';
|
|
653
|
+
let foundParen = false;
|
|
654
|
+
while (!scanner.eof()) {
|
|
655
|
+
const ch = scanner.peek();
|
|
656
|
+
if (ch === undefined) {
|
|
657
|
+
break;
|
|
658
|
+
}
|
|
659
|
+
if (ch === '(') {
|
|
660
|
+
foundParen = true;
|
|
661
|
+
break;
|
|
662
|
+
}
|
|
663
|
+
if (ch === '\n') {
|
|
664
|
+
break;
|
|
665
|
+
}
|
|
666
|
+
scanner.next();
|
|
667
|
+
linkText += ch;
|
|
668
|
+
}
|
|
669
|
+
if (foundParen && linkText.length > 0) {
|
|
670
|
+
scanner.next();
|
|
671
|
+
let url = '';
|
|
672
|
+
let foundCloseParen = false;
|
|
673
|
+
while (!scanner.eof()) {
|
|
674
|
+
const ch = scanner.peek();
|
|
675
|
+
if (ch === ')') {
|
|
676
|
+
scanner.next();
|
|
677
|
+
foundCloseParen = true;
|
|
678
|
+
break;
|
|
679
|
+
}
|
|
680
|
+
scanner.next();
|
|
681
|
+
url += ch;
|
|
682
|
+
}
|
|
683
|
+
if (foundCloseParen && url.length > 0) {
|
|
684
|
+
const children = ctx.parseNested(linkText.trim(), startLine);
|
|
685
|
+
const linkNode = {
|
|
686
|
+
type: 'link',
|
|
687
|
+
href: url,
|
|
688
|
+
children,
|
|
689
|
+
};
|
|
690
|
+
if (mergedAttrs.color) {
|
|
691
|
+
linkNode.colorAttr = mergedAttrs.color;
|
|
692
|
+
}
|
|
693
|
+
if (mergedAttrs.secondaryColor) {
|
|
694
|
+
linkNode.underlineColorAttr = mergedAttrs.secondaryColor;
|
|
695
|
+
}
|
|
696
|
+
return linkNode;
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
scanner.index = saveIndex;
|
|
700
|
+
scanner.line = saveLine;
|
|
701
|
+
scanner.column = saveColumn;
|
|
702
|
+
const node = parseInlineAttrsNode(scanner, ctx, mergedAttrs, startLine, startColumn, mergedRawInside);
|
|
703
|
+
if (node) {
|
|
704
|
+
return node;
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
return `[${inside}]`;
|
|
708
|
+
}
|
|
709
|
+
exports.bracketRule = {
|
|
710
|
+
flushTextBefore: true,
|
|
711
|
+
parse(scanner, ctx) {
|
|
712
|
+
const result = parseBracketExpression(scanner, ctx);
|
|
713
|
+
if (!result) {
|
|
714
|
+
return { kind: 'append', text: '' };
|
|
715
|
+
}
|
|
716
|
+
if (typeof result === 'string') {
|
|
717
|
+
return { kind: 'emitText', text: result };
|
|
718
|
+
}
|
|
719
|
+
return { kind: 'emit', node: result };
|
|
720
|
+
},
|
|
721
|
+
};
|