@wdprlib/parser 4.4.0 → 5.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 +400 -175
- package/dist/index.d.cts +16 -13
- package/dist/index.d.ts +16 -13
- package/dist/index.js +388 -161
- package/package.json +2 -2
- package/src/index.ts +2 -0
- package/src/parser/parse/context.ts +7 -2
- package/src/parser/parse/index.ts +21 -3
- package/src/parser/parse/parser.ts +37 -28
- package/src/parser/preprocess/expr/index.ts +26 -0
- package/src/parser/preprocess/utils/raw-regions.ts +16 -7
- package/src/parser/rules/block/include/index.ts +20 -2
- package/src/parser/rules/block/module/include/resolve/index.ts +28 -0
- package/src/parser/rules/block/module/include/resolve/iterate.ts +28 -4
- package/src/parser/rules/block/module/include/scanner.ts +58 -1
- package/src/parser/rules/block/module/index.ts +2 -0
- package/src/parser/rules/block/module/listpages/index.ts +2 -0
- package/src/parser/rules/block/module/listpages/selectors.ts +64 -0
- package/src/parser/rules/block/module/listpages/types/external-data.ts +22 -0
- package/src/parser/rules/contracts/parse-context.ts +2 -0
- package/src/pipeline/process.ts +118 -34
package/src/pipeline/process.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import { DEFAULT_SETTINGS, type PageRef, type WikitextPageContext } from "@wdprlib/ast";
|
|
2
|
-
import { parse } from "../parser";
|
|
3
|
-
import { extractDataRequirements } from "../parser/rules/block/module/listpages/extract";
|
|
4
1
|
import {
|
|
5
|
-
|
|
6
|
-
type
|
|
7
|
-
type
|
|
8
|
-
|
|
2
|
+
DEFAULT_SETTINGS,
|
|
3
|
+
type Diagnostic,
|
|
4
|
+
type PageRef,
|
|
5
|
+
type WikitextPageContext,
|
|
6
|
+
} from "@wdprlib/ast";
|
|
7
|
+
import { parseWithIncludeDeferral } from "../parser/parse";
|
|
8
|
+
import { extractDataRequirements } from "../parser/rules/block/module/listpages/extract";
|
|
9
|
+
import type { AsyncIncludeFetcher, IncludeDependency } from "../parser/rules/block/module/include";
|
|
10
|
+
import { resolveIncludesAsyncWithTraceSelective } from "../parser/rules/block/module/include/resolve";
|
|
9
11
|
import type { DataProvider } from "../parser/rules/block/module/types-common";
|
|
10
12
|
import { resolveModulesWithAsyncParse } from "../parser/rules/block/module/resolution/resolve-async";
|
|
11
13
|
import type {
|
|
@@ -14,6 +16,12 @@ import type {
|
|
|
14
16
|
ProcessWikitextOptions,
|
|
15
17
|
} from "./types";
|
|
16
18
|
|
|
19
|
+
const DEFAULT_MODULE_MAX_PASSES = 5;
|
|
20
|
+
const PIPELINE_DIAGNOSTIC_POSITION = {
|
|
21
|
+
start: { line: 1, column: 1, offset: 0 },
|
|
22
|
+
end: { line: 1, column: 1, offset: 0 },
|
|
23
|
+
};
|
|
24
|
+
|
|
17
25
|
export async function processWikitext<TPage extends WikitextPageContext>(
|
|
18
26
|
source: string,
|
|
19
27
|
options: ProcessWikitextOptions<TPage>,
|
|
@@ -24,52 +32,128 @@ export async function processWikitext<TPage extends WikitextPageContext>(
|
|
|
24
32
|
settings,
|
|
25
33
|
};
|
|
26
34
|
const dependencies: IncludeDependency[] = [];
|
|
35
|
+
const diagnostics: Diagnostic[] = [];
|
|
27
36
|
const fetchInclude = createRequestIncludeFetcher(
|
|
28
37
|
options.dataProvider?.fetchInclude
|
|
29
38
|
? (pageRef) => options.dataProvider!.fetchInclude!(pageRef, callbackContext)
|
|
30
39
|
: undefined,
|
|
31
40
|
);
|
|
32
41
|
const resolveSource = async (input: string): Promise<string> => {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
42
|
+
let expanded = input;
|
|
43
|
+
if (fetchInclude) {
|
|
44
|
+
const resolution = await resolveIncludesAsyncWithTraceSelective(
|
|
45
|
+
input,
|
|
46
|
+
fetchInclude,
|
|
47
|
+
(reference) => isCurrentPageInclude(reference.location, options.page),
|
|
48
|
+
{
|
|
49
|
+
maxIterations: options.includeMaxIterations,
|
|
50
|
+
settings,
|
|
51
|
+
},
|
|
52
|
+
);
|
|
53
|
+
dependencies.push(...resolution.dependencies);
|
|
54
|
+
if (resolution.reachedMaxIterations) {
|
|
55
|
+
diagnostics.push(
|
|
56
|
+
createLimitDiagnostic(
|
|
57
|
+
"include-resolution-limit",
|
|
58
|
+
`Include expansion stopped after ${options.includeMaxIterations ?? 10} iterations.`,
|
|
59
|
+
),
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
expanded = resolution.source;
|
|
63
|
+
}
|
|
64
|
+
return expanded;
|
|
40
65
|
};
|
|
41
66
|
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
});
|
|
48
|
-
const extraction = extractDataRequirements(initial.ast);
|
|
49
|
-
const dataProvider = createModuleDataProvider(options, callbackContext);
|
|
50
|
-
const resolved = await resolveModulesWithAsyncParse(initial.ast, dataProvider, {
|
|
51
|
-
parse: async (fragmentSource) =>
|
|
52
|
-
parse(await resolveSource(fragmentSource), {
|
|
67
|
+
const parseSource = async (input: string) => {
|
|
68
|
+
const expanded = await resolveSource(input);
|
|
69
|
+
return parseWithIncludeDeferral(
|
|
70
|
+
expanded,
|
|
71
|
+
{
|
|
53
72
|
settings,
|
|
54
73
|
pageTags: options.page.tags,
|
|
55
74
|
appendImplicitFootnoteBlock: false,
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
75
|
+
},
|
|
76
|
+
(location) => isCurrentPageInclude(location, options.page),
|
|
77
|
+
);
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const initial = await parseSource(source);
|
|
81
|
+
diagnostics.push(...initial.diagnostics);
|
|
82
|
+
const dataProvider = createModuleDataProvider(options, callbackContext);
|
|
83
|
+
const parseFragment = parseSource;
|
|
84
|
+
let ast = initial.ast;
|
|
85
|
+
|
|
86
|
+
for (let pass = 0; pass < DEFAULT_MODULE_MAX_PASSES; pass++) {
|
|
87
|
+
const extraction = extractDataRequirements(ast);
|
|
88
|
+
if (pass > 0 && !hasResolvableRequirements(extraction.requirements, options.dataProvider)) {
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const resolved = await resolveModulesWithAsyncParse(ast, dataProvider, {
|
|
93
|
+
parse: parseFragment,
|
|
94
|
+
compiledListPagesTemplates: extraction.compiledListPagesTemplates,
|
|
95
|
+
compiledListUsersTemplates: extraction.compiledListUsersTemplates,
|
|
96
|
+
requirements: extraction.requirements,
|
|
97
|
+
urlPath: options.page.urlPath,
|
|
98
|
+
pageTags: options.page.tags,
|
|
99
|
+
});
|
|
100
|
+
ast = resolved.ast;
|
|
101
|
+
diagnostics.push(...resolved.diagnostics);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (hasResolvableRequirements(extractDataRequirements(ast).requirements, options.dataProvider)) {
|
|
105
|
+
diagnostics.push(
|
|
106
|
+
createLimitDiagnostic(
|
|
107
|
+
"module-resolution-limit",
|
|
108
|
+
`Module resolution stopped after ${DEFAULT_MODULE_MAX_PASSES} passes.`,
|
|
109
|
+
),
|
|
110
|
+
);
|
|
111
|
+
}
|
|
63
112
|
|
|
64
113
|
return {
|
|
65
|
-
ast
|
|
114
|
+
ast,
|
|
66
115
|
page: options.page,
|
|
67
116
|
settings,
|
|
68
|
-
diagnostics
|
|
117
|
+
diagnostics,
|
|
69
118
|
dependencies,
|
|
70
119
|
};
|
|
71
120
|
}
|
|
72
121
|
|
|
122
|
+
function isCurrentPageInclude(location: PageRef, page: WikitextPageContext): boolean {
|
|
123
|
+
if (location.site !== null) {
|
|
124
|
+
if (!page.site || location.site.toLowerCase() !== page.site.toLowerCase()) return false;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const target = location.page.toLowerCase();
|
|
128
|
+
return target === page.fullName.toLowerCase() || target === page.unixName?.toLowerCase();
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function hasResolvableRequirements(
|
|
132
|
+
requirements: ReturnType<typeof extractDataRequirements>["requirements"],
|
|
133
|
+
provider:
|
|
134
|
+
| {
|
|
135
|
+
fetchListPages?: unknown;
|
|
136
|
+
fetchListUsers?: unknown;
|
|
137
|
+
fetchTagCloud?: unknown;
|
|
138
|
+
}
|
|
139
|
+
| undefined,
|
|
140
|
+
): boolean {
|
|
141
|
+
return Boolean(
|
|
142
|
+
(provider?.fetchListPages && requirements.listPages.length > 0) ||
|
|
143
|
+
(provider?.fetchListUsers && requirements.listUsers.length > 0) ||
|
|
144
|
+
(provider?.fetchTagCloud && requirements.tagCloud.length > 0),
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function createLimitDiagnostic(code: string, message: string): Diagnostic {
|
|
149
|
+
return {
|
|
150
|
+
severity: "warning",
|
|
151
|
+
code,
|
|
152
|
+
message,
|
|
153
|
+
position: PIPELINE_DIAGNOSTIC_POSITION,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
|
|
73
157
|
function createModuleDataProvider<TPage extends WikitextPageContext>(
|
|
74
158
|
options: ProcessWikitextOptions<TPage>,
|
|
75
159
|
context: ProcessWikitextCallbackContext<TPage>,
|