toolcraft 0.0.799 → 0.0.800
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/composition.json +2 -2
- package/dist/composition.json +2 -2
- package/node_modules/@poe-code/safe-fs/dist/core.d.ts +1 -1
- package/node_modules/@poe-code/xml-ast/README.md +34 -9
- package/node_modules/@poe-code/xml-ast/dist/attributes.d.ts +9 -1
- package/node_modules/@poe-code/xml-ast/dist/attributes.js +2 -2
- package/node_modules/@poe-code/xml-ast/dist/frames.d.ts +17 -3
- package/node_modules/@poe-code/xml-ast/dist/frames.js +22 -0
- package/node_modules/@poe-code/xml-ast/dist/index.d.ts +9 -2
- package/node_modules/@poe-code/xml-ast/dist/index.js +75 -26
- package/node_modules/@poe-code/xml-ast/dist/source.d.ts +4 -0
- package/node_modules/tiny-stdio-mcp-server/dist/composition.json +1 -1
- package/node_modules/toolcraft-schema/package.json +1 -1
- package/package.json +2 -2
package/composition.json
CHANGED
|
@@ -138,7 +138,7 @@
|
|
|
138
138
|
},
|
|
139
139
|
{
|
|
140
140
|
"name": "toolcraft",
|
|
141
|
-
"version": "0.0.
|
|
141
|
+
"version": "0.0.800",
|
|
142
142
|
"license": "MIT"
|
|
143
143
|
},
|
|
144
144
|
{
|
|
@@ -148,7 +148,7 @@
|
|
|
148
148
|
},
|
|
149
149
|
{
|
|
150
150
|
"name": "toolcraft-schema",
|
|
151
|
-
"version": "0.0.
|
|
151
|
+
"version": "0.0.800",
|
|
152
152
|
"license": "MIT"
|
|
153
153
|
},
|
|
154
154
|
{
|
package/dist/composition.json
CHANGED
|
@@ -138,7 +138,7 @@
|
|
|
138
138
|
},
|
|
139
139
|
{
|
|
140
140
|
"name": "toolcraft",
|
|
141
|
-
"version": "0.0.
|
|
141
|
+
"version": "0.0.800",
|
|
142
142
|
"license": "MIT"
|
|
143
143
|
},
|
|
144
144
|
{
|
|
@@ -148,7 +148,7 @@
|
|
|
148
148
|
},
|
|
149
149
|
{
|
|
150
150
|
"name": "toolcraft-schema",
|
|
151
|
-
"version": "0.0.
|
|
151
|
+
"version": "0.0.800",
|
|
152
152
|
"license": "MIT"
|
|
153
153
|
},
|
|
154
154
|
{
|
|
@@ -9,7 +9,7 @@ export * from "./fs/webdav/index.js";
|
|
|
9
9
|
export * from "./bridge/index.js";
|
|
10
10
|
export * from "./python/index.js";
|
|
11
11
|
export { parseXml, parseXmlSteps, parseXmlSourceSteps, normalizeXmlChunks, parseXmlStream, XmlLimitError } from "./xml.js";
|
|
12
|
-
export type { XmlName, XmlAttribute, XmlContent, XmlElement, XmlLimits, XmlParserFrame, XmlFrameRequest, XmlNamespaceScope, XmlNamespaceRequest, XmlAttributeRequest, XmlAttributeRecord } from "./xml.js";
|
|
12
|
+
export type { XmlName, XmlAttribute, XmlContent, XmlElement, XmlLimits, XmlParserFrame, XmlFrameRequest, XmlNamespaceScope, XmlNamespaceRequest, XmlSourceRead, XmlSourceSpan, XmlAttributeRequest, XmlAttributeRecord } from "./xml.js";
|
|
13
13
|
export * from "./contracts/object.js";
|
|
14
14
|
export { ObjectAuthority } from "./fs/object-authority.js";
|
|
15
15
|
export * from "./fs/s3/index.js";
|
|
@@ -64,31 +64,48 @@ size cost. The default string and stream APIs retain their existing ancestry beh
|
|
|
64
64
|
|
|
65
65
|
Also set `storeNamespaces: true` to resolve namespace scopes through host-backed
|
|
66
66
|
immutable storage. `namespaceOperation: "get"` supplies a scope and prefix; fill
|
|
67
|
-
`value` when present and set `complete: true`. For `"
|
|
67
|
+
`value` when present and set `complete: true`. For `"has"`, fill `found` using
|
|
68
|
+
membership without reading the URI value. For `"set"`, bind the supplied prefix
|
|
68
69
|
and value in a new scope, then fill `result` with its storage `reference` and the
|
|
69
70
|
number of distinct bindings (`size`). Frames carry this scope handle so shadowing
|
|
70
71
|
never changes ancestor scopes. In this mode event elements have an empty
|
|
71
72
|
`namespaces` map; their names and attributes still carry resolved namespace URIs.
|
|
72
|
-
The codec remains filesystem-independent
|
|
73
|
-
|
|
73
|
+
The codec remains filesystem-independent. With `deferNamespaces: true`, resolved
|
|
74
|
+
URI metadata uses optional `namespaceReference` handles instead of complete strings.
|
|
75
|
+
Service `namespaceOperation: "reference"` by supplying the token `reference` when
|
|
76
|
+
present and setting `complete: true`. These handles belong to the host scope store;
|
|
77
|
+
retain or stream them before retiring that store. Built-in xml/xmlns names keep
|
|
78
|
+
their short namespace strings. Individual names still retain their token cost;
|
|
79
|
+
attribute values can use the fragment protocol below.
|
|
74
80
|
|
|
75
81
|
Set `storeAttributes: true` to move current-tag attribute values, source order,
|
|
76
82
|
and duplicate-name state behind `attributeOperation` requests (`has`, `append`,
|
|
77
83
|
`read`, and `expanded`). Service the request's `found` or `result` field as described
|
|
78
|
-
by `XmlAttributeRequest`, keeping records in caller-owned backing.
|
|
84
|
+
by `XmlAttributeRequest`, keeping records in caller-owned backing. When namespace
|
|
85
|
+
storage is also enabled, `expanded` supplies the local name and a `namespace` scope
|
|
86
|
+
and prefix. Check the pair of resolved URI and local name without joining them in
|
|
87
|
+
memory; an empty prefix means no attribute namespace, regardless of the default
|
|
88
|
+
element namespace. With this flag,
|
|
79
89
|
element `attributes` arrays are empty. Supply `onAttribute(attribute, element)` to
|
|
80
90
|
receive resolved attributes in source order, after the open event and before any
|
|
81
91
|
content or close event. The parser yields between attributes so a host can await
|
|
82
92
|
storage or a consumer. Namespace declarations may follow prefixed attributes;
|
|
83
93
|
resolution and duplicate-expanded-name validation still happen after the complete
|
|
84
|
-
start tag. With `fragmentAttributes: true`, ordinary values are validated
|
|
85
|
-
stored as
|
|
94
|
+
start tag. With `fragmentAttributes: true`, ordinary values are validated through source spans; all attribute
|
|
95
|
+
values are stored as spans on attribute records and replayed in at most 512 UTF-16
|
|
86
96
|
units. Hosts must preserve the optional `source` field in append/read requests.
|
|
87
97
|
The third `onAttribute` argument is `true` for continuations of the same logical
|
|
88
98
|
attribute; await each fragment before requesting the next step. Empty attributes
|
|
89
99
|
still emit once. Entity diagnostics are emitted during validation, not replay.
|
|
90
|
-
This mode requires `storeAttributes: true`.
|
|
91
|
-
|
|
100
|
+
This mode requires `storeAttributes: true`. Combining it with `storeNamespaces`
|
|
101
|
+
also validates namespace declarations in bounded fragments. A namespace `set`
|
|
102
|
+
request's `value` may then be a generator: strings are decoded value fragments,
|
|
103
|
+
numbers are work checkpoints, and objects are source-read requests. Service each
|
|
104
|
+
step before advancing, consume the complete value before filling `result`, and
|
|
105
|
+
close the producer if storage fails. Reserved URI checks preserve their diagnostic
|
|
106
|
+
order without joining fragments. Expanded-name events return complete URI strings
|
|
107
|
+
unless deferred namespace metadata is enabled; individual names still retain
|
|
108
|
+
their token cost.
|
|
92
109
|
|
|
93
110
|
Pass `undefined` as the source length to parse incrementally. Such read requests
|
|
94
111
|
have `streaming: true` and request at most 512 UTF-16 units. Return any nonempty
|
|
@@ -107,4 +124,12 @@ decoding replay bounded source windows before publishing a logical node, retaini
|
|
|
107
124
|
its diagnostic and limit ordering. Numeric entity references are decoded without
|
|
108
125
|
materializing the token. Set `compactDeclaration: true` to retain normalized declaration fields without
|
|
109
126
|
copying long whitespace spans; validation always reads bounded windows. The
|
|
110
|
-
buffered API keeps the original declaration spelling.
|
|
127
|
+
buffered API keeps the original declaration spelling.
|
|
128
|
+
|
|
129
|
+
Combine `fragmentContent` with `deferContentNames: true` to validate long
|
|
130
|
+
processing-instruction targets through source windows. Their events have an empty
|
|
131
|
+
`target` and a `targetSource` span; replay that span before retiring the source.
|
|
132
|
+
All body continuations carry the same target span. Short targets remain strings.
|
|
133
|
+
The stored document engine transfers these spans to its own token store and
|
|
134
|
+
streams targets during output. Element and attribute names still require their
|
|
135
|
+
own memory budget.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { XmlNamespaceScope } from "./frames.js";
|
|
1
2
|
export interface XmlAttributeRecord {
|
|
2
3
|
name: string;
|
|
3
4
|
prefix: string;
|
|
@@ -20,6 +21,10 @@ export type XmlAttributeRequest = {
|
|
|
20
21
|
state: XmlAttributeState;
|
|
21
22
|
name: string;
|
|
22
23
|
found?: boolean;
|
|
24
|
+
namespace?: {
|
|
25
|
+
scope: XmlNamespaceScope;
|
|
26
|
+
prefix: string;
|
|
27
|
+
};
|
|
23
28
|
} | {
|
|
24
29
|
attributeOperation: 'append';
|
|
25
30
|
state: XmlAttributeState;
|
|
@@ -50,5 +55,8 @@ export declare class XmlAttributes {
|
|
|
50
55
|
end: number;
|
|
51
56
|
}): Generator<XmlAttributeRequest, void, void>;
|
|
52
57
|
read(reference: number, values: boolean): Generator<XmlAttributeRequest, XmlAttributeRecord, void>;
|
|
53
|
-
expanded(name: string
|
|
58
|
+
expanded(name: string, namespace?: {
|
|
59
|
+
scope: XmlNamespaceScope;
|
|
60
|
+
prefix: string;
|
|
61
|
+
}): Generator<XmlAttributeRequest, boolean, void>;
|
|
54
62
|
}
|
|
@@ -47,13 +47,13 @@ export class XmlAttributes {
|
|
|
47
47
|
throw new TypeError('Incomplete XML attribute read');
|
|
48
48
|
return request.result;
|
|
49
49
|
}
|
|
50
|
-
*expanded(name) {
|
|
50
|
+
*expanded(name, namespace) {
|
|
51
51
|
if (!this.external) {
|
|
52
52
|
const found = this.expandedNames.has(name);
|
|
53
53
|
this.expandedNames.add(name);
|
|
54
54
|
return found;
|
|
55
55
|
}
|
|
56
|
-
const request = { attributeOperation: 'expanded', state: this.state, name };
|
|
56
|
+
const request = { attributeOperation: 'expanded', state: this.state, name, ...(namespace ? { namespace } : {}) };
|
|
57
57
|
yield request;
|
|
58
58
|
if (request.found === undefined)
|
|
59
59
|
throw new TypeError('Incomplete XML expanded attribute lookup');
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { XmlSourceStep } from './source.js';
|
|
2
|
+
import type { XmlContent, XmlElement, XmlName } from './index.js';
|
|
2
3
|
export interface XmlParserFrame {
|
|
3
4
|
element: XmlElement;
|
|
4
5
|
content: XmlContent[] | undefined;
|
|
@@ -33,6 +34,17 @@ export interface XmlNamespaceScope {
|
|
|
33
34
|
readonly size: number;
|
|
34
35
|
}
|
|
35
36
|
export type XmlNamespaceRequest = {
|
|
37
|
+
readonly namespaceOperation: 'reference';
|
|
38
|
+
readonly scope: XmlNamespaceScope;
|
|
39
|
+
readonly prefix: string;
|
|
40
|
+
reference?: number;
|
|
41
|
+
complete?: true;
|
|
42
|
+
} | {
|
|
43
|
+
readonly namespaceOperation: 'has';
|
|
44
|
+
readonly scope: XmlNamespaceScope;
|
|
45
|
+
readonly prefix: string;
|
|
46
|
+
found?: boolean;
|
|
47
|
+
} | {
|
|
36
48
|
readonly namespaceOperation: 'get';
|
|
37
49
|
readonly scope: XmlNamespaceScope;
|
|
38
50
|
readonly prefix: string;
|
|
@@ -42,8 +54,10 @@ export type XmlNamespaceRequest = {
|
|
|
42
54
|
readonly namespaceOperation: 'set';
|
|
43
55
|
readonly scope: XmlNamespaceScope;
|
|
44
56
|
readonly prefix: string;
|
|
45
|
-
readonly value: string
|
|
57
|
+
readonly value: string | Generator<XmlSourceStep | string, void, void>;
|
|
46
58
|
result?: XmlNamespaceScope;
|
|
47
59
|
};
|
|
48
60
|
export declare function namespaceValue(scope: Map<string, string> | XmlNamespaceScope, prefix: string): Generator<XmlNamespaceRequest, string | undefined, void>;
|
|
49
|
-
export declare function
|
|
61
|
+
export declare function namespaceMetadata(scope: Map<string, string> | XmlNamespaceScope, prefix: string, deferred?: boolean): Generator<XmlNamespaceRequest, Pick<XmlName, 'namespace' | 'namespaceReference'>, void>;
|
|
62
|
+
export declare function hasNamespace(scope: Map<string, string> | XmlNamespaceScope, prefix: string): Generator<XmlNamespaceRequest, boolean, void>;
|
|
63
|
+
export declare function bindNamespace(scope: Map<string, string> | XmlNamespaceScope, prefix: string, value: string | Generator<XmlSourceStep | string, void, void>): Generator<XmlNamespaceRequest, Map<string, string> | XmlNamespaceScope, void>;
|
|
@@ -52,8 +52,30 @@ export function* namespaceValue(scope, prefix) {
|
|
|
52
52
|
throw new TypeError('Incomplete XML namespace read');
|
|
53
53
|
return request.value;
|
|
54
54
|
}
|
|
55
|
+
export function* namespaceMetadata(scope, prefix, deferred = false) {
|
|
56
|
+
if (!deferred || scope instanceof Map)
|
|
57
|
+
return { namespace: (yield* namespaceValue(scope, prefix)) ?? '' };
|
|
58
|
+
if (prefix === 'xml')
|
|
59
|
+
return { namespace: 'http://www.w3.org/XML/1998/namespace' };
|
|
60
|
+
const request = { namespaceOperation: 'reference', scope, prefix };
|
|
61
|
+
yield request;
|
|
62
|
+
if (!request.complete)
|
|
63
|
+
throw new TypeError('Incomplete XML namespace reference lookup');
|
|
64
|
+
return { namespace: '', ...(request.reference === undefined ? {} : { namespaceReference: request.reference }) };
|
|
65
|
+
}
|
|
66
|
+
export function* hasNamespace(scope, prefix) {
|
|
67
|
+
if (scope instanceof Map)
|
|
68
|
+
return scope.has(prefix);
|
|
69
|
+
const request = { namespaceOperation: 'has', scope, prefix };
|
|
70
|
+
yield request;
|
|
71
|
+
if (request.found === undefined)
|
|
72
|
+
throw new TypeError('Incomplete XML namespace membership lookup');
|
|
73
|
+
return request.found;
|
|
74
|
+
}
|
|
55
75
|
export function* bindNamespace(scope, prefix, value) {
|
|
56
76
|
if (scope instanceof Map) {
|
|
77
|
+
if (typeof value !== 'string')
|
|
78
|
+
throw new TypeError('Streamed XML namespace values require external scopes');
|
|
57
79
|
scope.set(prefix, value);
|
|
58
80
|
return scope;
|
|
59
81
|
}
|
|
@@ -3,13 +3,14 @@ export type { XmlAttributeRequest, XmlAttributeRecord, XmlAttributeState } from
|
|
|
3
3
|
import { type XmlNamespaceRequest, type XmlFrameRequest } from "./frames.js";
|
|
4
4
|
export type { XmlParserFrame, XmlFrameRequest, XmlNamespaceScope, XmlNamespaceRequest } from "./frames.js";
|
|
5
5
|
export { normalizeXmlChunks } from "./characters.js";
|
|
6
|
-
import { type XmlSourceStep } from "./source.js";
|
|
7
|
-
export type { XmlSourceRead, XmlSourceStep } from "./source.js";
|
|
6
|
+
import { type XmlSourceSpan, type XmlSourceStep } from "./source.js";
|
|
7
|
+
export type { XmlSourceRead, XmlSourceSpan, XmlSourceStep } from "./source.js";
|
|
8
8
|
import type { XmlStreamEvent } from "./stream.js";
|
|
9
9
|
export { XmlLimitError } from "./errors.js";
|
|
10
10
|
export interface XmlName {
|
|
11
11
|
readonly name: string;
|
|
12
12
|
readonly namespace: string;
|
|
13
|
+
readonly namespaceReference?: number;
|
|
13
14
|
readonly localName: string;
|
|
14
15
|
}
|
|
15
16
|
export interface XmlAttribute extends XmlName {
|
|
@@ -21,6 +22,8 @@ export type XmlContent = XmlElement | {
|
|
|
21
22
|
} | {
|
|
22
23
|
readonly kind: "processing-instruction";
|
|
23
24
|
readonly target: string;
|
|
25
|
+
readonly targetSource?: XmlSourceSpan;
|
|
26
|
+
readonly targetReference?: number;
|
|
24
27
|
readonly text: string;
|
|
25
28
|
};
|
|
26
29
|
export interface XmlElement extends XmlName {
|
|
@@ -65,6 +68,10 @@ export interface XmlSourceLimits extends XmlStepLimits {
|
|
|
65
68
|
readonly storeFrames?: boolean;
|
|
66
69
|
/** Resolve namespace scopes through host-serviced requests. Requires retainTree: false. */
|
|
67
70
|
readonly storeNamespaces?: boolean;
|
|
71
|
+
/** Carry host namespace token references in event metadata. Requires stored namespaces. */
|
|
72
|
+
readonly deferNamespaces?: boolean;
|
|
73
|
+
/** Emit long processing-instruction targets as source spans. Requires fragmentContent. */
|
|
74
|
+
readonly deferContentNames?: boolean;
|
|
68
75
|
/** Store attribute collections through host requests and emit resolved attributes individually. */
|
|
69
76
|
readonly storeAttributes?: boolean;
|
|
70
77
|
readonly fragmentAttributes?: boolean;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { XmlAttributes } from "./attributes.js";
|
|
2
|
-
import { XmlFrames, bindNamespace, namespaceValue } from "./frames.js";
|
|
2
|
+
import { XmlFrames, bindNamespace, namespaceValue, namespaceMetadata, hasNamespace } from "./frames.js";
|
|
3
3
|
import { validCharacter } from "./characters.js";
|
|
4
4
|
export { normalizeXmlChunks } from "./characters.js";
|
|
5
5
|
import { XmlSource } from "./source.js";
|
|
@@ -68,6 +68,40 @@ function qualifiedNameSync(name, cache) {
|
|
|
68
68
|
}
|
|
69
69
|
return parts;
|
|
70
70
|
}
|
|
71
|
+
/** Validate a name span without retaining its spelling. */
|
|
72
|
+
function* validateNameSpan(source, start, end) {
|
|
73
|
+
let first = true, colon = false, work = 0;
|
|
74
|
+
for (let offset = start; offset < end;) {
|
|
75
|
+
let point = yield* source.charCodeAt(offset);
|
|
76
|
+
if (point >= 0xd800 && point <= 0xdbff && offset + 1 < end) {
|
|
77
|
+
const low = yield* source.charCodeAt(offset + 1);
|
|
78
|
+
if (low >= 0xdc00 && low <= 0xdfff)
|
|
79
|
+
point = 0x10000 + (point - 0xd800) * 1024 + low - 0xdc00;
|
|
80
|
+
}
|
|
81
|
+
if (point === 58) {
|
|
82
|
+
if (colon || first)
|
|
83
|
+
invalid("invalid qualified name");
|
|
84
|
+
colon = true;
|
|
85
|
+
first = true;
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
if (!(first ? nameStart(point) : namePart(point)))
|
|
89
|
+
invalid("invalid qualified name");
|
|
90
|
+
first = false;
|
|
91
|
+
}
|
|
92
|
+
const size = point > 0xffff ? 2 : 1;
|
|
93
|
+
offset += size;
|
|
94
|
+
work += size;
|
|
95
|
+
if (work >= 512) {
|
|
96
|
+
yield 512;
|
|
97
|
+
work -= 512;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (first)
|
|
101
|
+
invalid("invalid qualified name");
|
|
102
|
+
if (work)
|
|
103
|
+
yield work;
|
|
104
|
+
}
|
|
71
105
|
function* entity(source, start, end, recover) {
|
|
72
106
|
// Inspect only a bounded prefix, even for arbitrarily long numeric references.
|
|
73
107
|
const prefix = typeof source === "string" ? source.slice(start, Math.min(end, start + 4))
|
|
@@ -260,12 +294,16 @@ function validateLimits(limits) {
|
|
|
260
294
|
}
|
|
261
295
|
export function* parseXmlSourceSteps(length, limits = {}) {
|
|
262
296
|
validateLimits(limits);
|
|
297
|
+
if (limits.deferContentNames && !limits.fragmentContent)
|
|
298
|
+
throw new TypeError("Deferred XML content names require fragmentContent: true");
|
|
263
299
|
if (limits.fragmentAttributes && !limits.storeAttributes)
|
|
264
300
|
throw new TypeError("XML attribute fragments require storeAttributes: true");
|
|
265
301
|
if (limits.storeFrames && limits.retainTree !== false)
|
|
266
302
|
throw new TypeError("Stored XML frames require retainTree: false");
|
|
267
303
|
if (limits.storeAttributes && limits.retainTree !== false)
|
|
268
304
|
throw new TypeError("Stored XML attributes require retainTree: false");
|
|
305
|
+
if (limits.deferNamespaces && !limits.storeNamespaces)
|
|
306
|
+
throw new TypeError("Deferred XML namespaces require stored namespaces");
|
|
269
307
|
if (limits.storeNamespaces && limits.retainTree !== false)
|
|
270
308
|
throw new TypeError("Stored XML namespaces require retainTree: false");
|
|
271
309
|
if (limits.fragmentContent && limits.retainTree !== false)
|
|
@@ -322,7 +360,7 @@ export function* parseXmlSourceSteps(length, limits = {}) {
|
|
|
322
360
|
}
|
|
323
361
|
return offset - start;
|
|
324
362
|
};
|
|
325
|
-
const scanName = function* () {
|
|
363
|
+
const scanName = function* (defer = false) {
|
|
326
364
|
const start = offset;
|
|
327
365
|
while (yield* source.has(offset)) {
|
|
328
366
|
const c = (yield* source.charCodeAt(offset));
|
|
@@ -335,6 +373,10 @@ export function* parseXmlSourceSteps(length, limits = {}) {
|
|
|
335
373
|
pendingWork -= 512;
|
|
336
374
|
}
|
|
337
375
|
}
|
|
376
|
+
if (defer && offset - start > 512) {
|
|
377
|
+
yield* validateNameSpan(source, start, offset);
|
|
378
|
+
return ["", "", "", { start, end: offset }];
|
|
379
|
+
}
|
|
338
380
|
const name = (yield* source.slice(start, offset));
|
|
339
381
|
pendingWork += offset - start;
|
|
340
382
|
while (pendingWork >= 512) {
|
|
@@ -344,7 +386,7 @@ export function* parseXmlSourceSteps(length, limits = {}) {
|
|
|
344
386
|
const [prefix, localName] = qualifiedNameSync(name, qualifiedNames);
|
|
345
387
|
return [name, prefix, localName];
|
|
346
388
|
};
|
|
347
|
-
const rawContent = function* (kind, start, end, parent, target = "") {
|
|
389
|
+
const rawContent = function* (kind, start, end, parent, target = "", targetSource) {
|
|
348
390
|
if (end - start > maxTextLength - textLength)
|
|
349
391
|
throw new XmlLimitError("maxTextLength", "XML text limit exceeded");
|
|
350
392
|
textLength += end - start;
|
|
@@ -358,7 +400,7 @@ export function* parseXmlSourceSteps(length, limits = {}) {
|
|
|
358
400
|
finish--;
|
|
359
401
|
}
|
|
360
402
|
const text = yield* source.slice(cursor, finish);
|
|
361
|
-
const content = kind === "processing-instruction" ? { kind, target, text } : { kind, text };
|
|
403
|
+
const content = kind === "processing-instruction" ? { kind, target, text, ...(targetSource ? { targetSource } : {}) } : { kind, text };
|
|
362
404
|
if (kind === "cdata" && retainTree)
|
|
363
405
|
parent.element.text += text;
|
|
364
406
|
if (retain)
|
|
@@ -494,7 +536,7 @@ export function* parseXmlSourceSteps(length, limits = {}) {
|
|
|
494
536
|
else if ((yield* source.startsWith("<?", offset))) {
|
|
495
537
|
const start = offset;
|
|
496
538
|
offset += 2;
|
|
497
|
-
const [target] = yield* scanName();
|
|
539
|
+
const [target, , , targetSource] = yield* scanName(limits.deferContentNames);
|
|
498
540
|
while (pendingWork >= 512) {
|
|
499
541
|
yield 512;
|
|
500
542
|
pendingWork -= 512;
|
|
@@ -527,7 +569,7 @@ export function* parseXmlSourceSteps(length, limits = {}) {
|
|
|
527
569
|
yield 512;
|
|
528
570
|
pendingWork -= 512;
|
|
529
571
|
}
|
|
530
|
-
yield* rawContent("processing-instruction", body, end, yield* stack.peek(), target);
|
|
572
|
+
yield* rawContent("processing-instruction", body, end, yield* stack.peek(), target, targetSource);
|
|
531
573
|
}
|
|
532
574
|
offset = end + 2;
|
|
533
575
|
}
|
|
@@ -608,18 +650,23 @@ export function* parseXmlSourceSteps(length, limits = {}) {
|
|
|
608
650
|
}
|
|
609
651
|
if (end < 0)
|
|
610
652
|
invalid("unterminated attribute");
|
|
611
|
-
const fragmented = limits.fragmentAttributes && attribute !== "xmlns" && attrPrefix !== "xmlns";
|
|
612
|
-
|
|
653
|
+
const fragmented = limits.fragmentAttributes && (limits.storeNamespaces || attribute !== "xmlns" && attrPrefix !== "xmlns");
|
|
654
|
+
const valueStart = offset;
|
|
655
|
+
let value = "", size = 0, matchesXml = true, matchesXmlns = true;
|
|
613
656
|
if (fragmented) {
|
|
614
657
|
if ((yield* source.indexOf("<", offset, end)) >= 0)
|
|
615
658
|
invalid("less-than in attribute");
|
|
616
|
-
let size = 0;
|
|
617
659
|
for (const part of textFragments(source, offset, end, true, limits.recover, true)) {
|
|
618
660
|
if (typeof part !== "string")
|
|
619
661
|
yield part;
|
|
620
|
-
else
|
|
662
|
+
else {
|
|
663
|
+
matchesXml = matchesXml && part === xmlNamespace.slice(size, size + part.length);
|
|
664
|
+
matchesXmlns = matchesXmlns && part === xmlnsNamespace.slice(size, size + part.length);
|
|
621
665
|
size += part.length;
|
|
666
|
+
}
|
|
622
667
|
}
|
|
668
|
+
matchesXml = matchesXml && size === xmlNamespace.length;
|
|
669
|
+
matchesXmlns = matchesXmlns && size === xmlnsNamespace.length;
|
|
623
670
|
if (size > maxTextLength - textLength)
|
|
624
671
|
throw new XmlLimitError("maxTextLength", "XML text limit exceeded");
|
|
625
672
|
textLength += size;
|
|
@@ -646,13 +693,13 @@ export function* parseXmlSourceSteps(length, limits = {}) {
|
|
|
646
693
|
}
|
|
647
694
|
admitText(value);
|
|
648
695
|
}
|
|
649
|
-
yield* attributes.append(attribute, attrPrefix, attrLocal, value,
|
|
696
|
+
yield* attributes.append(attribute, attrPrefix, attrLocal, value, limits.fragmentAttributes ? { start: offset, end } : undefined);
|
|
650
697
|
offset = end + 1;
|
|
651
698
|
if (attribute === "xmlns" || attribute.startsWith("xmlns:")) {
|
|
652
699
|
const nsPrefix = attribute === "xmlns" ? "" : attribute.slice(6);
|
|
653
|
-
if (nsPrefix === "xmlns" || value === xmlnsNamespace
|
|
654
|
-
|| (nsPrefix === "xml") !== (value === xmlNamespace)
|
|
655
|
-
|| (nsPrefix !== "" && value === ""))
|
|
700
|
+
if (nsPrefix === "xmlns" || (fragmented ? matchesXmlns : value === xmlnsNamespace)
|
|
701
|
+
|| (nsPrefix === "xml") !== (fragmented ? matchesXml : value === xmlNamespace)
|
|
702
|
+
|| (nsPrefix !== "" && (fragmented ? size === 0 : value === "")))
|
|
656
703
|
invalid("invalid namespace binding");
|
|
657
704
|
if (!ownsNamespaces && namespaces instanceof Map) {
|
|
658
705
|
const copy = new Map();
|
|
@@ -663,7 +710,8 @@ export function* parseXmlSourceSteps(length, limits = {}) {
|
|
|
663
710
|
namespaces = copy;
|
|
664
711
|
ownsNamespaces = true;
|
|
665
712
|
}
|
|
666
|
-
namespaces = yield* bindNamespace(namespaces, nsPrefix,
|
|
713
|
+
namespaces = yield* bindNamespace(namespaces, nsPrefix, fragmented
|
|
714
|
+
? textFragments(source, valueStart, end, true, limits.recover ? () => { } : undefined, true) : value);
|
|
667
715
|
if (namespaces.size > maxNamespaces)
|
|
668
716
|
throw new XmlLimitError("maxNamespaces", "XML namespace scope limit exceeded");
|
|
669
717
|
}
|
|
@@ -676,11 +724,12 @@ export function* parseXmlSourceSteps(length, limits = {}) {
|
|
|
676
724
|
if (attribute === "xmlns" || attribute.startsWith("xmlns:"))
|
|
677
725
|
continue;
|
|
678
726
|
pendingWork += attribute.length;
|
|
679
|
-
if (attrPrefix && (yield*
|
|
727
|
+
if (attrPrefix && !(yield* hasNamespace(namespaces, attrPrefix)))
|
|
680
728
|
invalid("unbound attribute prefix");
|
|
681
729
|
if (attributes.length > 1) {
|
|
682
|
-
const
|
|
683
|
-
|
|
730
|
+
const backed = limits.storeAttributes && !(namespaces instanceof Map) ? namespaces : undefined;
|
|
731
|
+
const key = backed ? attrLocal : `${attrPrefix ? (yield* namespaceValue(namespaces, attrPrefix)) : ""}\0${attrLocal}`;
|
|
732
|
+
if (yield* attributes.expanded(key, backed ? { scope: backed, prefix: attrPrefix } : undefined))
|
|
684
733
|
invalid("duplicate expanded attribute");
|
|
685
734
|
}
|
|
686
735
|
}
|
|
@@ -690,14 +739,14 @@ export function* parseXmlSourceSteps(length, limits = {}) {
|
|
|
690
739
|
yield 512;
|
|
691
740
|
pendingWork -= 512;
|
|
692
741
|
}
|
|
693
|
-
if (prefix === "xmlns" || (prefix && (yield*
|
|
742
|
+
if (prefix === "xmlns" || (prefix && !(yield* hasNamespace(namespaces, prefix))))
|
|
694
743
|
invalid("unbound element prefix");
|
|
695
744
|
if (++nodes > maxNodes)
|
|
696
745
|
throw new XmlLimitError("maxNodes", "XML resource limit exceeded");
|
|
697
746
|
if (stack.length + 1 > maxDepth)
|
|
698
747
|
throw new XmlLimitError("maxDepth", "XML resource limit exceeded");
|
|
699
|
-
const namespace =
|
|
700
|
-
limits.onElement?.({ name, namespace, localName }, (yield* stack.peek())?.element, stack.length + 1);
|
|
748
|
+
const namespace = yield* namespaceMetadata(namespaces, prefix, limits.deferNamespaces);
|
|
749
|
+
limits.onElement?.({ name, ...namespace, localName }, (yield* stack.peek())?.element, stack.length + 1);
|
|
701
750
|
admitContent();
|
|
702
751
|
const retainedAttributes = [];
|
|
703
752
|
if (retainContent) {
|
|
@@ -717,7 +766,7 @@ export function* parseXmlSourceSteps(length, limits = {}) {
|
|
|
717
766
|
pendingWork -= 512;
|
|
718
767
|
}
|
|
719
768
|
const content = retain ? [] : undefined;
|
|
720
|
-
const element = { kind: "element", name, namespace, localName, children: [], text: "", content: content ?? emptyContent, attributes: retainContent ? retainedAttributes : emptyAttributes, namespaces: retainContent && namespaces instanceof Map ? namespaces : emptyNamespaces, ...(root === undefined && retainContent ? { prolog, epilog, ...(declaration === undefined ? {} : { declaration }) } : {}) };
|
|
769
|
+
const element = { kind: "element", name, ...namespace, localName, children: [], text: "", content: content ?? emptyContent, attributes: retainContent ? retainedAttributes : emptyAttributes, namespaces: retainContent && namespaces instanceof Map ? namespaces : emptyNamespaces, ...(root === undefined && retainContent ? { prolog, epilog, ...(declaration === undefined ? {} : { declaration }) } : {}) };
|
|
721
770
|
const parent = (yield* stack.peek());
|
|
722
771
|
if (parent) {
|
|
723
772
|
if (retainTree) {
|
|
@@ -747,8 +796,8 @@ export function* parseXmlSourceSteps(length, limits = {}) {
|
|
|
747
796
|
for (let cursor = attributes.first; cursor;) {
|
|
748
797
|
const attribute = yield* attributes.read(cursor, true);
|
|
749
798
|
cursor = attribute.next;
|
|
750
|
-
const namespace = attribute.name === "xmlns" || attribute.prefix === "xmlns" ? xmlnsNamespace
|
|
751
|
-
: attribute.prefix ?
|
|
799
|
+
const namespace = attribute.name === "xmlns" || attribute.prefix === "xmlns" ? { namespace: xmlnsNamespace }
|
|
800
|
+
: attribute.prefix ? yield* namespaceMetadata(namespaces, attribute.prefix, limits.deferNamespaces) : { namespace: "" };
|
|
752
801
|
let continuation = false;
|
|
753
802
|
if (attribute.source) {
|
|
754
803
|
for (const part of textFragments(source, attribute.source.start, attribute.source.end, true, limits.recover ? () => { } : undefined, true)) {
|
|
@@ -756,13 +805,13 @@ export function* parseXmlSourceSteps(length, limits = {}) {
|
|
|
756
805
|
yield part;
|
|
757
806
|
continue;
|
|
758
807
|
}
|
|
759
|
-
limits.onAttribute({ name: attribute.name, localName: attribute.localName, namespace, value: part }, element, continuation);
|
|
808
|
+
limits.onAttribute({ name: attribute.name, localName: attribute.localName, ...namespace, value: part }, element, continuation);
|
|
760
809
|
continuation = true;
|
|
761
810
|
yield 1;
|
|
762
811
|
}
|
|
763
812
|
}
|
|
764
813
|
if (!continuation) {
|
|
765
|
-
limits.onAttribute({ name: attribute.name, localName: attribute.localName, namespace, value: attribute.value }, element);
|
|
814
|
+
limits.onAttribute({ name: attribute.name, localName: attribute.localName, ...namespace, value: attribute.value }, element);
|
|
766
815
|
yield 1;
|
|
767
816
|
}
|
|
768
817
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "toolcraft",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.800",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -177,7 +177,7 @@
|
|
|
177
177
|
"saxes"
|
|
178
178
|
],
|
|
179
179
|
"optionalDependencies": {
|
|
180
|
-
"toolcraft-schema": "0.0.
|
|
180
|
+
"toolcraft-schema": "0.0.800",
|
|
181
181
|
"toolcraft-design": "*",
|
|
182
182
|
"@poe-code/frontmatter": "*",
|
|
183
183
|
"@poe-code/agent-mcp-config": "*",
|