@wdprlib/parser 1.1.2 → 2.0.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 +369 -26
- package/dist/index.d.cts +24 -11
- package/dist/index.d.ts +24 -11
- package/dist/index.js +351 -8
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -31,7 +31,7 @@ var __export = (target, all) => {
|
|
|
31
31
|
var exports_src = {};
|
|
32
32
|
__export(exports_src, {
|
|
33
33
|
tokenize: () => tokenize,
|
|
34
|
-
text: () =>
|
|
34
|
+
text: () => import_ast5.text,
|
|
35
35
|
resolveModules: () => resolveModules,
|
|
36
36
|
resolveListUsers: () => resolveListUsers,
|
|
37
37
|
resolveIncludes: () => resolveIncludes,
|
|
@@ -42,34 +42,35 @@ __export(exports_src, {
|
|
|
42
42
|
parseDateSelector: () => parseDateSelector,
|
|
43
43
|
parseCategory: () => parseCategory,
|
|
44
44
|
parse: () => parse,
|
|
45
|
-
paragraph: () =>
|
|
45
|
+
paragraph: () => import_ast5.paragraph,
|
|
46
46
|
normalizeQuery: () => normalizeQuery,
|
|
47
|
-
listItemSubList: () =>
|
|
48
|
-
listItemElements: () =>
|
|
49
|
-
list: () =>
|
|
50
|
-
link: () =>
|
|
51
|
-
lineBreak: () =>
|
|
52
|
-
italics: () =>
|
|
47
|
+
listItemSubList: () => import_ast5.listItemSubList,
|
|
48
|
+
listItemElements: () => import_ast5.listItemElements,
|
|
49
|
+
list: () => import_ast5.list,
|
|
50
|
+
link: () => import_ast5.link,
|
|
51
|
+
lineBreak: () => import_ast5.lineBreak,
|
|
52
|
+
italics: () => import_ast5.italics,
|
|
53
53
|
isListUsersModule: () => isListUsersModule2,
|
|
54
|
-
horizontalRule: () =>
|
|
55
|
-
heading: () =>
|
|
54
|
+
horizontalRule: () => import_ast5.horizontalRule,
|
|
55
|
+
heading: () => import_ast5.heading,
|
|
56
56
|
extractListUsersVariables: () => extractListUsersVariables,
|
|
57
57
|
extractDataRequirements: () => extractDataRequirements,
|
|
58
58
|
createToken: () => createToken,
|
|
59
|
-
createSettings: () =>
|
|
60
|
-
createPosition: () =>
|
|
61
|
-
createPoint: () =>
|
|
62
|
-
container: () =>
|
|
59
|
+
createSettings: () => import_ast6.createSettings,
|
|
60
|
+
createPosition: () => import_ast5.createPosition,
|
|
61
|
+
createPoint: () => import_ast5.createPoint,
|
|
62
|
+
container: () => import_ast5.container,
|
|
63
63
|
compileTemplate: () => compileTemplate,
|
|
64
64
|
compileListUsersTemplate: () => compileListUsersTemplate,
|
|
65
|
-
bold: () =>
|
|
65
|
+
bold: () => import_ast5.bold,
|
|
66
|
+
STYLE_SLOT_PREFIX: () => import_ast4.STYLE_SLOT_PREFIX,
|
|
66
67
|
Parser: () => Parser,
|
|
67
68
|
Lexer: () => Lexer,
|
|
68
|
-
DEFAULT_SETTINGS: () =>
|
|
69
|
+
DEFAULT_SETTINGS: () => import_ast6.DEFAULT_SETTINGS
|
|
69
70
|
});
|
|
70
71
|
module.exports = __toCommonJS(exports_src);
|
|
71
|
-
var
|
|
72
|
-
var
|
|
72
|
+
var import_ast5 = require("@wdprlib/ast");
|
|
73
|
+
var import_ast6 = require("@wdprlib/ast");
|
|
73
74
|
|
|
74
75
|
// packages/parser/src/lexer/tokens.ts
|
|
75
76
|
function createToken(type, value, position, lineStart = false) {
|
|
@@ -1527,6 +1528,17 @@ function parseLiItem(ctx, startPos, listType) {
|
|
|
1527
1528
|
pos++;
|
|
1528
1529
|
}
|
|
1529
1530
|
}
|
|
1531
|
+
if (!isLiClose(ctx, pos)) {
|
|
1532
|
+
ctx.diagnostics.push({
|
|
1533
|
+
severity: "warning",
|
|
1534
|
+
code: "unclosed-block",
|
|
1535
|
+
message: "Missing closing tag [[/li]] for [[li]]",
|
|
1536
|
+
position: ctx.tokens[startPos]?.position ?? {
|
|
1537
|
+
start: { line: 0, column: 0, offset: 0 },
|
|
1538
|
+
end: { line: 0, column: 0, offset: 0 }
|
|
1539
|
+
}
|
|
1540
|
+
});
|
|
1541
|
+
}
|
|
1530
1542
|
if (isLiClose(ctx, pos)) {
|
|
1531
1543
|
const closeConsumed = consumeCloseTag(ctx, pos);
|
|
1532
1544
|
consumed += closeConsumed;
|
|
@@ -1619,11 +1631,13 @@ function parseListBlock(ctx, startPos, listType) {
|
|
|
1619
1631
|
consumed++;
|
|
1620
1632
|
}
|
|
1621
1633
|
const items = [];
|
|
1634
|
+
let foundListClose = false;
|
|
1622
1635
|
while (pos < ctx.tokens.length) {
|
|
1623
1636
|
const token = ctx.tokens[pos];
|
|
1624
1637
|
if (!token || token.type === "EOF")
|
|
1625
1638
|
break;
|
|
1626
1639
|
if (isListClose(ctx, pos, listType)) {
|
|
1640
|
+
foundListClose = true;
|
|
1627
1641
|
const closeConsumed = consumeCloseTag(ctx, pos);
|
|
1628
1642
|
consumed += closeConsumed;
|
|
1629
1643
|
break;
|
|
@@ -1747,6 +1761,17 @@ function parseListBlock(ctx, startPos, listType) {
|
|
|
1747
1761
|
});
|
|
1748
1762
|
}
|
|
1749
1763
|
}
|
|
1764
|
+
if (!foundListClose) {
|
|
1765
|
+
ctx.diagnostics.push({
|
|
1766
|
+
severity: "warning",
|
|
1767
|
+
code: "unclosed-block",
|
|
1768
|
+
message: `Missing closing tag [[/${listType}]] for [[${listType}]]`,
|
|
1769
|
+
position: ctx.tokens[startPos]?.position ?? {
|
|
1770
|
+
start: { line: 0, column: 0, offset: 0 },
|
|
1771
|
+
end: { line: 0, column: 0, offset: 0 }
|
|
1772
|
+
}
|
|
1773
|
+
});
|
|
1774
|
+
}
|
|
1750
1775
|
const listData = {
|
|
1751
1776
|
type: listType === "ol" ? "numbered" : "bullet",
|
|
1752
1777
|
attributes: attrResult.attrs,
|
|
@@ -2182,8 +2207,19 @@ var divRule = {
|
|
|
2182
2207
|
if (ctx.tokens[pos]?.type !== "NEWLINE") {
|
|
2183
2208
|
return consumeFailedDiv(ctx);
|
|
2184
2209
|
}
|
|
2210
|
+
if (ctx.divClosesBudget === 0) {
|
|
2211
|
+
return { success: false };
|
|
2212
|
+
}
|
|
2185
2213
|
pos++;
|
|
2186
2214
|
consumed++;
|
|
2215
|
+
const openPosition = openToken.position;
|
|
2216
|
+
let bodyBudget;
|
|
2217
|
+
if (ctx.divClosesBudget !== undefined) {
|
|
2218
|
+
bodyBudget = ctx.divClosesBudget - 1;
|
|
2219
|
+
} else {
|
|
2220
|
+
const closesInScope = countDivCloses(ctx, pos);
|
|
2221
|
+
bodyBudget = closesInScope > 0 ? closesInScope - 1 : 0;
|
|
2222
|
+
}
|
|
2187
2223
|
const closeCondition = (checkCtx) => {
|
|
2188
2224
|
const token = checkCtx.tokens[checkCtx.pos];
|
|
2189
2225
|
if (token?.type === "BLOCK_END_OPEN") {
|
|
@@ -2194,7 +2230,7 @@ var divRule = {
|
|
|
2194
2230
|
}
|
|
2195
2231
|
return false;
|
|
2196
2232
|
};
|
|
2197
|
-
const bodyCtx = { ...ctx, pos };
|
|
2233
|
+
const bodyCtx = { ...ctx, pos, divClosesBudget: bodyBudget };
|
|
2198
2234
|
let children;
|
|
2199
2235
|
if (paragraphStrip) {
|
|
2200
2236
|
const bodyResult = parseBlocksUntil(bodyCtx, closeCondition);
|
|
@@ -2207,6 +2243,14 @@ var divRule = {
|
|
|
2207
2243
|
pos += bodyResult.consumed;
|
|
2208
2244
|
children = bodyResult.elements;
|
|
2209
2245
|
}
|
|
2246
|
+
if (ctx.tokens[pos]?.type !== "BLOCK_END_OPEN") {
|
|
2247
|
+
ctx.diagnostics.push({
|
|
2248
|
+
severity: "warning",
|
|
2249
|
+
code: "unclosed-block",
|
|
2250
|
+
message: `Missing closing tag [[/div]] for [[${blockName}]]`,
|
|
2251
|
+
position: openPosition
|
|
2252
|
+
});
|
|
2253
|
+
}
|
|
2210
2254
|
if (ctx.tokens[pos]?.type === "BLOCK_END_OPEN") {
|
|
2211
2255
|
pos++;
|
|
2212
2256
|
consumed++;
|
|
@@ -2240,6 +2284,21 @@ var divRule = {
|
|
|
2240
2284
|
};
|
|
2241
2285
|
}
|
|
2242
2286
|
};
|
|
2287
|
+
function countDivCloses(ctx, startPos) {
|
|
2288
|
+
let count = 0;
|
|
2289
|
+
for (let i = startPos;i < ctx.tokens.length; i++) {
|
|
2290
|
+
const t = ctx.tokens[i];
|
|
2291
|
+
if (!t || t.type === "EOF")
|
|
2292
|
+
break;
|
|
2293
|
+
if (t.type === "BLOCK_END_OPEN") {
|
|
2294
|
+
const nameResult = parseBlockName(ctx, i + 1);
|
|
2295
|
+
if (nameResult?.name === "div") {
|
|
2296
|
+
count++;
|
|
2297
|
+
}
|
|
2298
|
+
}
|
|
2299
|
+
}
|
|
2300
|
+
return count;
|
|
2301
|
+
}
|
|
2243
2302
|
function consumeFailedDiv(ctx) {
|
|
2244
2303
|
const elements = [];
|
|
2245
2304
|
let pos = ctx.pos;
|
|
@@ -2251,6 +2310,20 @@ function consumeFailedDiv(ctx) {
|
|
|
2251
2310
|
const t = ctx.tokens[scanPos];
|
|
2252
2311
|
if (!t || t.type === "EOF")
|
|
2253
2312
|
break;
|
|
2313
|
+
if (t.type === "BLOCK_OPEN" && t.lineStart && scanPos > pos) {
|
|
2314
|
+
const nameResult = parseBlockName(ctx, scanPos + 1);
|
|
2315
|
+
if (nameResult?.name === "div" || nameResult?.name === "div_") {
|
|
2316
|
+
let checkPos = scanPos + 1 + nameResult.consumed;
|
|
2317
|
+
const attrResult = parseAttributes(ctx, checkPos);
|
|
2318
|
+
checkPos += attrResult.consumed;
|
|
2319
|
+
if (ctx.tokens[checkPos]?.type === "BLOCK_CLOSE") {
|
|
2320
|
+
checkPos++;
|
|
2321
|
+
if (ctx.tokens[checkPos]?.type === "NEWLINE" || ctx.tokens[checkPos]?.type === "EOF") {
|
|
2322
|
+
break;
|
|
2323
|
+
}
|
|
2324
|
+
}
|
|
2325
|
+
}
|
|
2326
|
+
}
|
|
2254
2327
|
if (t.type === "BLOCK_END_OPEN") {
|
|
2255
2328
|
const nameResult = parseBlockName(ctx, scanPos + 1);
|
|
2256
2329
|
if (nameResult?.name === "div") {
|
|
@@ -2267,6 +2340,23 @@ function consumeFailedDiv(ctx) {
|
|
|
2267
2340
|
if (lastClosePos === -1) {
|
|
2268
2341
|
return { success: false };
|
|
2269
2342
|
}
|
|
2343
|
+
const endPosForDiag = lastClosePos;
|
|
2344
|
+
for (let diagPos = ctx.pos;diagPos < endPosForDiag; diagPos++) {
|
|
2345
|
+
const t = ctx.tokens[diagPos];
|
|
2346
|
+
if (t?.type === "BLOCK_OPEN") {
|
|
2347
|
+
const nameResult = parseBlockName(ctx, diagPos + 1);
|
|
2348
|
+
if (nameResult?.name === "div" || nameResult?.name === "div_") {
|
|
2349
|
+
if (t.position) {
|
|
2350
|
+
ctx.diagnostics.push({
|
|
2351
|
+
severity: "error",
|
|
2352
|
+
code: "inline-block-element",
|
|
2353
|
+
message: `[[${nameResult.name}]] must be followed by a newline to be a block element`,
|
|
2354
|
+
position: t.position
|
|
2355
|
+
});
|
|
2356
|
+
}
|
|
2357
|
+
}
|
|
2358
|
+
}
|
|
2359
|
+
}
|
|
2270
2360
|
const endPos = lastClosePos + lastCloseConsumed;
|
|
2271
2361
|
while (pos < endPos && pos < ctx.tokens.length) {
|
|
2272
2362
|
const t = ctx.tokens[pos];
|
|
@@ -2383,6 +2473,7 @@ var codeBlockRule = {
|
|
|
2383
2473
|
consumed++;
|
|
2384
2474
|
}
|
|
2385
2475
|
let codeContent = "";
|
|
2476
|
+
let foundClose = closingSwallowed;
|
|
2386
2477
|
while (!closingSwallowed && pos < ctx.tokens.length) {
|
|
2387
2478
|
const token = ctx.tokens[pos];
|
|
2388
2479
|
if (!token || token.type === "EOF") {
|
|
@@ -2391,6 +2482,7 @@ var codeBlockRule = {
|
|
|
2391
2482
|
if (token.type === "BLOCK_END_OPEN") {
|
|
2392
2483
|
const closeNameResult = parseBlockName(ctx, pos + 1);
|
|
2393
2484
|
if (closeNameResult && closeNameResult.name === "code") {
|
|
2485
|
+
foundClose = true;
|
|
2394
2486
|
pos++;
|
|
2395
2487
|
consumed++;
|
|
2396
2488
|
pos += closeNameResult.consumed;
|
|
@@ -2410,6 +2502,14 @@ var codeBlockRule = {
|
|
|
2410
2502
|
pos++;
|
|
2411
2503
|
consumed++;
|
|
2412
2504
|
}
|
|
2505
|
+
if (!foundClose) {
|
|
2506
|
+
ctx.diagnostics.push({
|
|
2507
|
+
severity: "warning",
|
|
2508
|
+
code: "unclosed-block",
|
|
2509
|
+
message: "Missing closing tag [[/code]] for [[code]]",
|
|
2510
|
+
position: openToken.position
|
|
2511
|
+
});
|
|
2512
|
+
}
|
|
2413
2513
|
codeContent = codeContent.replace(/\n$/, "");
|
|
2414
2514
|
const codeBlockData = {
|
|
2415
2515
|
contents: codeContent,
|
|
@@ -2568,6 +2668,7 @@ var collapsibleRule = {
|
|
|
2568
2668
|
}
|
|
2569
2669
|
pos++;
|
|
2570
2670
|
consumed++;
|
|
2671
|
+
const openPosition = openToken.position;
|
|
2571
2672
|
const hasNewlineAfterOpen = ctx.tokens[pos]?.type === "NEWLINE";
|
|
2572
2673
|
if (hasNewlineAfterOpen) {
|
|
2573
2674
|
pos++;
|
|
@@ -2618,6 +2719,14 @@ var collapsibleRule = {
|
|
|
2618
2719
|
pos += bodyResult.consumed;
|
|
2619
2720
|
bodyElements = mergeParagraphs(bodyResult.elements);
|
|
2620
2721
|
}
|
|
2722
|
+
if (!isCollapsibleClose(ctx, pos)) {
|
|
2723
|
+
ctx.diagnostics.push({
|
|
2724
|
+
severity: "warning",
|
|
2725
|
+
code: "unclosed-block",
|
|
2726
|
+
message: "Missing closing tag [[/collapsible]] for [[collapsible]]",
|
|
2727
|
+
position: openPosition
|
|
2728
|
+
});
|
|
2729
|
+
}
|
|
2621
2730
|
if (isCollapsibleClose(ctx, pos)) {
|
|
2622
2731
|
const closeConsumed = consumeCloseTag2(ctx, pos);
|
|
2623
2732
|
consumed += closeConsumed;
|
|
@@ -2946,6 +3055,7 @@ var tableBlockRule = {
|
|
|
2946
3055
|
consumed++;
|
|
2947
3056
|
}
|
|
2948
3057
|
const rows = [];
|
|
3058
|
+
let foundTableClose = false;
|
|
2949
3059
|
while (pos < ctx.tokens.length) {
|
|
2950
3060
|
while (ctx.tokens[pos]?.type === "WHITESPACE" || ctx.tokens[pos]?.type === "NEWLINE") {
|
|
2951
3061
|
pos++;
|
|
@@ -2958,6 +3068,7 @@ var tableBlockRule = {
|
|
|
2958
3068
|
if (token.type === "BLOCK_END_OPEN") {
|
|
2959
3069
|
const closeNameResult = parseBlockName(ctx, pos + 1);
|
|
2960
3070
|
if (closeNameResult?.name === "table") {
|
|
3071
|
+
foundTableClose = true;
|
|
2961
3072
|
pos++;
|
|
2962
3073
|
consumed++;
|
|
2963
3074
|
pos += closeNameResult.consumed;
|
|
@@ -2988,6 +3099,14 @@ var tableBlockRule = {
|
|
|
2988
3099
|
pos++;
|
|
2989
3100
|
consumed++;
|
|
2990
3101
|
}
|
|
3102
|
+
if (!foundTableClose) {
|
|
3103
|
+
ctx.diagnostics.push({
|
|
3104
|
+
severity: "warning",
|
|
3105
|
+
code: "unclosed-block",
|
|
3106
|
+
message: "Missing closing tag [[/table]] for [[table]]",
|
|
3107
|
+
position: openToken.position
|
|
3108
|
+
});
|
|
3109
|
+
}
|
|
2991
3110
|
const hasValidContent = rows.some((row) => row.cells.length > 0);
|
|
2992
3111
|
if (!hasValidContent) {
|
|
2993
3112
|
return { success: false };
|
|
@@ -3035,6 +3154,7 @@ function parseRow(ctx, startPos) {
|
|
|
3035
3154
|
consumed++;
|
|
3036
3155
|
}
|
|
3037
3156
|
const cells = [];
|
|
3157
|
+
let foundRowClose = false;
|
|
3038
3158
|
while (pos < ctx.tokens.length) {
|
|
3039
3159
|
while (ctx.tokens[pos]?.type === "WHITESPACE" || ctx.tokens[pos]?.type === "NEWLINE") {
|
|
3040
3160
|
pos++;
|
|
@@ -3047,6 +3167,7 @@ function parseRow(ctx, startPos) {
|
|
|
3047
3167
|
if (token.type === "BLOCK_END_OPEN") {
|
|
3048
3168
|
const closeNameResult = parseBlockName(ctx, pos + 1);
|
|
3049
3169
|
if (closeNameResult?.name === "row") {
|
|
3170
|
+
foundRowClose = true;
|
|
3050
3171
|
pos++;
|
|
3051
3172
|
consumed++;
|
|
3052
3173
|
pos += closeNameResult.consumed;
|
|
@@ -3077,6 +3198,17 @@ function parseRow(ctx, startPos) {
|
|
|
3077
3198
|
pos++;
|
|
3078
3199
|
consumed++;
|
|
3079
3200
|
}
|
|
3201
|
+
if (!foundRowClose) {
|
|
3202
|
+
ctx.diagnostics.push({
|
|
3203
|
+
severity: "warning",
|
|
3204
|
+
code: "unclosed-block",
|
|
3205
|
+
message: "Missing closing tag [[/row]] for [[row]]",
|
|
3206
|
+
position: ctx.tokens[startPos]?.position ?? {
|
|
3207
|
+
start: { line: 0, column: 0, offset: 0 },
|
|
3208
|
+
end: { line: 0, column: 0, offset: 0 }
|
|
3209
|
+
}
|
|
3210
|
+
});
|
|
3211
|
+
}
|
|
3080
3212
|
return {
|
|
3081
3213
|
row: {
|
|
3082
3214
|
attributes: attrResult.attrs,
|
|
@@ -3139,6 +3271,17 @@ function parseCell(ctx, startPos) {
|
|
|
3139
3271
|
consumed += bodyResult.consumed;
|
|
3140
3272
|
pos += bodyResult.consumed;
|
|
3141
3273
|
const hadParagraphBreaks = bodyResult.hadParagraphBreaks;
|
|
3274
|
+
if (ctx.tokens[pos]?.type !== "BLOCK_END_OPEN") {
|
|
3275
|
+
ctx.diagnostics.push({
|
|
3276
|
+
severity: "warning",
|
|
3277
|
+
code: "unclosed-block",
|
|
3278
|
+
message: `Missing closing tag [[/${closeName}]] for [[${closeName}]]`,
|
|
3279
|
+
position: ctx.tokens[startPos]?.position ?? {
|
|
3280
|
+
start: { line: 0, column: 0, offset: 0 },
|
|
3281
|
+
end: { line: 0, column: 0, offset: 0 }
|
|
3282
|
+
}
|
|
3283
|
+
});
|
|
3284
|
+
}
|
|
3142
3285
|
if (ctx.tokens[pos]?.type === "BLOCK_END_OPEN") {
|
|
3143
3286
|
pos++;
|
|
3144
3287
|
consumed++;
|
|
@@ -3596,6 +3739,7 @@ var moduleRule = {
|
|
|
3596
3739
|
pos++;
|
|
3597
3740
|
consumed++;
|
|
3598
3741
|
let bodyContent = "";
|
|
3742
|
+
let foundClose = false;
|
|
3599
3743
|
while (pos < ctx.tokens.length) {
|
|
3600
3744
|
const token = ctx.tokens[pos];
|
|
3601
3745
|
if (!token || token.type === "EOF") {
|
|
@@ -3604,6 +3748,7 @@ var moduleRule = {
|
|
|
3604
3748
|
if (token.type === "BLOCK_END_OPEN") {
|
|
3605
3749
|
const closeNameResult = parseBlockName(ctx, pos + 1);
|
|
3606
3750
|
if (closeNameResult && (closeNameResult.name === "module" || closeNameResult.name === "module654")) {
|
|
3751
|
+
foundClose = true;
|
|
3607
3752
|
pos++;
|
|
3608
3753
|
consumed++;
|
|
3609
3754
|
pos += closeNameResult.consumed;
|
|
@@ -3623,6 +3768,14 @@ var moduleRule = {
|
|
|
3623
3768
|
pos++;
|
|
3624
3769
|
consumed++;
|
|
3625
3770
|
}
|
|
3771
|
+
if (!foundClose) {
|
|
3772
|
+
ctx.diagnostics.push({
|
|
3773
|
+
severity: "warning",
|
|
3774
|
+
code: "unclosed-block",
|
|
3775
|
+
message: "Missing closing tag [[/module]] for [[module]]",
|
|
3776
|
+
position: openToken.position
|
|
3777
|
+
});
|
|
3778
|
+
}
|
|
3626
3779
|
if (bodyContent.trim()) {
|
|
3627
3780
|
body = bodyContent.trim();
|
|
3628
3781
|
}
|
|
@@ -4016,7 +4169,16 @@ var alignRule = {
|
|
|
4016
4169
|
const bodyResult = parseBlocksUntil(bodyCtx, closeCondition);
|
|
4017
4170
|
consumed += bodyResult.consumed;
|
|
4018
4171
|
pos += bodyResult.consumed;
|
|
4172
|
+
const directionSymbol = { left: "<", right: ">", center: "=", justify: "==" }[direction];
|
|
4019
4173
|
const closeCheck = isAlignClose({ ...ctx, pos }, direction);
|
|
4174
|
+
if (!closeCheck.match) {
|
|
4175
|
+
ctx.diagnostics.push({
|
|
4176
|
+
severity: "warning",
|
|
4177
|
+
code: "unclosed-block",
|
|
4178
|
+
message: `Missing closing tag [[/${directionSymbol}]] for [[${directionSymbol}]]`,
|
|
4179
|
+
position: openToken.position
|
|
4180
|
+
});
|
|
4181
|
+
}
|
|
4020
4182
|
if (closeCheck.match) {
|
|
4021
4183
|
consumed += closeCheck.consumed;
|
|
4022
4184
|
pos += closeCheck.consumed;
|
|
@@ -4104,6 +4266,17 @@ function parseTab(ctx) {
|
|
|
4104
4266
|
const bodyResult = parseBlocksUntil(bodyCtx, closeCondition);
|
|
4105
4267
|
consumed += bodyResult.consumed;
|
|
4106
4268
|
pos += bodyResult.consumed;
|
|
4269
|
+
if (ctx.tokens[pos]?.type !== "BLOCK_END_OPEN") {
|
|
4270
|
+
ctx.diagnostics.push({
|
|
4271
|
+
severity: "warning",
|
|
4272
|
+
code: "unclosed-block",
|
|
4273
|
+
message: "Missing closing tag [[/tab]] for [[tab]]",
|
|
4274
|
+
position: ctx.tokens[ctx.pos]?.position ?? {
|
|
4275
|
+
start: { line: 0, column: 0, offset: 0 },
|
|
4276
|
+
end: { line: 0, column: 0, offset: 0 }
|
|
4277
|
+
}
|
|
4278
|
+
});
|
|
4279
|
+
}
|
|
4107
4280
|
if (ctx.tokens[pos]?.type === "BLOCK_END_OPEN") {
|
|
4108
4281
|
pos++;
|
|
4109
4282
|
consumed++;
|
|
@@ -4167,6 +4340,9 @@ var tabviewRule = {
|
|
|
4167
4340
|
const tabs = [];
|
|
4168
4341
|
const tabCtx = { ...ctx, pos };
|
|
4169
4342
|
while (pos < ctx.tokens.length) {
|
|
4343
|
+
if (ctx.tokens[pos]?.type === "EOF") {
|
|
4344
|
+
break;
|
|
4345
|
+
}
|
|
4170
4346
|
if (ctx.tokens[pos]?.type === "BLOCK_END_OPEN") {
|
|
4171
4347
|
const closeNameResult = parseBlockName(ctx, pos + 1);
|
|
4172
4348
|
const closeName = closeNameResult?.name.toLowerCase();
|
|
@@ -4188,6 +4364,19 @@ var tabviewRule = {
|
|
|
4188
4364
|
}
|
|
4189
4365
|
}
|
|
4190
4366
|
}
|
|
4367
|
+
const hasTabviewClose = ctx.tokens[pos]?.type === "BLOCK_END_OPEN" && (() => {
|
|
4368
|
+
const n = parseBlockName(ctx, pos + 1);
|
|
4369
|
+
const name = n?.name.toLowerCase();
|
|
4370
|
+
return name === "tabview" || name === "tabs";
|
|
4371
|
+
})();
|
|
4372
|
+
if (!hasTabviewClose) {
|
|
4373
|
+
ctx.diagnostics.push({
|
|
4374
|
+
severity: "warning",
|
|
4375
|
+
code: "unclosed-block",
|
|
4376
|
+
message: `Missing closing tag [[/${blockName}]] for [[${blockName}]]`,
|
|
4377
|
+
position: openToken.position
|
|
4378
|
+
});
|
|
4379
|
+
}
|
|
4191
4380
|
if (ctx.tokens[pos]?.type === "BLOCK_END_OPEN") {
|
|
4192
4381
|
pos++;
|
|
4193
4382
|
consumed++;
|
|
@@ -4426,6 +4615,14 @@ var mathBlockRule = {
|
|
|
4426
4615
|
pos++;
|
|
4427
4616
|
consumed++;
|
|
4428
4617
|
}
|
|
4618
|
+
if (ctx.tokens[pos]?.type !== "BLOCK_END_OPEN") {
|
|
4619
|
+
ctx.diagnostics.push({
|
|
4620
|
+
severity: "warning",
|
|
4621
|
+
code: "unclosed-block",
|
|
4622
|
+
message: "Missing closing tag [[/math]] for [[math]]",
|
|
4623
|
+
position: openToken.position
|
|
4624
|
+
});
|
|
4625
|
+
}
|
|
4429
4626
|
if (ctx.tokens[pos]?.type === "BLOCK_END_OPEN") {
|
|
4430
4627
|
pos++;
|
|
4431
4628
|
consumed++;
|
|
@@ -4508,6 +4705,12 @@ var htmlBlockRule = {
|
|
|
4508
4705
|
consumed++;
|
|
4509
4706
|
}
|
|
4510
4707
|
if (!foundClose) {
|
|
4708
|
+
ctx.diagnostics.push({
|
|
4709
|
+
severity: "warning",
|
|
4710
|
+
code: "unclosed-block",
|
|
4711
|
+
message: "Missing closing tag [[/html]] for [[html]]",
|
|
4712
|
+
position: openToken.position
|
|
4713
|
+
});
|
|
4511
4714
|
return { success: false };
|
|
4512
4715
|
}
|
|
4513
4716
|
if (ctx.tokens[pos]?.type === "BLOCK_END_OPEN") {
|
|
@@ -4597,6 +4800,12 @@ var embedBlockRule = {
|
|
|
4597
4800
|
consumed++;
|
|
4598
4801
|
}
|
|
4599
4802
|
if (!foundClose) {
|
|
4803
|
+
ctx.diagnostics.push({
|
|
4804
|
+
severity: "warning",
|
|
4805
|
+
code: "unclosed-block",
|
|
4806
|
+
message: `Missing closing tag [[/${blockName}]] for [[${blockName}]]`,
|
|
4807
|
+
position: openToken.position
|
|
4808
|
+
});
|
|
4600
4809
|
return { success: false };
|
|
4601
4810
|
}
|
|
4602
4811
|
if (ctx.tokens[pos]?.type === "BLOCK_END_OPEN") {
|
|
@@ -4826,6 +5035,14 @@ var iftagsRule = {
|
|
|
4826
5035
|
const bodyResult = parseBlocksUntil(bodyCtx, closeCondition);
|
|
4827
5036
|
consumed += bodyResult.consumed;
|
|
4828
5037
|
pos += bodyResult.consumed;
|
|
5038
|
+
if (ctx.tokens[pos]?.type !== "BLOCK_END_OPEN") {
|
|
5039
|
+
ctx.diagnostics.push({
|
|
5040
|
+
severity: "warning",
|
|
5041
|
+
code: "unclosed-block",
|
|
5042
|
+
message: "Missing closing tag [[/iftags]] for [[iftags]]",
|
|
5043
|
+
position: openToken.position
|
|
5044
|
+
});
|
|
5045
|
+
}
|
|
4829
5046
|
if (ctx.tokens[pos]?.type === "BLOCK_END_OPEN") {
|
|
4830
5047
|
pos++;
|
|
4831
5048
|
consumed++;
|
|
@@ -5029,6 +5246,12 @@ var orphanLiRule = {
|
|
|
5029
5246
|
consumed++;
|
|
5030
5247
|
}
|
|
5031
5248
|
if (!foundClose) {
|
|
5249
|
+
ctx.diagnostics.push({
|
|
5250
|
+
severity: "warning",
|
|
5251
|
+
code: "unclosed-block",
|
|
5252
|
+
message: "Missing closing tag [[/li]] for [[li]]",
|
|
5253
|
+
position: openToken.position
|
|
5254
|
+
});
|
|
5032
5255
|
return { success: false };
|
|
5033
5256
|
}
|
|
5034
5257
|
return {
|
|
@@ -5219,6 +5442,12 @@ var bibliographyRule = {
|
|
|
5219
5442
|
consumed++;
|
|
5220
5443
|
}
|
|
5221
5444
|
if (!foundClose) {
|
|
5445
|
+
ctx.diagnostics.push({
|
|
5446
|
+
severity: "warning",
|
|
5447
|
+
code: "unclosed-block",
|
|
5448
|
+
message: "Missing closing tag [[/bibliography]] for [[bibliography]]",
|
|
5449
|
+
position: openToken.position
|
|
5450
|
+
});
|
|
5222
5451
|
return { success: false };
|
|
5223
5452
|
}
|
|
5224
5453
|
const definitionItems = entries.map((entry) => ({
|
|
@@ -6140,6 +6369,7 @@ var commentRule = {
|
|
|
6140
6369
|
name: "comment",
|
|
6141
6370
|
startTokens: ["COMMENT_OPEN"],
|
|
6142
6371
|
parse(ctx) {
|
|
6372
|
+
const openToken = currentToken(ctx);
|
|
6143
6373
|
let pos = ctx.pos + 1;
|
|
6144
6374
|
let consumed = 1;
|
|
6145
6375
|
while (pos < ctx.tokens.length) {
|
|
@@ -6157,11 +6387,23 @@ var commentRule = {
|
|
|
6157
6387
|
};
|
|
6158
6388
|
}
|
|
6159
6389
|
if (token.type === "EOF") {
|
|
6390
|
+
ctx.diagnostics.push({
|
|
6391
|
+
severity: "warning",
|
|
6392
|
+
code: "unclosed-comment",
|
|
6393
|
+
message: "Unterminated comment: missing closing --]",
|
|
6394
|
+
position: openToken.position
|
|
6395
|
+
});
|
|
6160
6396
|
return { success: false };
|
|
6161
6397
|
}
|
|
6162
6398
|
pos++;
|
|
6163
6399
|
consumed++;
|
|
6164
6400
|
}
|
|
6401
|
+
ctx.diagnostics.push({
|
|
6402
|
+
severity: "warning",
|
|
6403
|
+
code: "unclosed-comment",
|
|
6404
|
+
message: "Unterminated comment: missing closing --]",
|
|
6405
|
+
position: openToken.position
|
|
6406
|
+
});
|
|
6165
6407
|
return { success: false };
|
|
6166
6408
|
}
|
|
6167
6409
|
};
|
|
@@ -6419,6 +6661,12 @@ var spanRule = {
|
|
|
6419
6661
|
}
|
|
6420
6662
|
}
|
|
6421
6663
|
if (!foundClose) {
|
|
6664
|
+
ctx.diagnostics.push({
|
|
6665
|
+
severity: "warning",
|
|
6666
|
+
code: "unclosed-block",
|
|
6667
|
+
message: `Missing closing tag [[/span]] for [[${blockName}]]`,
|
|
6668
|
+
position: openToken.position
|
|
6669
|
+
});
|
|
6422
6670
|
return { success: false };
|
|
6423
6671
|
}
|
|
6424
6672
|
if (paragraphStrip) {
|
|
@@ -6619,6 +6867,7 @@ var sizeRule = {
|
|
|
6619
6867
|
pos++;
|
|
6620
6868
|
consumed++;
|
|
6621
6869
|
const children = [];
|
|
6870
|
+
let foundClose = false;
|
|
6622
6871
|
while (pos < ctx.tokens.length) {
|
|
6623
6872
|
const token = ctx.tokens[pos];
|
|
6624
6873
|
if (!token || token.type === "EOF") {
|
|
@@ -6627,6 +6876,7 @@ var sizeRule = {
|
|
|
6627
6876
|
if (token.type === "BLOCK_END_OPEN") {
|
|
6628
6877
|
const closeNameResult = parseBlockName(ctx, pos + 1);
|
|
6629
6878
|
if (closeNameResult && closeNameResult.name === "size") {
|
|
6879
|
+
foundClose = true;
|
|
6630
6880
|
pos++;
|
|
6631
6881
|
consumed++;
|
|
6632
6882
|
pos += closeNameResult.consumed;
|
|
@@ -6650,6 +6900,14 @@ var sizeRule = {
|
|
|
6650
6900
|
consumed++;
|
|
6651
6901
|
}
|
|
6652
6902
|
}
|
|
6903
|
+
if (!foundClose) {
|
|
6904
|
+
ctx.diagnostics.push({
|
|
6905
|
+
severity: "warning",
|
|
6906
|
+
code: "unclosed-block",
|
|
6907
|
+
message: "Missing closing tag [[/size]] for [[size]]",
|
|
6908
|
+
position: openToken.position
|
|
6909
|
+
});
|
|
6910
|
+
}
|
|
6653
6911
|
return {
|
|
6654
6912
|
success: true,
|
|
6655
6913
|
elements: [
|
|
@@ -6699,6 +6957,7 @@ var footnoteRule = {
|
|
|
6699
6957
|
consumed++;
|
|
6700
6958
|
const paragraphs = [[]];
|
|
6701
6959
|
let currentParagraph = 0;
|
|
6960
|
+
let foundClose = false;
|
|
6702
6961
|
while (pos < ctx.tokens.length) {
|
|
6703
6962
|
const token = ctx.tokens[pos];
|
|
6704
6963
|
if (!token || token.type === "EOF") {
|
|
@@ -6707,6 +6966,7 @@ var footnoteRule = {
|
|
|
6707
6966
|
if (token.type === "BLOCK_END_OPEN") {
|
|
6708
6967
|
const closeNameResult = parseBlockName(ctx, pos + 1);
|
|
6709
6968
|
if (closeNameResult && closeNameResult.name === "footnote") {
|
|
6969
|
+
foundClose = true;
|
|
6710
6970
|
pos++;
|
|
6711
6971
|
consumed++;
|
|
6712
6972
|
pos += closeNameResult.consumed;
|
|
@@ -6783,6 +7043,14 @@ var footnoteRule = {
|
|
|
6783
7043
|
});
|
|
6784
7044
|
}
|
|
6785
7045
|
}
|
|
7046
|
+
if (!foundClose) {
|
|
7047
|
+
ctx.diagnostics.push({
|
|
7048
|
+
severity: "warning",
|
|
7049
|
+
code: "unclosed-block",
|
|
7050
|
+
message: "Missing closing tag [[/footnote]] for [[footnote]]",
|
|
7051
|
+
position: openToken.position
|
|
7052
|
+
});
|
|
7053
|
+
}
|
|
6786
7054
|
ctx.footnotes.push(children);
|
|
6787
7055
|
return {
|
|
6788
7056
|
success: true,
|
|
@@ -7278,6 +7546,12 @@ var anchorRule = {
|
|
|
7278
7546
|
}
|
|
7279
7547
|
}
|
|
7280
7548
|
if (!foundClose) {
|
|
7549
|
+
ctx.diagnostics.push({
|
|
7550
|
+
severity: "warning",
|
|
7551
|
+
code: "unclosed-block",
|
|
7552
|
+
message: `Missing closing tag [[/a]] for [[${nameResult.name}]]`,
|
|
7553
|
+
position: openToken.position
|
|
7554
|
+
});
|
|
7281
7555
|
return { success: false };
|
|
7282
7556
|
}
|
|
7283
7557
|
if (paragraphStrip) {
|
|
@@ -8256,6 +8530,50 @@ function cleanElement(el) {
|
|
|
8256
8530
|
}
|
|
8257
8531
|
return el;
|
|
8258
8532
|
}
|
|
8533
|
+
// packages/parser/src/parser/postprocess/divAdjacentParagraph.ts
|
|
8534
|
+
function isParagraphContainer2(el) {
|
|
8535
|
+
if (!el || el.element !== "container")
|
|
8536
|
+
return false;
|
|
8537
|
+
return el.data.type === "paragraph";
|
|
8538
|
+
}
|
|
8539
|
+
function isDivContainer(el) {
|
|
8540
|
+
if (!el || el.element !== "container")
|
|
8541
|
+
return false;
|
|
8542
|
+
return el.data.type === "div";
|
|
8543
|
+
}
|
|
8544
|
+
function suppressAtLevel(elements) {
|
|
8545
|
+
if (elements.length <= 1)
|
|
8546
|
+
return elements;
|
|
8547
|
+
const unwrap = new Array(elements.length).fill(false);
|
|
8548
|
+
for (let i = 0;i < elements.length; i++) {
|
|
8549
|
+
if (!isParagraphContainer2(elements[i]))
|
|
8550
|
+
continue;
|
|
8551
|
+
const prevIsDiv = i > 0 && isDivContainer(elements[i - 1]);
|
|
8552
|
+
const nextIsDiv = i < elements.length - 1 && isDivContainer(elements[i + 1]);
|
|
8553
|
+
if (prevIsDiv || nextIsDiv) {
|
|
8554
|
+
unwrap[i] = true;
|
|
8555
|
+
}
|
|
8556
|
+
}
|
|
8557
|
+
const result = [];
|
|
8558
|
+
for (let i = 0;i < elements.length; i++) {
|
|
8559
|
+
const el = elements[i];
|
|
8560
|
+
if (!el)
|
|
8561
|
+
continue;
|
|
8562
|
+
if (unwrap[i] && el.element === "container") {
|
|
8563
|
+
const inner = el.data.elements;
|
|
8564
|
+
if (i > 0 && isDivContainer(elements[i - 1])) {
|
|
8565
|
+
result.push({ element: "line-break" });
|
|
8566
|
+
}
|
|
8567
|
+
result.push(...inner);
|
|
8568
|
+
} else {
|
|
8569
|
+
result.push(el);
|
|
8570
|
+
}
|
|
8571
|
+
}
|
|
8572
|
+
return result;
|
|
8573
|
+
}
|
|
8574
|
+
function suppressDivAdjacentParagraphs(elements) {
|
|
8575
|
+
return suppressAtLevel(elements);
|
|
8576
|
+
}
|
|
8259
8577
|
// packages/parser/src/parser/toc.ts
|
|
8260
8578
|
class TocIndexer {
|
|
8261
8579
|
index = 0;
|
|
@@ -8333,6 +8651,7 @@ class Parser {
|
|
|
8333
8651
|
htmlBlocks: [],
|
|
8334
8652
|
footnoteBlockParsed: false,
|
|
8335
8653
|
bibcites: [],
|
|
8654
|
+
diagnostics: [],
|
|
8336
8655
|
blockRules,
|
|
8337
8656
|
blockFallbackRule: paragraphRule,
|
|
8338
8657
|
inlineRules
|
|
@@ -8345,7 +8664,8 @@ class Parser {
|
|
|
8345
8664
|
children.push(...blocks);
|
|
8346
8665
|
}
|
|
8347
8666
|
const mergedChildren = mergeSpanStripParagraphs(children);
|
|
8348
|
-
const
|
|
8667
|
+
const divProcessed = suppressDivAdjacentParagraphs(mergedChildren);
|
|
8668
|
+
const cleanedChildren = cleanInternalFlags(divProcessed);
|
|
8349
8669
|
const hasFootnoteBlock = cleanedChildren.some((el) => el.element === "footnote-block");
|
|
8350
8670
|
if (!hasFootnoteBlock) {
|
|
8351
8671
|
cleanedChildren.push({
|
|
@@ -8369,7 +8689,7 @@ class Parser {
|
|
|
8369
8689
|
if (this.ctx.htmlBlocks.length > 0) {
|
|
8370
8690
|
result["html-blocks"] = this.ctx.htmlBlocks;
|
|
8371
8691
|
}
|
|
8372
|
-
return result;
|
|
8692
|
+
return { ast: result, diagnostics: this.ctx.diagnostics };
|
|
8373
8693
|
}
|
|
8374
8694
|
isAtEnd() {
|
|
8375
8695
|
return this.ctx.pos >= this.ctx.tokens.length || this.currentToken().type === "EOF";
|
|
@@ -9580,6 +9900,7 @@ function resolveAndNormalizeQuery(requirement, urlParams) {
|
|
|
9580
9900
|
function parseTagCondition(condition) {
|
|
9581
9901
|
const required = [];
|
|
9582
9902
|
const forbidden = [];
|
|
9903
|
+
const optional = [];
|
|
9583
9904
|
const parts = condition.trim().split(/\s+/);
|
|
9584
9905
|
for (const part of parts) {
|
|
9585
9906
|
if (!part)
|
|
@@ -9593,12 +9914,15 @@ function parseTagCondition(condition) {
|
|
|
9593
9914
|
if (tag)
|
|
9594
9915
|
forbidden.push(tag);
|
|
9595
9916
|
} else {
|
|
9596
|
-
|
|
9917
|
+
optional.push(part);
|
|
9597
9918
|
}
|
|
9598
9919
|
}
|
|
9599
|
-
return { required, forbidden };
|
|
9920
|
+
return { required, forbidden, optional };
|
|
9600
9921
|
}
|
|
9601
9922
|
function evaluateTagCondition(condition, pageTags) {
|
|
9923
|
+
if (condition.required.length === 0 && condition.forbidden.length === 0 && condition.optional.length === 0) {
|
|
9924
|
+
return false;
|
|
9925
|
+
}
|
|
9602
9926
|
const tagSet = new Set(pageTags);
|
|
9603
9927
|
for (const tag of condition.required) {
|
|
9604
9928
|
if (!tagSet.has(tag)) {
|
|
@@ -9610,6 +9934,11 @@ function evaluateTagCondition(condition, pageTags) {
|
|
|
9610
9934
|
return false;
|
|
9611
9935
|
}
|
|
9612
9936
|
}
|
|
9937
|
+
if (condition.optional.length > 0) {
|
|
9938
|
+
if (!condition.optional.some((tag) => tagSet.has(tag))) {
|
|
9939
|
+
return false;
|
|
9940
|
+
}
|
|
9941
|
+
}
|
|
9613
9942
|
return true;
|
|
9614
9943
|
}
|
|
9615
9944
|
// packages/parser/src/parser/rules/block/module/iftags/resolve.ts
|
|
@@ -9745,6 +10074,7 @@ function resolveListUsers(_module, data, compiledTemplate, parse2) {
|
|
|
9745
10074
|
return itemAst.elements;
|
|
9746
10075
|
}
|
|
9747
10076
|
// packages/parser/src/parser/rules/block/module/resolve.ts
|
|
10077
|
+
var import_ast3 = require("@wdprlib/ast");
|
|
9748
10078
|
async function resolveModules(ast, dataProvider, options) {
|
|
9749
10079
|
let listPagesCtx = null;
|
|
9750
10080
|
const listPagesReqs = options.requirements.listPages ?? [];
|
|
@@ -9909,18 +10239,31 @@ function countModulesInElements(elements) {
|
|
|
9909
10239
|
}
|
|
9910
10240
|
function collectStyles(elements) {
|
|
9911
10241
|
const styles = [];
|
|
9912
|
-
const
|
|
10242
|
+
const ctx = { nextSlotId: 0 };
|
|
10243
|
+
const filtered = collectStylesFromElements(elements, styles, ctx);
|
|
9913
10244
|
return { elements: filtered, styles };
|
|
9914
10245
|
}
|
|
9915
|
-
function collectStylesFromElements(elements, styles) {
|
|
10246
|
+
function collectStylesFromElements(elements, styles, ctx) {
|
|
9916
10247
|
const result = [];
|
|
9917
10248
|
for (const element of elements) {
|
|
9918
10249
|
if (element.element === "style") {
|
|
9919
10250
|
styles.push(element.data);
|
|
9920
10251
|
continue;
|
|
9921
10252
|
}
|
|
9922
|
-
|
|
10253
|
+
if (element.element === "if-tags") {
|
|
10254
|
+
const slotId = ctx.nextSlotId++;
|
|
10255
|
+
styles.push(`${import_ast3.STYLE_SLOT_PREFIX}${slotId}`);
|
|
10256
|
+
result.push({
|
|
10257
|
+
element: "if-tags",
|
|
10258
|
+
data: { ...element.data, _styleSlot: slotId }
|
|
10259
|
+
});
|
|
10260
|
+
continue;
|
|
10261
|
+
}
|
|
10262
|
+
const mapped = mapElementChildren(element, (children) => collectStylesFromElements(children, styles, ctx));
|
|
9923
10263
|
result.push(mapped);
|
|
9924
10264
|
}
|
|
9925
10265
|
return result;
|
|
9926
10266
|
}
|
|
10267
|
+
|
|
10268
|
+
// packages/parser/src/parser/rules/block/module/index.ts
|
|
10269
|
+
var import_ast4 = require("@wdprlib/ast");
|