@wdprlib/parser 2.2.0 → 3.1.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 +921 -471
- package/dist/index.d.cts +50 -1
- package/dist/index.d.ts +50 -1
- package/dist/index.js +921 -471
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -36,6 +36,7 @@ __export(exports_src, {
|
|
|
36
36
|
resolveListUsers: () => resolveListUsers,
|
|
37
37
|
resolveIncludesAsync: () => resolveIncludesAsync,
|
|
38
38
|
resolveIncludes: () => resolveIncludes,
|
|
39
|
+
preprocessIftags: () => preprocessIftags,
|
|
39
40
|
parseTags: () => parseTags,
|
|
40
41
|
parseParent: () => parseParent,
|
|
41
42
|
parseOrder: () => parseOrder,
|
|
@@ -83,6 +84,7 @@ class Lexer {
|
|
|
83
84
|
state;
|
|
84
85
|
options;
|
|
85
86
|
splitBlockClosePositions = new Set;
|
|
87
|
+
blockOpenerDepth = 0;
|
|
86
88
|
constructor(source, options = {}) {
|
|
87
89
|
this.options = {
|
|
88
90
|
trackPositions: options.trackPositions ?? true
|
|
@@ -182,6 +184,11 @@ class Lexer {
|
|
|
182
184
|
const position = this.options.trackPositions ? import_ast.createPosition(startPos, endPos) : import_ast.createPosition(import_ast.createPoint(0, 0, 0), import_ast.createPoint(0, 0, 0));
|
|
183
185
|
const lineStart = this.state.tokens.length === 0 || this.state.tokens[this.state.tokens.length - 1]?.type === "NEWLINE";
|
|
184
186
|
this.state.tokens.push(createToken(type, value, position, lineStart));
|
|
187
|
+
if (type === "BLOCK_OPEN" || type === "BLOCK_END_OPEN") {
|
|
188
|
+
this.blockOpenerDepth++;
|
|
189
|
+
} else if (type === "BLOCK_CLOSE" && this.blockOpenerDepth > 0) {
|
|
190
|
+
this.blockOpenerDepth--;
|
|
191
|
+
}
|
|
185
192
|
}
|
|
186
193
|
scanToken() {
|
|
187
194
|
const char = this.current();
|
|
@@ -446,7 +453,7 @@ class Lexer {
|
|
|
446
453
|
}
|
|
447
454
|
if (char === '"') {
|
|
448
455
|
const lastNonWs = this.lastNonWhitespaceTokenType();
|
|
449
|
-
if (lastNonWs === "EQUALS") {
|
|
456
|
+
if (this.blockOpenerDepth > 0 && lastNonWs === "EQUALS") {
|
|
450
457
|
let quoted = this.advance();
|
|
451
458
|
while (!this.isAtEnd() && this.current() !== '"' && this.current() !== `
|
|
452
459
|
`) {
|
|
@@ -691,6 +698,28 @@ var KNOWN_BLOCK_NAMES = new Set([
|
|
|
691
698
|
"gallery",
|
|
692
699
|
"file"
|
|
693
700
|
]);
|
|
701
|
+
var INDENT_ACCEPTING_BLOCK_NAMES = new Set([
|
|
702
|
+
"bibliography",
|
|
703
|
+
"ul",
|
|
704
|
+
"ol",
|
|
705
|
+
"li",
|
|
706
|
+
"code",
|
|
707
|
+
"collapsible",
|
|
708
|
+
"div",
|
|
709
|
+
"div_",
|
|
710
|
+
"embed",
|
|
711
|
+
"embedvideo",
|
|
712
|
+
"embedaudio",
|
|
713
|
+
"html",
|
|
714
|
+
"iframe",
|
|
715
|
+
"iftags",
|
|
716
|
+
"math",
|
|
717
|
+
"module",
|
|
718
|
+
"module654",
|
|
719
|
+
"table",
|
|
720
|
+
"tabview",
|
|
721
|
+
"tabs"
|
|
722
|
+
]);
|
|
694
723
|
|
|
695
724
|
// packages/parser/src/parser/rules/utils.ts
|
|
696
725
|
var SAFE_ATTRIBUTES = new Set([
|
|
@@ -817,13 +846,14 @@ function parseBlockName(ctx, startPos) {
|
|
|
817
846
|
|
|
818
847
|
// packages/parser/src/parser/rules/inline/utils.ts
|
|
819
848
|
function isExcludedBlockToken(ctx, tokenPos) {
|
|
820
|
-
|
|
849
|
+
const excluded = ctx.scope.excludedBlockNames;
|
|
850
|
+
if (!excluded?.size)
|
|
821
851
|
return false;
|
|
822
852
|
const token = ctx.tokens[tokenPos];
|
|
823
853
|
if (token?.type !== "BLOCK_OPEN" && token?.type !== "BLOCK_END_OPEN")
|
|
824
854
|
return false;
|
|
825
855
|
const nameResult = parseBlockName(ctx, tokenPos + 1);
|
|
826
|
-
return nameResult !== null &&
|
|
856
|
+
return nameResult !== null && excluded.has(nameResult.name);
|
|
827
857
|
}
|
|
828
858
|
function isUnknownBlockToken(ctx, tokenPos) {
|
|
829
859
|
const token = ctx.tokens[tokenPos];
|
|
@@ -838,6 +868,15 @@ function isUnknownBlockToken(ctx, tokenPos) {
|
|
|
838
868
|
}
|
|
839
869
|
return !KNOWN_BLOCK_NAMES.has(nameResult.name);
|
|
840
870
|
}
|
|
871
|
+
function isIndentAcceptingBlock(ctx, tokenPos) {
|
|
872
|
+
const token = ctx.tokens[tokenPos];
|
|
873
|
+
if (token?.type !== "BLOCK_OPEN" && token?.type !== "BLOCK_END_OPEN")
|
|
874
|
+
return false;
|
|
875
|
+
const nameResult = parseBlockName(ctx, tokenPos + 1);
|
|
876
|
+
if (nameResult === null)
|
|
877
|
+
return false;
|
|
878
|
+
return INDENT_ACCEPTING_BLOCK_NAMES.has(nameResult.name);
|
|
879
|
+
}
|
|
841
880
|
function canApplyInlineRule(rule, token) {
|
|
842
881
|
if (rule.startTokens.length === 0) {
|
|
843
882
|
return true;
|
|
@@ -855,9 +894,9 @@ function parseInlineUntil(ctx, endType) {
|
|
|
855
894
|
if (!token || token.type === "EOF") {
|
|
856
895
|
break;
|
|
857
896
|
}
|
|
858
|
-
if (paragraphMode && ctx.blockCloseCondition) {
|
|
897
|
+
if (paragraphMode && ctx.scope.blockCloseCondition) {
|
|
859
898
|
const checkCtx = { ...ctx, pos };
|
|
860
|
-
if (ctx.blockCloseCondition(checkCtx)) {
|
|
899
|
+
if (ctx.scope.blockCloseCondition(checkCtx)) {
|
|
861
900
|
break;
|
|
862
901
|
}
|
|
863
902
|
}
|
|
@@ -909,7 +948,7 @@ function parseInlineUntil(ctx, endType) {
|
|
|
909
948
|
skipWhitespace++;
|
|
910
949
|
}
|
|
911
950
|
const blockNameToken = ctx.tokens[afterOpen + skipWhitespace];
|
|
912
|
-
if (blockNameToken && (blockNameToken.type === "TEXT" || blockNameToken.type === "IDENTIFIER") && blockNameToken.value.toLowerCase() === "footnoteblock" && ctx.footnoteBlockParsed) {
|
|
951
|
+
if (blockNameToken && (blockNameToken.type === "TEXT" || blockNameToken.type === "IDENTIFIER") && blockNameToken.value.toLowerCase() === "footnoteblock" && ctx.scope.footnoteBlockParsed) {
|
|
913
952
|
isInvalidBlockOpen = true;
|
|
914
953
|
}
|
|
915
954
|
}
|
|
@@ -931,7 +970,8 @@ function parseInlineUntil(ctx, endType) {
|
|
|
931
970
|
}
|
|
932
971
|
const isExcludedBlock = (nextMeaningfulToken?.type === "BLOCK_OPEN" || nextMeaningfulToken?.type === "BLOCK_END_OPEN") && isExcludedBlockToken(ctx, pos + lookAhead);
|
|
933
972
|
const isUnknownBlock = (nextMeaningfulToken?.type === "BLOCK_OPEN" || nextMeaningfulToken?.type === "BLOCK_END_OPEN") && isUnknownBlockToken(ctx, pos + lookAhead);
|
|
934
|
-
const
|
|
973
|
+
const isIndentedBlockOpener = nextMeaningfulToken && (nextMeaningfulToken.type === "BLOCK_OPEN" || nextMeaningfulToken.type === "BLOCK_END_OPEN") && isIndentAcceptingBlock(ctx, pos + lookAhead);
|
|
974
|
+
const isBlockStart = nextMeaningfulToken && BLOCK_START_TOKENS.includes(nextMeaningfulToken.type) && (nextMeaningfulToken.lineStart || isIndentedBlockOpener) && !isOrphanCloseSpan && !isAnchorName && !isInvalidBlockOpen && !isInvalidHeading && !isExcludedBlock && !isUnknownBlock;
|
|
935
975
|
if (!nextMeaningfulToken || nextMeaningfulToken.type === "NEWLINE" || nextMeaningfulToken.type === "EOF" || isBlockStart) {
|
|
936
976
|
if (isBlockStart && nodes.length > 0) {
|
|
937
977
|
const nextPos = pos + lookAhead;
|
|
@@ -1309,8 +1349,11 @@ function parseBlocksUntil(ctx, closeCondition, options) {
|
|
|
1309
1349
|
...ctx,
|
|
1310
1350
|
pos,
|
|
1311
1351
|
blockRules,
|
|
1312
|
-
|
|
1313
|
-
|
|
1352
|
+
scope: {
|
|
1353
|
+
...ctx.scope,
|
|
1354
|
+
blockCloseCondition: closeCondition,
|
|
1355
|
+
excludedBlockNames: excluded
|
|
1356
|
+
}
|
|
1314
1357
|
};
|
|
1315
1358
|
for (const rule of blockRules) {
|
|
1316
1359
|
if (canApplyBlockRule(rule, token)) {
|
|
@@ -2298,15 +2341,15 @@ var divRule = {
|
|
|
2298
2341
|
if (ctx.tokens[pos]?.type !== "NEWLINE") {
|
|
2299
2342
|
return consumeFailedDiv(ctx);
|
|
2300
2343
|
}
|
|
2301
|
-
if (ctx.divClosesBudget === 0) {
|
|
2344
|
+
if (ctx.scope.divClosesBudget === 0) {
|
|
2302
2345
|
return { success: false };
|
|
2303
2346
|
}
|
|
2304
2347
|
pos++;
|
|
2305
2348
|
consumed++;
|
|
2306
2349
|
const openPosition = openToken.position;
|
|
2307
2350
|
let bodyBudget;
|
|
2308
|
-
if (ctx.divClosesBudget !== undefined) {
|
|
2309
|
-
bodyBudget = ctx.divClosesBudget - 1;
|
|
2351
|
+
if (ctx.scope.divClosesBudget !== undefined) {
|
|
2352
|
+
bodyBudget = ctx.scope.divClosesBudget - 1;
|
|
2310
2353
|
} else {
|
|
2311
2354
|
const closesInScope = countDivCloses(ctx, pos);
|
|
2312
2355
|
bodyBudget = closesInScope > 0 ? closesInScope - 1 : 0;
|
|
@@ -2321,7 +2364,11 @@ var divRule = {
|
|
|
2321
2364
|
}
|
|
2322
2365
|
return false;
|
|
2323
2366
|
};
|
|
2324
|
-
const bodyCtx = {
|
|
2367
|
+
const bodyCtx = {
|
|
2368
|
+
...ctx,
|
|
2369
|
+
pos,
|
|
2370
|
+
scope: { ...ctx.scope, divClosesBudget: bodyBudget }
|
|
2371
|
+
};
|
|
2325
2372
|
let children;
|
|
2326
2373
|
if (paragraphStrip) {
|
|
2327
2374
|
const bodyResult = parseBlocksUntil(bodyCtx, closeCondition);
|
|
@@ -3964,10 +4011,10 @@ var footnoteBlockRule = {
|
|
|
3964
4011
|
}
|
|
3965
4012
|
pos++;
|
|
3966
4013
|
consumed++;
|
|
3967
|
-
if (ctx.footnoteBlockParsed) {
|
|
4014
|
+
if (ctx.scope.footnoteBlockParsed) {
|
|
3968
4015
|
return { success: false };
|
|
3969
4016
|
}
|
|
3970
|
-
ctx.
|
|
4017
|
+
ctx.scope = { ...ctx.scope, footnoteBlockParsed: true };
|
|
3971
4018
|
const title = attrs.title !== undefined ? attrs.title : null;
|
|
3972
4019
|
const hide = attrs.hide === "true" || attrs.hide === "yes";
|
|
3973
4020
|
return {
|
|
@@ -4723,6 +4770,24 @@ var mathBlockRule = {
|
|
|
4723
4770
|
};
|
|
4724
4771
|
|
|
4725
4772
|
// packages/parser/src/parser/rules/block/html.ts
|
|
4773
|
+
function lookaheadHasHtmlClose(ctx, from) {
|
|
4774
|
+
for (let i = from;i < ctx.tokens.length; i++) {
|
|
4775
|
+
const t = ctx.tokens[i];
|
|
4776
|
+
if (!t || t.type === "EOF")
|
|
4777
|
+
return false;
|
|
4778
|
+
if (t.type !== "BLOCK_END_OPEN")
|
|
4779
|
+
continue;
|
|
4780
|
+
const closeName = parseBlockName(ctx, i + 1);
|
|
4781
|
+
if (closeName?.name.toLowerCase() !== "html")
|
|
4782
|
+
continue;
|
|
4783
|
+
let cp = i + 1 + closeName.consumed;
|
|
4784
|
+
while (ctx.tokens[cp]?.type === "WHITESPACE")
|
|
4785
|
+
cp++;
|
|
4786
|
+
if (ctx.tokens[cp]?.type === "BLOCK_CLOSE")
|
|
4787
|
+
return true;
|
|
4788
|
+
}
|
|
4789
|
+
return false;
|
|
4790
|
+
}
|
|
4726
4791
|
var htmlBlockRule = {
|
|
4727
4792
|
name: "html",
|
|
4728
4793
|
startTokens: ["BLOCK_OPEN"],
|
|
@@ -4749,20 +4814,32 @@ var htmlBlockRule = {
|
|
|
4749
4814
|
}
|
|
4750
4815
|
pos++;
|
|
4751
4816
|
consumed++;
|
|
4817
|
+
const disabled = ctx.settings.allowHtmlBlocks === false;
|
|
4818
|
+
const hasCloseAhead = disabled && lookaheadHasHtmlClose(ctx, pos);
|
|
4752
4819
|
let contents = "";
|
|
4753
4820
|
let foundClose = false;
|
|
4754
4821
|
while (pos < ctx.tokens.length) {
|
|
4755
4822
|
const token = ctx.tokens[pos];
|
|
4756
4823
|
if (!token || token.type === "EOF")
|
|
4757
4824
|
break;
|
|
4825
|
+
if (disabled && !hasCloseAhead && token.type === "NEWLINE" && ctx.tokens[pos + 1]?.type === "NEWLINE") {
|
|
4826
|
+
break;
|
|
4827
|
+
}
|
|
4758
4828
|
if (token.type === "BLOCK_END_OPEN") {
|
|
4759
4829
|
const closeNameResult = parseBlockName(ctx, pos + 1);
|
|
4760
4830
|
if (closeNameResult?.name.toLowerCase() === "html") {
|
|
4761
|
-
|
|
4762
|
-
|
|
4831
|
+
let checkPos = pos + 1 + closeNameResult.consumed;
|
|
4832
|
+
while (ctx.tokens[checkPos]?.type === "WHITESPACE")
|
|
4833
|
+
checkPos++;
|
|
4834
|
+
if (ctx.tokens[checkPos]?.type === "BLOCK_CLOSE") {
|
|
4835
|
+
foundClose = true;
|
|
4836
|
+
break;
|
|
4837
|
+
}
|
|
4763
4838
|
}
|
|
4764
4839
|
}
|
|
4765
|
-
|
|
4840
|
+
if (!disabled) {
|
|
4841
|
+
contents += token.value;
|
|
4842
|
+
}
|
|
4766
4843
|
pos++;
|
|
4767
4844
|
consumed++;
|
|
4768
4845
|
}
|
|
@@ -4773,7 +4850,16 @@ var htmlBlockRule = {
|
|
|
4773
4850
|
message: "Missing closing tag [[/html]] for [[html]]",
|
|
4774
4851
|
position: openToken.position
|
|
4775
4852
|
});
|
|
4776
|
-
|
|
4853
|
+
if (!disabled) {
|
|
4854
|
+
return { success: false };
|
|
4855
|
+
}
|
|
4856
|
+
ctx.diagnostics.push({
|
|
4857
|
+
severity: "info",
|
|
4858
|
+
code: "html-block-disabled",
|
|
4859
|
+
message: "[[html]] block ignored: disabled by settings",
|
|
4860
|
+
position: openToken.position
|
|
4861
|
+
});
|
|
4862
|
+
return { success: true, elements: [], consumed };
|
|
4777
4863
|
}
|
|
4778
4864
|
if (ctx.tokens[pos]?.type === "BLOCK_END_OPEN") {
|
|
4779
4865
|
pos++;
|
|
@@ -4783,6 +4869,10 @@ var htmlBlockRule = {
|
|
|
4783
4869
|
pos += closeNameResult.consumed;
|
|
4784
4870
|
consumed += closeNameResult.consumed;
|
|
4785
4871
|
}
|
|
4872
|
+
while (ctx.tokens[pos]?.type === "WHITESPACE") {
|
|
4873
|
+
pos++;
|
|
4874
|
+
consumed++;
|
|
4875
|
+
}
|
|
4786
4876
|
if (ctx.tokens[pos]?.type === "BLOCK_CLOSE") {
|
|
4787
4877
|
pos++;
|
|
4788
4878
|
consumed++;
|
|
@@ -4792,6 +4882,15 @@ var htmlBlockRule = {
|
|
|
4792
4882
|
consumed++;
|
|
4793
4883
|
}
|
|
4794
4884
|
}
|
|
4885
|
+
if (disabled) {
|
|
4886
|
+
ctx.diagnostics.push({
|
|
4887
|
+
severity: "info",
|
|
4888
|
+
code: "html-block-disabled",
|
|
4889
|
+
message: "[[html]] block ignored: disabled by settings",
|
|
4890
|
+
position: openToken.position
|
|
4891
|
+
});
|
|
4892
|
+
return { success: true, elements: [], consumed };
|
|
4893
|
+
}
|
|
4795
4894
|
contents = contents.trim();
|
|
4796
4895
|
ctx.htmlBlocks.push(contents);
|
|
4797
4896
|
return {
|
|
@@ -6477,6 +6576,82 @@ var commentRule = {
|
|
|
6477
6576
|
}
|
|
6478
6577
|
};
|
|
6479
6578
|
|
|
6579
|
+
// packages/parser/src/parser/rules/inline/html.ts
|
|
6580
|
+
var htmlInlineRule = {
|
|
6581
|
+
name: "html",
|
|
6582
|
+
startTokens: ["BLOCK_OPEN"],
|
|
6583
|
+
parse(ctx) {
|
|
6584
|
+
const openToken = currentToken(ctx);
|
|
6585
|
+
if (openToken.type !== "BLOCK_OPEN") {
|
|
6586
|
+
return { success: false };
|
|
6587
|
+
}
|
|
6588
|
+
let pos = ctx.pos + 1;
|
|
6589
|
+
let consumed = 1;
|
|
6590
|
+
const nameResult = parseBlockName(ctx, pos);
|
|
6591
|
+
if (!nameResult || nameResult.name.toLowerCase() !== "html") {
|
|
6592
|
+
return { success: false };
|
|
6593
|
+
}
|
|
6594
|
+
pos += nameResult.consumed;
|
|
6595
|
+
consumed += nameResult.consumed;
|
|
6596
|
+
const attrResult = parseAttributesRaw(ctx, pos);
|
|
6597
|
+
pos += attrResult.consumed;
|
|
6598
|
+
consumed += attrResult.consumed;
|
|
6599
|
+
if (ctx.tokens[pos]?.type !== "BLOCK_CLOSE") {
|
|
6600
|
+
return { success: false };
|
|
6601
|
+
}
|
|
6602
|
+
pos++;
|
|
6603
|
+
consumed++;
|
|
6604
|
+
if (ctx.settings.allowHtmlBlocks !== false) {
|
|
6605
|
+
return { success: false };
|
|
6606
|
+
}
|
|
6607
|
+
const hasCloseAhead = lookaheadHasHtmlClose(ctx, pos);
|
|
6608
|
+
let foundClose = false;
|
|
6609
|
+
while (pos < ctx.tokens.length) {
|
|
6610
|
+
const token = ctx.tokens[pos];
|
|
6611
|
+
if (!token || token.type === "EOF")
|
|
6612
|
+
break;
|
|
6613
|
+
if (!hasCloseAhead && token.type === "NEWLINE" && ctx.tokens[pos + 1]?.type === "NEWLINE") {
|
|
6614
|
+
break;
|
|
6615
|
+
}
|
|
6616
|
+
if (token.type === "BLOCK_END_OPEN") {
|
|
6617
|
+
const closeNameResult = parseBlockName(ctx, pos + 1);
|
|
6618
|
+
if (closeNameResult?.name.toLowerCase() === "html") {
|
|
6619
|
+
let checkPos = pos + 1 + closeNameResult.consumed;
|
|
6620
|
+
while (ctx.tokens[checkPos]?.type === "WHITESPACE")
|
|
6621
|
+
checkPos++;
|
|
6622
|
+
if (ctx.tokens[checkPos]?.type === "BLOCK_CLOSE") {
|
|
6623
|
+
foundClose = true;
|
|
6624
|
+
consumed += checkPos - pos + 1;
|
|
6625
|
+
pos = checkPos + 1;
|
|
6626
|
+
if (ctx.tokens[pos]?.type === "NEWLINE") {
|
|
6627
|
+
pos++;
|
|
6628
|
+
consumed++;
|
|
6629
|
+
}
|
|
6630
|
+
break;
|
|
6631
|
+
}
|
|
6632
|
+
}
|
|
6633
|
+
}
|
|
6634
|
+
pos++;
|
|
6635
|
+
consumed++;
|
|
6636
|
+
}
|
|
6637
|
+
if (!foundClose) {
|
|
6638
|
+
ctx.diagnostics.push({
|
|
6639
|
+
severity: "warning",
|
|
6640
|
+
code: "unclosed-block",
|
|
6641
|
+
message: "Missing closing tag [[/html]] for [[html]]",
|
|
6642
|
+
position: openToken.position
|
|
6643
|
+
});
|
|
6644
|
+
}
|
|
6645
|
+
ctx.diagnostics.push({
|
|
6646
|
+
severity: "info",
|
|
6647
|
+
code: "html-block-disabled",
|
|
6648
|
+
message: "[[html]] block ignored: disabled by settings",
|
|
6649
|
+
position: openToken.position
|
|
6650
|
+
});
|
|
6651
|
+
return { success: true, elements: [], consumed };
|
|
6652
|
+
}
|
|
6653
|
+
};
|
|
6654
|
+
|
|
6480
6655
|
// packages/parser/src/parser/rules/inline/raw.ts
|
|
6481
6656
|
var rawRule = {
|
|
6482
6657
|
name: "raw",
|
|
@@ -8187,6 +8362,7 @@ var inlineRules = [
|
|
|
8187
8362
|
underscoreLineBreakRule,
|
|
8188
8363
|
newlineLineBreakRule,
|
|
8189
8364
|
commentRule,
|
|
8365
|
+
htmlInlineRule,
|
|
8190
8366
|
rawRule,
|
|
8191
8367
|
imageRule,
|
|
8192
8368
|
sizeRule,
|
|
@@ -8704,83 +8880,564 @@ function buildTableOfContents(entries) {
|
|
|
8704
8880
|
return trees.map((tree) => buildTocList(indexer, tree.list));
|
|
8705
8881
|
}
|
|
8706
8882
|
|
|
8707
|
-
// packages/parser/src/parser/
|
|
8708
|
-
|
|
8709
|
-
|
|
8710
|
-
|
|
8711
|
-
|
|
8712
|
-
|
|
8713
|
-
|
|
8714
|
-
|
|
8715
|
-
|
|
8716
|
-
|
|
8717
|
-
|
|
8718
|
-
|
|
8719
|
-
|
|
8720
|
-
|
|
8721
|
-
footnoteBlockParsed: false,
|
|
8722
|
-
bibcites: [],
|
|
8723
|
-
diagnostics: [],
|
|
8724
|
-
blockRules,
|
|
8725
|
-
blockFallbackRule: paragraphRule,
|
|
8726
|
-
inlineRules
|
|
8727
|
-
};
|
|
8728
|
-
}
|
|
8729
|
-
parse() {
|
|
8730
|
-
const children = [];
|
|
8731
|
-
while (!this.isAtEnd()) {
|
|
8732
|
-
const blocks = this.parseBlock();
|
|
8733
|
-
children.push(...blocks);
|
|
8734
|
-
}
|
|
8735
|
-
const mergedChildren = mergeSpanStripParagraphs(children);
|
|
8736
|
-
const divProcessed = suppressDivAdjacentParagraphs(mergedChildren);
|
|
8737
|
-
const cleanedChildren = cleanInternalFlags(divProcessed);
|
|
8738
|
-
const hasFootnoteBlock = cleanedChildren.some((el) => el.element === "footnote-block");
|
|
8739
|
-
if (!hasFootnoteBlock) {
|
|
8740
|
-
cleanedChildren.push({
|
|
8741
|
-
element: "footnote-block",
|
|
8742
|
-
data: { title: null, hide: false }
|
|
8743
|
-
});
|
|
8883
|
+
// packages/parser/src/parser/rules/block/module/walk.ts
|
|
8884
|
+
function walkElements(elements, callback) {
|
|
8885
|
+
for (const element of elements) {
|
|
8886
|
+
callback(element);
|
|
8887
|
+
if (element.element === "list") {
|
|
8888
|
+
const listData = element.data;
|
|
8889
|
+
for (const item of listData.items) {
|
|
8890
|
+
if (item["item-type"] === "elements") {
|
|
8891
|
+
walkElements(item.elements, callback);
|
|
8892
|
+
} else if (item["item-type"] === "sub-list") {
|
|
8893
|
+
walkElements([{ element: "list", data: item.data }], callback);
|
|
8894
|
+
}
|
|
8895
|
+
}
|
|
8896
|
+
continue;
|
|
8744
8897
|
}
|
|
8745
|
-
|
|
8746
|
-
|
|
8747
|
-
|
|
8748
|
-
|
|
8749
|
-
|
|
8750
|
-
|
|
8898
|
+
if (element.element === "table") {
|
|
8899
|
+
const tableData = element.data;
|
|
8900
|
+
for (const row of tableData.rows) {
|
|
8901
|
+
for (const cell of row.cells) {
|
|
8902
|
+
walkElements(cell.elements, callback);
|
|
8903
|
+
}
|
|
8904
|
+
}
|
|
8905
|
+
continue;
|
|
8751
8906
|
}
|
|
8752
|
-
if (
|
|
8753
|
-
|
|
8907
|
+
if (element.element === "definition-list") {
|
|
8908
|
+
const defListData = element.data;
|
|
8909
|
+
for (const item of defListData) {
|
|
8910
|
+
walkElements(item.key, callback);
|
|
8911
|
+
walkElements(item.value, callback);
|
|
8912
|
+
}
|
|
8913
|
+
continue;
|
|
8754
8914
|
}
|
|
8755
|
-
if (
|
|
8756
|
-
|
|
8915
|
+
if (element.element === "tab-view") {
|
|
8916
|
+
const tabData = element.data;
|
|
8917
|
+
for (const tab of tabData) {
|
|
8918
|
+
walkElements(tab.elements, callback);
|
|
8919
|
+
}
|
|
8920
|
+
continue;
|
|
8757
8921
|
}
|
|
8758
|
-
if (
|
|
8759
|
-
|
|
8922
|
+
if ("data" in element && element.data && typeof element.data === "object") {
|
|
8923
|
+
const data = element.data;
|
|
8924
|
+
if ("elements" in data && Array.isArray(data.elements)) {
|
|
8925
|
+
walkElements(data.elements, callback);
|
|
8926
|
+
}
|
|
8760
8927
|
}
|
|
8761
|
-
return { ast: result, diagnostics: this.ctx.diagnostics };
|
|
8762
|
-
}
|
|
8763
|
-
isAtEnd() {
|
|
8764
|
-
return this.ctx.pos >= this.ctx.tokens.length || this.currentToken().type === "EOF";
|
|
8765
|
-
}
|
|
8766
|
-
currentToken() {
|
|
8767
|
-
return this.ctx.tokens[this.ctx.pos] ?? this.eofToken();
|
|
8768
8928
|
}
|
|
8769
|
-
|
|
8929
|
+
}
|
|
8930
|
+
function mapElementChildren(element, transform) {
|
|
8931
|
+
if (element.element === "list") {
|
|
8932
|
+
const listData = element.data;
|
|
8933
|
+
const newItems = [];
|
|
8934
|
+
for (const item of listData.items) {
|
|
8935
|
+
if (item["item-type"] === "elements") {
|
|
8936
|
+
newItems.push({
|
|
8937
|
+
"item-type": "elements",
|
|
8938
|
+
attributes: item.attributes,
|
|
8939
|
+
elements: transform(item.elements)
|
|
8940
|
+
});
|
|
8941
|
+
} else if (item["item-type"] === "sub-list") {
|
|
8942
|
+
const subListResult = transform([{ element: "list", data: item.data }]);
|
|
8943
|
+
const resolvedList = subListResult[0];
|
|
8944
|
+
if (resolvedList?.element === "list") {
|
|
8945
|
+
newItems.push({
|
|
8946
|
+
"item-type": "sub-list",
|
|
8947
|
+
element: "list",
|
|
8948
|
+
data: resolvedList.data
|
|
8949
|
+
});
|
|
8950
|
+
} else {
|
|
8951
|
+
newItems.push(item);
|
|
8952
|
+
}
|
|
8953
|
+
}
|
|
8954
|
+
}
|
|
8770
8955
|
return {
|
|
8771
|
-
|
|
8772
|
-
|
|
8773
|
-
position: {
|
|
8774
|
-
start: { line: 0, column: 0, offset: 0 },
|
|
8775
|
-
end: { line: 0, column: 0, offset: 0 }
|
|
8776
|
-
},
|
|
8777
|
-
lineStart: false
|
|
8956
|
+
element: "list",
|
|
8957
|
+
data: { ...listData, items: newItems }
|
|
8778
8958
|
};
|
|
8779
8959
|
}
|
|
8780
|
-
|
|
8781
|
-
|
|
8782
|
-
|
|
8783
|
-
|
|
8960
|
+
if (element.element === "table") {
|
|
8961
|
+
const tableData = element.data;
|
|
8962
|
+
const newRows = [];
|
|
8963
|
+
for (const row of tableData.rows) {
|
|
8964
|
+
const newCells = [];
|
|
8965
|
+
for (const cell of row.cells) {
|
|
8966
|
+
newCells.push({ ...cell, elements: transform(cell.elements) });
|
|
8967
|
+
}
|
|
8968
|
+
newRows.push({ ...row, cells: newCells });
|
|
8969
|
+
}
|
|
8970
|
+
return {
|
|
8971
|
+
element: "table",
|
|
8972
|
+
data: { ...tableData, rows: newRows }
|
|
8973
|
+
};
|
|
8974
|
+
}
|
|
8975
|
+
if (element.element === "definition-list") {
|
|
8976
|
+
const defListData = element.data;
|
|
8977
|
+
const newItems = [];
|
|
8978
|
+
for (const item of defListData) {
|
|
8979
|
+
newItems.push({
|
|
8980
|
+
key_string: item.key_string,
|
|
8981
|
+
key: transform(item.key),
|
|
8982
|
+
value: transform(item.value)
|
|
8983
|
+
});
|
|
8984
|
+
}
|
|
8985
|
+
return {
|
|
8986
|
+
element: "definition-list",
|
|
8987
|
+
data: newItems
|
|
8988
|
+
};
|
|
8989
|
+
}
|
|
8990
|
+
if (element.element === "tab-view") {
|
|
8991
|
+
const tabData = element.data;
|
|
8992
|
+
const newTabs = [];
|
|
8993
|
+
for (const tab of tabData) {
|
|
8994
|
+
newTabs.push({ ...tab, elements: transform(tab.elements) });
|
|
8995
|
+
}
|
|
8996
|
+
return {
|
|
8997
|
+
element: "tab-view",
|
|
8998
|
+
data: newTabs
|
|
8999
|
+
};
|
|
9000
|
+
}
|
|
9001
|
+
if ("data" in element && element.data && typeof element.data === "object") {
|
|
9002
|
+
const data = element.data;
|
|
9003
|
+
if ("elements" in data && Array.isArray(data.elements)) {
|
|
9004
|
+
return {
|
|
9005
|
+
...element,
|
|
9006
|
+
data: {
|
|
9007
|
+
...data,
|
|
9008
|
+
elements: transform(data.elements)
|
|
9009
|
+
}
|
|
9010
|
+
};
|
|
9011
|
+
}
|
|
9012
|
+
}
|
|
9013
|
+
return element;
|
|
9014
|
+
}
|
|
9015
|
+
function mapElementChildrenWithState(element, state, transform) {
|
|
9016
|
+
if (element.element === "list") {
|
|
9017
|
+
const listData = element.data;
|
|
9018
|
+
const newItems = [];
|
|
9019
|
+
let currentState = state;
|
|
9020
|
+
for (const item of listData.items) {
|
|
9021
|
+
if (item["item-type"] === "elements") {
|
|
9022
|
+
const result = transform(item.elements, currentState);
|
|
9023
|
+
newItems.push({
|
|
9024
|
+
"item-type": "elements",
|
|
9025
|
+
attributes: item.attributes,
|
|
9026
|
+
elements: result.elements
|
|
9027
|
+
});
|
|
9028
|
+
currentState = result.state;
|
|
9029
|
+
} else if (item["item-type"] === "sub-list") {
|
|
9030
|
+
const result = transform([{ element: "list", data: item.data }], currentState);
|
|
9031
|
+
const resolvedList = result.elements[0];
|
|
9032
|
+
if (resolvedList?.element === "list") {
|
|
9033
|
+
newItems.push({
|
|
9034
|
+
"item-type": "sub-list",
|
|
9035
|
+
element: "list",
|
|
9036
|
+
data: resolvedList.data
|
|
9037
|
+
});
|
|
9038
|
+
} else {
|
|
9039
|
+
newItems.push(item);
|
|
9040
|
+
}
|
|
9041
|
+
currentState = result.state;
|
|
9042
|
+
}
|
|
9043
|
+
}
|
|
9044
|
+
return {
|
|
9045
|
+
element: {
|
|
9046
|
+
element: "list",
|
|
9047
|
+
data: { ...listData, items: newItems }
|
|
9048
|
+
},
|
|
9049
|
+
state: currentState
|
|
9050
|
+
};
|
|
9051
|
+
}
|
|
9052
|
+
if (element.element === "table") {
|
|
9053
|
+
const tableData = element.data;
|
|
9054
|
+
const newRows = [];
|
|
9055
|
+
let currentState = state;
|
|
9056
|
+
for (const row of tableData.rows) {
|
|
9057
|
+
const newCells = [];
|
|
9058
|
+
for (const cell of row.cells) {
|
|
9059
|
+
const result = transform(cell.elements, currentState);
|
|
9060
|
+
newCells.push({ ...cell, elements: result.elements });
|
|
9061
|
+
currentState = result.state;
|
|
9062
|
+
}
|
|
9063
|
+
newRows.push({ ...row, cells: newCells });
|
|
9064
|
+
}
|
|
9065
|
+
return {
|
|
9066
|
+
element: {
|
|
9067
|
+
element: "table",
|
|
9068
|
+
data: { ...tableData, rows: newRows }
|
|
9069
|
+
},
|
|
9070
|
+
state: currentState
|
|
9071
|
+
};
|
|
9072
|
+
}
|
|
9073
|
+
if (element.element === "definition-list") {
|
|
9074
|
+
const defListData = element.data;
|
|
9075
|
+
const newItems = [];
|
|
9076
|
+
let currentState = state;
|
|
9077
|
+
for (const item of defListData) {
|
|
9078
|
+
const keyResult = transform(item.key, currentState);
|
|
9079
|
+
currentState = keyResult.state;
|
|
9080
|
+
const valueResult = transform(item.value, currentState);
|
|
9081
|
+
currentState = valueResult.state;
|
|
9082
|
+
newItems.push({
|
|
9083
|
+
key_string: item.key_string,
|
|
9084
|
+
key: keyResult.elements,
|
|
9085
|
+
value: valueResult.elements
|
|
9086
|
+
});
|
|
9087
|
+
}
|
|
9088
|
+
return {
|
|
9089
|
+
element: {
|
|
9090
|
+
element: "definition-list",
|
|
9091
|
+
data: newItems
|
|
9092
|
+
},
|
|
9093
|
+
state: currentState
|
|
9094
|
+
};
|
|
9095
|
+
}
|
|
9096
|
+
if (element.element === "tab-view") {
|
|
9097
|
+
const tabData = element.data;
|
|
9098
|
+
const newTabs = [];
|
|
9099
|
+
let currentState = state;
|
|
9100
|
+
for (const tab of tabData) {
|
|
9101
|
+
const result = transform(tab.elements, currentState);
|
|
9102
|
+
newTabs.push({ ...tab, elements: result.elements });
|
|
9103
|
+
currentState = result.state;
|
|
9104
|
+
}
|
|
9105
|
+
return {
|
|
9106
|
+
element: {
|
|
9107
|
+
element: "tab-view",
|
|
9108
|
+
data: newTabs
|
|
9109
|
+
},
|
|
9110
|
+
state: currentState
|
|
9111
|
+
};
|
|
9112
|
+
}
|
|
9113
|
+
if ("data" in element && element.data && typeof element.data === "object") {
|
|
9114
|
+
const data = element.data;
|
|
9115
|
+
if ("elements" in data && Array.isArray(data.elements)) {
|
|
9116
|
+
const result = transform(data.elements, state);
|
|
9117
|
+
return {
|
|
9118
|
+
element: {
|
|
9119
|
+
...element,
|
|
9120
|
+
data: {
|
|
9121
|
+
...data,
|
|
9122
|
+
elements: result.elements
|
|
9123
|
+
}
|
|
9124
|
+
},
|
|
9125
|
+
state: result.state
|
|
9126
|
+
};
|
|
9127
|
+
}
|
|
9128
|
+
}
|
|
9129
|
+
return { element, state };
|
|
9130
|
+
}
|
|
9131
|
+
|
|
9132
|
+
// packages/parser/src/parser/rules/block/module/iftags/condition.ts
|
|
9133
|
+
function parseTagCondition(condition) {
|
|
9134
|
+
const required = [];
|
|
9135
|
+
const forbidden = [];
|
|
9136
|
+
const optional = [];
|
|
9137
|
+
const parts = condition.trim().split(/\s+/);
|
|
9138
|
+
for (const part of parts) {
|
|
9139
|
+
if (!part)
|
|
9140
|
+
continue;
|
|
9141
|
+
if (part.startsWith("+")) {
|
|
9142
|
+
const tag = part.slice(1);
|
|
9143
|
+
if (tag)
|
|
9144
|
+
required.push(tag);
|
|
9145
|
+
} else if (part.startsWith("-")) {
|
|
9146
|
+
const tag = part.slice(1);
|
|
9147
|
+
if (tag)
|
|
9148
|
+
forbidden.push(tag);
|
|
9149
|
+
} else {
|
|
9150
|
+
optional.push(part);
|
|
9151
|
+
}
|
|
9152
|
+
}
|
|
9153
|
+
return { required, forbidden, optional };
|
|
9154
|
+
}
|
|
9155
|
+
function evaluateTagCondition(condition, pageTags) {
|
|
9156
|
+
if (condition.required.length === 0 && condition.forbidden.length === 0 && condition.optional.length === 0) {
|
|
9157
|
+
return false;
|
|
9158
|
+
}
|
|
9159
|
+
const tagSet = new Set(pageTags);
|
|
9160
|
+
for (const tag of condition.required) {
|
|
9161
|
+
if (!tagSet.has(tag)) {
|
|
9162
|
+
return false;
|
|
9163
|
+
}
|
|
9164
|
+
}
|
|
9165
|
+
for (const tag of condition.forbidden) {
|
|
9166
|
+
if (tagSet.has(tag)) {
|
|
9167
|
+
return false;
|
|
9168
|
+
}
|
|
9169
|
+
}
|
|
9170
|
+
if (condition.optional.length > 0) {
|
|
9171
|
+
if (!condition.optional.some((tag) => tagSet.has(tag))) {
|
|
9172
|
+
return false;
|
|
9173
|
+
}
|
|
9174
|
+
}
|
|
9175
|
+
return true;
|
|
9176
|
+
}
|
|
9177
|
+
|
|
9178
|
+
// packages/parser/src/parser/rules/block/module/iftags/preprocess.ts
|
|
9179
|
+
var BASE_PLACEHOLDER_OPEN = "";
|
|
9180
|
+
var BASE_PLACEHOLDER_CLOSE = "";
|
|
9181
|
+
var INNERMOST_IFTAGS_PATTERN = /\[\[\s*iftags\b([^\]]*)\]\]((?:(?!\[\[\s*iftags\b|\[\[\/\s*iftags\s*\]\]).)*)\[\[\/\s*iftags\s*\]\]/gis;
|
|
9182
|
+
var RAW_BLOCK_OPEN_PATTERN = /\[\[\s*(code|html)\b[^\]]*\]\]/iy;
|
|
9183
|
+
function preprocessIftags(source, pageTags) {
|
|
9184
|
+
if (!source.includes("[["))
|
|
9185
|
+
return source;
|
|
9186
|
+
const sentinels = makeUniqueSentinels(source);
|
|
9187
|
+
const { masked, placeholders } = maskRawRegions(source, sentinels);
|
|
9188
|
+
const reduced = reduceIftags(masked, pageTags);
|
|
9189
|
+
return restorePlaceholders(reduced, placeholders, sentinels);
|
|
9190
|
+
}
|
|
9191
|
+
function makeUniqueSentinels(source) {
|
|
9192
|
+
let open = BASE_PLACEHOLDER_OPEN;
|
|
9193
|
+
let close = BASE_PLACEHOLDER_CLOSE;
|
|
9194
|
+
while (source.includes(open) || source.includes(close)) {
|
|
9195
|
+
open += BASE_PLACEHOLDER_OPEN;
|
|
9196
|
+
close += BASE_PLACEHOLDER_CLOSE;
|
|
9197
|
+
}
|
|
9198
|
+
return { open, close };
|
|
9199
|
+
}
|
|
9200
|
+
function reduceIftags(source, pageTags) {
|
|
9201
|
+
let current = source;
|
|
9202
|
+
const maxIterations = source.length + 1;
|
|
9203
|
+
const tagSet = pageTags ?? [];
|
|
9204
|
+
for (let i = 0;i < maxIterations; i++) {
|
|
9205
|
+
const depths = pageTags === null ? computeBracketDepths(current) : null;
|
|
9206
|
+
let changed = false;
|
|
9207
|
+
const next = current.replace(INNERMOST_IFTAGS_PATTERN, (match, cond, body, offset) => {
|
|
9208
|
+
if (depths !== null && depths[offset] === 0) {
|
|
9209
|
+
return match;
|
|
9210
|
+
}
|
|
9211
|
+
changed = true;
|
|
9212
|
+
const condition = parseTagCondition(cond);
|
|
9213
|
+
return evaluateTagCondition(condition, tagSet) ? body : "";
|
|
9214
|
+
});
|
|
9215
|
+
if (!changed)
|
|
9216
|
+
return current;
|
|
9217
|
+
current = next;
|
|
9218
|
+
}
|
|
9219
|
+
return current;
|
|
9220
|
+
}
|
|
9221
|
+
function computeBracketDepths(masked) {
|
|
9222
|
+
const n = masked.length;
|
|
9223
|
+
const depths = new Int32Array(n + 1);
|
|
9224
|
+
let depth = 0;
|
|
9225
|
+
let i = 0;
|
|
9226
|
+
while (i < n) {
|
|
9227
|
+
depths[i] = depth;
|
|
9228
|
+
const c = masked.charCodeAt(i);
|
|
9229
|
+
const c1 = i + 1 < n ? masked.charCodeAt(i + 1) : -1;
|
|
9230
|
+
const c2 = i + 2 < n ? masked.charCodeAt(i + 2) : -1;
|
|
9231
|
+
if (depth > 0 && c === 34 && precededByEqualsAttr(masked, i)) {
|
|
9232
|
+
const end = findQuoteEnd(masked, i + 1);
|
|
9233
|
+
for (let k = i;k <= end; k++)
|
|
9234
|
+
depths[k] = depth;
|
|
9235
|
+
i = end + 1;
|
|
9236
|
+
continue;
|
|
9237
|
+
}
|
|
9238
|
+
if (c === 91 && c1 === 91 && c2 === 91) {
|
|
9239
|
+
const end = findTripleLinkEnd(masked, i + 3);
|
|
9240
|
+
for (let k = i;k <= end; k++)
|
|
9241
|
+
depths[k] = depth;
|
|
9242
|
+
i = end + 1;
|
|
9243
|
+
continue;
|
|
9244
|
+
}
|
|
9245
|
+
if (c === 91 && c1 === 91) {
|
|
9246
|
+
depth++;
|
|
9247
|
+
depths[i + 1] = depth;
|
|
9248
|
+
i += 2;
|
|
9249
|
+
continue;
|
|
9250
|
+
}
|
|
9251
|
+
if (c === 93 && c1 === 93) {
|
|
9252
|
+
depth = Math.max(0, depth - 1);
|
|
9253
|
+
depths[i + 1] = depth;
|
|
9254
|
+
i += 2;
|
|
9255
|
+
continue;
|
|
9256
|
+
}
|
|
9257
|
+
if (c === 10) {
|
|
9258
|
+
depth = 0;
|
|
9259
|
+
}
|
|
9260
|
+
i++;
|
|
9261
|
+
}
|
|
9262
|
+
depths[n] = depth;
|
|
9263
|
+
return depths;
|
|
9264
|
+
}
|
|
9265
|
+
function precededByEqualsAttr(s, i) {
|
|
9266
|
+
let j = i - 1;
|
|
9267
|
+
while (j >= 0) {
|
|
9268
|
+
const ch = s.charCodeAt(j);
|
|
9269
|
+
if (ch === 32 || ch === 9) {
|
|
9270
|
+
j--;
|
|
9271
|
+
continue;
|
|
9272
|
+
}
|
|
9273
|
+
return ch === 61;
|
|
9274
|
+
}
|
|
9275
|
+
return false;
|
|
9276
|
+
}
|
|
9277
|
+
function findQuoteEnd(s, from) {
|
|
9278
|
+
for (let i = from;i < s.length; i++) {
|
|
9279
|
+
const ch = s.charCodeAt(i);
|
|
9280
|
+
if (ch === 34 || ch === 10)
|
|
9281
|
+
return i;
|
|
9282
|
+
}
|
|
9283
|
+
return s.length - 1;
|
|
9284
|
+
}
|
|
9285
|
+
function findTripleLinkEnd(s, from) {
|
|
9286
|
+
for (let i = from;i < s.length; i++) {
|
|
9287
|
+
if (s.charCodeAt(i) === 93 && i + 2 < s.length && s.charCodeAt(i + 1) === 93 && s.charCodeAt(i + 2) === 93) {
|
|
9288
|
+
return i + 2;
|
|
9289
|
+
}
|
|
9290
|
+
if (s.charCodeAt(i) === 10 && i + 1 < s.length && s.charCodeAt(i + 1) === 10) {
|
|
9291
|
+
return i;
|
|
9292
|
+
}
|
|
9293
|
+
}
|
|
9294
|
+
return s.length - 1;
|
|
9295
|
+
}
|
|
9296
|
+
function maskRawRegions(source, sentinels) {
|
|
9297
|
+
const placeholders = [];
|
|
9298
|
+
let masked = "";
|
|
9299
|
+
let i = 0;
|
|
9300
|
+
while (i < source.length) {
|
|
9301
|
+
if (source[i] === "[" && source[i + 1] === "[") {
|
|
9302
|
+
RAW_BLOCK_OPEN_PATTERN.lastIndex = i;
|
|
9303
|
+
const openMatch = RAW_BLOCK_OPEN_PATTERN.exec(source);
|
|
9304
|
+
if (openMatch) {
|
|
9305
|
+
const name = openMatch[1].toLowerCase();
|
|
9306
|
+
const openLen = openMatch[0].length;
|
|
9307
|
+
const closePattern = new RegExp(`\\[\\[\\/\\s*${name}\\s*\\]\\]`, "ig");
|
|
9308
|
+
closePattern.lastIndex = i + openLen;
|
|
9309
|
+
const closeMatch = closePattern.exec(source);
|
|
9310
|
+
if (closeMatch) {
|
|
9311
|
+
const regionEnd = closeMatch.index + closeMatch[0].length;
|
|
9312
|
+
masked += pushPlaceholder(placeholders, source.slice(i, regionEnd), sentinels);
|
|
9313
|
+
i = regionEnd;
|
|
9314
|
+
continue;
|
|
9315
|
+
}
|
|
9316
|
+
if (name === "code") {
|
|
9317
|
+
masked += pushPlaceholder(placeholders, source.slice(i), sentinels);
|
|
9318
|
+
i = source.length;
|
|
9319
|
+
continue;
|
|
9320
|
+
}
|
|
9321
|
+
}
|
|
9322
|
+
}
|
|
9323
|
+
if (source[i] === "@" && source[i + 1] === "<") {
|
|
9324
|
+
const close = source.indexOf(">@", i + 2);
|
|
9325
|
+
const newline = source.indexOf(`
|
|
9326
|
+
`, i + 2);
|
|
9327
|
+
if (close !== -1 && (newline === -1 || close < newline)) {
|
|
9328
|
+
const regionEnd = close + 2;
|
|
9329
|
+
masked += pushPlaceholder(placeholders, source.slice(i, regionEnd), sentinels);
|
|
9330
|
+
i = regionEnd;
|
|
9331
|
+
continue;
|
|
9332
|
+
}
|
|
9333
|
+
}
|
|
9334
|
+
if (source[i] === "@" && source[i + 1] === "@") {
|
|
9335
|
+
const close = source.indexOf("@@", i + 2);
|
|
9336
|
+
const newline = source.indexOf(`
|
|
9337
|
+
`, i + 2);
|
|
9338
|
+
if (close !== -1 && (newline === -1 || close < newline)) {
|
|
9339
|
+
const regionEnd = close + 2;
|
|
9340
|
+
masked += pushPlaceholder(placeholders, source.slice(i, regionEnd), sentinels);
|
|
9341
|
+
i = regionEnd;
|
|
9342
|
+
continue;
|
|
9343
|
+
}
|
|
9344
|
+
}
|
|
9345
|
+
masked += source[i];
|
|
9346
|
+
i++;
|
|
9347
|
+
}
|
|
9348
|
+
return { masked, placeholders };
|
|
9349
|
+
}
|
|
9350
|
+
function pushPlaceholder(placeholders, text, sentinels) {
|
|
9351
|
+
const idx = placeholders.length;
|
|
9352
|
+
placeholders.push(text);
|
|
9353
|
+
return `${sentinels.open}${idx}${sentinels.close}`;
|
|
9354
|
+
}
|
|
9355
|
+
function escapeRegex(str) {
|
|
9356
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
9357
|
+
}
|
|
9358
|
+
function restorePlaceholders(source, placeholders, sentinels) {
|
|
9359
|
+
const pattern = new RegExp(`${escapeRegex(sentinels.open)}(\\d+)${escapeRegex(sentinels.close)}`, "g");
|
|
9360
|
+
return source.replace(pattern, (_, idx) => placeholders[Number(idx)] ?? "");
|
|
9361
|
+
}
|
|
9362
|
+
|
|
9363
|
+
// packages/parser/src/parser/parse.ts
|
|
9364
|
+
class Parser {
|
|
9365
|
+
ctx;
|
|
9366
|
+
constructor(tokens, options = {}) {
|
|
9367
|
+
this.ctx = {
|
|
9368
|
+
tokens,
|
|
9369
|
+
pos: 0,
|
|
9370
|
+
version: options.version ?? "wikidot",
|
|
9371
|
+
trackPositions: options.trackPositions ?? true,
|
|
9372
|
+
settings: options.settings ?? import_ast2.DEFAULT_SETTINGS,
|
|
9373
|
+
footnotes: [],
|
|
9374
|
+
tocEntries: [],
|
|
9375
|
+
codeBlocks: [],
|
|
9376
|
+
htmlBlocks: [],
|
|
9377
|
+
bibcites: [],
|
|
9378
|
+
diagnostics: [],
|
|
9379
|
+
blockRules,
|
|
9380
|
+
blockFallbackRule: paragraphRule,
|
|
9381
|
+
inlineRules,
|
|
9382
|
+
scope: {
|
|
9383
|
+
footnoteBlockParsed: false
|
|
9384
|
+
}
|
|
9385
|
+
};
|
|
9386
|
+
}
|
|
9387
|
+
parse() {
|
|
9388
|
+
const children = [];
|
|
9389
|
+
while (!this.isAtEnd()) {
|
|
9390
|
+
const blocks = this.parseBlock();
|
|
9391
|
+
children.push(...blocks);
|
|
9392
|
+
}
|
|
9393
|
+
const mergedChildren = mergeSpanStripParagraphs(children);
|
|
9394
|
+
const divProcessed = suppressDivAdjacentParagraphs(mergedChildren);
|
|
9395
|
+
const cleanedChildren = cleanInternalFlags(divProcessed);
|
|
9396
|
+
if (!containsFootnoteBlock(cleanedChildren)) {
|
|
9397
|
+
cleanedChildren.push({
|
|
9398
|
+
element: "footnote-block",
|
|
9399
|
+
data: { title: null, hide: false }
|
|
9400
|
+
});
|
|
9401
|
+
}
|
|
9402
|
+
const tableOfContents = buildTableOfContents(this.ctx.tocEntries);
|
|
9403
|
+
const result = {
|
|
9404
|
+
elements: cleanedChildren
|
|
9405
|
+
};
|
|
9406
|
+
if (tableOfContents.length > 0) {
|
|
9407
|
+
result["table-of-contents"] = tableOfContents;
|
|
9408
|
+
}
|
|
9409
|
+
if (this.ctx.footnotes.length > 0) {
|
|
9410
|
+
result.footnotes = this.ctx.footnotes;
|
|
9411
|
+
}
|
|
9412
|
+
if (this.ctx.codeBlocks.length > 0) {
|
|
9413
|
+
result["code-blocks"] = this.ctx.codeBlocks;
|
|
9414
|
+
}
|
|
9415
|
+
if (this.ctx.htmlBlocks.length > 0) {
|
|
9416
|
+
result["html-blocks"] = this.ctx.htmlBlocks;
|
|
9417
|
+
}
|
|
9418
|
+
return { ast: result, diagnostics: this.ctx.diagnostics };
|
|
9419
|
+
}
|
|
9420
|
+
isAtEnd() {
|
|
9421
|
+
return this.ctx.pos >= this.ctx.tokens.length || this.currentToken().type === "EOF";
|
|
9422
|
+
}
|
|
9423
|
+
currentToken() {
|
|
9424
|
+
return this.ctx.tokens[this.ctx.pos] ?? this.eofToken();
|
|
9425
|
+
}
|
|
9426
|
+
eofToken() {
|
|
9427
|
+
return {
|
|
9428
|
+
type: "EOF",
|
|
9429
|
+
value: "",
|
|
9430
|
+
position: {
|
|
9431
|
+
start: { line: 0, column: 0, offset: 0 },
|
|
9432
|
+
end: { line: 0, column: 0, offset: 0 }
|
|
9433
|
+
},
|
|
9434
|
+
lineStart: false
|
|
9435
|
+
};
|
|
9436
|
+
}
|
|
9437
|
+
skipWhitespace() {
|
|
9438
|
+
while (this.currentToken().type === "WHITESPACE") {
|
|
9439
|
+
this.ctx.pos++;
|
|
9440
|
+
}
|
|
8784
9441
|
}
|
|
8785
9442
|
parseBlock() {
|
|
8786
9443
|
this.skipWhitespace();
|
|
@@ -8811,10 +9468,19 @@ class Parser {
|
|
|
8811
9468
|
}
|
|
8812
9469
|
}
|
|
8813
9470
|
function parse(source, options) {
|
|
8814
|
-
const
|
|
9471
|
+
const iftagsProcessed = options?.pageTags !== undefined ? preprocessIftags(source, options.pageTags) : source;
|
|
9472
|
+
const preprocessed = preprocess(iftagsProcessed);
|
|
8815
9473
|
const tokens = tokenize(preprocessed, { trackPositions: options?.trackPositions });
|
|
8816
9474
|
return new Parser(tokens, options).parse();
|
|
8817
9475
|
}
|
|
9476
|
+
function containsFootnoteBlock(elements) {
|
|
9477
|
+
let found = false;
|
|
9478
|
+
walkElements(elements, (el) => {
|
|
9479
|
+
if (el.element === "footnote-block")
|
|
9480
|
+
found = true;
|
|
9481
|
+
});
|
|
9482
|
+
return found;
|
|
9483
|
+
}
|
|
8818
9484
|
// packages/parser/src/parser/rules/block/module/listpages/compiler.ts
|
|
8819
9485
|
var DEFAULT_PREVIEW_LENGTH = 200;
|
|
8820
9486
|
var VARIABLE_REGEX = /%%([a-z_]+)(?:\{([^}]+)\})?(?:\((\d+)\))?(?:\|([^%]*(?:%(?!%)[^%]*)*))?%%/gi;
|
|
@@ -9036,334 +9702,85 @@ function strftime(date, format) {
|
|
|
9036
9702
|
return MONTHS[date.getMonth()] ?? "";
|
|
9037
9703
|
case "a":
|
|
9038
9704
|
return DAYS_SHORT[date.getDay()] ?? "";
|
|
9039
|
-
case "A":
|
|
9040
|
-
return DAYS[date.getDay()] ?? "";
|
|
9041
|
-
case "w":
|
|
9042
|
-
return String(date.getDay());
|
|
9043
|
-
case "j":
|
|
9044
|
-
return pad(getDayOfYear(date), 3);
|
|
9045
|
-
case "Z":
|
|
9046
|
-
return "UTC";
|
|
9047
|
-
case "z":
|
|
9048
|
-
return "+0000";
|
|
9049
|
-
case "%":
|
|
9050
|
-
return "%";
|
|
9051
|
-
default:
|
|
9052
|
-
return `%${token}`;
|
|
9053
|
-
}
|
|
9054
|
-
});
|
|
9055
|
-
}
|
|
9056
|
-
function getDayOfYear(date) {
|
|
9057
|
-
const start = new Date(date.getFullYear(), 0, 0);
|
|
9058
|
-
const diff = date.getTime() - start.getTime();
|
|
9059
|
-
const oneDay = 1000 * 60 * 60 * 24;
|
|
9060
|
-
return Math.floor(diff / oneDay);
|
|
9061
|
-
}
|
|
9062
|
-
|
|
9063
|
-
// packages/parser/src/parser/rules/block/module/listusers/compiler.ts
|
|
9064
|
-
var VARIABLE_REGEX2 = /%%([a-z_]+)%%/gi;
|
|
9065
|
-
function compileListUsersTemplate(template) {
|
|
9066
|
-
const parts = [];
|
|
9067
|
-
let lastIndex = 0;
|
|
9068
|
-
for (const match of template.matchAll(VARIABLE_REGEX2)) {
|
|
9069
|
-
if (match.index !== undefined && match.index > lastIndex) {
|
|
9070
|
-
parts.push(template.slice(lastIndex, match.index));
|
|
9071
|
-
}
|
|
9072
|
-
const [, varName] = match;
|
|
9073
|
-
if (!varName)
|
|
9074
|
-
continue;
|
|
9075
|
-
const getter = createVariableGetter2(varName.toLowerCase());
|
|
9076
|
-
parts.push(getter);
|
|
9077
|
-
lastIndex = match.index !== undefined ? match.index + match[0].length : lastIndex;
|
|
9078
|
-
}
|
|
9079
|
-
if (lastIndex < template.length) {
|
|
9080
|
-
parts.push(template.slice(lastIndex));
|
|
9081
|
-
}
|
|
9082
|
-
return (ctx) => {
|
|
9083
|
-
let result = "";
|
|
9084
|
-
for (const part of parts) {
|
|
9085
|
-
result += typeof part === "string" ? part : part(ctx);
|
|
9086
|
-
}
|
|
9087
|
-
return result;
|
|
9088
|
-
};
|
|
9089
|
-
}
|
|
9090
|
-
function createVariableGetter2(name) {
|
|
9091
|
-
switch (name) {
|
|
9092
|
-
case "number":
|
|
9093
|
-
return (ctx) => String(ctx.user.number);
|
|
9094
|
-
case "title":
|
|
9095
|
-
return (ctx) => ctx.user.title;
|
|
9096
|
-
case "name":
|
|
9097
|
-
return (ctx) => ctx.user.name;
|
|
9098
|
-
default:
|
|
9099
|
-
return () => "";
|
|
9100
|
-
}
|
|
9101
|
-
}
|
|
9102
|
-
|
|
9103
|
-
// packages/parser/src/parser/rules/block/module/listusers/extract.ts
|
|
9104
|
-
var VARIABLE_REGEX3 = /%%([a-z_]+)%%/gi;
|
|
9105
|
-
var KNOWN_VARIABLES = ["number", "title", "name"];
|
|
9106
|
-
function extractListUsersVariables(template) {
|
|
9107
|
-
const variables = new Set;
|
|
9108
|
-
for (const match of template.matchAll(VARIABLE_REGEX3)) {
|
|
9109
|
-
const [, varName] = match;
|
|
9110
|
-
if (!varName)
|
|
9111
|
-
continue;
|
|
9112
|
-
const normalized = varName.toLowerCase();
|
|
9113
|
-
if (KNOWN_VARIABLES.includes(normalized)) {
|
|
9114
|
-
variables.add(normalized);
|
|
9115
|
-
}
|
|
9116
|
-
}
|
|
9117
|
-
return Array.from(variables);
|
|
9118
|
-
}
|
|
9119
|
-
|
|
9120
|
-
// packages/parser/src/parser/rules/block/module/walk.ts
|
|
9121
|
-
function walkElements(elements, callback) {
|
|
9122
|
-
for (const element of elements) {
|
|
9123
|
-
callback(element);
|
|
9124
|
-
if (element.element === "list") {
|
|
9125
|
-
const listData = element.data;
|
|
9126
|
-
for (const item of listData.items) {
|
|
9127
|
-
if (item["item-type"] === "elements") {
|
|
9128
|
-
walkElements(item.elements, callback);
|
|
9129
|
-
} else if (item["item-type"] === "sub-list") {
|
|
9130
|
-
walkElements([{ element: "list", data: item.data }], callback);
|
|
9131
|
-
}
|
|
9132
|
-
}
|
|
9133
|
-
continue;
|
|
9134
|
-
}
|
|
9135
|
-
if (element.element === "table") {
|
|
9136
|
-
const tableData = element.data;
|
|
9137
|
-
for (const row of tableData.rows) {
|
|
9138
|
-
for (const cell of row.cells) {
|
|
9139
|
-
walkElements(cell.elements, callback);
|
|
9140
|
-
}
|
|
9141
|
-
}
|
|
9142
|
-
continue;
|
|
9143
|
-
}
|
|
9144
|
-
if (element.element === "definition-list") {
|
|
9145
|
-
const defListData = element.data;
|
|
9146
|
-
for (const item of defListData) {
|
|
9147
|
-
walkElements(item.key, callback);
|
|
9148
|
-
walkElements(item.value, callback);
|
|
9149
|
-
}
|
|
9150
|
-
continue;
|
|
9151
|
-
}
|
|
9152
|
-
if (element.element === "tab-view") {
|
|
9153
|
-
const tabData = element.data;
|
|
9154
|
-
for (const tab of tabData) {
|
|
9155
|
-
walkElements(tab.elements, callback);
|
|
9156
|
-
}
|
|
9157
|
-
continue;
|
|
9158
|
-
}
|
|
9159
|
-
if ("data" in element && element.data && typeof element.data === "object") {
|
|
9160
|
-
const data = element.data;
|
|
9161
|
-
if ("elements" in data && Array.isArray(data.elements)) {
|
|
9162
|
-
walkElements(data.elements, callback);
|
|
9163
|
-
}
|
|
9164
|
-
}
|
|
9165
|
-
}
|
|
9166
|
-
}
|
|
9167
|
-
function mapElementChildren(element, transform) {
|
|
9168
|
-
if (element.element === "list") {
|
|
9169
|
-
const listData = element.data;
|
|
9170
|
-
const newItems = [];
|
|
9171
|
-
for (const item of listData.items) {
|
|
9172
|
-
if (item["item-type"] === "elements") {
|
|
9173
|
-
newItems.push({
|
|
9174
|
-
"item-type": "elements",
|
|
9175
|
-
attributes: item.attributes,
|
|
9176
|
-
elements: transform(item.elements)
|
|
9177
|
-
});
|
|
9178
|
-
} else if (item["item-type"] === "sub-list") {
|
|
9179
|
-
const subListResult = transform([{ element: "list", data: item.data }]);
|
|
9180
|
-
const resolvedList = subListResult[0];
|
|
9181
|
-
if (resolvedList?.element === "list") {
|
|
9182
|
-
newItems.push({
|
|
9183
|
-
"item-type": "sub-list",
|
|
9184
|
-
element: "list",
|
|
9185
|
-
data: resolvedList.data
|
|
9186
|
-
});
|
|
9187
|
-
} else {
|
|
9188
|
-
newItems.push(item);
|
|
9189
|
-
}
|
|
9190
|
-
}
|
|
9191
|
-
}
|
|
9192
|
-
return {
|
|
9193
|
-
element: "list",
|
|
9194
|
-
data: { ...listData, items: newItems }
|
|
9195
|
-
};
|
|
9196
|
-
}
|
|
9197
|
-
if (element.element === "table") {
|
|
9198
|
-
const tableData = element.data;
|
|
9199
|
-
const newRows = [];
|
|
9200
|
-
for (const row of tableData.rows) {
|
|
9201
|
-
const newCells = [];
|
|
9202
|
-
for (const cell of row.cells) {
|
|
9203
|
-
newCells.push({ ...cell, elements: transform(cell.elements) });
|
|
9204
|
-
}
|
|
9205
|
-
newRows.push({ ...row, cells: newCells });
|
|
9206
|
-
}
|
|
9207
|
-
return {
|
|
9208
|
-
element: "table",
|
|
9209
|
-
data: { ...tableData, rows: newRows }
|
|
9210
|
-
};
|
|
9211
|
-
}
|
|
9212
|
-
if (element.element === "definition-list") {
|
|
9213
|
-
const defListData = element.data;
|
|
9214
|
-
const newItems = [];
|
|
9215
|
-
for (const item of defListData) {
|
|
9216
|
-
newItems.push({
|
|
9217
|
-
key_string: item.key_string,
|
|
9218
|
-
key: transform(item.key),
|
|
9219
|
-
value: transform(item.value)
|
|
9220
|
-
});
|
|
9221
|
-
}
|
|
9222
|
-
return {
|
|
9223
|
-
element: "definition-list",
|
|
9224
|
-
data: newItems
|
|
9225
|
-
};
|
|
9226
|
-
}
|
|
9227
|
-
if (element.element === "tab-view") {
|
|
9228
|
-
const tabData = element.data;
|
|
9229
|
-
const newTabs = [];
|
|
9230
|
-
for (const tab of tabData) {
|
|
9231
|
-
newTabs.push({ ...tab, elements: transform(tab.elements) });
|
|
9232
|
-
}
|
|
9233
|
-
return {
|
|
9234
|
-
element: "tab-view",
|
|
9235
|
-
data: newTabs
|
|
9236
|
-
};
|
|
9237
|
-
}
|
|
9238
|
-
if ("data" in element && element.data && typeof element.data === "object") {
|
|
9239
|
-
const data = element.data;
|
|
9240
|
-
if ("elements" in data && Array.isArray(data.elements)) {
|
|
9241
|
-
return {
|
|
9242
|
-
...element,
|
|
9243
|
-
data: {
|
|
9244
|
-
...data,
|
|
9245
|
-
elements: transform(data.elements)
|
|
9246
|
-
}
|
|
9247
|
-
};
|
|
9705
|
+
case "A":
|
|
9706
|
+
return DAYS[date.getDay()] ?? "";
|
|
9707
|
+
case "w":
|
|
9708
|
+
return String(date.getDay());
|
|
9709
|
+
case "j":
|
|
9710
|
+
return pad(getDayOfYear(date), 3);
|
|
9711
|
+
case "Z":
|
|
9712
|
+
return "UTC";
|
|
9713
|
+
case "z":
|
|
9714
|
+
return "+0000";
|
|
9715
|
+
case "%":
|
|
9716
|
+
return "%";
|
|
9717
|
+
default:
|
|
9718
|
+
return `%${token}`;
|
|
9248
9719
|
}
|
|
9249
|
-
}
|
|
9250
|
-
return element;
|
|
9720
|
+
});
|
|
9251
9721
|
}
|
|
9252
|
-
function
|
|
9253
|
-
|
|
9254
|
-
|
|
9255
|
-
|
|
9256
|
-
|
|
9257
|
-
|
|
9258
|
-
|
|
9259
|
-
|
|
9260
|
-
|
|
9261
|
-
|
|
9262
|
-
|
|
9263
|
-
|
|
9264
|
-
|
|
9265
|
-
|
|
9266
|
-
|
|
9267
|
-
const result = transform([{ element: "list", data: item.data }], currentState);
|
|
9268
|
-
const resolvedList = result.elements[0];
|
|
9269
|
-
if (resolvedList?.element === "list") {
|
|
9270
|
-
newItems.push({
|
|
9271
|
-
"item-type": "sub-list",
|
|
9272
|
-
element: "list",
|
|
9273
|
-
data: resolvedList.data
|
|
9274
|
-
});
|
|
9275
|
-
} else {
|
|
9276
|
-
newItems.push(item);
|
|
9277
|
-
}
|
|
9278
|
-
currentState = result.state;
|
|
9279
|
-
}
|
|
9280
|
-
}
|
|
9281
|
-
return {
|
|
9282
|
-
element: {
|
|
9283
|
-
element: "list",
|
|
9284
|
-
data: { ...listData, items: newItems }
|
|
9285
|
-
},
|
|
9286
|
-
state: currentState
|
|
9287
|
-
};
|
|
9288
|
-
}
|
|
9289
|
-
if (element.element === "table") {
|
|
9290
|
-
const tableData = element.data;
|
|
9291
|
-
const newRows = [];
|
|
9292
|
-
let currentState = state;
|
|
9293
|
-
for (const row of tableData.rows) {
|
|
9294
|
-
const newCells = [];
|
|
9295
|
-
for (const cell of row.cells) {
|
|
9296
|
-
const result = transform(cell.elements, currentState);
|
|
9297
|
-
newCells.push({ ...cell, elements: result.elements });
|
|
9298
|
-
currentState = result.state;
|
|
9299
|
-
}
|
|
9300
|
-
newRows.push({ ...row, cells: newCells });
|
|
9722
|
+
function getDayOfYear(date) {
|
|
9723
|
+
const start = new Date(date.getFullYear(), 0, 0);
|
|
9724
|
+
const diff = date.getTime() - start.getTime();
|
|
9725
|
+
const oneDay = 1000 * 60 * 60 * 24;
|
|
9726
|
+
return Math.floor(diff / oneDay);
|
|
9727
|
+
}
|
|
9728
|
+
|
|
9729
|
+
// packages/parser/src/parser/rules/block/module/listusers/compiler.ts
|
|
9730
|
+
var VARIABLE_REGEX2 = /%%([a-z_]+)%%/gi;
|
|
9731
|
+
function compileListUsersTemplate(template) {
|
|
9732
|
+
const parts = [];
|
|
9733
|
+
let lastIndex = 0;
|
|
9734
|
+
for (const match of template.matchAll(VARIABLE_REGEX2)) {
|
|
9735
|
+
if (match.index !== undefined && match.index > lastIndex) {
|
|
9736
|
+
parts.push(template.slice(lastIndex, match.index));
|
|
9301
9737
|
}
|
|
9302
|
-
|
|
9303
|
-
|
|
9304
|
-
|
|
9305
|
-
|
|
9306
|
-
|
|
9307
|
-
|
|
9308
|
-
};
|
|
9738
|
+
const [, varName] = match;
|
|
9739
|
+
if (!varName)
|
|
9740
|
+
continue;
|
|
9741
|
+
const getter = createVariableGetter2(varName.toLowerCase());
|
|
9742
|
+
parts.push(getter);
|
|
9743
|
+
lastIndex = match.index !== undefined ? match.index + match[0].length : lastIndex;
|
|
9309
9744
|
}
|
|
9310
|
-
if (
|
|
9311
|
-
|
|
9312
|
-
const newItems = [];
|
|
9313
|
-
let currentState = state;
|
|
9314
|
-
for (const item of defListData) {
|
|
9315
|
-
const keyResult = transform(item.key, currentState);
|
|
9316
|
-
currentState = keyResult.state;
|
|
9317
|
-
const valueResult = transform(item.value, currentState);
|
|
9318
|
-
currentState = valueResult.state;
|
|
9319
|
-
newItems.push({
|
|
9320
|
-
key_string: item.key_string,
|
|
9321
|
-
key: keyResult.elements,
|
|
9322
|
-
value: valueResult.elements
|
|
9323
|
-
});
|
|
9324
|
-
}
|
|
9325
|
-
return {
|
|
9326
|
-
element: {
|
|
9327
|
-
element: "definition-list",
|
|
9328
|
-
data: newItems
|
|
9329
|
-
},
|
|
9330
|
-
state: currentState
|
|
9331
|
-
};
|
|
9745
|
+
if (lastIndex < template.length) {
|
|
9746
|
+
parts.push(template.slice(lastIndex));
|
|
9332
9747
|
}
|
|
9333
|
-
|
|
9334
|
-
|
|
9335
|
-
const
|
|
9336
|
-
|
|
9337
|
-
for (const tab of tabData) {
|
|
9338
|
-
const result = transform(tab.elements, currentState);
|
|
9339
|
-
newTabs.push({ ...tab, elements: result.elements });
|
|
9340
|
-
currentState = result.state;
|
|
9748
|
+
return (ctx) => {
|
|
9749
|
+
let result = "";
|
|
9750
|
+
for (const part of parts) {
|
|
9751
|
+
result += typeof part === "string" ? part : part(ctx);
|
|
9341
9752
|
}
|
|
9342
|
-
return
|
|
9343
|
-
|
|
9344
|
-
|
|
9345
|
-
|
|
9346
|
-
|
|
9347
|
-
|
|
9348
|
-
|
|
9753
|
+
return result;
|
|
9754
|
+
};
|
|
9755
|
+
}
|
|
9756
|
+
function createVariableGetter2(name) {
|
|
9757
|
+
switch (name) {
|
|
9758
|
+
case "number":
|
|
9759
|
+
return (ctx) => String(ctx.user.number);
|
|
9760
|
+
case "title":
|
|
9761
|
+
return (ctx) => ctx.user.title;
|
|
9762
|
+
case "name":
|
|
9763
|
+
return (ctx) => ctx.user.name;
|
|
9764
|
+
default:
|
|
9765
|
+
return () => "";
|
|
9349
9766
|
}
|
|
9350
|
-
|
|
9351
|
-
|
|
9352
|
-
|
|
9353
|
-
|
|
9354
|
-
|
|
9355
|
-
|
|
9356
|
-
|
|
9357
|
-
|
|
9358
|
-
|
|
9359
|
-
|
|
9360
|
-
|
|
9361
|
-
|
|
9362
|
-
|
|
9363
|
-
|
|
9767
|
+
}
|
|
9768
|
+
|
|
9769
|
+
// packages/parser/src/parser/rules/block/module/listusers/extract.ts
|
|
9770
|
+
var VARIABLE_REGEX3 = /%%([a-z_]+)%%/gi;
|
|
9771
|
+
var KNOWN_VARIABLES = ["number", "title", "name"];
|
|
9772
|
+
function extractListUsersVariables(template) {
|
|
9773
|
+
const variables = new Set;
|
|
9774
|
+
for (const match of template.matchAll(VARIABLE_REGEX3)) {
|
|
9775
|
+
const [, varName] = match;
|
|
9776
|
+
if (!varName)
|
|
9777
|
+
continue;
|
|
9778
|
+
const normalized = varName.toLowerCase();
|
|
9779
|
+
if (KNOWN_VARIABLES.includes(normalized)) {
|
|
9780
|
+
variables.add(normalized);
|
|
9364
9781
|
}
|
|
9365
9782
|
}
|
|
9366
|
-
return
|
|
9783
|
+
return Array.from(variables);
|
|
9367
9784
|
}
|
|
9368
9785
|
|
|
9369
9786
|
// packages/parser/src/parser/rules/block/module/listpages/extract.ts
|
|
@@ -9965,51 +10382,6 @@ function resolveAndNormalizeQuery(requirement, urlParams) {
|
|
|
9965
10382
|
const resolved = resolveQuery(requirement, urlParams);
|
|
9966
10383
|
return normalizeQuery(resolved);
|
|
9967
10384
|
}
|
|
9968
|
-
// packages/parser/src/parser/rules/block/module/iftags/condition.ts
|
|
9969
|
-
function parseTagCondition(condition) {
|
|
9970
|
-
const required = [];
|
|
9971
|
-
const forbidden = [];
|
|
9972
|
-
const optional = [];
|
|
9973
|
-
const parts = condition.trim().split(/\s+/);
|
|
9974
|
-
for (const part of parts) {
|
|
9975
|
-
if (!part)
|
|
9976
|
-
continue;
|
|
9977
|
-
if (part.startsWith("+")) {
|
|
9978
|
-
const tag = part.slice(1);
|
|
9979
|
-
if (tag)
|
|
9980
|
-
required.push(tag);
|
|
9981
|
-
} else if (part.startsWith("-")) {
|
|
9982
|
-
const tag = part.slice(1);
|
|
9983
|
-
if (tag)
|
|
9984
|
-
forbidden.push(tag);
|
|
9985
|
-
} else {
|
|
9986
|
-
optional.push(part);
|
|
9987
|
-
}
|
|
9988
|
-
}
|
|
9989
|
-
return { required, forbidden, optional };
|
|
9990
|
-
}
|
|
9991
|
-
function evaluateTagCondition(condition, pageTags) {
|
|
9992
|
-
if (condition.required.length === 0 && condition.forbidden.length === 0 && condition.optional.length === 0) {
|
|
9993
|
-
return false;
|
|
9994
|
-
}
|
|
9995
|
-
const tagSet = new Set(pageTags);
|
|
9996
|
-
for (const tag of condition.required) {
|
|
9997
|
-
if (!tagSet.has(tag)) {
|
|
9998
|
-
return false;
|
|
9999
|
-
}
|
|
10000
|
-
}
|
|
10001
|
-
for (const tag of condition.forbidden) {
|
|
10002
|
-
if (tagSet.has(tag)) {
|
|
10003
|
-
return false;
|
|
10004
|
-
}
|
|
10005
|
-
}
|
|
10006
|
-
if (condition.optional.length > 0) {
|
|
10007
|
-
if (!condition.optional.some((tag) => tagSet.has(tag))) {
|
|
10008
|
-
return false;
|
|
10009
|
-
}
|
|
10010
|
-
}
|
|
10011
|
-
return true;
|
|
10012
|
-
}
|
|
10013
10385
|
// packages/parser/src/parser/rules/block/module/iftags/resolve.ts
|
|
10014
10386
|
function isIfTagsElement(element) {
|
|
10015
10387
|
return element.element === "if-tags";
|
|
@@ -10067,7 +10439,67 @@ async function resolveIncludesAsync(source, fetcher, options) {
|
|
|
10067
10439
|
};
|
|
10068
10440
|
return expandIterativeAsync(source, cachedFetcher, maxIterations);
|
|
10069
10441
|
}
|
|
10070
|
-
var
|
|
10442
|
+
var INCLUDE_OPEN_PATTERN = /^\[\[include\s/gim;
|
|
10443
|
+
function isRestOfLineBlank(source, pos) {
|
|
10444
|
+
for (let i = pos;i < source.length; i++) {
|
|
10445
|
+
const ch = source[i];
|
|
10446
|
+
if (ch === `
|
|
10447
|
+
`)
|
|
10448
|
+
return true;
|
|
10449
|
+
if (ch !== " " && ch !== "\t" && ch !== "\r")
|
|
10450
|
+
return false;
|
|
10451
|
+
}
|
|
10452
|
+
return true;
|
|
10453
|
+
}
|
|
10454
|
+
function scanIncludeDirectives(source) {
|
|
10455
|
+
const matches = [];
|
|
10456
|
+
const opener = new RegExp(INCLUDE_OPEN_PATTERN.source, INCLUDE_OPEN_PATTERN.flags);
|
|
10457
|
+
let m;
|
|
10458
|
+
while ((m = opener.exec(source)) !== null) {
|
|
10459
|
+
const start = m.index;
|
|
10460
|
+
const contentStart = start + m[0].length;
|
|
10461
|
+
const firstNewline = source.indexOf(`
|
|
10462
|
+
`, start);
|
|
10463
|
+
let depth = 0;
|
|
10464
|
+
let linkDepth = 0;
|
|
10465
|
+
let i = start;
|
|
10466
|
+
let closeEnd = -1;
|
|
10467
|
+
while (i < source.length) {
|
|
10468
|
+
if (source.startsWith("[[[", i)) {
|
|
10469
|
+
linkDepth++;
|
|
10470
|
+
i += 3;
|
|
10471
|
+
} else if (linkDepth > 0 && source.startsWith("]]]", i)) {
|
|
10472
|
+
linkDepth--;
|
|
10473
|
+
i += 3;
|
|
10474
|
+
} else if (linkDepth > 0) {
|
|
10475
|
+
i++;
|
|
10476
|
+
} else if (source.startsWith("[[", i)) {
|
|
10477
|
+
depth++;
|
|
10478
|
+
i += 2;
|
|
10479
|
+
} else if (source.startsWith("]]", i)) {
|
|
10480
|
+
const closeStart = i;
|
|
10481
|
+
depth--;
|
|
10482
|
+
i += 2;
|
|
10483
|
+
if (depth <= 0) {
|
|
10484
|
+
const onOpenerLine = firstNewline === -1 || closeStart < firstNewline;
|
|
10485
|
+
if (onOpenerLine || isRestOfLineBlank(source, i)) {
|
|
10486
|
+
closeEnd = i;
|
|
10487
|
+
break;
|
|
10488
|
+
}
|
|
10489
|
+
}
|
|
10490
|
+
} else {
|
|
10491
|
+
i++;
|
|
10492
|
+
}
|
|
10493
|
+
}
|
|
10494
|
+
if (closeEnd === -1) {
|
|
10495
|
+
opener.lastIndex = start + 2;
|
|
10496
|
+
continue;
|
|
10497
|
+
}
|
|
10498
|
+
matches.push({ start, end: closeEnd, inner: source.slice(contentStart, closeEnd - 2) });
|
|
10499
|
+
opener.lastIndex = closeEnd;
|
|
10500
|
+
}
|
|
10501
|
+
return matches;
|
|
10502
|
+
}
|
|
10071
10503
|
function parseIncludeDirective(inner) {
|
|
10072
10504
|
const normalized = inner.replace(/\n/g, " ");
|
|
10073
10505
|
const parts = normalized.split("|");
|
|
@@ -10091,14 +10523,24 @@ function parseIncludeDirective(inner) {
|
|
|
10091
10523
|
}
|
|
10092
10524
|
}
|
|
10093
10525
|
const variables = {};
|
|
10526
|
+
const hasConcrete = new Set;
|
|
10094
10527
|
for (const segment of varSegments) {
|
|
10095
10528
|
const eqIndex = segment.indexOf("=");
|
|
10096
|
-
if (eqIndex
|
|
10097
|
-
|
|
10098
|
-
|
|
10099
|
-
|
|
10529
|
+
if (eqIndex === -1)
|
|
10530
|
+
continue;
|
|
10531
|
+
const key = segment.slice(0, eqIndex).trim();
|
|
10532
|
+
if (!key)
|
|
10533
|
+
continue;
|
|
10534
|
+
const value = segment.slice(eqIndex + 1).trim();
|
|
10535
|
+
const isPlaceholder = /^\{\$[^}]*\}$/.test(value);
|
|
10536
|
+
const isConcrete = value !== "" && !isPlaceholder;
|
|
10537
|
+
if (isConcrete) {
|
|
10538
|
+
if (!hasConcrete.has(key)) {
|
|
10100
10539
|
variables[key] = value;
|
|
10540
|
+
hasConcrete.add(key);
|
|
10101
10541
|
}
|
|
10542
|
+
} else if (!Object.hasOwn(variables, key)) {
|
|
10543
|
+
variables[key] = value;
|
|
10102
10544
|
}
|
|
10103
10545
|
}
|
|
10104
10546
|
let location;
|
|
@@ -10115,7 +10557,7 @@ function parseIncludeDirective(inner) {
|
|
|
10115
10557
|
}
|
|
10116
10558
|
return { location, variables };
|
|
10117
10559
|
}
|
|
10118
|
-
function replaceOneInclude(
|
|
10560
|
+
function replaceOneInclude(inner, fetcher) {
|
|
10119
10561
|
const { location, variables } = parseIncludeDirective(inner);
|
|
10120
10562
|
const content = fetcher(location);
|
|
10121
10563
|
if (content === null) {
|
|
@@ -10128,25 +10570,33 @@ Page to be included "${location.page}" cannot be found!
|
|
|
10128
10570
|
function expandIterative(source, fetcher, maxIterations) {
|
|
10129
10571
|
let current = source;
|
|
10130
10572
|
for (let i = 0;i < maxIterations; i++) {
|
|
10131
|
-
const
|
|
10132
|
-
|
|
10133
|
-
|
|
10573
|
+
const directives = scanIncludeDirectives(current);
|
|
10574
|
+
if (directives.length === 0)
|
|
10575
|
+
break;
|
|
10576
|
+
let result = "";
|
|
10577
|
+
let lastPos = 0;
|
|
10578
|
+
for (const { start, end, inner } of directives) {
|
|
10579
|
+
result += current.slice(lastPos, start);
|
|
10580
|
+
result += replaceOneInclude(inner, fetcher);
|
|
10581
|
+
lastPos = end;
|
|
10582
|
+
}
|
|
10583
|
+
result += current.slice(lastPos);
|
|
10584
|
+
if (result === current)
|
|
10134
10585
|
break;
|
|
10586
|
+
current = result;
|
|
10135
10587
|
}
|
|
10136
10588
|
return current;
|
|
10137
10589
|
}
|
|
10138
10590
|
async function expandIterativeAsync(source, fetcher, maxIterations) {
|
|
10139
10591
|
let current = source;
|
|
10140
10592
|
for (let i = 0;i < maxIterations; i++) {
|
|
10141
|
-
const
|
|
10142
|
-
|
|
10593
|
+
const directives = scanIncludeDirectives(current);
|
|
10594
|
+
if (directives.length === 0)
|
|
10595
|
+
break;
|
|
10143
10596
|
let result = "";
|
|
10144
10597
|
let lastPos = 0;
|
|
10145
|
-
|
|
10146
|
-
|
|
10147
|
-
const fullMatch = match[0];
|
|
10148
|
-
const inner = match[1];
|
|
10149
|
-
result += current.slice(lastPos, match.index);
|
|
10598
|
+
for (const { start, end, inner } of directives) {
|
|
10599
|
+
result += current.slice(lastPos, start);
|
|
10150
10600
|
const { location, variables } = parseIncludeDirective(inner);
|
|
10151
10601
|
const content = await fetcher(location);
|
|
10152
10602
|
if (content === null) {
|
|
@@ -10156,12 +10606,12 @@ Page to be included "${location.page}" cannot be found!
|
|
|
10156
10606
|
} else {
|
|
10157
10607
|
result += substituteVariables(content, variables);
|
|
10158
10608
|
}
|
|
10159
|
-
lastPos =
|
|
10609
|
+
lastPos = end;
|
|
10160
10610
|
}
|
|
10161
10611
|
result += current.slice(lastPos);
|
|
10162
|
-
|
|
10163
|
-
if (current === previous)
|
|
10612
|
+
if (result === current)
|
|
10164
10613
|
break;
|
|
10614
|
+
current = result;
|
|
10165
10615
|
}
|
|
10166
10616
|
return current;
|
|
10167
10617
|
}
|