toolcraft 0.0.789 → 0.0.790
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 +15 -0
- package/node_modules/@poe-code/xml-ast/dist/characters.d.ts +1 -1
- package/node_modules/@poe-code/xml-ast/dist/characters.js +5 -1
- package/node_modules/@poe-code/xml-ast/dist/frames.d.ts +28 -0
- package/node_modules/@poe-code/xml-ast/dist/frames.js +45 -0
- package/node_modules/@poe-code/xml-ast/dist/index.d.ts +11 -1
- package/node_modules/@poe-code/xml-ast/dist/index.js +19 -17
- package/node_modules/@poe-code/xml-ast/dist/source.d.ts +9 -3
- package/node_modules/@poe-code/xml-ast/dist/source.js +43 -20
- 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.790",
|
|
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.790",
|
|
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.790",
|
|
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.790",
|
|
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 } from "./xml.js";
|
|
12
|
+
export type { XmlName, XmlAttribute, XmlContent, XmlElement, XmlLimits, XmlParserFrame, XmlFrameRequest } 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";
|
|
@@ -54,3 +54,18 @@ limits)`: numbers are work checkpoints; read requests specify UTF-16 `offset` an
|
|
|
54
54
|
iterator. The source must already be validated and normalized. This supports the
|
|
55
55
|
same repairs and events without a complete source string; tokens and open ancestry
|
|
56
56
|
still remain resident. Close the iterator and backing on errors or cancellation.
|
|
57
|
+
|
|
58
|
+
For tree-free external parsing, set `storeFrames: true` alongside `retainTree: false`.
|
|
59
|
+
The iterator also yields `frameOperation` requests: `push` saves the supplied frame,
|
|
60
|
+
`pop` removes the latest frame, and `peek` needs its `frame` filled with the saved
|
|
61
|
+
metadata. Keep the host stack in bounded backing storage. The parser caches one
|
|
62
|
+
current frame; individual frame metadata and namespace scopes still have their own
|
|
63
|
+
size cost. The default string and stream APIs retain their existing ancestry behavior.
|
|
64
|
+
|
|
65
|
+
Pass `undefined` as the source length to parse incrementally. Such read requests
|
|
66
|
+
have `streaming: true` and request at most 512 UTF-16 units. Return any nonempty
|
|
67
|
+
prefix available without pulling more input; set `complete: true` only when that
|
|
68
|
+
read reaches EOF (an empty EOF read is valid). Earlier offsets may be requested
|
|
69
|
+
again, so retain source spans in caller-backed storage. With `normalizeXmlChunks`,
|
|
70
|
+
pass `true` as the second argument to flush at input-chunk boundaries and preserve
|
|
71
|
+
early parser failures. The string parser and known-length protocol are unchanged.
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export declare function validCharacter(point: number): boolean;
|
|
2
2
|
/** Validate scalar values and normalize XML line endings in fixed windows. */
|
|
3
|
-
export declare function normalizeXmlChunks(source: AsyncIterable<string> | Iterable<string
|
|
3
|
+
export declare function normalizeXmlChunks(source: AsyncIterable<string> | Iterable<string>, flushChunks?: boolean): AsyncGenerator<string>;
|
|
@@ -5,7 +5,7 @@ export function validCharacter(point) {
|
|
|
5
5
|
|| (point >= 0x10000 && point <= 0x10ffff);
|
|
6
6
|
}
|
|
7
7
|
/** Validate scalar values and normalize XML line endings in fixed windows. */
|
|
8
|
-
export async function* normalizeXmlChunks(source) {
|
|
8
|
+
export async function* normalizeXmlChunks(source, flushChunks = false) {
|
|
9
9
|
let first = true, afterCR = false, high = 0, output = '';
|
|
10
10
|
for await (const chunk of source) {
|
|
11
11
|
for (let index = 0; index < chunk.length; index++) {
|
|
@@ -41,6 +41,10 @@ export async function* normalizeXmlChunks(source) {
|
|
|
41
41
|
output = '';
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
|
+
if (flushChunks && output) {
|
|
45
|
+
yield output;
|
|
46
|
+
output = '';
|
|
47
|
+
}
|
|
44
48
|
}
|
|
45
49
|
if (high)
|
|
46
50
|
throw new SyntaxError('Invalid XML: invalid character');
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { XmlContent, XmlElement } from './index.js';
|
|
2
|
+
export interface XmlParserFrame {
|
|
3
|
+
element: XmlElement;
|
|
4
|
+
content: XmlContent[] | undefined;
|
|
5
|
+
name: string;
|
|
6
|
+
namespaces: Map<string, string>;
|
|
7
|
+
}
|
|
8
|
+
export type XmlFrameRequest = {
|
|
9
|
+
readonly frameOperation: 'push';
|
|
10
|
+
readonly frame: XmlParserFrame;
|
|
11
|
+
} | {
|
|
12
|
+
readonly frameOperation: 'pop';
|
|
13
|
+
} | {
|
|
14
|
+
readonly frameOperation: 'peek';
|
|
15
|
+
frame?: XmlParserFrame;
|
|
16
|
+
};
|
|
17
|
+
/** External mode caches only the current frame. The host owns the linked stack. */
|
|
18
|
+
export declare class XmlFrames {
|
|
19
|
+
private readonly external;
|
|
20
|
+
private readonly frames;
|
|
21
|
+
private depth;
|
|
22
|
+
private current;
|
|
23
|
+
constructor(external: boolean);
|
|
24
|
+
get length(): number;
|
|
25
|
+
peek(): Generator<XmlFrameRequest, XmlParserFrame | undefined, void>;
|
|
26
|
+
push(frame: XmlParserFrame): Generator<XmlFrameRequest, void, void>;
|
|
27
|
+
pop(): Generator<XmlFrameRequest, XmlParserFrame | undefined, void>;
|
|
28
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/** External mode caches only the current frame. The host owns the linked stack. */
|
|
2
|
+
export class XmlFrames {
|
|
3
|
+
external;
|
|
4
|
+
frames = [];
|
|
5
|
+
depth = 0;
|
|
6
|
+
current;
|
|
7
|
+
constructor(external) {
|
|
8
|
+
this.external = external;
|
|
9
|
+
}
|
|
10
|
+
get length() { return this.external ? this.depth : this.frames.length; }
|
|
11
|
+
*peek() {
|
|
12
|
+
if (!this.external)
|
|
13
|
+
return this.frames.at(-1);
|
|
14
|
+
if (!this.depth)
|
|
15
|
+
return undefined;
|
|
16
|
+
if (!this.current) {
|
|
17
|
+
const request = { frameOperation: 'peek' };
|
|
18
|
+
yield request;
|
|
19
|
+
if (!request.frame)
|
|
20
|
+
throw new TypeError('Incomplete XML frame read');
|
|
21
|
+
this.current = request.frame;
|
|
22
|
+
}
|
|
23
|
+
return this.current;
|
|
24
|
+
}
|
|
25
|
+
*push(frame) {
|
|
26
|
+
if (!this.external) {
|
|
27
|
+
this.frames.push(frame);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
yield { frameOperation: 'push', frame };
|
|
31
|
+
this.current = frame;
|
|
32
|
+
this.depth++;
|
|
33
|
+
}
|
|
34
|
+
*pop() {
|
|
35
|
+
if (!this.external)
|
|
36
|
+
return this.frames.pop();
|
|
37
|
+
if (!this.depth)
|
|
38
|
+
return undefined;
|
|
39
|
+
const frame = yield* this.peek();
|
|
40
|
+
yield { frameOperation: 'pop' };
|
|
41
|
+
this.depth--;
|
|
42
|
+
this.current = undefined;
|
|
43
|
+
return frame;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { type XmlFrameRequest } from "./frames.js";
|
|
2
|
+
export type { XmlParserFrame, XmlFrameRequest } from "./frames.js";
|
|
1
3
|
export { normalizeXmlChunks } from "./characters.js";
|
|
2
4
|
import { type XmlSourceStep } from "./source.js";
|
|
3
5
|
export type { XmlSourceRead, XmlSourceStep } from "./source.js";
|
|
@@ -51,8 +53,16 @@ export interface XmlStepLimits extends XmlLimits {
|
|
|
51
53
|
* false. Drive the step iterator to await external consumers between windows. */
|
|
52
54
|
readonly events?: (event: XmlStreamEvent) => void;
|
|
53
55
|
}
|
|
56
|
+
export interface XmlSourceLimits extends XmlStepLimits {
|
|
57
|
+
/** Store active parser frames through host-serviced requests. Requires retainTree: false. */
|
|
58
|
+
readonly storeFrames?: boolean;
|
|
59
|
+
}
|
|
60
|
+
export type XmlParseStep = XmlSourceStep | XmlFrameRequest;
|
|
54
61
|
/** Parse a validated, BOM-free, line-normalized UTF-16 source via bounded read requests. */
|
|
55
|
-
export declare function parseXmlSourceSteps(length: number, limits?: XmlStepLimits
|
|
62
|
+
export declare function parseXmlSourceSteps(length: number | undefined, limits?: XmlStepLimits & {
|
|
63
|
+
readonly storeFrames?: false;
|
|
64
|
+
}): Generator<XmlSourceStep, XmlElement, void>;
|
|
65
|
+
export declare function parseXmlSourceSteps(length: number | undefined, limits: XmlSourceLimits): Generator<XmlParseStep, XmlElement, void>;
|
|
56
66
|
export declare function parseXmlSteps(input: string, limits?: XmlStepLimits): Generator<number, XmlElement, void>;
|
|
57
67
|
export declare function parseXml(input: string, limits?: XmlLimits): XmlElement;
|
|
58
68
|
export { parseXmlStream, type XmlStreamLimits, type XmlStreamEvent } from "./stream.js";
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { XmlFrames } from "./frames.js";
|
|
1
2
|
import { validCharacter } from "./characters.js";
|
|
2
3
|
export { normalizeXmlChunks } from "./characters.js";
|
|
3
4
|
import { XmlSource } from "./source.js";
|
|
@@ -189,9 +190,10 @@ function validateLimits(limits) {
|
|
|
189
190
|
if (limits.events && limits.retainTree !== false)
|
|
190
191
|
throw new TypeError("XML events require retainTree: false");
|
|
191
192
|
}
|
|
192
|
-
/** Parse a validated, BOM-free, line-normalized UTF-16 source via bounded read requests. */
|
|
193
193
|
export function* parseXmlSourceSteps(length, limits = {}) {
|
|
194
194
|
validateLimits(limits);
|
|
195
|
+
if (limits.storeFrames && limits.retainTree !== false)
|
|
196
|
+
throw new TypeError("Stored XML frames require retainTree: false");
|
|
195
197
|
const source = new XmlSource(length);
|
|
196
198
|
const maxDepth = limits.maxDepth ?? Infinity;
|
|
197
199
|
const maxNodes = limits.maxNodes ?? Infinity;
|
|
@@ -212,7 +214,7 @@ export function* parseXmlSourceSteps(length, limits = {}) {
|
|
|
212
214
|
throw new XmlLimitError("maxTextLength", "XML text limit exceeded");
|
|
213
215
|
textLength += text.length;
|
|
214
216
|
};
|
|
215
|
-
const stack =
|
|
217
|
+
const stack = new XmlFrames(limits.storeFrames === true);
|
|
216
218
|
let root;
|
|
217
219
|
const prolog = [];
|
|
218
220
|
const epilog = [];
|
|
@@ -230,7 +232,7 @@ export function* parseXmlSourceSteps(length, limits = {}) {
|
|
|
230
232
|
let pendingWork = 0;
|
|
231
233
|
const skipWhitespace = function* () {
|
|
232
234
|
const start = offset;
|
|
233
|
-
while (
|
|
235
|
+
while (yield* source.has(offset)) {
|
|
234
236
|
const c = (yield* source.charCodeAt(offset));
|
|
235
237
|
if (c !== 32 && c !== 9 && c !== 10 && c !== 13)
|
|
236
238
|
break;
|
|
@@ -245,7 +247,7 @@ export function* parseXmlSourceSteps(length, limits = {}) {
|
|
|
245
247
|
};
|
|
246
248
|
const scanName = function* () {
|
|
247
249
|
const start = offset;
|
|
248
|
-
while (
|
|
250
|
+
while (yield* source.has(offset)) {
|
|
249
251
|
const c = (yield* source.charCodeAt(offset));
|
|
250
252
|
if (c === 32 || c === 9 || c === 13 || c === 10 || c === 47 || c === 61 || c === 62 || c === 63)
|
|
251
253
|
break;
|
|
@@ -265,7 +267,7 @@ export function* parseXmlSourceSteps(length, limits = {}) {
|
|
|
265
267
|
const [prefix, localName] = qualifiedNameSync(name, qualifiedNames);
|
|
266
268
|
return [name, prefix, localName];
|
|
267
269
|
};
|
|
268
|
-
while (
|
|
270
|
+
while (yield* source.has(offset)) {
|
|
269
271
|
pendingWork += 1;
|
|
270
272
|
if (pendingWork >= 512) {
|
|
271
273
|
while (pendingWork >= 512) {
|
|
@@ -290,7 +292,7 @@ export function* parseXmlSourceSteps(length, limits = {}) {
|
|
|
290
292
|
pendingWork -= 512;
|
|
291
293
|
}
|
|
292
294
|
admitText(resolved);
|
|
293
|
-
const parent = stack.
|
|
295
|
+
const parent = (yield* stack.peek());
|
|
294
296
|
if (parent) {
|
|
295
297
|
if (retainTree)
|
|
296
298
|
parent.element.text += resolved;
|
|
@@ -331,7 +333,7 @@ export function* parseXmlSourceSteps(length, limits = {}) {
|
|
|
331
333
|
if (end < 0 || (yield* find(text, "--", 0)) >= 0 || text.endsWith("-")) {
|
|
332
334
|
invalid("malformed comment");
|
|
333
335
|
}
|
|
334
|
-
const parent = stack.
|
|
336
|
+
const parent = (yield* stack.peek());
|
|
335
337
|
admitText(text);
|
|
336
338
|
admitContent();
|
|
337
339
|
if (retain) {
|
|
@@ -348,7 +350,7 @@ export function* parseXmlSourceSteps(length, limits = {}) {
|
|
|
348
350
|
invalid("unterminated CDATA");
|
|
349
351
|
const cdataText = (yield* source.slice(offset + 9, end));
|
|
350
352
|
admitText(cdataText);
|
|
351
|
-
const parent = stack.
|
|
353
|
+
const parent = (yield* stack.peek());
|
|
352
354
|
if (retainTree)
|
|
353
355
|
parent.element.text += cdataText;
|
|
354
356
|
admitContent();
|
|
@@ -380,7 +382,7 @@ export function* parseXmlSourceSteps(length, limits = {}) {
|
|
|
380
382
|
else if (content && !" \t\n\r".includes(content[0]))
|
|
381
383
|
invalid("invalid processing instruction");
|
|
382
384
|
if (!(target.length === 3 && target.toLowerCase() === "xml")) {
|
|
383
|
-
const parent = stack.
|
|
385
|
+
const parent = (yield* stack.peek());
|
|
384
386
|
let wsStart = 0;
|
|
385
387
|
while (wsStart < content.length && " \t\n\r".includes(content[wsStart]))
|
|
386
388
|
wsStart++;
|
|
@@ -410,14 +412,14 @@ export function* parseXmlSourceSteps(length, limits = {}) {
|
|
|
410
412
|
yield 512;
|
|
411
413
|
pendingWork -= 512;
|
|
412
414
|
}
|
|
413
|
-
const closed = (yield* source.slice(offset++, offset)) === ">" ? stack.pop() : undefined;
|
|
415
|
+
const closed = (yield* source.slice(offset++, offset)) === ">" ? (yield* stack.pop()) : undefined;
|
|
414
416
|
if (closed?.name !== name) {
|
|
415
417
|
if (!limits.recover)
|
|
416
418
|
invalid("mismatched closing tag");
|
|
417
419
|
limits.recover("mismatched closing tag");
|
|
418
420
|
}
|
|
419
421
|
if (closed)
|
|
420
|
-
limits.events?.({ type: "close", element: closed.element, parent: stack.
|
|
422
|
+
limits.events?.({ type: "close", element: closed.element, parent: (yield* stack.peek())?.element });
|
|
421
423
|
}
|
|
422
424
|
else {
|
|
423
425
|
offset++;
|
|
@@ -436,7 +438,7 @@ export function* parseXmlSourceSteps(length, limits = {}) {
|
|
|
436
438
|
}
|
|
437
439
|
let attributes;
|
|
438
440
|
const attrMeta = [];
|
|
439
|
-
let namespaces = stack.
|
|
441
|
+
let namespaces = (yield* stack.peek())?.namespaces ?? new Map([["xml", xmlNamespace]]);
|
|
440
442
|
let ownsNamespaces = stack.length === 0;
|
|
441
443
|
while (!repeated) {
|
|
442
444
|
const ws = (yield* skipWhitespace());
|
|
@@ -543,7 +545,7 @@ export function* parseXmlSourceSteps(length, limits = {}) {
|
|
|
543
545
|
if (stack.length + 1 > maxDepth)
|
|
544
546
|
throw new XmlLimitError("maxDepth", "XML resource limit exceeded");
|
|
545
547
|
const namespace = namespaces.get(prefix) ?? "";
|
|
546
|
-
limits.onElement?.({ name, namespace, localName }, stack.
|
|
548
|
+
limits.onElement?.({ name, namespace, localName }, (yield* stack.peek())?.element, stack.length + 1);
|
|
547
549
|
admitContent();
|
|
548
550
|
const retainedAttributes = [];
|
|
549
551
|
if (retainContent && attributes) {
|
|
@@ -562,7 +564,7 @@ export function* parseXmlSourceSteps(length, limits = {}) {
|
|
|
562
564
|
}
|
|
563
565
|
const content = retain ? [] : undefined;
|
|
564
566
|
const element = { kind: "element", name, namespace, localName, children: [], text: "", content: content ?? emptyContent, attributes: retainContent ? retainedAttributes : emptyAttributes, namespaces: retainContent ? namespaces : emptyNamespaces, ...(root === undefined && retainContent ? { prolog, epilog, ...(declaration === undefined ? {} : { declaration }) } : {}) };
|
|
565
|
-
const parent = stack.
|
|
567
|
+
const parent = (yield* stack.peek());
|
|
566
568
|
if (parent) {
|
|
567
569
|
if (retainTree) {
|
|
568
570
|
parent.element.children.push(element);
|
|
@@ -587,7 +589,7 @@ export function* parseXmlSourceSteps(length, limits = {}) {
|
|
|
587
589
|
previousEmpty = { suffix: name + "/>", name, prefix, localName };
|
|
588
590
|
limits.events?.({ type: "open", element, parent: parent?.element });
|
|
589
591
|
if (!empty)
|
|
590
|
-
stack.push({ element, content, name, namespaces });
|
|
592
|
+
yield* stack.push({ element, content, name, namespaces });
|
|
591
593
|
else
|
|
592
594
|
limits.events?.({ type: "close", element, parent: parent?.element });
|
|
593
595
|
}
|
|
@@ -603,8 +605,8 @@ export function* parseXmlSourceSteps(length, limits = {}) {
|
|
|
603
605
|
invalid("incomplete document");
|
|
604
606
|
limits.recover("incomplete document");
|
|
605
607
|
while (stack.length) {
|
|
606
|
-
const closed = stack.pop();
|
|
607
|
-
limits.events?.({ type: "close", element: closed.element, parent: stack.
|
|
608
|
+
const closed = (yield* stack.pop());
|
|
609
|
+
limits.events?.({ type: "close", element: closed.element, parent: (yield* stack.peek())?.element });
|
|
608
610
|
yield 1;
|
|
609
611
|
}
|
|
610
612
|
}
|
|
@@ -1,16 +1,22 @@
|
|
|
1
|
-
/** Fill value
|
|
1
|
+
/** Fill value before advancing. Streaming reads may be short; mark complete at EOF. */
|
|
2
2
|
export interface XmlSourceRead {
|
|
3
3
|
readonly offset: number;
|
|
4
4
|
readonly length: number;
|
|
5
|
+
readonly streaming?: boolean;
|
|
5
6
|
value?: string;
|
|
7
|
+
complete?: boolean;
|
|
6
8
|
}
|
|
7
9
|
export type XmlSourceStep = number | XmlSourceRead;
|
|
8
10
|
/** One fixed window; individual returned tokens still have their own size cost. */
|
|
9
11
|
export declare class XmlSource {
|
|
10
|
-
readonly length: number;
|
|
11
12
|
private window;
|
|
12
13
|
private start;
|
|
13
|
-
|
|
14
|
+
private end;
|
|
15
|
+
private readonly streaming;
|
|
16
|
+
constructor(length: number | undefined);
|
|
17
|
+
get length(): number;
|
|
18
|
+
private load;
|
|
19
|
+
has(offset: number): Generator<XmlSourceStep, boolean, void>;
|
|
14
20
|
slice(start: number, end?: number): Generator<XmlSourceStep, string, void>;
|
|
15
21
|
charCodeAt(offset: number): Generator<XmlSourceStep, number, void>;
|
|
16
22
|
startsWith(value: string, offset: number): Generator<XmlSourceStep, boolean, void>;
|
|
@@ -1,27 +1,44 @@
|
|
|
1
1
|
/** One fixed window; individual returned tokens still have their own size cost. */
|
|
2
2
|
export class XmlSource {
|
|
3
|
-
length;
|
|
4
3
|
window = '';
|
|
5
4
|
start = -1;
|
|
5
|
+
end;
|
|
6
|
+
streaming;
|
|
6
7
|
constructor(length) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
if (length !== undefined && (!Number.isSafeInteger(length) || length < 0))
|
|
9
|
+
throw new RangeError('Invalid XML source length');
|
|
10
|
+
this.streaming = length === undefined;
|
|
11
|
+
this.end = length ?? Infinity;
|
|
12
|
+
}
|
|
13
|
+
get length() { return this.end; }
|
|
14
|
+
*load(offset) {
|
|
15
|
+
if (offset >= this.end || offset >= this.start && offset < this.start + this.window.length)
|
|
16
|
+
return;
|
|
17
|
+
const start = this.streaming ? offset : Math.floor(offset / 4096) * 4096;
|
|
18
|
+
const request = { offset: start, length: Math.min(this.streaming ? 512 : 4096, this.end - start),
|
|
19
|
+
...(this.streaming ? { streaming: true } : {}) };
|
|
20
|
+
yield request;
|
|
21
|
+
if (typeof request.value !== 'string' || request.value.length > request.length ||
|
|
22
|
+
(!this.streaming && request.value.length !== request.length) ||
|
|
23
|
+
(!request.value.length && !request.complete && this.streaming))
|
|
24
|
+
throw new TypeError('Incomplete XML source read');
|
|
25
|
+
if (this.streaming && request.complete)
|
|
26
|
+
this.end = start + request.value.length;
|
|
27
|
+
this.window = request.value;
|
|
28
|
+
this.start = start;
|
|
29
|
+
}
|
|
30
|
+
*has(offset) {
|
|
31
|
+
yield* this.load(offset);
|
|
32
|
+
return offset < this.end;
|
|
10
33
|
}
|
|
11
34
|
*slice(start, end = this.length) {
|
|
12
35
|
start = start < 0 ? Math.max(0, this.length + start) : Math.min(start, this.length);
|
|
13
36
|
end = end < 0 ? Math.max(0, this.length + end) : Math.min(end, this.length);
|
|
14
37
|
let result = '';
|
|
15
|
-
while (start < end) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
yield read;
|
|
20
|
-
if (typeof read.value !== 'string' || read.value.length !== read.length)
|
|
21
|
-
throw new TypeError('Incomplete XML source read');
|
|
22
|
-
this.window = read.value;
|
|
23
|
-
this.start = offset;
|
|
24
|
-
}
|
|
38
|
+
while (start < Math.min(end, this.length)) {
|
|
39
|
+
yield* this.load(start);
|
|
40
|
+
if (start >= this.end)
|
|
41
|
+
break;
|
|
25
42
|
const stop = Math.min(end, this.start + this.window.length);
|
|
26
43
|
result += this.window.slice(start - this.start, stop - this.start);
|
|
27
44
|
start = stop;
|
|
@@ -32,15 +49,21 @@ export class XmlSource {
|
|
|
32
49
|
return (yield* this.slice(offset, offset + 1)).charCodeAt(0);
|
|
33
50
|
}
|
|
34
51
|
*startsWith(value, offset) {
|
|
35
|
-
|
|
52
|
+
for (let index = 0; index < value.length; index++) {
|
|
53
|
+
if ((yield* this.charCodeAt(offset + index)) !== value.charCodeAt(index))
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
return true;
|
|
36
57
|
}
|
|
37
58
|
*indexOf(value, offset) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
const
|
|
59
|
+
let tail = '';
|
|
60
|
+
while (yield* this.has(offset)) {
|
|
61
|
+
const part = tail + this.window.slice(offset - this.start);
|
|
62
|
+
const found = part.indexOf(value);
|
|
41
63
|
if (found >= 0)
|
|
42
|
-
return offset + found;
|
|
43
|
-
|
|
64
|
+
return offset - tail.length + found;
|
|
65
|
+
tail = value.length > 1 ? part.slice(-(value.length - 1)) : '';
|
|
66
|
+
offset = this.start + this.window.length;
|
|
44
67
|
}
|
|
45
68
|
return -1;
|
|
46
69
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "toolcraft",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.790",
|
|
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.790",
|
|
181
181
|
"toolcraft-design": "*",
|
|
182
182
|
"@poe-code/frontmatter": "*",
|
|
183
183
|
"@poe-code/agent-mcp-config": "*",
|