@longsightgroup/qti3-core 0.10.6 → 0.11.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/README.md +126 -0
- package/dist/adaptive-turn-materializer.js +4 -5
- package/dist/adaptive-turn-materializer.js.map +1 -1
- package/dist/adaptive-turn.d.ts.map +1 -1
- package/dist/adaptive-turn.js +1 -0
- package/dist/adaptive-turn.js.map +1 -1
- package/dist/attempt-state.d.ts.map +1 -1
- package/dist/attempt-state.js +41 -1
- package/dist/attempt-state.js.map +1 -1
- package/dist/diagnostics.d.ts +13 -0
- package/dist/diagnostics.d.ts.map +1 -0
- package/dist/diagnostics.js +28 -0
- package/dist/diagnostics.js.map +1 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/item-submission-materialization.d.ts.map +1 -1
- package/dist/item-submission-materialization.js +2 -0
- package/dist/item-submission-materialization.js.map +1 -1
- package/dist/parser-processing.d.ts.map +1 -1
- package/dist/parser-processing.js +8 -18
- package/dist/parser-processing.js.map +1 -1
- package/dist/parser-values.d.ts.map +1 -1
- package/dist/parser-values.js +1 -3
- package/dist/parser-values.js.map +1 -1
- package/dist/parser.js +32 -0
- package/dist/parser.js.map +1 -1
- package/dist/processing-equality.d.ts +10 -0
- package/dist/processing-equality.d.ts.map +1 -0
- package/dist/processing-equality.js +78 -0
- package/dist/processing-equality.js.map +1 -0
- package/dist/processing-evaluator-comparison.d.ts.map +1 -1
- package/dist/processing-evaluator-comparison.js +14 -9
- package/dist/processing-evaluator-comparison.js.map +1 -1
- package/dist/processing-evaluator-numeric.d.ts.map +1 -1
- package/dist/processing-evaluator-numeric.js +2 -1
- package/dist/processing-evaluator-numeric.js.map +1 -1
- package/dist/processing-evaluator-string.d.ts.map +1 -1
- package/dist/processing-evaluator-string.js +26 -10
- package/dist/processing-evaluator-string.js.map +1 -1
- package/dist/processing-evaluator-variable.d.ts.map +1 -1
- package/dist/processing-evaluator-variable.js +9 -3
- package/dist/processing-evaluator-variable.js.map +1 -1
- package/dist/processing-evaluator.d.ts +5 -1
- package/dist/processing-evaluator.d.ts.map +1 -1
- package/dist/processing-evaluator.js +13 -4
- package/dist/processing-evaluator.js.map +1 -1
- package/dist/processing-expression-children.d.ts.map +1 -1
- package/dist/processing-expression-children.js +2 -3
- package/dist/processing-expression-children.js.map +1 -1
- package/dist/processing-expression-tags.d.ts +2 -1
- package/dist/processing-expression-tags.d.ts.map +1 -1
- package/dist/processing-expression-tags.js +2 -1
- package/dist/processing-expression-tags.js.map +1 -1
- package/dist/processing-mapping.d.ts.map +1 -1
- package/dist/processing-mapping.js +26 -16
- package/dist/processing-mapping.js.map +1 -1
- package/dist/processing-state.d.ts +2 -2
- package/dist/processing-state.d.ts.map +1 -1
- package/dist/processing-state.js +5 -2
- package/dist/processing-state.js.map +1 -1
- package/dist/processing-values.d.ts +1 -2
- package/dist/processing-values.d.ts.map +1 -1
- package/dist/processing-values.js +1 -3
- package/dist/processing-values.js.map +1 -1
- package/dist/processing-variables.d.ts.map +1 -1
- package/dist/processing-variables.js +10 -5
- package/dist/processing-variables.js.map +1 -1
- package/dist/qti-package-assets.d.ts.map +1 -1
- package/dist/qti-package-assets.js +16 -10
- package/dist/qti-package-assets.js.map +1 -1
- package/dist/qti-package-manifest.d.ts +1 -0
- package/dist/qti-package-manifest.d.ts.map +1 -1
- package/dist/qti-package-manifest.js +1 -0
- package/dist/qti-package-manifest.js.map +1 -1
- package/dist/qti-package-metadata.d.ts.map +1 -1
- package/dist/qti-package-metadata.js +11 -0
- package/dist/qti-package-metadata.js.map +1 -1
- package/dist/qti-package-plan.d.ts +1 -1
- package/dist/qti-package-plan.d.ts.map +1 -1
- package/dist/qti-package-types.d.ts +9 -0
- package/dist/qti-package-types.d.ts.map +1 -1
- package/dist/qti-package-xml.d.ts +6 -1
- package/dist/qti-package-xml.d.ts.map +1 -1
- package/dist/qti-package-xml.js +11 -6
- package/dist/qti-package-xml.js.map +1 -1
- package/dist/qti-package-zip.d.ts +13 -1
- package/dist/qti-package-zip.d.ts.map +1 -1
- package/dist/qti-package-zip.js +185 -54
- package/dist/qti-package-zip.js.map +1 -1
- package/dist/qti-package.d.ts +12 -5
- package/dist/qti-package.d.ts.map +1 -1
- package/dist/qti-package.js +63 -8
- package/dist/qti-package.js.map +1 -1
- package/dist/response-validation-policy.d.ts.map +1 -1
- package/dist/response-validation-policy.js +3 -1
- package/dist/response-validation-policy.js.map +1 -1
- package/dist/response-validation.d.ts.map +1 -1
- package/dist/response-validation.js +2 -1
- package/dist/response-validation.js.map +1 -1
- package/dist/serializer-processing-expressions.d.ts.map +1 -1
- package/dist/serializer-processing-expressions.js +2 -10
- package/dist/serializer-processing-expressions.js.map +1 -1
- package/dist/server-scoring.d.ts.map +1 -1
- package/dist/server-scoring.js +1 -0
- package/dist/server-scoring.js.map +1 -1
- package/dist/session-builtins.d.ts +16 -0
- package/dist/session-builtins.d.ts.map +1 -0
- package/dist/session-builtins.js +58 -0
- package/dist/session-builtins.js.map +1 -0
- package/dist/session.d.ts +5 -1
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +63 -11
- package/dist/session.js.map +1 -1
- package/dist/support-evidence.d.ts.map +1 -1
- package/dist/support-evidence.js +2 -0
- package/dist/support-evidence.js.map +1 -1
- package/dist/support.d.ts.map +1 -1
- package/dist/support.js +64 -23
- package/dist/support.js.map +1 -1
- package/dist/trusted-item-session.d.ts +4 -1
- package/dist/trusted-item-session.d.ts.map +1 -1
- package/dist/trusted-item-session.js +8 -3
- package/dist/trusted-item-session.js.map +1 -1
- package/dist/types.d.ts +21 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/validation-declaration-entries.d.ts.map +1 -1
- package/dist/validation-declaration-entries.js +11 -1
- package/dist/validation-declaration-entries.js.map +1 -1
- package/dist/validation-item-children.d.ts +4 -0
- package/dist/validation-item-children.d.ts.map +1 -0
- package/dist/validation-item-children.js +45 -0
- package/dist/validation-item-children.js.map +1 -0
- package/dist/validation-processing.d.ts.map +1 -1
- package/dist/validation-processing.js +45 -12
- package/dist/validation-processing.js.map +1 -1
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js +12 -0
- package/dist/validation.js.map +1 -1
- package/dist/value-guards.d.ts +4 -0
- package/dist/value-guards.d.ts.map +1 -0
- package/dist/value-guards.js +5 -0
- package/dist/value-guards.js.map +1 -0
- package/dist/xml-schema-regex-data.d.ts +48 -0
- package/dist/xml-schema-regex-data.d.ts.map +1 -0
- package/dist/xml-schema-regex-data.js +403 -0
- package/dist/xml-schema-regex-data.js.map +1 -0
- package/dist/xml-schema-regex-parser.d.ts +31 -0
- package/dist/xml-schema-regex-parser.d.ts.map +1 -0
- package/dist/xml-schema-regex-parser.js +245 -0
- package/dist/xml-schema-regex-parser.js.map +1 -0
- package/dist/xml-schema-regex.d.ts +14 -0
- package/dist/xml-schema-regex.d.ts.map +1 -0
- package/dist/xml-schema-regex.js +114 -0
- package/dist/xml-schema-regex.js.map +1 -0
- package/package.json +1 -1
- package/src/adaptive-turn-materializer.ts +4 -3
- package/src/adaptive-turn.ts +1 -0
- package/src/attempt-state.ts +54 -1
- package/src/diagnostics.ts +29 -0
- package/src/index.ts +9 -0
- package/src/item-submission-materialization.ts +2 -0
- package/src/parser-processing.ts +15 -18
- package/src/parser-values.ts +1 -5
- package/src/parser.ts +34 -0
- package/src/processing-equality.ts +104 -0
- package/src/processing-evaluator-comparison.ts +19 -14
- package/src/processing-evaluator-numeric.ts +2 -6
- package/src/processing-evaluator-string.ts +25 -18
- package/src/processing-evaluator-variable.ts +8 -3
- package/src/processing-evaluator.ts +20 -7
- package/src/processing-expression-children.ts +2 -3
- package/src/processing-expression-tags.ts +2 -1
- package/src/processing-mapping.ts +31 -25
- package/src/processing-state.ts +6 -1
- package/src/processing-values.ts +2 -11
- package/src/processing-variables.ts +9 -7
- package/src/qti-package-assets.ts +20 -13
- package/src/qti-package-manifest.ts +1 -0
- package/src/qti-package-metadata.ts +11 -0
- package/src/qti-package-plan.ts +1 -1
- package/src/qti-package-types.ts +10 -0
- package/src/qti-package-xml.ts +11 -6
- package/src/qti-package-zip.ts +330 -97
- package/src/qti-package.ts +106 -7
- package/src/response-validation-policy.ts +5 -1
- package/src/response-validation.ts +2 -1
- package/src/serializer-processing-expressions.ts +8 -25
- package/src/server-scoring.ts +1 -0
- package/src/session-builtins.ts +75 -0
- package/src/session.ts +64 -8
- package/src/support-evidence.ts +2 -0
- package/src/support.ts +84 -23
- package/src/trusted-item-session.ts +13 -2
- package/src/types.ts +30 -4
- package/src/validation-declaration-entries.ts +11 -1
- package/src/validation-item-children.ts +48 -0
- package/src/validation-processing.ts +47 -10
- package/src/validation.ts +14 -0
- package/src/value-guards.ts +6 -0
- package/src/xml-schema-regex-data.ts +404 -0
- package/src/xml-schema-regex-parser.ts +234 -0
- package/src/xml-schema-regex.ts +115 -0
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import { xmlNameCharacters, xmlNameInitial, xmlSchemaBlocks } from "./xml-schema-regex-data.js";
|
|
2
|
+
export const XML_REGEX_MAX_PATTERN_LENGTH = 16_384;
|
|
3
|
+
export const XML_REGEX_MAX_DEPTH = 64;
|
|
4
|
+
const categories = /^(?:L[ultmo]?|M[nce]?|N[dlo]?|P[cdseifo]?|Z[slp]?|S[mcko]?|C[cfon]?)$/;
|
|
5
|
+
const singleEscapes = { n: "\n", r: "\r", t: "\t" };
|
|
6
|
+
const multiEscapes = {
|
|
7
|
+
s: "[ \\t\\n\\r]",
|
|
8
|
+
S: "[^ \\t\\n\\r]",
|
|
9
|
+
d: "\\p{Nd}",
|
|
10
|
+
D: "\\P{Nd}",
|
|
11
|
+
w: "[^\\p{P}\\p{Z}\\p{C}]",
|
|
12
|
+
W: "[\\p{P}\\p{Z}\\p{C}]",
|
|
13
|
+
i: `[${xmlNameInitial}]`,
|
|
14
|
+
I: `[^${xmlNameInitial}]`,
|
|
15
|
+
c: `[${xmlNameCharacters}]`,
|
|
16
|
+
C: `[^${xmlNameCharacters}]`,
|
|
17
|
+
};
|
|
18
|
+
/** Parses Appendix F syntax; native regexes only classify one code point at a time. */
|
|
19
|
+
export function parseXmlSchemaRegex(pattern) {
|
|
20
|
+
if (pattern.length > XML_REGEX_MAX_PATTERN_LENGTH)
|
|
21
|
+
return {
|
|
22
|
+
ok: false,
|
|
23
|
+
problem: { code: "limit", message: "Pattern exceeds 16384 UTF-16 code units." },
|
|
24
|
+
};
|
|
25
|
+
let offset = 0;
|
|
26
|
+
let problem;
|
|
27
|
+
const peek = () => pattern[offset];
|
|
28
|
+
const hasProblem = () => problem !== undefined;
|
|
29
|
+
const fail = (message, code = "syntax") => {
|
|
30
|
+
problem ??= { code, message: `${message} At pattern offset ${offset}.` };
|
|
31
|
+
return undefined;
|
|
32
|
+
};
|
|
33
|
+
function literal(character) {
|
|
34
|
+
if (!isXmlRegexCharacter(character))
|
|
35
|
+
return fail("Pattern contains a non-XML character.");
|
|
36
|
+
const point = character.codePointAt(0) ?? 0;
|
|
37
|
+
return { source: `\\u{${point.toString(16)}}`, point };
|
|
38
|
+
}
|
|
39
|
+
function escape() {
|
|
40
|
+
offset += 1;
|
|
41
|
+
const character = peek();
|
|
42
|
+
if (character === undefined)
|
|
43
|
+
return fail("Incomplete escape.");
|
|
44
|
+
offset += 1;
|
|
45
|
+
if (Object.hasOwn(singleEscapes, character))
|
|
46
|
+
return literal(singleEscapes[character] ?? "");
|
|
47
|
+
if ("\\|.?*+(){}-[]^".includes(character))
|
|
48
|
+
return literal(character);
|
|
49
|
+
if (Object.hasOwn(multiEscapes, character))
|
|
50
|
+
return { source: multiEscapes[character] ?? "" };
|
|
51
|
+
if (character !== "p" && character !== "P")
|
|
52
|
+
return fail("Unknown XML Schema escape.");
|
|
53
|
+
if (peek() !== "{")
|
|
54
|
+
return fail("Expected a Unicode property in braces.");
|
|
55
|
+
offset += 1;
|
|
56
|
+
const end = pattern.indexOf("}", offset);
|
|
57
|
+
if (end < 0)
|
|
58
|
+
return fail("Unclosed Unicode property.");
|
|
59
|
+
const property = pattern.slice(offset, end);
|
|
60
|
+
offset = end + 1;
|
|
61
|
+
if (categories.test(property))
|
|
62
|
+
return { source: `\\${character}{${property}}` };
|
|
63
|
+
const block = property.startsWith("Is") ? property.slice(2) : "";
|
|
64
|
+
if (!Object.hasOwn(xmlSchemaBlocks, block))
|
|
65
|
+
return fail("Unknown XML Schema Unicode property.");
|
|
66
|
+
const ranges = xmlSchemaBlocks[block];
|
|
67
|
+
// Preserve the Appendix F Specials block's legacy BOM member as well.
|
|
68
|
+
return {
|
|
69
|
+
source: `[${character === "P" ? "^" : ""}${ranges}${block === "Specials" ? "\\u{FEFF}" : ""}]`,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
function classToken() {
|
|
73
|
+
const character = peek();
|
|
74
|
+
if (character === "\\")
|
|
75
|
+
return escape();
|
|
76
|
+
if (character === undefined || character === "[" || character === "]")
|
|
77
|
+
return fail("Expected a character in the class.");
|
|
78
|
+
const code = pattern.codePointAt(offset);
|
|
79
|
+
if (code === undefined)
|
|
80
|
+
return fail("Expected a character.");
|
|
81
|
+
const value = String.fromCodePoint(code);
|
|
82
|
+
offset += value.length;
|
|
83
|
+
return literal(value);
|
|
84
|
+
}
|
|
85
|
+
function characterClass(depth) {
|
|
86
|
+
if (depth > XML_REGEX_MAX_DEPTH)
|
|
87
|
+
return fail("Character-class nesting exceeds 64.", "limit");
|
|
88
|
+
offset += 1;
|
|
89
|
+
const negative = peek() === "^";
|
|
90
|
+
if (negative)
|
|
91
|
+
offset += 1;
|
|
92
|
+
const members = [];
|
|
93
|
+
let subtraction;
|
|
94
|
+
while (!hasProblem() && peek() !== "]") {
|
|
95
|
+
if (members.length > 0 && pattern.slice(offset, offset + 2) === "-[") {
|
|
96
|
+
offset += 1;
|
|
97
|
+
subtraction = characterClass(depth + 1);
|
|
98
|
+
if (peek() !== "]")
|
|
99
|
+
return fail("Subtraction must end the character class.");
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
const wasDash = peek() === "-";
|
|
103
|
+
if (wasDash && members.length > 0 && pattern[offset + 1] !== "]")
|
|
104
|
+
return fail("An unescaped dash must begin or end a class.");
|
|
105
|
+
const first = classToken();
|
|
106
|
+
if (!first)
|
|
107
|
+
return undefined;
|
|
108
|
+
if (!wasDash &&
|
|
109
|
+
peek() === "-" &&
|
|
110
|
+
pattern[offset + 1] !== "[" &&
|
|
111
|
+
pattern[offset + 1] !== "]") {
|
|
112
|
+
offset += 1;
|
|
113
|
+
if (peek() === "-")
|
|
114
|
+
return fail("Escape a dash used as a range endpoint.");
|
|
115
|
+
const last = classToken();
|
|
116
|
+
if (!last)
|
|
117
|
+
return undefined;
|
|
118
|
+
if (first.point === undefined || last.point === undefined || first.point > last.point)
|
|
119
|
+
return fail("Invalid character range.");
|
|
120
|
+
members.push(`[${first.source}-${last.source}]`);
|
|
121
|
+
}
|
|
122
|
+
else
|
|
123
|
+
members.push(first.source);
|
|
124
|
+
}
|
|
125
|
+
if (problem)
|
|
126
|
+
return undefined;
|
|
127
|
+
if (peek() !== "]" || members.length === 0)
|
|
128
|
+
return fail("Unclosed or empty character class.");
|
|
129
|
+
offset += 1;
|
|
130
|
+
const union = `(?:${members.join("|")})`;
|
|
131
|
+
const base = negative ? `(?!${union})[\\s\\S]` : union;
|
|
132
|
+
return subtraction === undefined ? base : `(?!${subtraction})${base}`;
|
|
133
|
+
}
|
|
134
|
+
function characterNode(source) {
|
|
135
|
+
try {
|
|
136
|
+
return { type: "character", matcher: new RegExp(`^(?:${source})$`, "u") };
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
return fail("Unable to compile the character class.");
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
function atom(depth) {
|
|
143
|
+
if (depth > XML_REGEX_MAX_DEPTH)
|
|
144
|
+
return fail("Group nesting exceeds 64.", "limit");
|
|
145
|
+
const token = peek();
|
|
146
|
+
if (token === "(") {
|
|
147
|
+
offset += 1;
|
|
148
|
+
const expression = expressionAt(depth + 1);
|
|
149
|
+
if (peek() !== ")")
|
|
150
|
+
return fail("Unclosed group.");
|
|
151
|
+
offset += 1;
|
|
152
|
+
return expression;
|
|
153
|
+
}
|
|
154
|
+
if (token === "[") {
|
|
155
|
+
const source = characterClass(depth + 1);
|
|
156
|
+
return source === undefined ? undefined : characterNode(source);
|
|
157
|
+
}
|
|
158
|
+
if (token === ".") {
|
|
159
|
+
offset += 1;
|
|
160
|
+
return characterNode("[^\\n\\r]");
|
|
161
|
+
}
|
|
162
|
+
if (token === "\\") {
|
|
163
|
+
const escaped = escape();
|
|
164
|
+
return escaped ? characterNode(escaped.source) : undefined;
|
|
165
|
+
}
|
|
166
|
+
if (token === undefined || "?*+{}]|)".includes(token))
|
|
167
|
+
return fail("Unexpected metacharacter.");
|
|
168
|
+
const value = classToken();
|
|
169
|
+
return value ? characterNode(value.source) : undefined;
|
|
170
|
+
}
|
|
171
|
+
function piece(depth) {
|
|
172
|
+
const child = atom(depth);
|
|
173
|
+
if (!child)
|
|
174
|
+
return undefined;
|
|
175
|
+
const quantifier = peek();
|
|
176
|
+
if (quantifier === "?" || quantifier === "*" || quantifier === "+") {
|
|
177
|
+
offset += 1;
|
|
178
|
+
return {
|
|
179
|
+
type: "repeat",
|
|
180
|
+
child,
|
|
181
|
+
minimum: quantifier === "+" ? 1 : 0,
|
|
182
|
+
maximum: quantifier === "?" ? 1 : Infinity,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
if (quantifier !== "{")
|
|
186
|
+
return child;
|
|
187
|
+
const match = /^\{([0-9]+)(?:,([0-9]*))?\}/.exec(pattern.slice(offset));
|
|
188
|
+
if (!match || match[1] === undefined)
|
|
189
|
+
return fail("Malformed quantifier.");
|
|
190
|
+
offset += match[0].length;
|
|
191
|
+
const minimum = Number(match[1]);
|
|
192
|
+
const maximum = match[2] === undefined ? minimum : match[2] === "" ? Infinity : Number(match[2]);
|
|
193
|
+
if (!Number.isSafeInteger(minimum) || (maximum !== Infinity && !Number.isSafeInteger(maximum)))
|
|
194
|
+
return fail("Quantifier exceeds the safe integer range.", "limit");
|
|
195
|
+
if (maximum < minimum)
|
|
196
|
+
return fail("Quantifier maximum is smaller than its minimum.");
|
|
197
|
+
return { type: "repeat", child, minimum, maximum };
|
|
198
|
+
}
|
|
199
|
+
function expressionAt(depth) {
|
|
200
|
+
const branches = [];
|
|
201
|
+
while (!hasProblem()) {
|
|
202
|
+
const children = [];
|
|
203
|
+
while (peek() !== undefined && peek() !== "|" && peek() !== ")" && !hasProblem()) {
|
|
204
|
+
const node = piece(depth);
|
|
205
|
+
if (!node)
|
|
206
|
+
return undefined;
|
|
207
|
+
children.push(node);
|
|
208
|
+
}
|
|
209
|
+
branches.push({ type: "sequence", children });
|
|
210
|
+
if (peek() !== "|")
|
|
211
|
+
break;
|
|
212
|
+
offset += 1;
|
|
213
|
+
}
|
|
214
|
+
return { type: "choice", children: branches };
|
|
215
|
+
}
|
|
216
|
+
const expression = expressionAt(0);
|
|
217
|
+
if (!problem && offset !== pattern.length)
|
|
218
|
+
fail("Unexpected closing delimiter.");
|
|
219
|
+
if (problem)
|
|
220
|
+
return { ok: false, problem };
|
|
221
|
+
return expression
|
|
222
|
+
? { ok: true, expression }
|
|
223
|
+
: { ok: false, problem: { code: "syntax", message: "Invalid pattern." } };
|
|
224
|
+
}
|
|
225
|
+
/** QTI StringOrVariableRef uses braces, so bare identifiers remain literal patterns. */
|
|
226
|
+
export function patternVariableIdentifier(pattern) {
|
|
227
|
+
if (!pattern.startsWith("{") || !pattern.endsWith("}"))
|
|
228
|
+
return undefined;
|
|
229
|
+
const identifier = pattern.slice(1, -1);
|
|
230
|
+
const initial = `[${xmlNameInitial}]`;
|
|
231
|
+
const rest = `[${xmlNameCharacters}]`;
|
|
232
|
+
return !identifier.includes(":") && new RegExp(`^${initial}${rest}*$`, "u").test(identifier)
|
|
233
|
+
? identifier
|
|
234
|
+
: undefined;
|
|
235
|
+
}
|
|
236
|
+
export function isXmlRegexCharacter(value) {
|
|
237
|
+
const point = value.codePointAt(0) ?? 0;
|
|
238
|
+
return (point === 9 ||
|
|
239
|
+
point === 10 ||
|
|
240
|
+
point === 13 ||
|
|
241
|
+
(point >= 0x20 && point <= 0xd7ff) ||
|
|
242
|
+
(point >= 0xe000 && point <= 0xfffd) ||
|
|
243
|
+
(point >= 0x10000 && point <= 0x10ffff));
|
|
244
|
+
}
|
|
245
|
+
//# sourceMappingURL=xml-schema-regex-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"xml-schema-regex-parser.js","sourceRoot":"","sources":["../src/xml-schema-regex-parser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAkBhG,MAAM,CAAC,MAAM,4BAA4B,GAAG,MAAM,CAAC;AACnD,MAAM,CAAC,MAAM,mBAAmB,GAAG,EAAE,CAAC;AACtC,MAAM,UAAU,GAAG,uEAAuE,CAAC;AAC3F,MAAM,aAAa,GAAqC,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC;AACtF,MAAM,YAAY,GAAqC;IACrD,CAAC,EAAE,cAAc;IACjB,CAAC,EAAE,eAAe;IAClB,CAAC,EAAE,SAAS;IACZ,CAAC,EAAE,SAAS;IACZ,CAAC,EAAE,uBAAuB;IAC1B,CAAC,EAAE,sBAAsB;IACzB,CAAC,EAAE,IAAI,cAAc,GAAG;IACxB,CAAC,EAAE,KAAK,cAAc,GAAG;IACzB,CAAC,EAAE,IAAI,iBAAiB,GAAG;IAC3B,CAAC,EAAE,KAAK,iBAAiB,GAAG;CAC7B,CAAC;AAEF,uFAAuF;AACvF,MAAM,UAAU,mBAAmB,CAAC,OAAe;IACjD,IAAI,OAAO,CAAC,MAAM,GAAG,4BAA4B;QAC/C,OAAO;YACL,EAAE,EAAE,KAAK;YACT,OAAO,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,0CAA0C,EAAE;SAChF,CAAC;IACJ,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,IAAI,OAAoC,CAAC;IACzC,MAAM,IAAI,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACnC,MAAM,UAAU,GAAG,GAAG,EAAE,CAAC,OAAO,KAAK,SAAS,CAAC;IAC/C,MAAM,IAAI,GAAG,CAAC,OAAe,EAAE,OAAgC,QAAQ,EAAa,EAAE;QACpF,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,sBAAsB,MAAM,GAAG,EAAE,CAAC;QACzE,OAAO,SAAS,CAAC;IACnB,CAAC,CAAC;IACF,SAAS,OAAO,CAAC,SAAiB;QAChC,IAAI,CAAC,mBAAmB,CAAC,SAAS,CAAC;YAAE,OAAO,IAAI,CAAC,uCAAuC,CAAC,CAAC;QAC1F,MAAM,KAAK,GAAG,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC5C,OAAO,EAAE,MAAM,EAAE,OAAO,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC;IACzD,CAAC;IACD,SAAS,MAAM;QACb,MAAM,IAAI,CAAC,CAAC;QACZ,MAAM,SAAS,GAAG,IAAI,EAAE,CAAC;QACzB,IAAI,SAAS,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAC/D,MAAM,IAAI,CAAC,CAAC;QACZ,IAAI,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,SAAS,CAAC;YAAE,OAAO,OAAO,CAAC,aAAa,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC;QAC5F,IAAI,iBAAiB,CAAC,QAAQ,CAAC,SAAS,CAAC;YAAE,OAAO,OAAO,CAAC,SAAS,CAAC,CAAC;QACrE,IAAI,MAAM,CAAC,MAAM,CAAC,YAAY,EAAE,SAAS,CAAC;YAAE,OAAO,EAAE,MAAM,EAAE,YAAY,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC;QAC7F,IAAI,SAAS,KAAK,GAAG,IAAI,SAAS,KAAK,GAAG;YAAE,OAAO,IAAI,CAAC,4BAA4B,CAAC,CAAC;QACtF,IAAI,IAAI,EAAE,KAAK,GAAG;YAAE,OAAO,IAAI,CAAC,wCAAwC,CAAC,CAAC;QAC1E,MAAM,IAAI,CAAC,CAAC;QACZ,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QACzC,IAAI,GAAG,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC,4BAA4B,CAAC,CAAC;QACvD,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAC5C,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC;QACjB,IAAI,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC;YAAE,OAAO,EAAE,MAAM,EAAE,KAAK,SAAS,IAAI,QAAQ,GAAG,EAAE,CAAC;QAChF,MAAM,KAAK,GAAG,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACjE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,eAAe,EAAE,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC,sCAAsC,CAAC,CAAC;QAChG,MAAM,MAAM,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;QACtC,sEAAsE;QACtE,OAAO;YACL,MAAM,EAAE,IAAI,SAAS,KAAK,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,GAAG,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,GAAG;SAC/F,CAAC;IACJ,CAAC;IACD,SAAS,UAAU;QACjB,MAAM,SAAS,GAAG,IAAI,EAAE,CAAC;QACzB,IAAI,SAAS,KAAK,IAAI;YAAE,OAAO,MAAM,EAAE,CAAC;QACxC,IAAI,SAAS,KAAK,SAAS,IAAI,SAAS,KAAK,GAAG,IAAI,SAAS,KAAK,GAAG;YACnE,OAAO,IAAI,CAAC,oCAAoC,CAAC,CAAC;QACpD,MAAM,IAAI,GAAG,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QACzC,IAAI,IAAI,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC,uBAAuB,CAAC,CAAC;QAC7D,MAAM,KAAK,GAAG,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QACzC,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC;QACvB,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC;IACxB,CAAC;IACD,SAAS,cAAc,CAAC,KAAa;QACnC,IAAI,KAAK,GAAG,mBAAmB;YAAE,OAAO,IAAI,CAAC,qCAAqC,EAAE,OAAO,CAAC,CAAC;QAC7F,MAAM,IAAI,CAAC,CAAC;QACZ,MAAM,QAAQ,GAAG,IAAI,EAAE,KAAK,GAAG,CAAC;QAChC,IAAI,QAAQ;YAAE,MAAM,IAAI,CAAC,CAAC;QAC1B,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,IAAI,WAA+B,CAAC;QACpC,OAAO,CAAC,UAAU,EAAE,IAAI,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YACvC,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;gBACrE,MAAM,IAAI,CAAC,CAAC;gBACZ,WAAW,GAAG,cAAc,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;gBACxC,IAAI,IAAI,EAAE,KAAK,GAAG;oBAAE,OAAO,IAAI,CAAC,2CAA2C,CAAC,CAAC;gBAC7E,MAAM;YACR,CAAC;YACD,MAAM,OAAO,GAAG,IAAI,EAAE,KAAK,GAAG,CAAC;YAC/B,IAAI,OAAO,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,GAAG;gBAC9D,OAAO,IAAI,CAAC,8CAA8C,CAAC,CAAC;YAC9D,MAAM,KAAK,GAAG,UAAU,EAAE,CAAC;YAC3B,IAAI,CAAC,KAAK;gBAAE,OAAO,SAAS,CAAC;YAC7B,IACE,CAAC,OAAO;gBACR,IAAI,EAAE,KAAK,GAAG;gBACd,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,GAAG;gBAC3B,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,GAAG,EAC3B,CAAC;gBACD,MAAM,IAAI,CAAC,CAAC;gBACZ,IAAI,IAAI,EAAE,KAAK,GAAG;oBAAE,OAAO,IAAI,CAAC,yCAAyC,CAAC,CAAC;gBAC3E,MAAM,IAAI,GAAG,UAAU,EAAE,CAAC;gBAC1B,IAAI,CAAC,IAAI;oBAAE,OAAO,SAAS,CAAC;gBAC5B,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK;oBACnF,OAAO,IAAI,CAAC,0BAA0B,CAAC,CAAC;gBAC1C,OAAO,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;YACnD,CAAC;;gBAAM,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACpC,CAAC;QACD,IAAI,OAAO;YAAE,OAAO,SAAS,CAAC;QAC9B,IAAI,IAAI,EAAE,KAAK,GAAG,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC,oCAAoC,CAAC,CAAC;QAC9F,MAAM,IAAI,CAAC,CAAC;QACZ,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;QACzC,MAAM,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC;QACvD,OAAO,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,WAAW,IAAI,IAAI,EAAE,CAAC;IACxE,CAAC;IACD,SAAS,aAAa,CAAC,MAAc;QACnC,IAAI,CAAC;YACH,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,MAAM,CAAC,OAAO,MAAM,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC;QAC5E,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC,wCAAwC,CAAC,CAAC;QACxD,CAAC;IACH,CAAC;IACD,SAAS,IAAI,CAAC,KAAa;QACzB,IAAI,KAAK,GAAG,mBAAmB;YAAE,OAAO,IAAI,CAAC,2BAA2B,EAAE,OAAO,CAAC,CAAC;QACnF,MAAM,KAAK,GAAG,IAAI,EAAE,CAAC;QACrB,IAAI,KAAK,KAAK,GAAG,EAAE,CAAC;YAClB,MAAM,IAAI,CAAC,CAAC;YACZ,MAAM,UAAU,GAAG,YAAY,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;YAC3C,IAAI,IAAI,EAAE,KAAK,GAAG;gBAAE,OAAO,IAAI,CAAC,iBAAiB,CAAC,CAAC;YACnD,MAAM,IAAI,CAAC,CAAC;YACZ,OAAO,UAAU,CAAC;QACpB,CAAC;QACD,IAAI,KAAK,KAAK,GAAG,EAAE,CAAC;YAClB,MAAM,MAAM,GAAG,cAAc,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;YACzC,OAAO,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QAClE,CAAC;QACD,IAAI,KAAK,KAAK,GAAG,EAAE,CAAC;YAClB,MAAM,IAAI,CAAC,CAAC;YACZ,OAAO,aAAa,CAAC,WAAW,CAAC,CAAC;QACpC,CAAC;QACD,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACnB,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC;YACzB,OAAO,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC7D,CAAC;QACD,IAAI,KAAK,KAAK,SAAS,IAAI,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC,2BAA2B,CAAC,CAAC;QAChG,MAAM,KAAK,GAAG,UAAU,EAAE,CAAC;QAC3B,OAAO,KAAK,CAAC,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACzD,CAAC;IACD,SAAS,KAAK,CAAC,KAAa;QAC1B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1B,IAAI,CAAC,KAAK;YAAE,OAAO,SAAS,CAAC;QAC7B,MAAM,UAAU,GAAG,IAAI,EAAE,CAAC;QAC1B,IAAI,UAAU,KAAK,GAAG,IAAI,UAAU,KAAK,GAAG,IAAI,UAAU,KAAK,GAAG,EAAE,CAAC;YACnE,MAAM,IAAI,CAAC,CAAC;YACZ,OAAO;gBACL,IAAI,EAAE,QAAQ;gBACd,KAAK;gBACL,OAAO,EAAE,UAAU,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBACnC,OAAO,EAAE,UAAU,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ;aAC3C,CAAC;QACJ,CAAC;QACD,IAAI,UAAU,KAAK,GAAG;YAAE,OAAO,KAAK,CAAC;QACrC,MAAM,KAAK,GAAG,6BAA6B,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;QACxE,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC,uBAAuB,CAAC,CAAC;QAC3E,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;QAC1B,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACjC,MAAM,OAAO,GACX,KAAK,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACnF,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;YAC5F,OAAO,IAAI,CAAC,4CAA4C,EAAE,OAAO,CAAC,CAAC;QACrE,IAAI,OAAO,GAAG,OAAO;YAAE,OAAO,IAAI,CAAC,iDAAiD,CAAC,CAAC;QACtF,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;IACrD,CAAC;IACD,SAAS,YAAY,CAAC,KAAa;QACjC,MAAM,QAAQ,GAAmB,EAAE,CAAC;QACpC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;YACrB,MAAM,QAAQ,GAAmB,EAAE,CAAC;YACpC,OAAO,IAAI,EAAE,KAAK,SAAS,IAAI,IAAI,EAAE,KAAK,GAAG,IAAI,IAAI,EAAE,KAAK,GAAG,IAAI,CAAC,UAAU,EAAE,EAAE,CAAC;gBACjF,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;gBAC1B,IAAI,CAAC,IAAI;oBAAE,OAAO,SAAS,CAAC;gBAC5B,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACtB,CAAC;YACD,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC,CAAC;YAC9C,IAAI,IAAI,EAAE,KAAK,GAAG;gBAAE,MAAM;YAC1B,MAAM,IAAI,CAAC,CAAC;QACd,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;IAChD,CAAC;IACD,MAAM,UAAU,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;IACnC,IAAI,CAAC,OAAO,IAAI,MAAM,KAAK,OAAO,CAAC,MAAM;QAAE,IAAI,CAAC,+BAA+B,CAAC,CAAC;IACjF,IAAI,OAAO;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;IAC3C,OAAO,UAAU;QACf,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE;QAC1B,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,kBAAkB,EAAE,EAAE,CAAC;AAC9E,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,yBAAyB,CAAC,OAAe;IACvD,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,SAAS,CAAC;IACzE,MAAM,UAAU,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACxC,MAAM,OAAO,GAAG,IAAI,cAAc,GAAG,CAAC;IACtC,MAAM,IAAI,GAAG,IAAI,iBAAiB,GAAG,CAAC;IACtC,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,OAAO,GAAG,IAAI,IAAI,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC;QAC1F,CAAC,CAAC,UAAU;QACZ,CAAC,CAAC,SAAS,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,KAAa;IAC/C,MAAM,KAAK,GAAG,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACxC,OAAO,CACL,KAAK,KAAK,CAAC;QACX,KAAK,KAAK,EAAE;QACZ,KAAK,KAAK,EAAE;QACZ,CAAC,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,MAAM,CAAC;QAClC,CAAC,KAAK,IAAI,MAAM,IAAI,KAAK,IAAI,MAAM,CAAC;QACpC,CAAC,KAAK,IAAI,OAAO,IAAI,KAAK,IAAI,QAAQ,CAAC,CACxC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type XmlRegexProblem } from "./xml-schema-regex-parser.js";
|
|
2
|
+
export { parseXmlSchemaRegex, patternVariableIdentifier } from "./xml-schema-regex-parser.js";
|
|
3
|
+
export declare const XML_REGEX_MAX_INPUT_LENGTH = 100000;
|
|
4
|
+
export declare const XML_REGEX_MAX_STEPS = 1000000;
|
|
5
|
+
export type XmlRegexMatchResult = {
|
|
6
|
+
ok: true;
|
|
7
|
+
matches: boolean;
|
|
8
|
+
} | {
|
|
9
|
+
ok: false;
|
|
10
|
+
problem: XmlRegexProblem;
|
|
11
|
+
};
|
|
12
|
+
/** Whole-string Appendix F matching using memoized position sets, never backtracking. */
|
|
13
|
+
export declare function matchXmlSchemaRegex(pattern: string, input: string): XmlRegexMatchResult;
|
|
14
|
+
//# sourceMappingURL=xml-schema-regex.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"xml-schema-regex.d.ts","sourceRoot":"","sources":["../src/xml-schema-regex.ts"],"names":[],"mappings":"AACA,OAAO,EAIL,KAAK,eAAe,EACrB,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EAAE,mBAAmB,EAAE,yBAAyB,EAAE,MAAM,8BAA8B,CAAC;AAC9F,eAAO,MAAM,0BAA0B,SAAU,CAAC;AAClD,eAAO,MAAM,mBAAmB,UAAY,CAAC;AAC7C,MAAM,MAAM,mBAAmB,GAC3B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,GAC9B;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,eAAe,CAAA;CAAE,CAAC;AAE5C,yFAAyF;AACzF,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,mBAAmB,CAkGvF"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { assertNever } from "./assert-never.js";
|
|
2
|
+
import { isXmlRegexCharacter, parseXmlSchemaRegex, } from "./xml-schema-regex-parser.js";
|
|
3
|
+
export { parseXmlSchemaRegex, patternVariableIdentifier } from "./xml-schema-regex-parser.js";
|
|
4
|
+
export const XML_REGEX_MAX_INPUT_LENGTH = 100_000;
|
|
5
|
+
export const XML_REGEX_MAX_STEPS = 1_000_000;
|
|
6
|
+
/** Whole-string Appendix F matching using memoized position sets, never backtracking. */
|
|
7
|
+
export function matchXmlSchemaRegex(pattern, input) {
|
|
8
|
+
const parsed = parseXmlSchemaRegex(pattern);
|
|
9
|
+
if (!parsed.ok)
|
|
10
|
+
return parsed;
|
|
11
|
+
if (input.length > XML_REGEX_MAX_INPUT_LENGTH)
|
|
12
|
+
return {
|
|
13
|
+
ok: false,
|
|
14
|
+
problem: { code: "limit", message: "Input exceeds 100000 UTF-16 code units." },
|
|
15
|
+
};
|
|
16
|
+
// XML Schema operates on Unicode code points, not grapheme clusters.
|
|
17
|
+
const characters = Array.from(input);
|
|
18
|
+
let remainingSteps = XML_REGEX_MAX_STEPS;
|
|
19
|
+
const memo = new Map();
|
|
20
|
+
const empty = new Set();
|
|
21
|
+
const spend = () => {
|
|
22
|
+
remainingSteps -= 1;
|
|
23
|
+
return remainingSteps >= 0;
|
|
24
|
+
};
|
|
25
|
+
function append(target, source) {
|
|
26
|
+
for (const position of source) {
|
|
27
|
+
if (!spend())
|
|
28
|
+
return;
|
|
29
|
+
target.add(position);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function advance(node, positions) {
|
|
33
|
+
const next = new Set();
|
|
34
|
+
for (const position of positions) {
|
|
35
|
+
if (!spend())
|
|
36
|
+
break;
|
|
37
|
+
append(next, match(node, position));
|
|
38
|
+
}
|
|
39
|
+
return next;
|
|
40
|
+
}
|
|
41
|
+
function match(node, start) {
|
|
42
|
+
if (!spend())
|
|
43
|
+
return empty;
|
|
44
|
+
const cached = memo.get(node)?.get(start);
|
|
45
|
+
if (cached)
|
|
46
|
+
return cached;
|
|
47
|
+
const result = evaluate(node, start);
|
|
48
|
+
let byPosition = memo.get(node);
|
|
49
|
+
if (!byPosition) {
|
|
50
|
+
byPosition = new Map();
|
|
51
|
+
memo.set(node, byPosition);
|
|
52
|
+
}
|
|
53
|
+
byPosition.set(start, result);
|
|
54
|
+
return result;
|
|
55
|
+
}
|
|
56
|
+
function evaluate(node, start) {
|
|
57
|
+
switch (node.type) {
|
|
58
|
+
case "character": {
|
|
59
|
+
const value = characters[start];
|
|
60
|
+
return value !== undefined && isXmlRegexCharacter(value) && node.matcher.test(value)
|
|
61
|
+
? new Set([start + 1])
|
|
62
|
+
: empty;
|
|
63
|
+
}
|
|
64
|
+
case "choice": {
|
|
65
|
+
const result = new Set();
|
|
66
|
+
for (const child of node.children) {
|
|
67
|
+
if (!spend())
|
|
68
|
+
break;
|
|
69
|
+
append(result, match(child, start));
|
|
70
|
+
}
|
|
71
|
+
return result;
|
|
72
|
+
}
|
|
73
|
+
case "sequence": {
|
|
74
|
+
let positions = new Set([start]);
|
|
75
|
+
for (const child of node.children) {
|
|
76
|
+
if (positions.size === 0 || !spend())
|
|
77
|
+
break;
|
|
78
|
+
positions = advance(child, positions);
|
|
79
|
+
}
|
|
80
|
+
return positions;
|
|
81
|
+
}
|
|
82
|
+
case "repeat": {
|
|
83
|
+
const result = new Set(node.minimum === 0 ? [start] : []);
|
|
84
|
+
let positions = new Set([start]);
|
|
85
|
+
for (let count = 1; count <= node.maximum && spend(); count += 1) {
|
|
86
|
+
const next = advance(node.child, positions);
|
|
87
|
+
if (next.size === 0)
|
|
88
|
+
break;
|
|
89
|
+
if (count >= node.minimum)
|
|
90
|
+
append(result, next);
|
|
91
|
+
// Nullable operands can reach a fixed point before a large minimum count.
|
|
92
|
+
if (next.size === positions.size &&
|
|
93
|
+
[...next].every((position) => positions.has(position))) {
|
|
94
|
+
if (count < node.minimum)
|
|
95
|
+
append(result, next);
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
positions = next;
|
|
99
|
+
}
|
|
100
|
+
return result;
|
|
101
|
+
}
|
|
102
|
+
default:
|
|
103
|
+
return assertNever(node);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
const matches = match(parsed.expression, 0).has(characters.length);
|
|
107
|
+
return remainingSteps < 0
|
|
108
|
+
? {
|
|
109
|
+
ok: false,
|
|
110
|
+
problem: { code: "limit", message: "Pattern matching exceeded 1000000 evaluation steps." },
|
|
111
|
+
}
|
|
112
|
+
: { ok: true, matches };
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=xml-schema-regex.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"xml-schema-regex.js","sourceRoot":"","sources":["../src/xml-schema-regex.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -53,14 +53,15 @@ export function materializeAdaptiveCandidateView(
|
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
function shouldPreserveFeedback(node: XmlNode, outcomes: Record<string, QtiValue>): boolean {
|
|
56
|
-
if (node.attributes["show-hide"] === "hide") return false;
|
|
57
56
|
const identifier = node.attributes.identifier;
|
|
58
57
|
const outcomeIdentifier = node.attributes["outcome-identifier"];
|
|
59
58
|
if (!identifier || !outcomeIdentifier) return false;
|
|
60
59
|
|
|
61
60
|
const outcome = outcomes[outcomeIdentifier] ?? null;
|
|
62
|
-
|
|
63
|
-
|
|
61
|
+
const matches = Array.isArray(outcome)
|
|
62
|
+
? outcome.includes(identifier)
|
|
63
|
+
: qtiValueToString(outcome) === identifier;
|
|
64
|
+
return node.attributes["show-hide"] === "hide" ? !matches : matches;
|
|
64
65
|
}
|
|
65
66
|
|
|
66
67
|
function isFeedbackElement(normalizedName: string): boolean {
|
package/src/adaptive-turn.ts
CHANGED
|
@@ -59,6 +59,7 @@ export function runTrustedAdaptiveItemTurn(
|
|
|
59
59
|
parsedItem: input.parsedItem,
|
|
60
60
|
diagnosticPrefix,
|
|
61
61
|
allowedUndeclaredResponseIdentifiers: input.allowedUndeclaredResponseIdentifiers,
|
|
62
|
+
sessionEnvironment: input.sessionEnvironment,
|
|
62
63
|
priorState: priorStateResult.state,
|
|
63
64
|
submission: {
|
|
64
65
|
trustedResponses: input.trustedResponses,
|
package/src/attempt-state.ts
CHANGED
|
@@ -16,9 +16,10 @@ import {
|
|
|
16
16
|
COMPLETION_UNKNOWN,
|
|
17
17
|
} from "./attempt-state-constants.js";
|
|
18
18
|
import { isQtiPortableCustomStateValue, isQtiValue, qtiValueToString } from "./value-format.js";
|
|
19
|
-
import { isRecordValue } from "./
|
|
19
|
+
import { isRecordValue } from "./value-guards.js";
|
|
20
20
|
import { parseQtiSliderDefinition, parseQtiSliderValue } from "./slider-definition.js";
|
|
21
21
|
import { qtiScalarMatchesBaseType } from "./validation-primitives.js";
|
|
22
|
+
import { validateQtiResponseVariables } from "./response-validation.js";
|
|
22
23
|
|
|
23
24
|
export function isQtiAttemptStateV1(value: unknown): value is QtiAttemptStateV1 {
|
|
24
25
|
return attemptStateErrors(value).length === 0;
|
|
@@ -72,6 +73,7 @@ export function assertCompatiblePriorState(
|
|
|
72
73
|
assertRestoredValueMatchesDeclaration("response", declaration, priorState.responses);
|
|
73
74
|
}
|
|
74
75
|
assertRestoredSliderResponses(document, priorState.responses);
|
|
76
|
+
assertRestoredGraphicGapResponses(document, priorState.responses);
|
|
75
77
|
for (const declaration of document.item.outcomeDeclarations) {
|
|
76
78
|
assertRestoredValueMatchesDeclaration("outcome", declaration, priorState.outcomes);
|
|
77
79
|
}
|
|
@@ -92,6 +94,32 @@ export function assertCompatiblePriorState(
|
|
|
92
94
|
}
|
|
93
95
|
}
|
|
94
96
|
|
|
97
|
+
function assertRestoredGraphicGapResponses(
|
|
98
|
+
document: QtiDocument,
|
|
99
|
+
responses: Record<string, QtiValue>,
|
|
100
|
+
): void {
|
|
101
|
+
const responseIdentifiers = document.item.interactions.flatMap((interaction) =>
|
|
102
|
+
interaction.type === "graphicGapMatch" && interaction.responseIdentifier
|
|
103
|
+
? [interaction.responseIdentifier]
|
|
104
|
+
: [],
|
|
105
|
+
);
|
|
106
|
+
if (responseIdentifiers.length === 0) return;
|
|
107
|
+
// Restore may resume an incomplete attempt, but cannot invent placements outside
|
|
108
|
+
// the authored domain or silently discard pairs to fit the interaction limits.
|
|
109
|
+
const result = validateQtiResponseVariables({
|
|
110
|
+
item: document.item,
|
|
111
|
+
responses,
|
|
112
|
+
responseIdentifiers,
|
|
113
|
+
allowIncompleteResponses: true,
|
|
114
|
+
});
|
|
115
|
+
const failure = result.diagnostics.find((diagnostic) => diagnostic.severity === "error");
|
|
116
|
+
if (failure) {
|
|
117
|
+
// Preserve the existing session-constructor assertion contract; player and
|
|
118
|
+
// trusted delivery boundaries translate this failure into typed diagnostics.
|
|
119
|
+
throw new Error(`Cannot restore response ${failure.identifier}: ${failure.message}`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
95
123
|
function assertRestoredSliderResponses(
|
|
96
124
|
document: QtiDocument,
|
|
97
125
|
responses: Record<string, QtiValue>,
|
|
@@ -200,6 +228,31 @@ function attemptStateErrors(value: unknown): string[] {
|
|
|
200
228
|
if (!isQtiValueRecord(value.outcomes)) {
|
|
201
229
|
errors.push("QTI attempt state outcomes must be a record of QTI values.");
|
|
202
230
|
}
|
|
231
|
+
if (value.builtInVariables !== undefined) {
|
|
232
|
+
const builtIns = value.builtInVariables;
|
|
233
|
+
if (
|
|
234
|
+
!isRecord(builtIns) ||
|
|
235
|
+
typeof builtIns.numAttempts !== "number" ||
|
|
236
|
+
!Number.isSafeInteger(builtIns.numAttempts) ||
|
|
237
|
+
builtIns.numAttempts < 0 ||
|
|
238
|
+
typeof builtIns.attemptInProgress !== "boolean" ||
|
|
239
|
+
(builtIns.attemptInProgress && builtIns.numAttempts === 0) ||
|
|
240
|
+
!(
|
|
241
|
+
builtIns.duration === null ||
|
|
242
|
+
(typeof builtIns.duration === "number" &&
|
|
243
|
+
Number.isFinite(builtIns.duration) &&
|
|
244
|
+
builtIns.duration >= 0)
|
|
245
|
+
) ||
|
|
246
|
+
!isRecord(builtIns.context) ||
|
|
247
|
+
!["candidateIdentifier", "testIdentifier", "environmentIdentifier"].every(
|
|
248
|
+
(key) => isRecord(builtIns.context) && typeof builtIns.context[key] === "string",
|
|
249
|
+
)
|
|
250
|
+
) {
|
|
251
|
+
errors.push(
|
|
252
|
+
"QTI attempt state builtInVariables requires a non-negative integer attempt count, attempt flag, finite non-negative duration or null, and three string context fields.",
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
203
256
|
if (value.templateValues !== undefined && !isQtiValueRecord(value.templateValues)) {
|
|
204
257
|
errors.push("QTI attempt state templateValues must be a record of QTI values.");
|
|
205
258
|
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { QtiDiagnostic } from "./types.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Return a new array containing the first diagnostic for each diagnosticKey, in input order.
|
|
5
|
+
* Source locations do not distinguish duplicates; the first object's metadata is retained.
|
|
6
|
+
* The input array and diagnostic objects are not modified or cloned.
|
|
7
|
+
*/
|
|
8
|
+
export function uniqueDiagnostics(diagnostics: readonly QtiDiagnostic[]): QtiDiagnostic[] {
|
|
9
|
+
const seen = new Set<string>();
|
|
10
|
+
return diagnostics.filter((diagnostic) => {
|
|
11
|
+
const key = diagnosticKey(diagnostic);
|
|
12
|
+
if (seen.has(key)) return false;
|
|
13
|
+
seen.add(key);
|
|
14
|
+
return true;
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Identify a diagnostic by code, severity, message, and path, excluding source location.
|
|
20
|
+
* Absent and empty paths are equivalent. Treat the returned string as an opaque key.
|
|
21
|
+
*/
|
|
22
|
+
export function diagnosticKey(diagnostic: QtiDiagnostic): string {
|
|
23
|
+
return JSON.stringify([
|
|
24
|
+
diagnostic.code,
|
|
25
|
+
diagnostic.severity,
|
|
26
|
+
diagnostic.message,
|
|
27
|
+
diagnostic.path ?? "",
|
|
28
|
+
]);
|
|
29
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -5,6 +5,7 @@ export {
|
|
|
5
5
|
type QtiAdaptiveTurnResult,
|
|
6
6
|
} from "./adaptive-turn.js";
|
|
7
7
|
export { assertNever } from "./assert-never.js";
|
|
8
|
+
export { diagnosticKey, uniqueDiagnostics } from "./diagnostics.js";
|
|
8
9
|
export {
|
|
9
10
|
createCatalogSupportResolution,
|
|
10
11
|
type QtiCatalogSupportResolution,
|
|
@@ -57,9 +58,13 @@ export {
|
|
|
57
58
|
discoverQtiPackageContentAssets,
|
|
58
59
|
normalizePackagePath,
|
|
59
60
|
QTI_ITEM_RESOURCE_TYPE,
|
|
61
|
+
isQtiItemResource,
|
|
60
62
|
QTI_PACKAGE_MANIFEST_PATH,
|
|
61
63
|
parseQtiPackage,
|
|
64
|
+
parseQtiPackageFromEntries,
|
|
62
65
|
readQtiPackageZipEntries,
|
|
66
|
+
readQtiPackageZipEntriesAsync,
|
|
67
|
+
scopeDiagnosticToPackagePath,
|
|
63
68
|
type QtiAssessmentSectionPackageModel,
|
|
64
69
|
type QtiAssessmentTestItemRef,
|
|
65
70
|
type QtiAssessmentTestPackageModel,
|
|
@@ -71,11 +76,14 @@ export {
|
|
|
71
76
|
type QtiPackageEntry,
|
|
72
77
|
type QtiPackageInflateContext,
|
|
73
78
|
type QtiPackageInflateRaw,
|
|
79
|
+
type QtiPackageInflateRawAsync,
|
|
80
|
+
type QtiPackageZipAsyncOptions,
|
|
74
81
|
type QtiItemSessionControl,
|
|
75
82
|
type QtiPackageItem,
|
|
76
83
|
type QtiPackageItemSource,
|
|
77
84
|
type QtiPackageParseOptions,
|
|
78
85
|
type QtiPackageParseResult,
|
|
86
|
+
type QtiPackageXmlFileSummary,
|
|
79
87
|
type QtiPackageResourceLimits,
|
|
80
88
|
type QtiPackageShape,
|
|
81
89
|
type QtiStandardAlignment,
|
|
@@ -184,6 +192,7 @@ export {
|
|
|
184
192
|
type QtiCustomOperatorRegistry,
|
|
185
193
|
type QtiItemSession,
|
|
186
194
|
type QtiItemSessionOptions,
|
|
195
|
+
type QtiSessionEnvironment,
|
|
187
196
|
} from "./session.js";
|
|
188
197
|
export {
|
|
189
198
|
deprecatedInteractionSupport,
|
|
@@ -65,6 +65,7 @@ export function materializeQtiItemSubmission(
|
|
|
65
65
|
parsedItem: parsedResult.parsed,
|
|
66
66
|
diagnosticPrefix: "itemSubmission",
|
|
67
67
|
allowedUndeclaredResponseIdentifiers: input.allowedUndeclaredResponseIdentifiers,
|
|
68
|
+
sessionEnvironment: input.sessionEnvironment,
|
|
68
69
|
priorState: priorState.state,
|
|
69
70
|
submission: {
|
|
70
71
|
trustedResponses: input.trustedResponses,
|
|
@@ -98,6 +99,7 @@ function materializeAdaptiveSubmission(
|
|
|
98
99
|
parsedItem,
|
|
99
100
|
diagnosticPrefix: "itemSubmission",
|
|
100
101
|
allowedUndeclaredResponseIdentifiers: input.allowedUndeclaredResponseIdentifiers,
|
|
102
|
+
sessionEnvironment: input.sessionEnvironment,
|
|
101
103
|
priorState: input.existingState,
|
|
102
104
|
trustedResponses: input.trustedResponses,
|
|
103
105
|
trustedInteractionStates: input.trustedInteractionStates,
|