@wdprlib/parser 2.0.10 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +130 -20
- package/dist/index.d.cts +38 -8
- package/dist/index.d.ts +38 -8
- package/dist/index.js +130 -20
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -34,6 +34,7 @@ __export(exports_src, {
|
|
|
34
34
|
text: () => import_ast5.text,
|
|
35
35
|
resolveModules: () => resolveModules,
|
|
36
36
|
resolveListUsers: () => resolveListUsers,
|
|
37
|
+
resolveIncludesAsync: () => resolveIncludesAsync,
|
|
37
38
|
resolveIncludes: () => resolveIncludes,
|
|
38
39
|
parseTags: () => parseTags,
|
|
39
40
|
parseParent: () => parseParent,
|
|
@@ -645,6 +646,51 @@ var BLOCK_START_TOKENS = [
|
|
|
645
646
|
"CLEAR_FLOAT_LEFT",
|
|
646
647
|
"CLEAR_FLOAT_RIGHT"
|
|
647
648
|
];
|
|
649
|
+
var KNOWN_BLOCK_NAMES = new Set([
|
|
650
|
+
"collapsible",
|
|
651
|
+
"div",
|
|
652
|
+
"div_",
|
|
653
|
+
"code",
|
|
654
|
+
"ul",
|
|
655
|
+
"ol",
|
|
656
|
+
"li",
|
|
657
|
+
"table",
|
|
658
|
+
"row",
|
|
659
|
+
"cell",
|
|
660
|
+
"hcell",
|
|
661
|
+
"tabview",
|
|
662
|
+
"tabs",
|
|
663
|
+
"module",
|
|
664
|
+
"module654",
|
|
665
|
+
"bibliography",
|
|
666
|
+
"footnoteblock",
|
|
667
|
+
"toc",
|
|
668
|
+
"iframe",
|
|
669
|
+
"math",
|
|
670
|
+
"html",
|
|
671
|
+
"iftags",
|
|
672
|
+
"include",
|
|
673
|
+
"f",
|
|
674
|
+
"embed",
|
|
675
|
+
"embedvideo",
|
|
676
|
+
"embedaudio",
|
|
677
|
+
"<",
|
|
678
|
+
">",
|
|
679
|
+
"=",
|
|
680
|
+
"==",
|
|
681
|
+
"span",
|
|
682
|
+
"span_",
|
|
683
|
+
"user",
|
|
684
|
+
"a",
|
|
685
|
+
"anchor",
|
|
686
|
+
"size",
|
|
687
|
+
"footnote",
|
|
688
|
+
"eref",
|
|
689
|
+
"$",
|
|
690
|
+
"image",
|
|
691
|
+
"gallery",
|
|
692
|
+
"file"
|
|
693
|
+
]);
|
|
648
694
|
|
|
649
695
|
// packages/parser/src/parser/rules/utils.ts
|
|
650
696
|
var SAFE_ATTRIBUTES = new Set([
|
|
@@ -779,6 +825,19 @@ function isExcludedBlockToken(ctx, tokenPos) {
|
|
|
779
825
|
const nameResult = parseBlockName(ctx, tokenPos + 1);
|
|
780
826
|
return nameResult !== null && ctx.excludedBlockNames.has(nameResult.name);
|
|
781
827
|
}
|
|
828
|
+
function isUnknownBlockToken(ctx, tokenPos) {
|
|
829
|
+
const token = ctx.tokens[tokenPos];
|
|
830
|
+
if (token?.type !== "BLOCK_OPEN" && token?.type !== "BLOCK_END_OPEN")
|
|
831
|
+
return false;
|
|
832
|
+
const nameResult = parseBlockName(ctx, tokenPos + 1);
|
|
833
|
+
if (nameResult === null) {
|
|
834
|
+
if (ctx.tokens[tokenPos + 1]?.type === "EQUALS") {
|
|
835
|
+
return false;
|
|
836
|
+
}
|
|
837
|
+
return true;
|
|
838
|
+
}
|
|
839
|
+
return !KNOWN_BLOCK_NAMES.has(nameResult.name);
|
|
840
|
+
}
|
|
782
841
|
function canApplyInlineRule(rule, token) {
|
|
783
842
|
if (rule.startTokens.length === 0) {
|
|
784
843
|
return true;
|
|
@@ -871,7 +930,8 @@ function parseInlineUntil(ctx, endType) {
|
|
|
871
930
|
}
|
|
872
931
|
}
|
|
873
932
|
const isExcludedBlock = (nextMeaningfulToken?.type === "BLOCK_OPEN" || nextMeaningfulToken?.type === "BLOCK_END_OPEN") && isExcludedBlockToken(ctx, pos + lookAhead);
|
|
874
|
-
const
|
|
933
|
+
const isUnknownBlock = (nextMeaningfulToken?.type === "BLOCK_OPEN" || nextMeaningfulToken?.type === "BLOCK_END_OPEN") && isUnknownBlockToken(ctx, pos + lookAhead);
|
|
934
|
+
const isBlockStart = nextMeaningfulToken && BLOCK_START_TOKENS.includes(nextMeaningfulToken.type) && nextMeaningfulToken.lineStart && !isOrphanCloseSpan && !isAnchorName && !isInvalidBlockOpen && !isInvalidHeading && !isExcludedBlock && !isUnknownBlock;
|
|
875
935
|
if (!nextMeaningfulToken || nextMeaningfulToken.type === "NEWLINE" || nextMeaningfulToken.type === "EOF" || isBlockStart) {
|
|
876
936
|
if (isBlockStart && nodes.length > 0) {
|
|
877
937
|
const nextPos = pos + lookAhead;
|
|
@@ -1208,7 +1268,6 @@ function buildListData(topLtype, list) {
|
|
|
1208
1268
|
items
|
|
1209
1269
|
};
|
|
1210
1270
|
}
|
|
1211
|
-
|
|
1212
1271
|
// packages/parser/src/parser/rules/block/utils.ts
|
|
1213
1272
|
function canApplyBlockRule(rule, token) {
|
|
1214
1273
|
if (rule.requiresLineStart && !token.lineStart) {
|
|
@@ -9968,7 +10027,7 @@ function resolveIncludes(source, fetcher, options) {
|
|
|
9968
10027
|
if (options?.settings && !options.settings.enablePageSyntax) {
|
|
9969
10028
|
return source;
|
|
9970
10029
|
}
|
|
9971
|
-
const
|
|
10030
|
+
const maxIterations = options?.maxIterations ?? 10;
|
|
9972
10031
|
const cache = new Map;
|
|
9973
10032
|
const cachedFetcher = (pageRef) => {
|
|
9974
10033
|
const key = normalizePageKey(pageRef);
|
|
@@ -9984,7 +10043,29 @@ function resolveIncludes(source, fetcher, options) {
|
|
|
9984
10043
|
cache.set(key, result);
|
|
9985
10044
|
return result;
|
|
9986
10045
|
};
|
|
9987
|
-
return
|
|
10046
|
+
return expandIterative(source, cachedFetcher, maxIterations);
|
|
10047
|
+
}
|
|
10048
|
+
async function resolveIncludesAsync(source, fetcher, options) {
|
|
10049
|
+
if (options?.settings && !options.settings.enablePageSyntax) {
|
|
10050
|
+
return source;
|
|
10051
|
+
}
|
|
10052
|
+
const maxIterations = options?.maxIterations ?? 10;
|
|
10053
|
+
const cache = new Map;
|
|
10054
|
+
const cachedFetcher = async (pageRef) => {
|
|
10055
|
+
const key = normalizePageKey(pageRef);
|
|
10056
|
+
if (cache.has(key)) {
|
|
10057
|
+
return cache.get(key);
|
|
10058
|
+
}
|
|
10059
|
+
let result;
|
|
10060
|
+
try {
|
|
10061
|
+
result = await fetcher(pageRef);
|
|
10062
|
+
} catch {
|
|
10063
|
+
result = null;
|
|
10064
|
+
}
|
|
10065
|
+
cache.set(key, result);
|
|
10066
|
+
return result;
|
|
10067
|
+
};
|
|
10068
|
+
return expandIterativeAsync(source, cachedFetcher, maxIterations);
|
|
9988
10069
|
}
|
|
9989
10070
|
var INCLUDE_PATTERN = /^\[\[include\s([^\]]*(?:\](?!\])[^\]]*)*)\]\]/gim;
|
|
9990
10071
|
function parseIncludeDirective(inner) {
|
|
@@ -10034,26 +10115,55 @@ function parseIncludeDirective(inner) {
|
|
|
10034
10115
|
}
|
|
10035
10116
|
return { location, variables };
|
|
10036
10117
|
}
|
|
10037
|
-
function
|
|
10038
|
-
|
|
10039
|
-
|
|
10040
|
-
|
|
10041
|
-
|
|
10042
|
-
|
|
10043
|
-
if (trace.includes(pageKey)) {
|
|
10044
|
-
return `[[div class="error-block"]]
|
|
10045
|
-
Circular include detected: "${location.page}"
|
|
10118
|
+
function replaceOneInclude(_match, inner, fetcher) {
|
|
10119
|
+
const { location, variables } = parseIncludeDirective(inner);
|
|
10120
|
+
const content = fetcher(location);
|
|
10121
|
+
if (content === null) {
|
|
10122
|
+
return `[[div class="error-block"]]
|
|
10123
|
+
Page to be included "${location.page}" cannot be found!
|
|
10046
10124
|
[[/div]]`;
|
|
10047
|
-
|
|
10048
|
-
|
|
10049
|
-
|
|
10050
|
-
|
|
10125
|
+
}
|
|
10126
|
+
return substituteVariables(content, variables);
|
|
10127
|
+
}
|
|
10128
|
+
function expandIterative(source, fetcher, maxIterations) {
|
|
10129
|
+
let current = source;
|
|
10130
|
+
for (let i = 0;i < maxIterations; i++) {
|
|
10131
|
+
const previous = current;
|
|
10132
|
+
current = current.replace(INCLUDE_PATTERN, (_match, inner) => replaceOneInclude(_match, inner, fetcher));
|
|
10133
|
+
if (current === previous)
|
|
10134
|
+
break;
|
|
10135
|
+
}
|
|
10136
|
+
return current;
|
|
10137
|
+
}
|
|
10138
|
+
async function expandIterativeAsync(source, fetcher, maxIterations) {
|
|
10139
|
+
let current = source;
|
|
10140
|
+
for (let i = 0;i < maxIterations; i++) {
|
|
10141
|
+
const previous = current;
|
|
10142
|
+
const pattern = new RegExp(INCLUDE_PATTERN.source, INCLUDE_PATTERN.flags);
|
|
10143
|
+
let result = "";
|
|
10144
|
+
let lastPos = 0;
|
|
10145
|
+
let match;
|
|
10146
|
+
while ((match = pattern.exec(current)) !== null) {
|
|
10147
|
+
const fullMatch = match[0];
|
|
10148
|
+
const inner = match[1];
|
|
10149
|
+
result += current.slice(lastPos, match.index);
|
|
10150
|
+
const { location, variables } = parseIncludeDirective(inner);
|
|
10151
|
+
const content = await fetcher(location);
|
|
10152
|
+
if (content === null) {
|
|
10153
|
+
result += `[[div class="error-block"]]
|
|
10051
10154
|
Page to be included "${location.page}" cannot be found!
|
|
10052
10155
|
[[/div]]`;
|
|
10156
|
+
} else {
|
|
10157
|
+
result += substituteVariables(content, variables);
|
|
10158
|
+
}
|
|
10159
|
+
lastPos = match.index + fullMatch.length;
|
|
10053
10160
|
}
|
|
10054
|
-
|
|
10055
|
-
|
|
10056
|
-
|
|
10161
|
+
result += current.slice(lastPos);
|
|
10162
|
+
current = result;
|
|
10163
|
+
if (current === previous)
|
|
10164
|
+
break;
|
|
10165
|
+
}
|
|
10166
|
+
return current;
|
|
10057
10167
|
}
|
|
10058
10168
|
function normalizePageKey(location) {
|
|
10059
10169
|
const site = location.site ?? "";
|
package/dist/index.d.cts
CHANGED
|
@@ -859,21 +859,36 @@ import { PageRef, WikitextSettings as WikitextSettings3 } from "@wdprlib/ast";
|
|
|
859
859
|
*/
|
|
860
860
|
type IncludeFetcher = (pageRef: PageRef) => string | null;
|
|
861
861
|
/**
|
|
862
|
-
*
|
|
862
|
+
* Async callback to fetch page content for include resolution.
|
|
863
|
+
* Returns a promise of the wikitext source, or null if the page does not exist.
|
|
864
|
+
*
|
|
865
|
+
* @security The fetcher is called with user-provided page references.
|
|
866
|
+
* Implementations should validate and sanitize page references before
|
|
867
|
+
* using them in database queries or file system access.
|
|
868
|
+
*/
|
|
869
|
+
type AsyncIncludeFetcher = (pageRef: PageRef) => Promise<string | null>;
|
|
870
|
+
/**
|
|
871
|
+
* Options for resolveIncludes / resolveIncludesAsync
|
|
863
872
|
*/
|
|
864
873
|
interface ResolveIncludesOptions {
|
|
865
|
-
/**
|
|
866
|
-
|
|
874
|
+
/**
|
|
875
|
+
* Maximum number of expansion iterations (default: 10).
|
|
876
|
+
*
|
|
877
|
+
* Each iteration replaces all `[[include]]` directives in the current
|
|
878
|
+
* source with fetched content. Iteration stops when the source is
|
|
879
|
+
* unchanged or this limit is reached.
|
|
880
|
+
*/
|
|
881
|
+
maxIterations?: number;
|
|
867
882
|
/** Wikitext settings. If enablePageSyntax is false, includes are not expanded. */
|
|
868
883
|
settings?: WikitextSettings3;
|
|
869
884
|
}
|
|
870
885
|
/**
|
|
871
886
|
* Expand all [[include]] directives in the source text.
|
|
872
887
|
*
|
|
873
|
-
*
|
|
874
|
-
*
|
|
875
|
-
*
|
|
876
|
-
*
|
|
888
|
+
* Uses Wikidot-compatible iterative expansion: each iteration replaces
|
|
889
|
+
* all include directives in the current source with fetched (and
|
|
890
|
+
* variable-substituted) content. Iteration continues until no further
|
|
891
|
+
* changes occur or `maxIterations` is reached.
|
|
877
892
|
*
|
|
878
893
|
* @example
|
|
879
894
|
* ```ts
|
|
@@ -883,6 +898,21 @@ interface ResolveIncludesOptions {
|
|
|
883
898
|
*/
|
|
884
899
|
declare function resolveIncludes(source: string, fetcher: IncludeFetcher, options?: ResolveIncludesOptions): string;
|
|
885
900
|
/**
|
|
901
|
+
* Async version of {@link resolveIncludes}.
|
|
902
|
+
*
|
|
903
|
+
* Expand all [[include]] directives using an async fetcher, allowing
|
|
904
|
+
* page content to be loaded from async sources such as databases.
|
|
905
|
+
*
|
|
906
|
+
* @example
|
|
907
|
+
* ```ts
|
|
908
|
+
* const expanded = await resolveIncludesAsync(source, async (ref) => {
|
|
909
|
+
* return await db.getPageContent(ref.page);
|
|
910
|
+
* });
|
|
911
|
+
* const ast = parse(expanded);
|
|
912
|
+
* ```
|
|
913
|
+
*/
|
|
914
|
+
declare function resolveIncludesAsync(source: string, fetcher: AsyncIncludeFetcher, options?: ResolveIncludesOptions): Promise<string>;
|
|
915
|
+
/**
|
|
886
916
|
* Compile a ListUsers template string into an executable function.
|
|
887
917
|
*
|
|
888
918
|
* The template is split into alternating static strings and dynamic getter
|
|
@@ -981,4 +1011,4 @@ interface ResolveOptions {
|
|
|
981
1011
|
*/
|
|
982
1012
|
declare function resolveModules(ast: SyntaxTree2, dataProvider: DataProvider, options: ResolveOptions): Promise<SyntaxTree2>;
|
|
983
1013
|
import { STYLE_SLOT_PREFIX } from "@wdprlib/ast";
|
|
984
|
-
export { tokenize, text, resolveModules, resolveListUsers, resolveIncludes, parseTags, parseParent, parseOrder, parseNumericSelector, parseDateSelector, parseCategory, parse, paragraph, normalizeQuery, listItemSubList, listItemElements, list, link, lineBreak, italics, isListUsersModule, horizontalRule, heading, extractListUsersVariables, extractDataRequirements, createToken, createSettings, createPosition, createPoint, container, compileTemplate, compileListUsersTemplate, bold, WikitextSettings4 as WikitextSettings, WikitextMode, Version2 as Version, VariableMap, VariableContext, UserInfo, TokenType, Token, TocEntry2 as TocEntry, TableRow, TableData, TableCell, TabData, SyntaxTree3 as SyntaxTree, SiteContext, STYLE_SLOT_PREFIX, ResolveOptions, ResolveIncludesOptions, Position2 as Position, Point, ParserOptions, Parser, ParseResult2 as ParseResult, ParseFunction, PageRef2 as PageRef, PageData, NormalizedTags, NormalizedParent, NormalizedOrder, NormalizedNumericSelector, NormalizedListPagesQuery, NormalizedDateSelector, NormalizedCategory, Module4 as Module, ListUsersVariableContext, ListUsersVariable, ListUsersUserData, ListUsersExternalData, ListUsersDataRequirement, ListUsersDataFetcher, ListUsersCompiledTemplate, ListType, ListPagesVariable, ListPagesQuery, ListPagesExternalData, ListPagesDataRequirement, ListPagesDataFetcher, ListItem, ListData, LinkType, LinkLocation, LinkLabel, LexerOptions, Lexer, IncludeFetcher, ImageSource, HeadingLevel, Heading, HeaderType, FloatAlignment, ExtractionResult, Embed, Element6 as Element, DiagnosticSeverity, Diagnostic2 as Diagnostic, DefinitionListItem, DateItem, DataRequirements, DataProvider, DEFAULT_SETTINGS, ContainerType, ContainerData, CompiledTemplate, CollapsibleData, CodeBlockData2 as CodeBlockData, ClearFloat, AttributeMap, AnchorTarget, Alignment, AlignType };
|
|
1014
|
+
export { tokenize, text, resolveModules, resolveListUsers, resolveIncludesAsync, resolveIncludes, parseTags, parseParent, parseOrder, parseNumericSelector, parseDateSelector, parseCategory, parse, paragraph, normalizeQuery, listItemSubList, listItemElements, list, link, lineBreak, italics, isListUsersModule, horizontalRule, heading, extractListUsersVariables, extractDataRequirements, createToken, createSettings, createPosition, createPoint, container, compileTemplate, compileListUsersTemplate, bold, WikitextSettings4 as WikitextSettings, WikitextMode, Version2 as Version, VariableMap, VariableContext, UserInfo, TokenType, Token, TocEntry2 as TocEntry, TableRow, TableData, TableCell, TabData, SyntaxTree3 as SyntaxTree, SiteContext, STYLE_SLOT_PREFIX, ResolveOptions, ResolveIncludesOptions, Position2 as Position, Point, ParserOptions, Parser, ParseResult2 as ParseResult, ParseFunction, PageRef2 as PageRef, PageData, NormalizedTags, NormalizedParent, NormalizedOrder, NormalizedNumericSelector, NormalizedListPagesQuery, NormalizedDateSelector, NormalizedCategory, Module4 as Module, ListUsersVariableContext, ListUsersVariable, ListUsersUserData, ListUsersExternalData, ListUsersDataRequirement, ListUsersDataFetcher, ListUsersCompiledTemplate, ListType, ListPagesVariable, ListPagesQuery, ListPagesExternalData, ListPagesDataRequirement, ListPagesDataFetcher, ListItem, ListData, LinkType, LinkLocation, LinkLabel, LexerOptions, Lexer, IncludeFetcher, ImageSource, HeadingLevel, Heading, HeaderType, FloatAlignment, ExtractionResult, Embed, Element6 as Element, DiagnosticSeverity, Diagnostic2 as Diagnostic, DefinitionListItem, DateItem, DataRequirements, DataProvider, DEFAULT_SETTINGS, ContainerType, ContainerData, CompiledTemplate, CollapsibleData, CodeBlockData2 as CodeBlockData, ClearFloat, AttributeMap, AsyncIncludeFetcher, AnchorTarget, Alignment, AlignType };
|
package/dist/index.d.ts
CHANGED
|
@@ -859,21 +859,36 @@ import { PageRef, WikitextSettings as WikitextSettings3 } from "@wdprlib/ast";
|
|
|
859
859
|
*/
|
|
860
860
|
type IncludeFetcher = (pageRef: PageRef) => string | null;
|
|
861
861
|
/**
|
|
862
|
-
*
|
|
862
|
+
* Async callback to fetch page content for include resolution.
|
|
863
|
+
* Returns a promise of the wikitext source, or null if the page does not exist.
|
|
864
|
+
*
|
|
865
|
+
* @security The fetcher is called with user-provided page references.
|
|
866
|
+
* Implementations should validate and sanitize page references before
|
|
867
|
+
* using them in database queries or file system access.
|
|
868
|
+
*/
|
|
869
|
+
type AsyncIncludeFetcher = (pageRef: PageRef) => Promise<string | null>;
|
|
870
|
+
/**
|
|
871
|
+
* Options for resolveIncludes / resolveIncludesAsync
|
|
863
872
|
*/
|
|
864
873
|
interface ResolveIncludesOptions {
|
|
865
|
-
/**
|
|
866
|
-
|
|
874
|
+
/**
|
|
875
|
+
* Maximum number of expansion iterations (default: 10).
|
|
876
|
+
*
|
|
877
|
+
* Each iteration replaces all `[[include]]` directives in the current
|
|
878
|
+
* source with fetched content. Iteration stops when the source is
|
|
879
|
+
* unchanged or this limit is reached.
|
|
880
|
+
*/
|
|
881
|
+
maxIterations?: number;
|
|
867
882
|
/** Wikitext settings. If enablePageSyntax is false, includes are not expanded. */
|
|
868
883
|
settings?: WikitextSettings3;
|
|
869
884
|
}
|
|
870
885
|
/**
|
|
871
886
|
* Expand all [[include]] directives in the source text.
|
|
872
887
|
*
|
|
873
|
-
*
|
|
874
|
-
*
|
|
875
|
-
*
|
|
876
|
-
*
|
|
888
|
+
* Uses Wikidot-compatible iterative expansion: each iteration replaces
|
|
889
|
+
* all include directives in the current source with fetched (and
|
|
890
|
+
* variable-substituted) content. Iteration continues until no further
|
|
891
|
+
* changes occur or `maxIterations` is reached.
|
|
877
892
|
*
|
|
878
893
|
* @example
|
|
879
894
|
* ```ts
|
|
@@ -883,6 +898,21 @@ interface ResolveIncludesOptions {
|
|
|
883
898
|
*/
|
|
884
899
|
declare function resolveIncludes(source: string, fetcher: IncludeFetcher, options?: ResolveIncludesOptions): string;
|
|
885
900
|
/**
|
|
901
|
+
* Async version of {@link resolveIncludes}.
|
|
902
|
+
*
|
|
903
|
+
* Expand all [[include]] directives using an async fetcher, allowing
|
|
904
|
+
* page content to be loaded from async sources such as databases.
|
|
905
|
+
*
|
|
906
|
+
* @example
|
|
907
|
+
* ```ts
|
|
908
|
+
* const expanded = await resolveIncludesAsync(source, async (ref) => {
|
|
909
|
+
* return await db.getPageContent(ref.page);
|
|
910
|
+
* });
|
|
911
|
+
* const ast = parse(expanded);
|
|
912
|
+
* ```
|
|
913
|
+
*/
|
|
914
|
+
declare function resolveIncludesAsync(source: string, fetcher: AsyncIncludeFetcher, options?: ResolveIncludesOptions): Promise<string>;
|
|
915
|
+
/**
|
|
886
916
|
* Compile a ListUsers template string into an executable function.
|
|
887
917
|
*
|
|
888
918
|
* The template is split into alternating static strings and dynamic getter
|
|
@@ -981,4 +1011,4 @@ interface ResolveOptions {
|
|
|
981
1011
|
*/
|
|
982
1012
|
declare function resolveModules(ast: SyntaxTree2, dataProvider: DataProvider, options: ResolveOptions): Promise<SyntaxTree2>;
|
|
983
1013
|
import { STYLE_SLOT_PREFIX } from "@wdprlib/ast";
|
|
984
|
-
export { tokenize, text, resolveModules, resolveListUsers, resolveIncludes, parseTags, parseParent, parseOrder, parseNumericSelector, parseDateSelector, parseCategory, parse, paragraph, normalizeQuery, listItemSubList, listItemElements, list, link, lineBreak, italics, isListUsersModule, horizontalRule, heading, extractListUsersVariables, extractDataRequirements, createToken, createSettings, createPosition, createPoint, container, compileTemplate, compileListUsersTemplate, bold, WikitextSettings4 as WikitextSettings, WikitextMode, Version2 as Version, VariableMap, VariableContext, UserInfo, TokenType, Token, TocEntry2 as TocEntry, TableRow, TableData, TableCell, TabData, SyntaxTree3 as SyntaxTree, SiteContext, STYLE_SLOT_PREFIX, ResolveOptions, ResolveIncludesOptions, Position2 as Position, Point, ParserOptions, Parser, ParseResult2 as ParseResult, ParseFunction, PageRef2 as PageRef, PageData, NormalizedTags, NormalizedParent, NormalizedOrder, NormalizedNumericSelector, NormalizedListPagesQuery, NormalizedDateSelector, NormalizedCategory, Module4 as Module, ListUsersVariableContext, ListUsersVariable, ListUsersUserData, ListUsersExternalData, ListUsersDataRequirement, ListUsersDataFetcher, ListUsersCompiledTemplate, ListType, ListPagesVariable, ListPagesQuery, ListPagesExternalData, ListPagesDataRequirement, ListPagesDataFetcher, ListItem, ListData, LinkType, LinkLocation, LinkLabel, LexerOptions, Lexer, IncludeFetcher, ImageSource, HeadingLevel, Heading, HeaderType, FloatAlignment, ExtractionResult, Embed, Element6 as Element, DiagnosticSeverity, Diagnostic2 as Diagnostic, DefinitionListItem, DateItem, DataRequirements, DataProvider, DEFAULT_SETTINGS, ContainerType, ContainerData, CompiledTemplate, CollapsibleData, CodeBlockData2 as CodeBlockData, ClearFloat, AttributeMap, AnchorTarget, Alignment, AlignType };
|
|
1014
|
+
export { tokenize, text, resolveModules, resolveListUsers, resolveIncludesAsync, resolveIncludes, parseTags, parseParent, parseOrder, parseNumericSelector, parseDateSelector, parseCategory, parse, paragraph, normalizeQuery, listItemSubList, listItemElements, list, link, lineBreak, italics, isListUsersModule, horizontalRule, heading, extractListUsersVariables, extractDataRequirements, createToken, createSettings, createPosition, createPoint, container, compileTemplate, compileListUsersTemplate, bold, WikitextSettings4 as WikitextSettings, WikitextMode, Version2 as Version, VariableMap, VariableContext, UserInfo, TokenType, Token, TocEntry2 as TocEntry, TableRow, TableData, TableCell, TabData, SyntaxTree3 as SyntaxTree, SiteContext, STYLE_SLOT_PREFIX, ResolveOptions, ResolveIncludesOptions, Position2 as Position, Point, ParserOptions, Parser, ParseResult2 as ParseResult, ParseFunction, PageRef2 as PageRef, PageData, NormalizedTags, NormalizedParent, NormalizedOrder, NormalizedNumericSelector, NormalizedListPagesQuery, NormalizedDateSelector, NormalizedCategory, Module4 as Module, ListUsersVariableContext, ListUsersVariable, ListUsersUserData, ListUsersExternalData, ListUsersDataRequirement, ListUsersDataFetcher, ListUsersCompiledTemplate, ListType, ListPagesVariable, ListPagesQuery, ListPagesExternalData, ListPagesDataRequirement, ListPagesDataFetcher, ListItem, ListData, LinkType, LinkLocation, LinkLabel, LexerOptions, Lexer, IncludeFetcher, ImageSource, HeadingLevel, Heading, HeaderType, FloatAlignment, ExtractionResult, Embed, Element6 as Element, DiagnosticSeverity, Diagnostic2 as Diagnostic, DefinitionListItem, DateItem, DataRequirements, DataProvider, DEFAULT_SETTINGS, ContainerType, ContainerData, CompiledTemplate, CollapsibleData, CodeBlockData2 as CodeBlockData, ClearFloat, AttributeMap, AsyncIncludeFetcher, AnchorTarget, Alignment, AlignType };
|
package/dist/index.js
CHANGED
|
@@ -590,6 +590,51 @@ var BLOCK_START_TOKENS = [
|
|
|
590
590
|
"CLEAR_FLOAT_LEFT",
|
|
591
591
|
"CLEAR_FLOAT_RIGHT"
|
|
592
592
|
];
|
|
593
|
+
var KNOWN_BLOCK_NAMES = new Set([
|
|
594
|
+
"collapsible",
|
|
595
|
+
"div",
|
|
596
|
+
"div_",
|
|
597
|
+
"code",
|
|
598
|
+
"ul",
|
|
599
|
+
"ol",
|
|
600
|
+
"li",
|
|
601
|
+
"table",
|
|
602
|
+
"row",
|
|
603
|
+
"cell",
|
|
604
|
+
"hcell",
|
|
605
|
+
"tabview",
|
|
606
|
+
"tabs",
|
|
607
|
+
"module",
|
|
608
|
+
"module654",
|
|
609
|
+
"bibliography",
|
|
610
|
+
"footnoteblock",
|
|
611
|
+
"toc",
|
|
612
|
+
"iframe",
|
|
613
|
+
"math",
|
|
614
|
+
"html",
|
|
615
|
+
"iftags",
|
|
616
|
+
"include",
|
|
617
|
+
"f",
|
|
618
|
+
"embed",
|
|
619
|
+
"embedvideo",
|
|
620
|
+
"embedaudio",
|
|
621
|
+
"<",
|
|
622
|
+
">",
|
|
623
|
+
"=",
|
|
624
|
+
"==",
|
|
625
|
+
"span",
|
|
626
|
+
"span_",
|
|
627
|
+
"user",
|
|
628
|
+
"a",
|
|
629
|
+
"anchor",
|
|
630
|
+
"size",
|
|
631
|
+
"footnote",
|
|
632
|
+
"eref",
|
|
633
|
+
"$",
|
|
634
|
+
"image",
|
|
635
|
+
"gallery",
|
|
636
|
+
"file"
|
|
637
|
+
]);
|
|
593
638
|
|
|
594
639
|
// packages/parser/src/parser/rules/utils.ts
|
|
595
640
|
var SAFE_ATTRIBUTES = new Set([
|
|
@@ -724,6 +769,19 @@ function isExcludedBlockToken(ctx, tokenPos) {
|
|
|
724
769
|
const nameResult = parseBlockName(ctx, tokenPos + 1);
|
|
725
770
|
return nameResult !== null && ctx.excludedBlockNames.has(nameResult.name);
|
|
726
771
|
}
|
|
772
|
+
function isUnknownBlockToken(ctx, tokenPos) {
|
|
773
|
+
const token = ctx.tokens[tokenPos];
|
|
774
|
+
if (token?.type !== "BLOCK_OPEN" && token?.type !== "BLOCK_END_OPEN")
|
|
775
|
+
return false;
|
|
776
|
+
const nameResult = parseBlockName(ctx, tokenPos + 1);
|
|
777
|
+
if (nameResult === null) {
|
|
778
|
+
if (ctx.tokens[tokenPos + 1]?.type === "EQUALS") {
|
|
779
|
+
return false;
|
|
780
|
+
}
|
|
781
|
+
return true;
|
|
782
|
+
}
|
|
783
|
+
return !KNOWN_BLOCK_NAMES.has(nameResult.name);
|
|
784
|
+
}
|
|
727
785
|
function canApplyInlineRule(rule, token) {
|
|
728
786
|
if (rule.startTokens.length === 0) {
|
|
729
787
|
return true;
|
|
@@ -816,7 +874,8 @@ function parseInlineUntil(ctx, endType) {
|
|
|
816
874
|
}
|
|
817
875
|
}
|
|
818
876
|
const isExcludedBlock = (nextMeaningfulToken?.type === "BLOCK_OPEN" || nextMeaningfulToken?.type === "BLOCK_END_OPEN") && isExcludedBlockToken(ctx, pos + lookAhead);
|
|
819
|
-
const
|
|
877
|
+
const isUnknownBlock = (nextMeaningfulToken?.type === "BLOCK_OPEN" || nextMeaningfulToken?.type === "BLOCK_END_OPEN") && isUnknownBlockToken(ctx, pos + lookAhead);
|
|
878
|
+
const isBlockStart = nextMeaningfulToken && BLOCK_START_TOKENS.includes(nextMeaningfulToken.type) && nextMeaningfulToken.lineStart && !isOrphanCloseSpan && !isAnchorName && !isInvalidBlockOpen && !isInvalidHeading && !isExcludedBlock && !isUnknownBlock;
|
|
820
879
|
if (!nextMeaningfulToken || nextMeaningfulToken.type === "NEWLINE" || nextMeaningfulToken.type === "EOF" || isBlockStart) {
|
|
821
880
|
if (isBlockStart && nodes.length > 0) {
|
|
822
881
|
const nextPos = pos + lookAhead;
|
|
@@ -1153,7 +1212,6 @@ function buildListData(topLtype, list) {
|
|
|
1153
1212
|
items
|
|
1154
1213
|
};
|
|
1155
1214
|
}
|
|
1156
|
-
|
|
1157
1215
|
// packages/parser/src/parser/rules/block/utils.ts
|
|
1158
1216
|
function canApplyBlockRule(rule, token) {
|
|
1159
1217
|
if (rule.requiresLineStart && !token.lineStart) {
|
|
@@ -9913,7 +9971,7 @@ function resolveIncludes(source, fetcher, options) {
|
|
|
9913
9971
|
if (options?.settings && !options.settings.enablePageSyntax) {
|
|
9914
9972
|
return source;
|
|
9915
9973
|
}
|
|
9916
|
-
const
|
|
9974
|
+
const maxIterations = options?.maxIterations ?? 10;
|
|
9917
9975
|
const cache = new Map;
|
|
9918
9976
|
const cachedFetcher = (pageRef) => {
|
|
9919
9977
|
const key = normalizePageKey(pageRef);
|
|
@@ -9929,7 +9987,29 @@ function resolveIncludes(source, fetcher, options) {
|
|
|
9929
9987
|
cache.set(key, result);
|
|
9930
9988
|
return result;
|
|
9931
9989
|
};
|
|
9932
|
-
return
|
|
9990
|
+
return expandIterative(source, cachedFetcher, maxIterations);
|
|
9991
|
+
}
|
|
9992
|
+
async function resolveIncludesAsync(source, fetcher, options) {
|
|
9993
|
+
if (options?.settings && !options.settings.enablePageSyntax) {
|
|
9994
|
+
return source;
|
|
9995
|
+
}
|
|
9996
|
+
const maxIterations = options?.maxIterations ?? 10;
|
|
9997
|
+
const cache = new Map;
|
|
9998
|
+
const cachedFetcher = async (pageRef) => {
|
|
9999
|
+
const key = normalizePageKey(pageRef);
|
|
10000
|
+
if (cache.has(key)) {
|
|
10001
|
+
return cache.get(key);
|
|
10002
|
+
}
|
|
10003
|
+
let result;
|
|
10004
|
+
try {
|
|
10005
|
+
result = await fetcher(pageRef);
|
|
10006
|
+
} catch {
|
|
10007
|
+
result = null;
|
|
10008
|
+
}
|
|
10009
|
+
cache.set(key, result);
|
|
10010
|
+
return result;
|
|
10011
|
+
};
|
|
10012
|
+
return expandIterativeAsync(source, cachedFetcher, maxIterations);
|
|
9933
10013
|
}
|
|
9934
10014
|
var INCLUDE_PATTERN = /^\[\[include\s([^\]]*(?:\](?!\])[^\]]*)*)\]\]/gim;
|
|
9935
10015
|
function parseIncludeDirective(inner) {
|
|
@@ -9979,26 +10059,55 @@ function parseIncludeDirective(inner) {
|
|
|
9979
10059
|
}
|
|
9980
10060
|
return { location, variables };
|
|
9981
10061
|
}
|
|
9982
|
-
function
|
|
9983
|
-
|
|
9984
|
-
|
|
9985
|
-
|
|
9986
|
-
|
|
9987
|
-
|
|
9988
|
-
if (trace.includes(pageKey)) {
|
|
9989
|
-
return `[[div class="error-block"]]
|
|
9990
|
-
Circular include detected: "${location.page}"
|
|
10062
|
+
function replaceOneInclude(_match, inner, fetcher) {
|
|
10063
|
+
const { location, variables } = parseIncludeDirective(inner);
|
|
10064
|
+
const content = fetcher(location);
|
|
10065
|
+
if (content === null) {
|
|
10066
|
+
return `[[div class="error-block"]]
|
|
10067
|
+
Page to be included "${location.page}" cannot be found!
|
|
9991
10068
|
[[/div]]`;
|
|
9992
|
-
|
|
9993
|
-
|
|
9994
|
-
|
|
9995
|
-
|
|
10069
|
+
}
|
|
10070
|
+
return substituteVariables(content, variables);
|
|
10071
|
+
}
|
|
10072
|
+
function expandIterative(source, fetcher, maxIterations) {
|
|
10073
|
+
let current = source;
|
|
10074
|
+
for (let i = 0;i < maxIterations; i++) {
|
|
10075
|
+
const previous = current;
|
|
10076
|
+
current = current.replace(INCLUDE_PATTERN, (_match, inner) => replaceOneInclude(_match, inner, fetcher));
|
|
10077
|
+
if (current === previous)
|
|
10078
|
+
break;
|
|
10079
|
+
}
|
|
10080
|
+
return current;
|
|
10081
|
+
}
|
|
10082
|
+
async function expandIterativeAsync(source, fetcher, maxIterations) {
|
|
10083
|
+
let current = source;
|
|
10084
|
+
for (let i = 0;i < maxIterations; i++) {
|
|
10085
|
+
const previous = current;
|
|
10086
|
+
const pattern = new RegExp(INCLUDE_PATTERN.source, INCLUDE_PATTERN.flags);
|
|
10087
|
+
let result = "";
|
|
10088
|
+
let lastPos = 0;
|
|
10089
|
+
let match;
|
|
10090
|
+
while ((match = pattern.exec(current)) !== null) {
|
|
10091
|
+
const fullMatch = match[0];
|
|
10092
|
+
const inner = match[1];
|
|
10093
|
+
result += current.slice(lastPos, match.index);
|
|
10094
|
+
const { location, variables } = parseIncludeDirective(inner);
|
|
10095
|
+
const content = await fetcher(location);
|
|
10096
|
+
if (content === null) {
|
|
10097
|
+
result += `[[div class="error-block"]]
|
|
9996
10098
|
Page to be included "${location.page}" cannot be found!
|
|
9997
10099
|
[[/div]]`;
|
|
10100
|
+
} else {
|
|
10101
|
+
result += substituteVariables(content, variables);
|
|
10102
|
+
}
|
|
10103
|
+
lastPos = match.index + fullMatch.length;
|
|
9998
10104
|
}
|
|
9999
|
-
|
|
10000
|
-
|
|
10001
|
-
|
|
10105
|
+
result += current.slice(lastPos);
|
|
10106
|
+
current = result;
|
|
10107
|
+
if (current === previous)
|
|
10108
|
+
break;
|
|
10109
|
+
}
|
|
10110
|
+
return current;
|
|
10002
10111
|
}
|
|
10003
10112
|
function normalizePageKey(location) {
|
|
10004
10113
|
const site = location.site ?? "";
|
|
@@ -10227,6 +10336,7 @@ export {
|
|
|
10227
10336
|
text,
|
|
10228
10337
|
resolveModules,
|
|
10229
10338
|
resolveListUsers,
|
|
10339
|
+
resolveIncludesAsync,
|
|
10230
10340
|
resolveIncludes,
|
|
10231
10341
|
parseTags,
|
|
10232
10342
|
parseParent,
|