This commit is contained in:
2026-03-31 16:38:22 -07:00
commit 38940436a7
2112 changed files with 376929 additions and 0 deletions

15
node_modules/@rgrove/parse-xml/LICENSE generated vendored Normal file
View File

@ -0,0 +1,15 @@
ISC License
Copyright Ryan Grove <ryan@wonko.com>
Permission to use, copy, modify, and/or distribute this software for any purpose
with or without fee is hereby granted, provided that the above copyright notice
and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.

228
node_modules/@rgrove/parse-xml/README.md generated vendored Normal file
View File

@ -0,0 +1,228 @@
# parse-xml
A fast, safe, compliant XML parser for Node.js and browsers.
[![npm version](https://badge.fury.io/js/%40rgrove%2Fparse-xml.svg)](https://badge.fury.io/js/%40rgrove%2Fparse-xml) [![Bundle size](https://badgen.net/bundlephobia/minzip/@rgrove/parse-xml)](https://bundlephobia.com/result?p=@rgrove/parse-xml) [![CI](https://github.com/rgrove/parse-xml/actions/workflows/ci.yml/badge.svg)](https://github.com/rgrove/parse-xml/actions/workflows/ci.yml)
## Links
- [API Docs](https://rgrove.github.io/parse-xml/)
- [GitHub](https://github.com/rgrove/parse-xml)
- [npm](https://www.npmjs.com/package/@rgrove/parse-xml)
## Installation
```
npm install @rgrove/parse-xml
```
Or, if you like living dangerously, you can load [the minified bundle](https://unpkg.com/@rgrove/parse-xml/dist/global.min.js) in a browser via [Unpkg](https://unpkg.com/) and use the `parseXml` global.
## Features
- Returns a convenient [object tree](#basic-usage) representing an XML document.
- Works great in Node.js and browsers.
- Provides [helpful, detailed error messages](#friendly-errors) with context when a document is not well-formed.
- Mostly conforms to [XML 1.0 (Fifth Edition)](https://www.w3.org/TR/2008/REC-xml-20081126/) as a non-validating parser (see [below](#not-features) for details).
- Passes all relevant tests in the [XML Conformance Test Suite](https://www.w3.org/XML/Test/).
- Written in TypeScript and compiled to ES2020 JavaScript for Node.js and ES2017 JavaScript for browsers. The browser build is also optimized for minification.
- Extremely [fast](#benchmark) and surprisingly [small](https://bundlephobia.com/result?p=@rgrove/parse-xml).
- Zero dependencies.
## Not Features
While this parser is capable of parsing document type declarations (`<!DOCTYPE ... >`) and including them in the node tree, it doesn't actually do anything with them. External document type definitions won't be loaded, and the parser won't validate the document against a DTD or resolve custom entity references defined in a DTD.
In addition, the only supported character encoding is UTF-8 because it's not feasible (or useful) to support other character encodings in JavaScript.
## Examples
### Basic Usage
**ESM**
```js
import { parseXml } from '@rgrove/parse-xml';
parseXml('<kittens fuzzy="yes">I like fuzzy kittens.</kittens>');
```
**CommonJS**
```js
const { parseXml } = require('@rgrove/parse-xml');
parseXml('<kittens fuzzy="yes">I like fuzzy kittens.</kittens>');
```
The result is an [`XmlDocument`](https://rgrove.github.io/parse-xml/classes/XmlDocument.html) instance containing the parsed document, with a structure that looks like this (some properties and methods are excluded for clarity; see the [API docs](https://rgrove.github.io/parse-xml/) for details):
```js
{
type: 'document',
children: [
{
type: 'element',
name: 'kittens',
attributes: {
fuzzy: 'yes'
},
children: [
{
type: 'text',
text: 'I like fuzzy kittens.'
}
],
parent: { ... },
isRootNode: true
}
]
}
```
All parse-xml objects have `toJSON()` methods that return JSON-serializable objects, so you can easily convert an XML document to JSON:
```js
let json = JSON.stringify(parseXml(xml));
```
### Friendly Errors
When something goes wrong, parse-xml throws an error that tells you exactly what happened and shows you where the problem is so you can fix it.
```js
parseXml('<foo><bar>baz</foo>');
```
**Output**
```
Error: Missing end tag for element bar (line 1, column 14)
<foo><bar>baz</foo>
^
```
In addition to a helpful message, error objects have the following properties:
- **column** _Number_
Column where the error occurred (1-based).
- **excerpt** _String_
Excerpt from the input string that contains the problem.
- **line** _Number_
Line where the error occurred (1-based).
- **pos** _Number_
Character position where the error occurred relative to the beginning of the input (0-based).
## Why another XML parser?
There are many XML parsers for Node, and some of them are good. However, most of them suffer from one or more of the following shortcomings:
- Native dependencies.
- Loose, non-standard parsing behavior that can lead to unexpected or even unsafe results when given input the author didn't anticipate.
- Kitchen sink APIs that tightly couple a parser with DOM manipulation functions, a stringifier, or other tooling that isn't directly related to parsing and consuming XML.
- Stream-based parsing. This is great in the rare case that you need to parse truly enormous documents, but can be a pain to work with when all you want is a node tree.
- Poor error handling.
- Too big or too Node-specific to work well in browsers.
parse-xml's goal is to be a small, fast, safe, compliant, non-streaming, non-validating, browser-friendly parser, because I think this is an under-served niche.
I think parse-xml demonstrates that it's not necessary to jettison the spec entirely or to write complex code in order to implement a small, fast XML parser.
Also, it was fun.
## Benchmark
Here's how parse-xml's performance stacks up against a few comparable libraries:
- [fast-xml-parser](https://github.com/NaturalIntelligence/fast-xml-parser), which claims to be the fastest pure JavaScript XML parser
- [libxmljs2](https://github.com/marudor/libxmljs2), which is based on the native libxml library written in C
- [xmldoc](https://github.com/nfarina/xmldoc), which is based on [sax-js](https://github.com/isaacs/sax-js)
While libxmljs2 is faster at parsing medium and large documents, its performance comes at the expense of a large C dependency, no browser support, and a [history of security vulnerabilities](https://www.cvedetails.com/vulnerability-list/vendor_id-1962/product_id-3311/Xmlsoft-Libxml2.html) in the underlying libxml2 library.
In these results, "ops/s" refers to operations per second. Higher is faster.
```
Node.js v22.10.0 / Darwin arm64
Apple M1 Max
Running "Small document (291 bytes)" suite...
Progress: 100%
@rgrove/parse-xml 4.2.0:
253 082 ops/s, ±0.16% | fastest
fast-xml-parser 4.5.0:
127 232 ops/s, ±0.44% | 49.73% slower
libxmljs2 0.35.0 (native):
68 709 ops/s, ±2.77% | slowest, 72.85% slower
xmldoc 1.3.0 (sax-js):
122 345 ops/s, ±0.15% | 51.66% slower
Finished 4 cases!
Fastest: @rgrove/parse-xml 4.2.0
Slowest: libxmljs2 0.35.0 (native)
Running "Medium document (72081 bytes)" suite...
Progress: 100%
@rgrove/parse-xml 4.2.0:
1 350 ops/s, ±0.18% | 29.5% slower
fast-xml-parser 4.5.0:
560 ops/s, ±0.48% | slowest, 70.76% slower
libxmljs2 0.35.0 (native):
1 915 ops/s, ±2.64% | fastest
xmldoc 1.3.0 (sax-js):
824 ops/s, ±0.20% | 56.97% slower
Finished 4 cases!
Fastest: libxmljs2 0.35.0 (native)
Slowest: fast-xml-parser 4.5.0
Running "Large document (1162464 bytes)" suite...
Progress: 100%
@rgrove/parse-xml 4.2.0:
109 ops/s, ±0.17% | 40.11% slower
fast-xml-parser 4.5.0:
48 ops/s, ±0.55% | slowest, 73.63% slower
libxmljs2 0.35.0 (native):
182 ops/s, ±1.16% | fastest
xmldoc 1.3.0 (sax-js):
73 ops/s, ±0.50% | 59.89% slower
Finished 4 cases!
Fastest: libxmljs2 0.35.0 (native)
Slowest: fast-xml-parser 4.5.0
```
See the [parse-xml-benchmark](https://github.com/rgrove/parse-xml-benchmark) repo for instructions on how to run this benchmark yourself.
## License
[ISC License](LICENSE)

1166
node_modules/@rgrove/parse-xml/dist/browser.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

7
node_modules/@rgrove/parse-xml/dist/browser.js.map generated vendored Normal file

File diff suppressed because one or more lines are too long

11
node_modules/@rgrove/parse-xml/dist/global.min.js generated vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

27
node_modules/@rgrove/parse-xml/dist/index.d.ts generated vendored Normal file
View File

@ -0,0 +1,27 @@
import type { ParserOptions } from './lib/Parser.js';
export * from './lib/types.js';
export { XmlCdata } from './lib/XmlCdata.js';
export { XmlComment } from './lib/XmlComment.js';
export { XmlDeclaration } from './lib/XmlDeclaration.js';
export { XmlDocument } from './lib/XmlDocument.js';
export { XmlDocumentType } from './lib/XmlDocumentType.js';
export { XmlElement } from './lib/XmlElement.js';
export { XmlError } from './lib/XmlError.js';
export { XmlNode } from './lib/XmlNode.js';
export { XmlProcessingInstruction } from './lib/XmlProcessingInstruction.js';
export { XmlText } from './lib/XmlText.js';
export type { ParserOptions } from './lib/Parser.js';
/**
* Parses the given XML string and returns an `XmlDocument` instance
* representing the document tree.
*
* @example
*
* import { parseXml } from '@rgrove/parse-xml';
* let doc = parseXml('<kittens fuzzy="yes">I like fuzzy kittens.</kittens>');
*
* @param xml XML string to parse.
* @param options Parser options.
*/
export declare function parseXml(xml: string, options?: ParserOptions): import("./lib/XmlDocument.js").XmlDocument;
//# sourceMappingURL=index.d.ts.map

1
node_modules/@rgrove/parse-xml/dist/index.d.ts.map generated vendored Normal file
View File

@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAErD,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EAAE,wBAAwB,EAAE,MAAM,mCAAmC,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAE3C,YAAY,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAErD;;;;;;;;;;;GAWG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,8CAE5D"}

56
node_modules/@rgrove/parse-xml/dist/index.js generated vendored Normal file
View File

@ -0,0 +1,56 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.XmlText = exports.XmlProcessingInstruction = exports.XmlNode = exports.XmlError = exports.XmlElement = exports.XmlDocumentType = exports.XmlDocument = exports.XmlDeclaration = exports.XmlComment = exports.XmlCdata = void 0;
exports.parseXml = parseXml;
const Parser_js_1 = require("./lib/Parser.js");
__exportStar(require("./lib/types.js"), exports);
var XmlCdata_js_1 = require("./lib/XmlCdata.js");
Object.defineProperty(exports, "XmlCdata", { enumerable: true, get: function () { return XmlCdata_js_1.XmlCdata; } });
var XmlComment_js_1 = require("./lib/XmlComment.js");
Object.defineProperty(exports, "XmlComment", { enumerable: true, get: function () { return XmlComment_js_1.XmlComment; } });
var XmlDeclaration_js_1 = require("./lib/XmlDeclaration.js");
Object.defineProperty(exports, "XmlDeclaration", { enumerable: true, get: function () { return XmlDeclaration_js_1.XmlDeclaration; } });
var XmlDocument_js_1 = require("./lib/XmlDocument.js");
Object.defineProperty(exports, "XmlDocument", { enumerable: true, get: function () { return XmlDocument_js_1.XmlDocument; } });
var XmlDocumentType_js_1 = require("./lib/XmlDocumentType.js");
Object.defineProperty(exports, "XmlDocumentType", { enumerable: true, get: function () { return XmlDocumentType_js_1.XmlDocumentType; } });
var XmlElement_js_1 = require("./lib/XmlElement.js");
Object.defineProperty(exports, "XmlElement", { enumerable: true, get: function () { return XmlElement_js_1.XmlElement; } });
var XmlError_js_1 = require("./lib/XmlError.js");
Object.defineProperty(exports, "XmlError", { enumerable: true, get: function () { return XmlError_js_1.XmlError; } });
var XmlNode_js_1 = require("./lib/XmlNode.js");
Object.defineProperty(exports, "XmlNode", { enumerable: true, get: function () { return XmlNode_js_1.XmlNode; } });
var XmlProcessingInstruction_js_1 = require("./lib/XmlProcessingInstruction.js");
Object.defineProperty(exports, "XmlProcessingInstruction", { enumerable: true, get: function () { return XmlProcessingInstruction_js_1.XmlProcessingInstruction; } });
var XmlText_js_1 = require("./lib/XmlText.js");
Object.defineProperty(exports, "XmlText", { enumerable: true, get: function () { return XmlText_js_1.XmlText; } });
/**
* Parses the given XML string and returns an `XmlDocument` instance
* representing the document tree.
*
* @example
*
* import { parseXml } from '@rgrove/parse-xml';
* let doc = parseXml('<kittens fuzzy="yes">I like fuzzy kittens.</kittens>');
*
* @param xml XML string to parse.
* @param options Parser options.
*/
function parseXml(xml, options) {
return (new Parser_js_1.Parser(xml, options)).document;
}
//# sourceMappingURL=index.js.map

1
node_modules/@rgrove/parse-xml/dist/index.js.map generated vendored Normal file
View File

@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AA8BA,4BAEC;AAhCD,+CAAyC;AAIzC,iDAA+B;AAC/B,iDAA6C;AAApC,uGAAA,QAAQ,OAAA;AACjB,qDAAiD;AAAxC,2GAAA,UAAU,OAAA;AACnB,6DAAyD;AAAhD,mHAAA,cAAc,OAAA;AACvB,uDAAmD;AAA1C,6GAAA,WAAW,OAAA;AACpB,+DAA2D;AAAlD,qHAAA,eAAe,OAAA;AACxB,qDAAiD;AAAxC,2GAAA,UAAU,OAAA;AACnB,iDAA6C;AAApC,uGAAA,QAAQ,OAAA;AACjB,+CAA2C;AAAlC,qGAAA,OAAO,OAAA;AAChB,iFAA6E;AAApE,uIAAA,wBAAwB,OAAA;AACjC,+CAA2C;AAAlC,qGAAA,OAAO,OAAA;AAIhB;;;;;;;;;;;GAWG;AACH,SAAgB,QAAQ,CAAC,GAAW,EAAE,OAAuB;IAC3D,OAAO,CAAC,IAAI,kBAAM,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC;AAC7C,CAAC"}

265
node_modules/@rgrove/parse-xml/dist/lib/Parser.d.ts generated vendored Normal file
View File

@ -0,0 +1,265 @@
import { XmlDocument } from './XmlDocument.js';
import { XmlError } from './XmlError.js';
import { XmlNode } from './XmlNode.js';
/**
* Parses an XML string into an `XmlDocument`.
*
* @private
*/
export declare class Parser {
readonly document: XmlDocument;
private currentNode;
private readonly options;
private readonly scanner;
/**
* @param xml XML string to parse.
* @param options Parser options.
*/
constructor(xml: string, options?: ParserOptions);
/**
* Adds the given `XmlNode` as a child of `this.currentNode`.
*/
addNode(node: XmlNode, charIndex: number): boolean;
/**
* Adds the given _text_ to the document, either by appending it to a
* preceding `XmlText` node (if possible) or by creating a new `XmlText` node.
*/
addText(text: string, charIndex: number): boolean;
/**
* Consumes element attributes.
*
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#sec-starttags
*/
consumeAttributes(): Record<string, string>;
/**
* Consumes an `AttValue` (attribute value) if possible.
*
* @returns
* Contents of the `AttValue` minus quotes, or `false` if nothing was
* consumed. An empty string indicates that an `AttValue` was consumed but
* was empty.
*
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#NT-AttValue
*/
consumeAttributeValue(): string | false;
/**
* Consumes a CDATA section if possible.
*
* @returns Whether a CDATA section was consumed.
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#sec-cdata-sect
*/
consumeCdataSection(): boolean;
/**
* Consumes character data if possible.
*
* @returns Whether character data was consumed.
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#dt-chardata
*/
consumeCharData(): boolean;
/**
* Consumes a comment if possible.
*
* @returns Whether a comment was consumed.
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#NT-Comment
*/
consumeComment(): boolean;
/**
* Consumes a reference in a content context if possible.
*
* This differs from `consumeReference()` in that a consumed reference will be
* added to the document as a text node instead of returned.
*
* @returns Whether a reference was consumed.
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#entproc
*/
consumeContentReference(): boolean;
/**
* Consumes a doctype declaration if possible.
*
* This is a loose implementation since doctype declarations are currently
* discarded without further parsing.
*
* @returns Whether a doctype declaration was consumed.
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#dtd
*/
consumeDoctypeDeclaration(): boolean;
/**
* Consumes an element if possible.
*
* @returns Whether an element was consumed.
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#NT-element
*/
consumeElement(): boolean;
/**
* Consumes an `Eq` production if possible.
*
* @returns Whether an `Eq` production was consumed.
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#NT-Eq
*/
consumeEqual(): boolean;
/**
* Consumes `Misc` content if possible.
*
* @returns Whether anything was consumed.
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#NT-Misc
*/
consumeMisc(): boolean;
/**
* Consumes one or more `Name` characters if possible.
*
* @returns `Name` characters, or an empty string if none were consumed.
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#NT-Name
*/
consumeName(): string;
/**
* Consumes a processing instruction if possible.
*
* @returns Whether a processing instruction was consumed.
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#sec-pi
*/
consumeProcessingInstruction(): boolean;
/**
* Consumes a prolog if possible.
*
* @returns Whether a prolog was consumed.
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#sec-prolog-dtd
*/
consumeProlog(): boolean;
/**
* Consumes a public identifier literal if possible.
*
* @returns
* Value of the public identifier literal minus quotes, or `false` if
* nothing was consumed. An empty string indicates that a public id literal
* was consumed but was empty.
*
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#NT-PubidLiteral
*/
consumePubidLiteral(): string | false;
/**
* Consumes a reference if possible.
*
* This differs from `consumeContentReference()` in that a consumed reference
* will be returned rather than added to the document.
*
* @returns
* Parsed reference value, or `false` if nothing was consumed (to
* distinguish from a reference that resolves to an empty string).
*
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#NT-Reference
*/
consumeReference(): string | false;
/**
* Consumes a `SystemLiteral` if possible.
*
* A `SystemLiteral` is similar to an attribute value, but allows the
* characters `<` and `&` and doesn't replace references.
*
* @returns
* Value of the `SystemLiteral` minus quotes, or `false` if nothing was
* consumed. An empty string indicates that a `SystemLiteral` was consumed
* but was empty.
*
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#NT-SystemLiteral
*/
consumeSystemLiteral(): string | false;
/**
* Consumes one or more whitespace characters if possible.
*
* @returns Whether any whitespace characters were consumed.
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#white
*/
consumeWhitespace(): boolean;
/**
* Consumes an XML declaration if possible.
*
* @returns Whether an XML declaration was consumed.
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#NT-XMLDecl
*/
consumeXmlDeclaration(): boolean;
/**
* Returns an `XmlError` for the current scanner position.
*/
error(message: string): XmlError;
/**
* Parses the XML input.
*/
parse(): void;
/**
* Throws an invalid character error if any character in the given _string_
* isn't a valid XML character.
*/
validateChars(string: string): void;
}
export type ParserOptions = {
/**
* When `true`, an undefined named entity (like "&bogus;") will be left in the
* output as is instead of causing a parse error.
*
* @default false
*/
ignoreUndefinedEntities?: boolean;
/**
* When `true`, the starting and ending byte offsets of each node in the input
* string will be made available via `start` and `end` properties on the node.
*
* @default false
*/
includeOffsets?: boolean;
/**
* When `true`, CDATA sections will be preserved in the document as `XmlCdata`
* nodes. Otherwise CDATA sections will be represented as `XmlText` nodes,
* which keeps the node tree simpler and easier to work with.
*
* @default false
*/
preserveCdata?: boolean;
/**
* When `true`, comments will be preserved in the document as `XmlComment`
* nodes. Otherwise comments will not be included in the node tree.
*
* @default false
*/
preserveComments?: boolean;
/**
* When `true`, a document type declaration (if present) will be preserved in
* the document as an `XmlDocumentType` node. Otherwise the declaration will
* not be included in the node tree.
*
* Note that when this is `true` and a document type declaration is present,
* the DTD will precede the root node in the node tree (normally the root
* node would be first).
*
* @default false
*/
preserveDocumentType?: boolean;
/**
* When `true`, an XML declaration (if present) will be preserved in the
* document as an `XmlDeclaration` node. Otherwise the declaration will not be
* included in the node tree.
*
* Note that when this is `true` and an XML declaration is present, the
* XML declaration will be the first child of the document (normally the root
* node would be first).
*
* @default false
*/
preserveXmlDeclaration?: boolean;
/**
* When an undefined named entity is encountered, this function will be called
* with the entity as its only argument. It should return a string value with
* which to replace the entity, or `null` or `undefined` to treat the entity
* as undefined (which may result in a parse error depending on the value of
* `ignoreUndefinedEntities`).
*/
resolveUndefinedEntity?: (entity: string) => string | null | undefined;
/**
* When `true`, attributes in an element's `attributes` object will be sorted
* in alphanumeric order by name. Otherwise they'll retain their original
* order as found in the XML.
*
* @default false
*/
sortAttributes?: boolean;
};
//# sourceMappingURL=Parser.d.ts.map

View File

@ -0,0 +1 @@
{"version":3,"file":"Parser.d.ts","sourceRoot":"","sources":["../../src/lib/Parser.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAG/C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAMvC;;;;GAIG;AACH,qBAAa,MAAM;IACjB,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;IAE/B,OAAO,CAAC,WAAW,CAA2B;IAC9C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgB;IACxC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgB;IAExC;;;OAGG;gBACS,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,aAAkB;IAepD;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM;IAexC;;;OAGG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;IA2BvC;;;;OAIG;IACH,iBAAiB,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IA6C3C;;;;;;;;;OASG;IACH,qBAAqB,IAAI,MAAM,GAAG,KAAK;IAkDvC;;;;;OAKG;IACH,mBAAmB,IAAI,OAAO;IAoB9B;;;;;OAKG;IACH,eAAe,IAAI,OAAO;IAkB1B;;;;;OAKG;IACH,cAAc,IAAI,OAAO;IAwBzB;;;;;;;;OAQG;IACH,uBAAuB,IAAI,OAAO;IASlC;;;;;;;;OAQG;IACH,yBAAyB,IAAI,OAAO;IAiEpC;;;;;OAKG;IACH,cAAc,IAAI,OAAO;IA6DzB;;;;;OAKG;IACH,YAAY,IAAI,OAAO;IAWvB;;;;;OAKG;IACH,WAAW,IAAI,OAAO;IAMtB;;;;;OAKG;IACH,WAAW,IAAI,MAAM;IAMrB;;;;;OAKG;IACH,4BAA4B,IAAI,OAAO;IAqCvC;;;;;OAKG;IACH,aAAa,IAAI,OAAO;IAexB;;;;;;;;;OASG;IACH,mBAAmB,IAAI,MAAM,GAAG,KAAK;IAYrC;;;;;;;;;;;OAWG;IACH,gBAAgB,IAAI,MAAM,GAAG,KAAK;IAoElC;;;;;;;;;;;;OAYG;IACH,oBAAoB,IAAI,MAAM,GAAG,KAAK;IAkBtC;;;;;OAKG;IACH,iBAAiB,IAAI,OAAO;IAI5B;;;;;OAKG;IACH,qBAAqB,IAAI,OAAO;IA+DhC;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM;IAKrB;;OAEG;IACH,KAAK;IAeL;;;OAGG;IACH,aAAa,CAAC,MAAM,EAAE,MAAM;CAgB7B;AAqBD,MAAM,MAAM,aAAa,GAAG;IAC1B;;;;;OAKG;IACH,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAElC;;;;;OAKG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAE3B;;;;;;;;;;OAUG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAE/B;;;;;;;;;;OAUG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;IAEjC;;;;;;OAMG;IACH,sBAAsB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAEvE;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAC"}

678
node_modules/@rgrove/parse-xml/dist/lib/Parser.js generated vendored Normal file
View File

@ -0,0 +1,678 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Parser = void 0;
const StringScanner_js_1 = require("./StringScanner.js");
const syntax = __importStar(require("./syntax.js"));
const XmlCdata_js_1 = require("./XmlCdata.js");
const XmlComment_js_1 = require("./XmlComment.js");
const XmlDeclaration_js_1 = require("./XmlDeclaration.js");
const XmlDocument_js_1 = require("./XmlDocument.js");
const XmlDocumentType_js_1 = require("./XmlDocumentType.js");
const XmlElement_js_1 = require("./XmlElement.js");
const XmlError_js_1 = require("./XmlError.js");
const XmlNode_js_1 = require("./XmlNode.js");
const XmlProcessingInstruction_js_1 = require("./XmlProcessingInstruction.js");
const XmlText_js_1 = require("./XmlText.js");
const emptyString = '';
/**
* Parses an XML string into an `XmlDocument`.
*
* @private
*/
class Parser {
/**
* @param xml XML string to parse.
* @param options Parser options.
*/
constructor(xml, options = {}) {
let doc = this.document = new XmlDocument_js_1.XmlDocument();
this.currentNode = doc;
this.options = options;
this.scanner = new StringScanner_js_1.StringScanner(xml);
if (this.options.includeOffsets) {
doc.start = 0;
doc.end = xml.length;
}
this.parse();
}
/**
* Adds the given `XmlNode` as a child of `this.currentNode`.
*/
addNode(node, charIndex) {
node.parent = this.currentNode;
if (this.options.includeOffsets) {
node.start = this.scanner.charIndexToByteIndex(charIndex);
node.end = this.scanner.charIndexToByteIndex();
}
// @ts-expect-error: XmlDocument has a more limited set of possible children
// than XmlElement so TypeScript is unhappy, but we always do the right
// thing.
this.currentNode.children.push(node);
return true;
}
/**
* Adds the given _text_ to the document, either by appending it to a
* preceding `XmlText` node (if possible) or by creating a new `XmlText` node.
*/
addText(text, charIndex) {
let { children } = this.currentNode;
let { length } = children;
text = normalizeLineBreaks(text);
if (length > 0) {
let prevNode = children[length - 1];
if (prevNode?.type === XmlNode_js_1.XmlNode.TYPE_TEXT) {
let textNode = prevNode;
// The previous node is a text node, so we can append to it and avoid
// creating another node.
textNode.text += text;
if (this.options.includeOffsets) {
textNode.end = this.scanner.charIndexToByteIndex();
}
return true;
}
}
return this.addNode(new XmlText_js_1.XmlText(text), charIndex);
}
/**
* Consumes element attributes.
*
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#sec-starttags
*/
consumeAttributes() {
let attributes = Object.create(null);
while (this.consumeWhitespace()) {
let attrName = this.consumeName();
if (!attrName) {
break;
}
let attrValue = this.consumeEqual() && this.consumeAttributeValue();
if (attrValue === false) {
throw this.error('Attribute value expected');
}
if (attrName in attributes) {
throw this.error(`Duplicate attribute: ${attrName}`);
}
if (attrName === 'xml:space'
&& attrValue !== 'default'
&& attrValue !== 'preserve') {
throw this.error('Value of the `xml:space` attribute must be "default" or "preserve"');
}
attributes[attrName] = attrValue;
}
if (this.options.sortAttributes) {
let attrNames = Object.keys(attributes).sort();
let sortedAttributes = Object.create(null);
for (let i = 0; i < attrNames.length; ++i) {
let attrName = attrNames[i];
sortedAttributes[attrName] = attributes[attrName];
}
attributes = sortedAttributes;
}
return attributes;
}
/**
* Consumes an `AttValue` (attribute value) if possible.
*
* @returns
* Contents of the `AttValue` minus quotes, or `false` if nothing was
* consumed. An empty string indicates that an `AttValue` was consumed but
* was empty.
*
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#NT-AttValue
*/
consumeAttributeValue() {
let { scanner } = this;
let quote = scanner.peek();
if (quote !== '"' && quote !== "'") {
return false;
}
scanner.advance();
let chars;
let isClosed = false;
let value = emptyString;
let regex = quote === '"'
? syntax.attValueCharDoubleQuote
: syntax.attValueCharSingleQuote;
matchLoop: while (!scanner.isEnd) {
chars = scanner.consumeUntilMatch(regex);
if (chars) {
this.validateChars(chars);
value += chars.replace(syntax.attValueNormalizedWhitespace, ' ');
}
switch (scanner.peek()) {
case quote:
isClosed = true;
break matchLoop;
case '&':
value += this.consumeReference();
continue;
case '<':
throw this.error('Unescaped `<` is not allowed in an attribute value');
default:
break matchLoop;
}
}
if (!isClosed) {
throw this.error('Unclosed attribute');
}
scanner.advance();
return value;
}
/**
* Consumes a CDATA section if possible.
*
* @returns Whether a CDATA section was consumed.
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#sec-cdata-sect
*/
consumeCdataSection() {
let { scanner } = this;
let startIndex = scanner.charIndex;
if (!scanner.consumeString('<![CDATA[')) {
return false;
}
let text = scanner.consumeUntilString(']]>');
this.validateChars(text);
if (!scanner.consumeString(']]>')) {
throw this.error('Unclosed CDATA section');
}
return this.options.preserveCdata
? this.addNode(new XmlCdata_js_1.XmlCdata(normalizeLineBreaks(text)), startIndex)
: this.addText(text, startIndex);
}
/**
* Consumes character data if possible.
*
* @returns Whether character data was consumed.
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#dt-chardata
*/
consumeCharData() {
let { scanner } = this;
let startIndex = scanner.charIndex;
let charData = scanner.consumeUntilMatch(syntax.endCharData);
if (!charData) {
return false;
}
this.validateChars(charData);
if (scanner.peek(3) === ']]>') {
throw this.error('Element content may not contain the CDATA section close delimiter `]]>`');
}
return this.addText(charData, startIndex);
}
/**
* Consumes a comment if possible.
*
* @returns Whether a comment was consumed.
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#NT-Comment
*/
consumeComment() {
let { scanner } = this;
let startIndex = scanner.charIndex;
if (!scanner.consumeString('<!--')) {
return false;
}
let content = scanner.consumeUntilString('--');
this.validateChars(content);
if (!scanner.consumeString('-->')) {
if (scanner.peek(2) === '--') {
throw this.error("The string `--` isn't allowed inside a comment");
}
throw this.error('Unclosed comment');
}
return this.options.preserveComments
? this.addNode(new XmlComment_js_1.XmlComment(normalizeLineBreaks(content)), startIndex)
: true;
}
/**
* Consumes a reference in a content context if possible.
*
* This differs from `consumeReference()` in that a consumed reference will be
* added to the document as a text node instead of returned.
*
* @returns Whether a reference was consumed.
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#entproc
*/
consumeContentReference() {
let startIndex = this.scanner.charIndex;
let ref = this.consumeReference();
return ref
? this.addText(ref, startIndex)
: false;
}
/**
* Consumes a doctype declaration if possible.
*
* This is a loose implementation since doctype declarations are currently
* discarded without further parsing.
*
* @returns Whether a doctype declaration was consumed.
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#dtd
*/
consumeDoctypeDeclaration() {
let { scanner } = this;
let startIndex = scanner.charIndex;
if (!scanner.consumeString('<!DOCTYPE')) {
return false;
}
let name = this.consumeWhitespace()
&& this.consumeName();
if (!name) {
throw this.error('Expected a name');
}
let publicId;
let systemId;
if (this.consumeWhitespace()) {
if (scanner.consumeString('PUBLIC')) {
publicId = this.consumeWhitespace()
&& this.consumePubidLiteral();
if (publicId === false) {
throw this.error('Expected a public identifier');
}
this.consumeWhitespace();
}
if (publicId !== undefined || scanner.consumeString('SYSTEM')) {
this.consumeWhitespace();
systemId = this.consumeSystemLiteral();
if (systemId === false) {
throw this.error('Expected a system identifier');
}
this.consumeWhitespace();
}
}
let internalSubset;
if (scanner.consumeString('[')) {
// The internal subset may contain comments that contain `]` characters,
// so we can't use `consumeUntilString()` here.
internalSubset = scanner.consumeUntilMatch(/\][\x20\t\r\n]*>/);
if (!scanner.consumeString(']')) {
throw this.error('Unclosed internal subset');
}
this.consumeWhitespace();
}
if (!scanner.consumeString('>')) {
throw this.error('Unclosed doctype declaration');
}
return this.options.preserveDocumentType
? this.addNode(new XmlDocumentType_js_1.XmlDocumentType(name, publicId, systemId, internalSubset), startIndex)
: true;
}
/**
* Consumes an element if possible.
*
* @returns Whether an element was consumed.
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#NT-element
*/
consumeElement() {
let { scanner } = this;
let startIndex = scanner.charIndex;
if (!scanner.consumeString('<')) {
return false;
}
let name = this.consumeName();
if (!name) {
scanner.reset(startIndex);
return false;
}
let attributes = this.consumeAttributes();
let isEmpty = !!scanner.consumeString('/>');
let element = new XmlElement_js_1.XmlElement(name, attributes);
element.parent = this.currentNode;
if (!isEmpty) {
if (!scanner.consumeString('>')) {
throw this.error(`Unclosed start tag for element \`${name}\``);
}
this.currentNode = element;
do {
this.consumeCharData();
} while (this.consumeElement()
|| this.consumeContentReference()
|| this.consumeCdataSection()
|| this.consumeProcessingInstruction()
|| this.consumeComment());
let endTagMark = scanner.charIndex;
let endTagName;
if (!scanner.consumeString('</')
|| !(endTagName = this.consumeName())
|| endTagName !== name) {
scanner.reset(endTagMark);
throw this.error(`Missing end tag for element ${name}`);
}
this.consumeWhitespace();
if (!scanner.consumeString('>')) {
throw this.error(`Unclosed end tag for element ${name}`);
}
this.currentNode = element.parent;
}
return this.addNode(element, startIndex);
}
/**
* Consumes an `Eq` production if possible.
*
* @returns Whether an `Eq` production was consumed.
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#NT-Eq
*/
consumeEqual() {
this.consumeWhitespace();
if (this.scanner.consumeString('=')) {
this.consumeWhitespace();
return true;
}
return false;
}
/**
* Consumes `Misc` content if possible.
*
* @returns Whether anything was consumed.
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#NT-Misc
*/
consumeMisc() {
return this.consumeComment()
|| this.consumeProcessingInstruction()
|| this.consumeWhitespace();
}
/**
* Consumes one or more `Name` characters if possible.
*
* @returns `Name` characters, or an empty string if none were consumed.
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#NT-Name
*/
consumeName() {
return syntax.isNameStartChar(this.scanner.peek())
? this.scanner.consumeMatchFn(syntax.isNameChar)
: emptyString;
}
/**
* Consumes a processing instruction if possible.
*
* @returns Whether a processing instruction was consumed.
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#sec-pi
*/
consumeProcessingInstruction() {
let { scanner } = this;
let startIndex = scanner.charIndex;
if (!scanner.consumeString('<?')) {
return false;
}
let name = this.consumeName();
if (name) {
if (name.toLowerCase() === 'xml') {
scanner.reset(startIndex);
throw this.error("XML declaration isn't allowed here");
}
}
else {
throw this.error('Invalid processing instruction');
}
if (!this.consumeWhitespace()) {
if (scanner.consumeString('?>')) {
return this.addNode(new XmlProcessingInstruction_js_1.XmlProcessingInstruction(name), startIndex);
}
throw this.error('Whitespace is required after a processing instruction name');
}
let content = scanner.consumeUntilString('?>');
this.validateChars(content);
if (!scanner.consumeString('?>')) {
throw this.error('Unterminated processing instruction');
}
return this.addNode(new XmlProcessingInstruction_js_1.XmlProcessingInstruction(name, normalizeLineBreaks(content)), startIndex);
}
/**
* Consumes a prolog if possible.
*
* @returns Whether a prolog was consumed.
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#sec-prolog-dtd
*/
consumeProlog() {
let { scanner } = this;
let startIndex = scanner.charIndex;
this.consumeXmlDeclaration();
while (this.consumeMisc()) { } // eslint-disable-line no-empty
if (this.consumeDoctypeDeclaration()) {
while (this.consumeMisc()) { } // eslint-disable-line no-empty
}
return startIndex < scanner.charIndex;
}
/**
* Consumes a public identifier literal if possible.
*
* @returns
* Value of the public identifier literal minus quotes, or `false` if
* nothing was consumed. An empty string indicates that a public id literal
* was consumed but was empty.
*
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#NT-PubidLiteral
*/
consumePubidLiteral() {
let startIndex = this.scanner.charIndex;
let value = this.consumeSystemLiteral();
if (value !== false && !/^[-\x20\r\na-zA-Z0-9'()+,./:=?;!*#@$_%]*$/.test(value)) {
this.scanner.reset(startIndex);
throw this.error('Invalid character in public identifier');
}
return value;
}
/**
* Consumes a reference if possible.
*
* This differs from `consumeContentReference()` in that a consumed reference
* will be returned rather than added to the document.
*
* @returns
* Parsed reference value, or `false` if nothing was consumed (to
* distinguish from a reference that resolves to an empty string).
*
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#NT-Reference
*/
consumeReference() {
let { scanner } = this;
if (!scanner.consumeString('&')) {
return false;
}
let ref = scanner.consumeMatchFn(syntax.isReferenceChar);
if (scanner.consume() !== ';') {
throw this.error('Unterminated reference (a reference must end with `;`)');
}
let parsedValue;
if (ref[0] === '#') {
// This is a character reference.
let codePoint = ref[1] === 'x'
? parseInt(ref.slice(2), 16) // Hex codepoint.
: parseInt(ref.slice(1), 10); // Decimal codepoint.
if (isNaN(codePoint)) {
throw this.error('Invalid character reference');
}
if (!syntax.isXmlCodePoint(codePoint)) {
throw this.error('Character reference resolves to an invalid character');
}
parsedValue = String.fromCodePoint(codePoint);
}
else {
// This is an entity reference.
parsedValue = syntax.predefinedEntities[ref];
if (parsedValue === undefined) {
let { ignoreUndefinedEntities, resolveUndefinedEntity, } = this.options;
let wrappedRef = `&${ref};`; // for backcompat with <= 2.x
if (resolveUndefinedEntity) {
let resolvedValue = resolveUndefinedEntity(wrappedRef);
if (resolvedValue !== null && resolvedValue !== undefined) {
let type = typeof resolvedValue;
if (type !== 'string') {
throw new TypeError(`\`resolveUndefinedEntity()\` must return a string, \`null\`, or \`undefined\`, but returned a value of type ${type}`);
}
return resolvedValue;
}
}
if (ignoreUndefinedEntities) {
return wrappedRef;
}
scanner.reset(-wrappedRef.length);
throw this.error(`Named entity isn't defined: ${wrappedRef}`);
}
}
return parsedValue;
}
/**
* Consumes a `SystemLiteral` if possible.
*
* A `SystemLiteral` is similar to an attribute value, but allows the
* characters `<` and `&` and doesn't replace references.
*
* @returns
* Value of the `SystemLiteral` minus quotes, or `false` if nothing was
* consumed. An empty string indicates that a `SystemLiteral` was consumed
* but was empty.
*
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#NT-SystemLiteral
*/
consumeSystemLiteral() {
let { scanner } = this;
let quote = scanner.consumeString('"') || scanner.consumeString("'");
if (!quote) {
return false;
}
let value = scanner.consumeUntilString(quote);
this.validateChars(value);
if (!scanner.consumeString(quote)) {
throw this.error('Missing end quote');
}
return value;
}
/**
* Consumes one or more whitespace characters if possible.
*
* @returns Whether any whitespace characters were consumed.
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#white
*/
consumeWhitespace() {
return !!this.scanner.consumeMatchFn(syntax.isWhitespace);
}
/**
* Consumes an XML declaration if possible.
*
* @returns Whether an XML declaration was consumed.
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#NT-XMLDecl
*/
consumeXmlDeclaration() {
let { scanner } = this;
let startIndex = scanner.charIndex;
if (!scanner.consumeString('<?xml')) {
return false;
}
if (!this.consumeWhitespace()) {
throw this.error('Invalid XML declaration');
}
let version = !!scanner.consumeString('version')
&& this.consumeEqual()
&& this.consumeSystemLiteral();
if (version === false) {
throw this.error('XML version is missing or invalid');
}
else if (!/^1\.[0-9]+$/.test(version)) {
throw this.error('Invalid character in version number');
}
let encoding;
let standalone;
if (this.consumeWhitespace()) {
encoding = !!scanner.consumeString('encoding')
&& this.consumeEqual()
&& this.consumeSystemLiteral();
if (encoding) {
if (!/^[A-Za-z][\w.-]*$/.test(encoding)) {
throw this.error('Invalid character in encoding name');
}
this.consumeWhitespace();
}
standalone = !!scanner.consumeString('standalone')
&& this.consumeEqual()
&& this.consumeSystemLiteral();
if (standalone) {
if (standalone !== 'yes' && standalone !== 'no') {
throw this.error('Only "yes" and "no" are permitted as values of `standalone`');
}
this.consumeWhitespace();
}
}
if (!scanner.consumeString('?>')) {
throw this.error('Invalid or unclosed XML declaration');
}
return this.options.preserveXmlDeclaration
? this.addNode(new XmlDeclaration_js_1.XmlDeclaration(version, encoding || undefined, standalone || undefined), startIndex)
: true;
}
/**
* Returns an `XmlError` for the current scanner position.
*/
error(message) {
let { scanner } = this;
return new XmlError_js_1.XmlError(message, scanner.charIndex, scanner.string);
}
/**
* Parses the XML input.
*/
parse() {
this.scanner.consumeString('\uFEFF'); // byte order mark
this.consumeProlog();
if (!this.consumeElement()) {
throw this.error('Root element is missing or invalid');
}
while (this.consumeMisc()) { } // eslint-disable-line no-empty
if (!this.scanner.isEnd) {
throw this.error('Extra content at the end of the document');
}
}
/**
* Throws an invalid character error if any character in the given _string_
* isn't a valid XML character.
*/
validateChars(string) {
let { length } = string;
for (let i = 0; i < length; ++i) {
let cp = string.codePointAt(i);
if (!syntax.isXmlCodePoint(cp)) {
this.scanner.reset(-([...string].length - i));
throw this.error('Invalid character');
}
if (cp > 65535) {
i += 1;
}
}
}
}
exports.Parser = Parser;
// -- Private Functions --------------------------------------------------------
/**
* Normalizes line breaks in the given text by replacing CRLF sequences and lone
* CR characters with LF characters.
*/
function normalizeLineBreaks(text) {
let i = 0;
while ((i = text.indexOf('\r', i)) !== -1) {
text = text[i + 1] === '\n'
? text.slice(0, i) + text.slice(i + 1)
: text.slice(0, i) + '\n' + text.slice(i + 1);
}
return text;
}
//# sourceMappingURL=Parser.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,91 @@
/** @private */
export declare class StringScanner {
charIndex: number;
readonly string: string;
private readonly charCount;
private readonly charsToBytes;
private readonly length;
private readonly multiByteMode;
constructor(string: string);
/**
* Whether the current character index is at the end of the input string.
*/
get isEnd(): boolean;
/**
* Returns the number of characters in the given string, which may differ from
* the byte length if the string contains multibyte characters.
*/
protected charLength(string: string, multiByteSafe?: boolean): number;
/**
* Advances the scanner by the given number of characters, stopping if the end
* of the string is reached.
*/
advance(count?: number): void;
/**
* Returns the byte index of the given character index in the string. The two
* may differ in strings that contain multibyte characters.
*/
charIndexToByteIndex(charIndex?: number): number;
/**
* Consumes and returns the given number of characters if possible, advancing
* the scanner and stopping if the end of the string is reached.
*
* If no characters could be consumed, an empty string will be returned.
*/
consume(charCount?: number): string;
/**
* Consumes and returns the given number of bytes if possible, advancing the
* scanner and stopping if the end of the string is reached.
*
* It's up to the caller to ensure that the given byte count doesn't split a
* multibyte character.
*
* If no bytes could be consumed, an empty string will be returned.
*/
consumeBytes(byteCount: number): string;
/**
* Consumes and returns all characters for which the given function returns
* `true`, stopping when `false` is returned or the end of the input is
* reached.
*/
consumeMatchFn(fn: (char: string) => boolean): string;
/**
* Consumes the given string if it exists at the current character index, and
* advances the scanner.
*
* If the given string doesn't exist at the current character index, an empty
* string will be returned and the scanner will not be advanced.
*/
consumeString(stringToConsume: string): string;
/**
* Consumes characters until the given global regex is matched, advancing the
* scanner up to (but not beyond) the beginning of the match. If the regex
* doesn't match, nothing will be consumed.
*
* Returns the consumed string, or an empty string if nothing was consumed.
*/
consumeUntilMatch(regex: RegExp): string;
/**
* Consumes characters until the given string is found, advancing the scanner
* up to (but not beyond) that point. If the string is never found, nothing
* will be consumed.
*
* Returns the consumed string, or an empty string if nothing was consumed.
*/
consumeUntilString(searchString: string): string;
/**
* Returns the given number of characters starting at the current character
* index, without advancing the scanner and without exceeding the end of the
* input string.
*/
peek(count?: number): string;
/**
* Resets the scanner position to the given character _index_, or to the start
* of the input string if no index is given.
*
* If _index_ is negative, the scanner position will be moved backward by that
* many characters, stopping if the beginning of the string is reached.
*/
reset(index?: number): void;
}
//# sourceMappingURL=StringScanner.d.ts.map

View File

@ -0,0 +1 @@
{"version":3,"file":"StringScanner.d.ts","sourceRoot":"","sources":["../../src/lib/StringScanner.ts"],"names":[],"mappings":"AAGA,eAAe;AACf,qBAAa,aAAa;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAExB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAuB;IACpD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAU;gBAE5B,MAAM,EAAE,MAAM;IAsB1B;;OAEG;IACH,IAAI,KAAK,YAER;IAID;;;OAGG;IACH,SAAS,CAAC,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,UAAqB,GAAG,MAAM;IAWhF;;;OAGG;IACH,OAAO,CAAC,KAAK,SAAI;IAIjB;;;OAGG;IACH,oBAAoB,CAAC,SAAS,GAAE,MAAuB,GAAG,MAAM;IAMhE;;;;;OAKG;IACH,OAAO,CAAC,SAAS,SAAI,GAAG,MAAM;IAM9B;;;;;;;;OAQG;IACH,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAOvC;;;;OAIG;IACH,cAAc,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,GAAG,MAAM;IA6BrD;;;;;;OAMG;IACH,aAAa,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM;IAY9C;;;;;;OAMG;IACH,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAUxC;;;;;;OAMG;IACH,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;IAShD;;;;OAIG;IACH,IAAI,CAAC,KAAK,SAAI,GAAG,MAAM;IAQvB;;;;;;OAMG;IACH,KAAK,CAAC,KAAK,SAAI;CAKhB"}

View File

@ -0,0 +1,187 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.StringScanner = void 0;
const emptyString = '';
const surrogatePair = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
/** @private */
class StringScanner {
constructor(string) {
this.charCount = this.charLength(string, true);
this.charIndex = 0;
this.length = string.length;
this.multiByteMode = this.charCount !== this.length;
this.string = string;
if (this.multiByteMode) {
let charsToBytes = [];
// Create a mapping of character indexes to byte indexes. Since the string
// contains multibyte characters, a byte index may not necessarily align
// with a character index.
for (let byteIndex = 0, charIndex = 0; charIndex < this.charCount; ++charIndex) {
charsToBytes[charIndex] = byteIndex;
byteIndex += string.codePointAt(byteIndex) > 65535 ? 2 : 1;
}
this.charsToBytes = charsToBytes;
}
}
/**
* Whether the current character index is at the end of the input string.
*/
get isEnd() {
return this.charIndex >= this.charCount;
}
// -- Protected Methods ------------------------------------------------------
/**
* Returns the number of characters in the given string, which may differ from
* the byte length if the string contains multibyte characters.
*/
charLength(string, multiByteSafe = this.multiByteMode) {
// We could get the char length with `[ ...string ].length`, but that's
// actually slower than replacing surrogate pairs with single-byte
// characters and then counting the result.
return multiByteSafe
? string.replace(surrogatePair, '_').length
: string.length;
}
// -- Public Methods ---------------------------------------------------------
/**
* Advances the scanner by the given number of characters, stopping if the end
* of the string is reached.
*/
advance(count = 1) {
this.charIndex = Math.min(this.charCount, this.charIndex + count);
}
/**
* Returns the byte index of the given character index in the string. The two
* may differ in strings that contain multibyte characters.
*/
charIndexToByteIndex(charIndex = this.charIndex) {
return this.multiByteMode
? this.charsToBytes[charIndex] ?? Infinity
: charIndex;
}
/**
* Consumes and returns the given number of characters if possible, advancing
* the scanner and stopping if the end of the string is reached.
*
* If no characters could be consumed, an empty string will be returned.
*/
consume(charCount = 1) {
let chars = this.peek(charCount);
this.advance(charCount);
return chars;
}
/**
* Consumes and returns the given number of bytes if possible, advancing the
* scanner and stopping if the end of the string is reached.
*
* It's up to the caller to ensure that the given byte count doesn't split a
* multibyte character.
*
* If no bytes could be consumed, an empty string will be returned.
*/
consumeBytes(byteCount) {
let byteIndex = this.charIndexToByteIndex();
let result = this.string.slice(byteIndex, byteIndex + byteCount);
this.advance(this.charLength(result));
return result;
}
/**
* Consumes and returns all characters for which the given function returns
* `true`, stopping when `false` is returned or the end of the input is
* reached.
*/
consumeMatchFn(fn) {
let { length, multiByteMode, string } = this;
let startByteIndex = this.charIndexToByteIndex();
let endByteIndex = startByteIndex;
if (multiByteMode) {
while (endByteIndex < length) {
let char = string[endByteIndex];
let isSurrogatePair = char >= '\uD800' && char <= '\uDBFF';
if (isSurrogatePair) {
char += string[endByteIndex + 1];
}
if (!fn(char)) {
break;
}
endByteIndex += isSurrogatePair ? 2 : 1;
}
}
else {
while (endByteIndex < length && fn(string[endByteIndex])) {
++endByteIndex;
}
}
return this.consumeBytes(endByteIndex - startByteIndex);
}
/**
* Consumes the given string if it exists at the current character index, and
* advances the scanner.
*
* If the given string doesn't exist at the current character index, an empty
* string will be returned and the scanner will not be advanced.
*/
consumeString(stringToConsume) {
let { length } = stringToConsume;
let byteIndex = this.charIndexToByteIndex();
if (stringToConsume === this.string.slice(byteIndex, byteIndex + length)) {
this.advance(length === 1 ? 1 : this.charLength(stringToConsume));
return stringToConsume;
}
return emptyString;
}
/**
* Consumes characters until the given global regex is matched, advancing the
* scanner up to (but not beyond) the beginning of the match. If the regex
* doesn't match, nothing will be consumed.
*
* Returns the consumed string, or an empty string if nothing was consumed.
*/
consumeUntilMatch(regex) {
let matchByteIndex = this.string
.slice(this.charIndexToByteIndex())
.search(regex);
return matchByteIndex > 0
? this.consumeBytes(matchByteIndex)
: emptyString;
}
/**
* Consumes characters until the given string is found, advancing the scanner
* up to (but not beyond) that point. If the string is never found, nothing
* will be consumed.
*
* Returns the consumed string, or an empty string if nothing was consumed.
*/
consumeUntilString(searchString) {
let byteIndex = this.charIndexToByteIndex();
let matchByteIndex = this.string.indexOf(searchString, byteIndex);
return matchByteIndex > 0
? this.consumeBytes(matchByteIndex - byteIndex)
: emptyString;
}
/**
* Returns the given number of characters starting at the current character
* index, without advancing the scanner and without exceeding the end of the
* input string.
*/
peek(count = 1) {
let { charIndex, string } = this;
return this.multiByteMode
? string.slice(this.charIndexToByteIndex(charIndex), this.charIndexToByteIndex(charIndex + count))
: string.slice(charIndex, charIndex + count);
}
/**
* Resets the scanner position to the given character _index_, or to the start
* of the input string if no index is given.
*
* If _index_ is negative, the scanner position will be moved backward by that
* many characters, stopping if the beginning of the string is reached.
*/
reset(index = 0) {
this.charIndex = index >= 0
? Math.min(this.charCount, index)
: Math.max(0, this.charIndex + index);
}
}
exports.StringScanner = StringScanner;
//# sourceMappingURL=StringScanner.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"StringScanner.js","sourceRoot":"","sources":["../../src/lib/StringScanner.ts"],"names":[],"mappings":"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"}

View File

@ -0,0 +1,8 @@
import { XmlText } from './XmlText.js';
/**
* A CDATA section within an XML document.
*/
export declare class XmlCdata extends XmlText {
get type(): string;
}
//# sourceMappingURL=XmlCdata.d.ts.map

View File

@ -0,0 +1 @@
{"version":3,"file":"XmlCdata.d.ts","sourceRoot":"","sources":["../../src/lib/XmlCdata.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC;;GAEG;AACH,qBAAa,QAAS,SAAQ,OAAO;IACnC,IAAa,IAAI,WAEhB;CACF"}

15
node_modules/@rgrove/parse-xml/dist/lib/XmlCdata.js generated vendored Normal file
View File

@ -0,0 +1,15 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.XmlCdata = void 0;
const XmlNode_js_1 = require("./XmlNode.js");
const XmlText_js_1 = require("./XmlText.js");
/**
* A CDATA section within an XML document.
*/
class XmlCdata extends XmlText_js_1.XmlText {
get type() {
return XmlNode_js_1.XmlNode.TYPE_CDATA;
}
}
exports.XmlCdata = XmlCdata;
//# sourceMappingURL=XmlCdata.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"XmlCdata.js","sourceRoot":"","sources":["../../src/lib/XmlCdata.ts"],"names":[],"mappings":";;;AAAA,6CAAuC;AACvC,6CAAuC;AAEvC;;GAEG;AACH,MAAa,QAAS,SAAQ,oBAAO;IACnC,IAAa,IAAI;QACf,OAAO,oBAAO,CAAC,UAAU,CAAC;IAC5B,CAAC;CACF;AAJD,4BAIC"}

View File

@ -0,0 +1,16 @@
import { XmlNode } from './XmlNode.js';
/**
* A comment within an XML document.
*/
export declare class XmlComment extends XmlNode {
/**
* Content of this comment.
*/
content: string;
constructor(content?: string);
get type(): string;
toJSON(): import("./types.js").JsonObject & {
content: string;
};
}
//# sourceMappingURL=XmlComment.d.ts.map

View File

@ -0,0 +1 @@
{"version":3,"file":"XmlComment.d.ts","sourceRoot":"","sources":["../../src/lib/XmlComment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC;;GAEG;AACH,qBAAa,UAAW,SAAQ,OAAO;IACrC;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;gBAEJ,OAAO,SAAK;IAKxB,IAAa,IAAI,WAEhB;IAEQ,MAAM;;;CAKhB"}

23
node_modules/@rgrove/parse-xml/dist/lib/XmlComment.js generated vendored Normal file
View File

@ -0,0 +1,23 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.XmlComment = void 0;
const XmlNode_js_1 = require("./XmlNode.js");
/**
* A comment within an XML document.
*/
class XmlComment extends XmlNode_js_1.XmlNode {
constructor(content = '') {
super();
this.content = content;
}
get type() {
return XmlNode_js_1.XmlNode.TYPE_COMMENT;
}
toJSON() {
return Object.assign(XmlNode_js_1.XmlNode.prototype.toJSON.call(this), {
content: this.content,
});
}
}
exports.XmlComment = XmlComment;
//# sourceMappingURL=XmlComment.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"XmlComment.js","sourceRoot":"","sources":["../../src/lib/XmlComment.ts"],"names":[],"mappings":";;;AAAA,6CAAuC;AAEvC;;GAEG;AACH,MAAa,UAAW,SAAQ,oBAAO;IAMrC,YAAY,OAAO,GAAG,EAAE;QACtB,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED,IAAa,IAAI;QACf,OAAO,oBAAO,CAAC,YAAY,CAAC;IAC9B,CAAC;IAEQ,MAAM;QACb,OAAO,MAAM,CAAC,MAAM,CAAC,oBAAO,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;YACxD,OAAO,EAAE,IAAI,CAAC,OAAO;SACtB,CAAC,CAAC;IACL,CAAC;CACF;AApBD,gCAoBC"}

View File

@ -0,0 +1,30 @@
import { XmlNode } from './XmlNode.js';
/**
* An XML declaration within an XML document.
*
* @example
*
* ```xml
* <?xml version="1.0" encoding="UTF-8"?>
* ```
*/
export declare class XmlDeclaration extends XmlNode {
/**
* Value of the encoding declaration in this XML declaration, or `null` if no
* encoding declaration was present.
*/
encoding: string | null;
/**
* Value of the standalone declaration in this XML declaration, or `null` if
* no standalone declaration was present.
*/
standalone: 'yes' | 'no' | null;
/**
* Value of the version declaration in this XML declaration.
*/
version: string;
constructor(version: string, encoding?: string, standalone?: typeof XmlDeclaration.prototype.standalone);
get type(): string;
toJSON(): import("./types.js").JsonObject;
}
//# sourceMappingURL=XmlDeclaration.d.ts.map

View File

@ -0,0 +1 @@
{"version":3,"file":"XmlDeclaration.d.ts","sourceRoot":"","sources":["../../src/lib/XmlDeclaration.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC;;;;;;;;GAQG;AACH,qBAAa,cAAe,SAAQ,OAAO;IACzC;;;OAGG;IACH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAExB;;;OAGG;IACH,UAAU,EAAE,KAAK,GAAG,IAAI,GAAG,IAAI,CAAC;IAEhC;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;gBAGd,OAAO,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,MAAM,EACjB,UAAU,CAAC,EAAE,OAAO,cAAc,CAAC,SAAS,CAAC,UAAU;IASzD,IAAa,IAAI,WAEhB;IAEQ,MAAM;CAYhB"}

View File

@ -0,0 +1,36 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.XmlDeclaration = void 0;
const XmlNode_js_1 = require("./XmlNode.js");
/**
* An XML declaration within an XML document.
*
* @example
*
* ```xml
* <?xml version="1.0" encoding="UTF-8"?>
* ```
*/
class XmlDeclaration extends XmlNode_js_1.XmlNode {
constructor(version, encoding, standalone) {
super();
this.version = version;
this.encoding = encoding ?? null;
this.standalone = standalone ?? null;
}
get type() {
return XmlNode_js_1.XmlNode.TYPE_XML_DECLARATION;
}
toJSON() {
let json = XmlNode_js_1.XmlNode.prototype.toJSON.call(this);
json.version = this.version;
for (let key of ['encoding', 'standalone']) {
if (this[key] !== null) {
json[key] = this[key];
}
}
return json;
}
}
exports.XmlDeclaration = XmlDeclaration;
//# sourceMappingURL=XmlDeclaration.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"XmlDeclaration.js","sourceRoot":"","sources":["../../src/lib/XmlDeclaration.ts"],"names":[],"mappings":";;;AAAA,6CAAuC;AAEvC;;;;;;;;GAQG;AACH,MAAa,cAAe,SAAQ,oBAAO;IAkBzC,YACE,OAAe,EACf,QAAiB,EACjB,UAAuD;QAEvD,KAAK,EAAE,CAAC;QAER,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,QAAQ,GAAG,QAAQ,IAAI,IAAI,CAAC;QACjC,IAAI,CAAC,UAAU,GAAG,UAAU,IAAI,IAAI,CAAC;IACvC,CAAC;IAED,IAAa,IAAI;QACf,OAAO,oBAAO,CAAC,oBAAoB,CAAC;IACtC,CAAC;IAEQ,MAAM;QACb,IAAI,IAAI,GAAG,oBAAO,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/C,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;QAE5B,KAAK,IAAI,GAAG,IAAI,CAAC,UAAU,EAAE,YAAY,CAAU,EAAE,CAAC;YACpD,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC;gBACvB,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;YACxB,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AA9CD,wCA8CC"}

View File

@ -0,0 +1,31 @@
import { XmlElement } from './XmlElement.js';
import { XmlNode } from './XmlNode.js';
import type { XmlComment } from './XmlComment.js';
import type { XmlDeclaration } from './XmlDeclaration.js';
import type { XmlDocumentType } from './XmlDocumentType.js';
import type { XmlProcessingInstruction } from './XmlProcessingInstruction.js';
/**
* Represents an XML document. All elements within the document are descendants
* of this node.
*/
export declare class XmlDocument extends XmlNode {
/**
* Child nodes of this document.
*/
readonly children: Array<XmlComment | XmlDeclaration | XmlDocumentType | XmlProcessingInstruction | XmlElement>;
constructor(children?: Array<XmlComment | XmlDeclaration | XmlDocumentType | XmlElement | XmlProcessingInstruction>);
get document(): this;
/**
* Root element of this document, or `null` if this document is empty.
*/
get root(): XmlElement | null;
/**
* Text content of this document and all its descendants.
*/
get text(): string;
get type(): string;
toJSON(): import("./types.js").JsonObject & {
children: import("./types.js").JsonObject[];
};
}
//# sourceMappingURL=XmlDocument.d.ts.map

View File

@ -0,0 +1 @@
{"version":3,"file":"XmlDocument.d.ts","sourceRoot":"","sources":["../../src/lib/XmlDocument.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AAE9E;;;GAGG;AACH,qBAAa,WAAY,SAAQ,OAAO;IACtC;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,UAAU,GAAG,cAAc,GAAG,eAAe,GAAG,wBAAwB,GAAG,UAAU,CAAC,CAAC;gBAEpG,QAAQ,GAAE,KAAK,CAAC,UAAU,GAAG,cAAc,GAAG,eAAe,GAAG,UAAU,GAAG,wBAAwB,CAAM;IAKvH,IAAa,QAAQ,SAEpB;IAED;;OAEG;IACH,IAAI,IAAI,IAAI,UAAU,GAAG,IAAI,CAQ5B;IAED;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAIjB;IAED,IAAa,IAAI,WAEhB;IAEQ,MAAM;;;CAKhB"}

47
node_modules/@rgrove/parse-xml/dist/lib/XmlDocument.js generated vendored Normal file
View File

@ -0,0 +1,47 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.XmlDocument = void 0;
const XmlElement_js_1 = require("./XmlElement.js");
const XmlNode_js_1 = require("./XmlNode.js");
/**
* Represents an XML document. All elements within the document are descendants
* of this node.
*/
class XmlDocument extends XmlNode_js_1.XmlNode {
constructor(children = []) {
super();
this.children = children;
}
get document() {
return this;
}
/**
* Root element of this document, or `null` if this document is empty.
*/
get root() {
for (let child of this.children) {
if (child instanceof XmlElement_js_1.XmlElement) {
return child;
}
}
return null;
}
/**
* Text content of this document and all its descendants.
*/
get text() {
return this.children
.map(child => 'text' in child ? child.text : '')
.join('');
}
get type() {
return XmlNode_js_1.XmlNode.TYPE_DOCUMENT;
}
toJSON() {
return Object.assign(XmlNode_js_1.XmlNode.prototype.toJSON.call(this), {
children: this.children.map(child => child.toJSON()),
});
}
}
exports.XmlDocument = XmlDocument;
//# sourceMappingURL=XmlDocument.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"XmlDocument.js","sourceRoot":"","sources":["../../src/lib/XmlDocument.ts"],"names":[],"mappings":";;;AAAA,mDAA6C;AAC7C,6CAAuC;AAOvC;;;GAGG;AACH,MAAa,WAAY,SAAQ,oBAAO;IAMtC,YAAY,WAAyG,EAAE;QACrH,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED,IAAa,QAAQ;QACnB,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;OAEG;IACH,IAAI,IAAI;QACN,KAAK,IAAI,KAAK,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAChC,IAAI,KAAK,YAAY,0BAAU,EAAE,CAAC;gBAChC,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;OAEG;IACH,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,QAAQ;aACjB,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;aAC/C,IAAI,CAAC,EAAE,CAAC,CAAC;IACd,CAAC;IAED,IAAa,IAAI;QACf,OAAO,oBAAO,CAAC,aAAa,CAAC;IAC/B,CAAC;IAEQ,MAAM;QACb,OAAO,MAAM,CAAC,MAAM,CAAC,oBAAO,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;YACxD,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;SACrD,CAAC,CAAC;IACL,CAAC;CACF;AA9CD,kCA8CC"}

View File

@ -0,0 +1,37 @@
import { XmlNode } from './XmlNode.js';
/**
* A document type declaration within an XML document.
*
* @example
*
* ```xml
* <!DOCTYPE kittens [
* <!ELEMENT kittens (#PCDATA)>
* ]>
* ```
*/
export declare class XmlDocumentType extends XmlNode {
/**
* Name of the root element described by this document type declaration.
*/
name: string;
/**
* Public identifier of the external subset of this document type declaration,
* or `null` if no public identifier was present.
*/
publicId: string | null;
/**
* System identifier of the external subset of this document type declaration,
* or `null` if no system identifier was present.
*/
systemId: string | null;
/**
* Internal subset of this document type declaration, or `null` if no internal
* subset was present.
*/
internalSubset: string | null;
constructor(name: string, publicId?: string, systemId?: string, internalSubset?: string);
get type(): string;
toJSON(): import("./types.js").JsonObject;
}
//# sourceMappingURL=XmlDocumentType.d.ts.map

View File

@ -0,0 +1 @@
{"version":3,"file":"XmlDocumentType.d.ts","sourceRoot":"","sources":["../../src/lib/XmlDocumentType.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC;;;;;;;;;;GAUG;AACH,qBAAa,eAAgB,SAAQ,OAAO;IAC1C;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;;OAGG;IACH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAExB;;;OAGG;IACH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAExB;;;OAGG;IACH,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;gBAG5B,IAAI,EAAE,MAAM,EACZ,QAAQ,CAAC,EAAE,MAAM,EACjB,QAAQ,CAAC,EAAE,MAAM,EACjB,cAAc,CAAC,EAAE,MAAM;IASzB,IAAa,IAAI,WAEhB;IAEQ,MAAM;CAYhB"}

View File

@ -0,0 +1,39 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.XmlDocumentType = void 0;
const XmlNode_js_1 = require("./XmlNode.js");
/**
* A document type declaration within an XML document.
*
* @example
*
* ```xml
* <!DOCTYPE kittens [
* <!ELEMENT kittens (#PCDATA)>
* ]>
* ```
*/
class XmlDocumentType extends XmlNode_js_1.XmlNode {
constructor(name, publicId, systemId, internalSubset) {
super();
this.name = name;
this.publicId = publicId ?? null;
this.systemId = systemId ?? null;
this.internalSubset = internalSubset ?? null;
}
get type() {
return XmlNode_js_1.XmlNode.TYPE_DOCUMENT_TYPE;
}
toJSON() {
let json = XmlNode_js_1.XmlNode.prototype.toJSON.call(this);
json.name = this.name;
for (let key of ['publicId', 'systemId', 'internalSubset']) {
if (this[key] !== null) {
json[key] = this[key];
}
}
return json;
}
}
exports.XmlDocumentType = XmlDocumentType;
//# sourceMappingURL=XmlDocumentType.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"XmlDocumentType.js","sourceRoot":"","sources":["../../src/lib/XmlDocumentType.ts"],"names":[],"mappings":";;;AAAA,6CAAuC;AAEvC;;;;;;;;;;GAUG;AACH,MAAa,eAAgB,SAAQ,oBAAO;IAwB1C,YACE,IAAY,EACZ,QAAiB,EACjB,QAAiB,EACjB,cAAuB;QAEvB,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,QAAQ,GAAG,QAAQ,IAAI,IAAI,CAAC;QACjC,IAAI,CAAC,QAAQ,GAAG,QAAQ,IAAI,IAAI,CAAC;QACjC,IAAI,CAAC,cAAc,GAAG,cAAc,IAAI,IAAI,CAAC;IAC/C,CAAC;IAED,IAAa,IAAI;QACf,OAAO,oBAAO,CAAC,kBAAkB,CAAC;IACpC,CAAC;IAEQ,MAAM;QACb,IAAI,IAAI,GAAG,oBAAO,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/C,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QAEtB,KAAK,IAAI,GAAG,IAAI,CAAC,UAAU,EAAE,UAAU,EAAE,gBAAgB,CAAU,EAAE,CAAC;YACpE,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC;gBACvB,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;YACxB,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AArDD,0CAqDC"}

View File

@ -0,0 +1,40 @@
import { XmlNode } from './XmlNode.js';
import type { JsonObject } from './types.js';
import type { XmlCdata } from './XmlCdata.js';
import type { XmlComment } from './XmlComment.js';
import type { XmlProcessingInstruction } from './XmlProcessingInstruction.js';
import type { XmlText } from './XmlText.js';
/**
* Element in an XML document.
*/
export declare class XmlElement extends XmlNode {
/**
* Attributes on this element.
*/
attributes: {
[attrName: string]: string;
};
/**
* Child nodes of this element.
*/
children: Array<XmlCdata | XmlComment | XmlElement | XmlProcessingInstruction | XmlText>;
/**
* Name of this element.
*/
name: string;
constructor(name: string, attributes?: {
[attrName: string]: string;
}, children?: Array<XmlCdata | XmlComment | XmlElement | XmlProcessingInstruction | XmlText>);
/**
* Whether this element is empty (meaning it has no children).
*/
get isEmpty(): boolean;
get preserveWhitespace(): boolean;
/**
* Text content of this element and all its descendants.
*/
get text(): string;
get type(): string;
toJSON(): JsonObject;
}
//# sourceMappingURL=XmlElement.d.ts.map

View File

@ -0,0 +1 @@
{"version":3,"file":"XmlElement.d.ts","sourceRoot":"","sources":["../../src/lib/XmlElement.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AAC9E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAE5C;;GAEG;AACH,qBAAa,UAAW,SAAQ,OAAO;IACrC;;OAEG;IACH,UAAU,EAAE;QAAC,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAA;KAAC,CAAC;IAEzC;;OAEG;IACH,QAAQ,EAAE,KAAK,CAAC,QAAQ,GAAG,UAAU,GAAG,UAAU,GAAG,wBAAwB,GAAG,OAAO,CAAC,CAAC;IAEzF;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;gBAGX,IAAI,EAAE,MAAM,EACZ,UAAU,GAAE;QAAC,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAA;KAAuB,EAC9D,QAAQ,GAAE,KAAK,CAAC,QAAQ,GAAG,UAAU,GAAG,UAAU,GAAG,wBAAwB,GAAG,OAAO,CAAM;IAS/F;;OAEG;IACH,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,IAAa,kBAAkB,IAAI,OAAO,CAYzC;IAED;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAIjB;IAED,IAAa,IAAI,WAEhB;IAEQ,MAAM,IAAI,UAAU;CAO9B"}

51
node_modules/@rgrove/parse-xml/dist/lib/XmlElement.js generated vendored Normal file
View File

@ -0,0 +1,51 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.XmlElement = void 0;
const XmlNode_js_1 = require("./XmlNode.js");
/**
* Element in an XML document.
*/
class XmlElement extends XmlNode_js_1.XmlNode {
constructor(name, attributes = Object.create(null), children = []) {
super();
this.name = name;
this.attributes = attributes;
this.children = children;
}
/**
* Whether this element is empty (meaning it has no children).
*/
get isEmpty() {
return this.children.length === 0;
}
get preserveWhitespace() {
let node = this; // eslint-disable-line @typescript-eslint/no-this-alias
while (node instanceof XmlElement) {
if ('xml:space' in node.attributes) {
return node.attributes['xml:space'] === 'preserve';
}
node = node.parent;
}
return false;
}
/**
* Text content of this element and all its descendants.
*/
get text() {
return this.children
.map(child => 'text' in child ? child.text : '')
.join('');
}
get type() {
return XmlNode_js_1.XmlNode.TYPE_ELEMENT;
}
toJSON() {
return Object.assign(XmlNode_js_1.XmlNode.prototype.toJSON.call(this), {
name: this.name,
attributes: this.attributes,
children: this.children.map(child => child.toJSON()),
});
}
}
exports.XmlElement = XmlElement;
//# sourceMappingURL=XmlElement.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"XmlElement.js","sourceRoot":"","sources":["../../src/lib/XmlElement.ts"],"names":[],"mappings":";;;AAAA,6CAAuC;AAQvC;;GAEG;AACH,MAAa,UAAW,SAAQ,oBAAO;IAgBrC,YACE,IAAY,EACZ,aAA2C,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,EAC9D,WAA2F,EAAE;QAE7F,KAAK,EAAE,CAAC;QAER,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED;;OAEG;IACH,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC;IACpC,CAAC;IAED,IAAa,kBAAkB;QAC7B,IAAI,IAAI,GAAmB,IAAI,CAAC,CAAC,uDAAuD;QAExF,OAAO,IAAI,YAAY,UAAU,EAAE,CAAC;YAClC,IAAI,WAAW,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;gBACnC,OAAO,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,KAAK,UAAU,CAAC;YACrD,CAAC;YAED,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC;QACrB,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;OAEG;IACH,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,QAAQ;aACjB,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;aAC/C,IAAI,CAAC,EAAE,CAAC,CAAC;IACd,CAAC;IAED,IAAa,IAAI;QACf,OAAO,oBAAO,CAAC,YAAY,CAAC;IAC9B,CAAC;IAEQ,MAAM;QACb,OAAO,MAAM,CAAC,MAAM,CAAC,oBAAO,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;YACxD,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;SACrD,CAAC,CAAC;IACL,CAAC;CACF;AArED,gCAqEC"}

24
node_modules/@rgrove/parse-xml/dist/lib/XmlError.d.ts generated vendored Normal file
View File

@ -0,0 +1,24 @@
/**
* An error that occurred while parsing XML.
*/
export declare class XmlError extends Error {
/**
* Character column at which this error occurred (1-based).
*/
readonly column: number;
/**
* Short excerpt from the input string that contains the problem.
*/
readonly excerpt: string;
/**
* Line number at which this error occurred (1-based).
*/
readonly line: number;
/**
* Character position at which this error occurred relative to the beginning
* of the input (0-based).
*/
readonly pos: number;
constructor(message: string, charIndex: number, xml: string);
}
//# sourceMappingURL=XmlError.d.ts.map

View File

@ -0,0 +1 @@
{"version":3,"file":"XmlError.d.ts","sourceRoot":"","sources":["../../src/lib/XmlError.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,qBAAa,QAAS,SAAQ,KAAK;IACjC;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAExB;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAEzB;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB;;;OAGG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;gBAGnB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM;CAmDd"}

52
node_modules/@rgrove/parse-xml/dist/lib/XmlError.js generated vendored Normal file
View File

@ -0,0 +1,52 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.XmlError = void 0;
/**
* An error that occurred while parsing XML.
*/
class XmlError extends Error {
constructor(message, charIndex, xml) {
let column = 1;
let excerpt = '';
let line = 1;
// Find the line and column where the error occurred.
for (let i = 0; i < charIndex; ++i) {
let char = xml[i];
if (char === '\n') {
column = 1;
excerpt = '';
line += 1;
}
else {
column += 1;
excerpt += char;
}
}
let eol = xml.indexOf('\n', charIndex);
excerpt += eol === -1
? xml.slice(charIndex)
: xml.slice(charIndex, eol);
let excerptStart = 0;
// Keep the excerpt below 50 chars, but always keep the error position in
// view.
if (excerpt.length > 50) {
if (column < 40) {
excerpt = excerpt.slice(0, 50);
}
else {
excerptStart = column - 20;
excerpt = excerpt.slice(excerptStart, column + 30);
}
}
super(`${message} (line ${line}, column ${column})\n`
+ ` ${excerpt}\n`
+ ' '.repeat(column - excerptStart + 1) + '^\n');
this.column = column;
this.excerpt = excerpt;
this.line = line;
this.name = 'XmlError';
this.pos = charIndex;
}
}
exports.XmlError = XmlError;
//# sourceMappingURL=XmlError.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"XmlError.js","sourceRoot":"","sources":["../../src/lib/XmlError.ts"],"names":[],"mappings":";;;AAAA;;GAEG;AACH,MAAa,QAAS,SAAQ,KAAK;IAsBjC,YACE,OAAe,EACf,SAAiB,EACjB,GAAW;QAEX,IAAI,MAAM,GAAG,CAAC,CAAC;QACf,IAAI,OAAO,GAAG,EAAE,CAAC;QACjB,IAAI,IAAI,GAAG,CAAC,CAAC;QAEb,qDAAqD;QACrD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,EAAE,EAAE,CAAC,EAAE,CAAC;YACnC,IAAI,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;YAElB,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;gBAClB,MAAM,GAAG,CAAC,CAAC;gBACX,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,IAAI,CAAC,CAAC;YACZ,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,CAAC,CAAC;gBACZ,OAAO,IAAI,IAAI,CAAC;YAClB,CAAC;QACH,CAAC;QAED,IAAI,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QAEvC,OAAO,IAAI,GAAG,KAAK,CAAC,CAAC;YACnB,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC;YACtB,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QAE9B,IAAI,YAAY,GAAG,CAAC,CAAC;QAErB,yEAAyE;QACzE,QAAQ;QACR,IAAI,OAAO,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;YACxB,IAAI,MAAM,GAAG,EAAE,EAAE,CAAC;gBAChB,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACjC,CAAC;iBAAM,CAAC;gBACN,YAAY,GAAG,MAAM,GAAG,EAAE,CAAC;gBAC3B,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,YAAY,EAAE,MAAM,GAAG,EAAE,CAAC,CAAC;YACrD,CAAC;QACH,CAAC;QAED,KAAK,CACH,GAAG,OAAO,UAAU,IAAI,YAAY,MAAM,KAAK;cAC3C,KAAK,OAAO,IAAI;cAChB,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,YAAY,GAAG,CAAC,CAAC,GAAG,KAAK,CAClD,CAAC;QAEF,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;QACvB,IAAI,CAAC,GAAG,GAAG,SAAS,CAAC;IACvB,CAAC;CACF;AA5ED,4BA4EC"}

93
node_modules/@rgrove/parse-xml/dist/lib/XmlNode.d.ts generated vendored Normal file
View File

@ -0,0 +1,93 @@
import type { JsonObject } from './types.js';
import type { XmlDocument } from './XmlDocument.js';
import type { XmlElement } from './XmlElement.js';
/**
* Base interface for a node in an XML document.
*/
export declare class XmlNode {
/**
* Type value for an `XmlCdata` node.
*/
static readonly TYPE_CDATA = "cdata";
/**
* Type value for an `XmlComment` node.
*/
static readonly TYPE_COMMENT = "comment";
/**
* Type value for an `XmlDocument` node.
*/
static readonly TYPE_DOCUMENT = "document";
/**
* Type value for an `XmlDocumentType` node.
*/
static readonly TYPE_DOCUMENT_TYPE = "doctype";
/**
* Type value for an `XmlElement` node.
*/
static readonly TYPE_ELEMENT = "element";
/**
* Type value for an `XmlProcessingInstruction` node.
*/
static readonly TYPE_PROCESSING_INSTRUCTION = "pi";
/**
* Type value for an `XmlText` node.
*/
static readonly TYPE_TEXT = "text";
/**
* Type value for an `XmlDeclaration` node.
*/
static readonly TYPE_XML_DECLARATION = "xmldecl";
/**
* Parent node of this node, or `null` if this node has no parent.
*/
parent: XmlDocument | XmlElement | null;
/**
* Starting byte offset of this node in the original XML string, or `-1` if
* the offset is unknown.
*/
start: number;
/**
* Ending byte offset of this node in the original XML string, or `-1` if the
* offset is unknown.
*/
end: number;
/**
* Document that contains this node, or `null` if this node is not associated
* with a document.
*/
get document(): XmlDocument | null;
/**
* Whether this node is the root node of the document (also known as the
* document element).
*/
get isRootNode(): boolean;
/**
* Whether whitespace should be preserved in the content of this element and
* its children.
*
* This is influenced by the value of the special `xml:space` attribute, and
* will be `true` for any node whose `xml:space` attribute is set to
* "preserve". If a node has no such attribute, it will inherit the value of
* the nearest ancestor that does (if any).
*
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#sec-white-space
*/
get preserveWhitespace(): boolean;
/**
* Type of this node.
*
* The value of this property is a string that matches one of the static
* `TYPE_*` properties on the `XmlNode` class (e.g. `TYPE_ELEMENT`,
* `TYPE_TEXT`, etc.).
*
* The `XmlNode` class itself is a base class and doesn't have its own type
* name.
*/
get type(): string;
/**
* Returns a JSON-serializable object representing this node, minus properties
* that could result in circular references.
*/
toJSON(): JsonObject;
}
//# sourceMappingURL=XmlNode.d.ts.map

View File

@ -0,0 +1 @@
{"version":3,"file":"XmlNode.d.ts","sourceRoot":"","sources":["../../src/lib/XmlNode.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD;;GAEG;AACH,qBAAa,OAAO;IAClB;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,UAAU,WAAW;IAErC;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,YAAY,aAAa;IAEzC;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,aAAa,cAAc;IAE3C;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,kBAAkB,aAAa;IAE/C;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,YAAY,aAAa;IAEzC;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,2BAA2B,QAAQ;IAEnD;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,SAAS,UAAU;IAEnC;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,oBAAoB,aAAa;IAEjD;;OAEG;IACH,MAAM,EAAE,WAAW,GAAG,UAAU,GAAG,IAAI,CAAQ;IAE/C;;;OAGG;IACH,KAAK,SAAM;IAEX;;;OAGG;IACH,GAAG,SAAM;IAET;;;OAGG;IACH,IAAI,QAAQ,IAAI,WAAW,GAAG,IAAI,CAEjC;IAED;;;OAGG;IACH,IAAI,UAAU,IAAI,OAAO,CAIxB;IAED;;;;;;;;;;OAUG;IACH,IAAI,kBAAkB,IAAI,OAAO,CAEhC;IAED;;;;;;;;;OASG;IACH,IAAI,IAAI,WAEP;IAED;;;OAGG;IACH,MAAM,IAAI,UAAU;CAoBrB"}

121
node_modules/@rgrove/parse-xml/dist/lib/XmlNode.js generated vendored Normal file
View File

@ -0,0 +1,121 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.XmlNode = void 0;
/**
* Base interface for a node in an XML document.
*/
class XmlNode {
constructor() {
/**
* Parent node of this node, or `null` if this node has no parent.
*/
this.parent = null;
/**
* Starting byte offset of this node in the original XML string, or `-1` if
* the offset is unknown.
*/
this.start = -1;
/**
* Ending byte offset of this node in the original XML string, or `-1` if the
* offset is unknown.
*/
this.end = -1;
}
/**
* Document that contains this node, or `null` if this node is not associated
* with a document.
*/
get document() {
return this.parent?.document ?? null;
}
/**
* Whether this node is the root node of the document (also known as the
* document element).
*/
get isRootNode() {
return this.parent !== null
&& this.parent === this.document
&& this.type === XmlNode.TYPE_ELEMENT;
}
/**
* Whether whitespace should be preserved in the content of this element and
* its children.
*
* This is influenced by the value of the special `xml:space` attribute, and
* will be `true` for any node whose `xml:space` attribute is set to
* "preserve". If a node has no such attribute, it will inherit the value of
* the nearest ancestor that does (if any).
*
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#sec-white-space
*/
get preserveWhitespace() {
return !!this.parent?.preserveWhitespace;
}
/**
* Type of this node.
*
* The value of this property is a string that matches one of the static
* `TYPE_*` properties on the `XmlNode` class (e.g. `TYPE_ELEMENT`,
* `TYPE_TEXT`, etc.).
*
* The `XmlNode` class itself is a base class and doesn't have its own type
* name.
*/
get type() {
return '';
}
/**
* Returns a JSON-serializable object representing this node, minus properties
* that could result in circular references.
*/
toJSON() {
let json = {
type: this.type,
};
if (this.isRootNode) {
json.isRootNode = true;
}
if (this.preserveWhitespace) {
json.preserveWhitespace = true;
}
if (this.start !== -1) {
json.start = this.start;
json.end = this.end;
}
return json;
}
}
exports.XmlNode = XmlNode;
/**
* Type value for an `XmlCdata` node.
*/
XmlNode.TYPE_CDATA = 'cdata';
/**
* Type value for an `XmlComment` node.
*/
XmlNode.TYPE_COMMENT = 'comment';
/**
* Type value for an `XmlDocument` node.
*/
XmlNode.TYPE_DOCUMENT = 'document';
/**
* Type value for an `XmlDocumentType` node.
*/
XmlNode.TYPE_DOCUMENT_TYPE = 'doctype';
/**
* Type value for an `XmlElement` node.
*/
XmlNode.TYPE_ELEMENT = 'element';
/**
* Type value for an `XmlProcessingInstruction` node.
*/
XmlNode.TYPE_PROCESSING_INSTRUCTION = 'pi';
/**
* Type value for an `XmlText` node.
*/
XmlNode.TYPE_TEXT = 'text';
/**
* Type value for an `XmlDeclaration` node.
*/
XmlNode.TYPE_XML_DECLARATION = 'xmldecl';
//# sourceMappingURL=XmlNode.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"XmlNode.js","sourceRoot":"","sources":["../../src/lib/XmlNode.ts"],"names":[],"mappings":";;;AAIA;;GAEG;AACH,MAAa,OAAO;IAApB;QAyCE;;WAEG;QACH,WAAM,GAAoC,IAAI,CAAC;QAE/C;;;WAGG;QACH,UAAK,GAAG,CAAC,CAAC,CAAC;QAEX;;;WAGG;QACH,QAAG,GAAG,CAAC,CAAC,CAAC;IAyEX,CAAC;IAvEC;;;OAGG;IACH,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,MAAM,EAAE,QAAQ,IAAI,IAAI,CAAC;IACvC,CAAC;IAED;;;OAGG;IACH,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,MAAM,KAAK,IAAI;eACtB,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,QAAQ;eAC7B,IAAI,CAAC,IAAI,KAAK,OAAO,CAAC,YAAY,CAAC;IAC1C,CAAC;IAED;;;;;;;;;;OAUG;IACH,IAAI,kBAAkB;QACpB,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,kBAAkB,CAAC;IAC3C,CAAC;IAED;;;;;;;;;OASG;IACH,IAAI,IAAI;QACN,OAAO,EAAE,CAAC;IACZ,CAAC;IAED;;;OAGG;IACH,MAAM;QACJ,IAAI,IAAI,GAAe;YACrB,IAAI,EAAE,IAAI,CAAC,IAAI;SAChB,CAAC;QAEF,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACzB,CAAC;QAED,IAAI,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC5B,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC;QACjC,CAAC;QAED,IAAI,IAAI,CAAC,KAAK,KAAK,CAAC,CAAC,EAAE,CAAC;YACtB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;YACxB,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;QACtB,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;;AAhIH,0BAiIC;AAhIC;;GAEG;AACa,kBAAU,GAAG,OAAO,AAAV,CAAW;AAErC;;GAEG;AACa,oBAAY,GAAG,SAAS,AAAZ,CAAa;AAEzC;;GAEG;AACa,qBAAa,GAAG,UAAU,AAAb,CAAc;AAE3C;;GAEG;AACa,0BAAkB,GAAG,SAAS,AAAZ,CAAa;AAE/C;;GAEG;AACa,oBAAY,GAAG,SAAS,AAAZ,CAAa;AAEzC;;GAEG;AACa,mCAA2B,GAAG,IAAI,AAAP,CAAQ;AAEnD;;GAEG;AACa,iBAAS,GAAG,MAAM,AAAT,CAAU;AAEnC;;GAEG;AACa,4BAAoB,GAAG,SAAS,AAAZ,CAAa"}

View File

@ -0,0 +1,22 @@
import { XmlNode } from './XmlNode.js';
/**
* A processing instruction within an XML document.
*/
export declare class XmlProcessingInstruction extends XmlNode {
/**
* Content of this processing instruction.
*/
content: string;
/**
* Name of this processing instruction. Also sometimes referred to as the
* processing instruction "target".
*/
name: string;
constructor(name: string, content?: string);
get type(): string;
toJSON(): import("./types.js").JsonObject & {
name: string;
content: string;
};
}
//# sourceMappingURL=XmlProcessingInstruction.d.ts.map

View File

@ -0,0 +1 @@
{"version":3,"file":"XmlProcessingInstruction.d.ts","sourceRoot":"","sources":["../../src/lib/XmlProcessingInstruction.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC;;GAEG;AACH,qBAAa,wBAAyB,SAAQ,OAAO;IACnD;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,IAAI,EAAE,MAAM,CAAC;gBAED,IAAI,EAAE,MAAM,EAAE,OAAO,SAAK;IAOtC,IAAa,IAAI,WAEhB;IAEQ,MAAM;;;;CAMhB"}

View File

@ -0,0 +1,25 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.XmlProcessingInstruction = void 0;
const XmlNode_js_1 = require("./XmlNode.js");
/**
* A processing instruction within an XML document.
*/
class XmlProcessingInstruction extends XmlNode_js_1.XmlNode {
constructor(name, content = '') {
super();
this.name = name;
this.content = content;
}
get type() {
return XmlNode_js_1.XmlNode.TYPE_PROCESSING_INSTRUCTION;
}
toJSON() {
return Object.assign(XmlNode_js_1.XmlNode.prototype.toJSON.call(this), {
name: this.name,
content: this.content,
});
}
}
exports.XmlProcessingInstruction = XmlProcessingInstruction;
//# sourceMappingURL=XmlProcessingInstruction.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"XmlProcessingInstruction.js","sourceRoot":"","sources":["../../src/lib/XmlProcessingInstruction.ts"],"names":[],"mappings":";;;AAAA,6CAAuC;AAEvC;;GAEG;AACH,MAAa,wBAAyB,SAAQ,oBAAO;IAYnD,YAAY,IAAY,EAAE,OAAO,GAAG,EAAE;QACpC,KAAK,EAAE,CAAC;QAER,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED,IAAa,IAAI;QACf,OAAO,oBAAO,CAAC,2BAA2B,CAAC;IAC7C,CAAC;IAEQ,MAAM;QACb,OAAO,MAAM,CAAC,MAAM,CAAC,oBAAO,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;YACxD,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,OAAO,EAAE,IAAI,CAAC,OAAO;SACtB,CAAC,CAAC;IACL,CAAC;CACF;AA7BD,4DA6BC"}

16
node_modules/@rgrove/parse-xml/dist/lib/XmlText.d.ts generated vendored Normal file
View File

@ -0,0 +1,16 @@
import { XmlNode } from './XmlNode.js';
/**
* Text content within an XML document.
*/
export declare class XmlText extends XmlNode {
/**
* Text content of this node.
*/
text: string;
constructor(text?: string);
get type(): string;
toJSON(): import("./types.js").JsonObject & {
text: string;
};
}
//# sourceMappingURL=XmlText.d.ts.map

View File

@ -0,0 +1 @@
{"version":3,"file":"XmlText.d.ts","sourceRoot":"","sources":["../../src/lib/XmlText.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC;;GAEG;AACH,qBAAa,OAAQ,SAAQ,OAAO;IAClC;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;gBAED,IAAI,SAAK;IAKrB,IAAa,IAAI,WAEhB;IAEQ,MAAM;;;CAKhB"}

23
node_modules/@rgrove/parse-xml/dist/lib/XmlText.js generated vendored Normal file
View File

@ -0,0 +1,23 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.XmlText = void 0;
const XmlNode_js_1 = require("./XmlNode.js");
/**
* Text content within an XML document.
*/
class XmlText extends XmlNode_js_1.XmlNode {
constructor(text = '') {
super();
this.text = text;
}
get type() {
return XmlNode_js_1.XmlNode.TYPE_TEXT;
}
toJSON() {
return Object.assign(XmlNode_js_1.XmlNode.prototype.toJSON.call(this), {
text: this.text,
});
}
}
exports.XmlText = XmlText;
//# sourceMappingURL=XmlText.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"XmlText.js","sourceRoot":"","sources":["../../src/lib/XmlText.ts"],"names":[],"mappings":";;;AAAA,6CAAuC;AAEvC;;GAEG;AACH,MAAa,OAAQ,SAAQ,oBAAO;IAMlC,YAAY,IAAI,GAAG,EAAE;QACnB,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,IAAa,IAAI;QACf,OAAO,oBAAO,CAAC,SAAS,CAAC;IAC3B,CAAC;IAEQ,MAAM;QACb,OAAO,MAAM,CAAC,MAAM,CAAC,oBAAO,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;YACxD,IAAI,EAAE,IAAI,CAAC,IAAI;SAChB,CAAC,CAAC;IACL,CAAC;CACF;AApBD,0BAoBC"}

69
node_modules/@rgrove/parse-xml/dist/lib/syntax.d.ts generated vendored Normal file
View File

@ -0,0 +1,69 @@
/**
* Regular expression that matches one or more `AttValue` characters in a
* double-quoted attribute value.
*
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#NT-AttValue
*/
export declare const attValueCharDoubleQuote: RegExp;
/**
* Regular expression that matches one or more `AttValue` characters in a
* single-quoted attribute value.
*
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#NT-AttValue
*/
export declare const attValueCharSingleQuote: RegExp;
/**
* Regular expression that matches a whitespace character that should be
* normalized to a space character in an attribute value.
*
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#AVNormalize
*/
export declare const attValueNormalizedWhitespace: RegExp;
/**
* Regular expression that matches one or more characters that signal the end of
* XML `CharData` content.
*
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#dt-chardata
*/
export declare const endCharData: RegExp;
/**
* Mapping of predefined entity names to their replacement values.
*
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#sec-predefined-ent
*/
export declare const predefinedEntities: Readonly<{
[name: string]: string;
}>;
/**
* Returns `true` if _char_ is an XML `NameChar`, `false` if it isn't.
*
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#NT-NameChar
*/
export declare function isNameChar(char: string): boolean;
/**
* Returns `true` if _char_ is an XML `NameStartChar`, `false` if it isn't.
*
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#NT-NameStartChar
*/
export declare function isNameStartChar(char: string, cp?: number): boolean;
/**
* Returns `true` if _char_ is a valid reference character (which may appear
* between `&` and `;` in a reference), `false` otherwise.
*
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#sec-references
*/
export declare function isReferenceChar(char: string): boolean;
/**
* Returns `true` if _char_ is an XML whitespace character, `false` otherwise.
*
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#white
*/
export declare function isWhitespace(char: string): boolean;
/**
* Returns `true` if _codepoint_ is a valid XML `Char` code point, `false`
* otherwise.
*
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#NT-Char
*/
export declare function isXmlCodePoint(cp: number): boolean;
//# sourceMappingURL=syntax.d.ts.map

View File

@ -0,0 +1 @@
{"version":3,"file":"syntax.d.ts","sourceRoot":"","sources":["../../src/lib/syntax.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,QAAU,CAAC;AAE/C;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,QAAU,CAAC;AAE/C;;;;;GAKG;AACH,eAAO,MAAM,4BAA4B,QAAmB,CAAC;AAE7D;;;;;GAKG;AACH,eAAO,MAAM,WAAW,QAAY,CAAC;AAErC;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,EAAE,QAAQ,CAAC;IAAC,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;CAAC,CAMhE,CAAC;AAEJ;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAehD;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAA0B,MAAM,GAAG,OAAO,CAkBzF;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAErD;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAOlD;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAOlD"}

128
node_modules/@rgrove/parse-xml/dist/lib/syntax.js generated vendored Normal file
View File

@ -0,0 +1,128 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.predefinedEntities = exports.endCharData = exports.attValueNormalizedWhitespace = exports.attValueCharSingleQuote = exports.attValueCharDoubleQuote = void 0;
exports.isNameChar = isNameChar;
exports.isNameStartChar = isNameStartChar;
exports.isReferenceChar = isReferenceChar;
exports.isWhitespace = isWhitespace;
exports.isXmlCodePoint = isXmlCodePoint;
/**
* Regular expression that matches one or more `AttValue` characters in a
* double-quoted attribute value.
*
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#NT-AttValue
*/
exports.attValueCharDoubleQuote = /["&<]/;
/**
* Regular expression that matches one or more `AttValue` characters in a
* single-quoted attribute value.
*
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#NT-AttValue
*/
exports.attValueCharSingleQuote = /['&<]/;
/**
* Regular expression that matches a whitespace character that should be
* normalized to a space character in an attribute value.
*
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#AVNormalize
*/
exports.attValueNormalizedWhitespace = /\r\n|[\n\r\t]/g;
/**
* Regular expression that matches one or more characters that signal the end of
* XML `CharData` content.
*
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#dt-chardata
*/
exports.endCharData = /<|&|]]>/;
/**
* Mapping of predefined entity names to their replacement values.
*
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#sec-predefined-ent
*/
exports.predefinedEntities = Object.freeze(Object.assign(Object.create(null), {
amp: '&',
apos: "'",
gt: '>',
lt: '<',
quot: '"',
}));
/**
* Returns `true` if _char_ is an XML `NameChar`, `false` if it isn't.
*
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#NT-NameChar
*/
function isNameChar(char) {
let cp = char.codePointAt(0);
// Including the most common NameStartChars here improves performance
// slightly.
return (cp >= 0x61 && cp <= 0x7A) // a-z
|| (cp >= 0x41 && cp <= 0x5A) // A-Z
|| (cp >= 0x30 && cp <= 0x39) // 0-9
|| cp === 0x2D // -
|| cp === 0x2E // .
|| cp === 0xB7
|| (cp >= 0x300 && cp <= 0x36F)
|| cp === 0x203F
|| cp === 0x2040
|| isNameStartChar(char, cp);
}
/**
* Returns `true` if _char_ is an XML `NameStartChar`, `false` if it isn't.
*
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#NT-NameStartChar
*/
function isNameStartChar(char, cp = char.codePointAt(0)) {
return (cp >= 0x61 && cp <= 0x7A) // a-z
|| (cp >= 0x41 && cp <= 0x5A) // A-Z
|| cp === 0x3A // :
|| cp === 0x5F // _
|| (cp >= 0xC0 && cp <= 0xD6)
|| (cp >= 0xD8 && cp <= 0xF6)
|| (cp >= 0xF8 && cp <= 0x2FF)
|| (cp >= 0x370 && cp <= 0x37D)
|| (cp >= 0x37F && cp <= 0x1FFF)
|| cp === 0x200C
|| cp === 0x200D
|| (cp >= 0x2070 && cp <= 0x218F)
|| (cp >= 0x2C00 && cp <= 0x2FEF)
|| (cp >= 0x3001 && cp <= 0xD7FF)
|| (cp >= 0xF900 && cp <= 0xFDCF)
|| (cp >= 0xFDF0 && cp <= 0xFFFD)
|| (cp >= 0x10000 && cp <= 0xEFFFF);
}
/**
* Returns `true` if _char_ is a valid reference character (which may appear
* between `&` and `;` in a reference), `false` otherwise.
*
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#sec-references
*/
function isReferenceChar(char) {
return char === '#' || isNameChar(char);
}
/**
* Returns `true` if _char_ is an XML whitespace character, `false` otherwise.
*
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#white
*/
function isWhitespace(char) {
let cp = char.codePointAt(0);
return cp === 0x20
|| cp === 0x9
|| cp === 0xA
|| cp === 0xD;
}
/**
* Returns `true` if _codepoint_ is a valid XML `Char` code point, `false`
* otherwise.
*
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#NT-Char
*/
function isXmlCodePoint(cp) {
return (cp >= 0x20 && cp <= 0xD7FF)
|| cp === 0xA
|| cp === 0x9
|| cp === 0xD
|| (cp >= 0xE000 && cp <= 0xFFFD)
|| (cp >= 0x10000 && cp <= 0x10FFFF);
}
//# sourceMappingURL=syntax.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"syntax.js","sourceRoot":"","sources":["../../src/lib/syntax.ts"],"names":[],"mappings":"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"}

5
node_modules/@rgrove/parse-xml/dist/lib/types.d.ts generated vendored Normal file
View File

@ -0,0 +1,5 @@
export type JsonObject = {
[key in string]?: JsonValue;
};
export type JsonValue = string | number | boolean | JsonObject | JsonValue[] | null;
//# sourceMappingURL=types.d.ts.map

View File

@ -0,0 +1 @@
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG;KAAE,GAAG,IAAI,MAAM,CAAC,CAAC,EAAE,SAAS;CAAC,CAAC;AACvD,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,UAAU,GAAG,SAAS,EAAE,GAAG,IAAI,CAAC"}

3
node_modules/@rgrove/parse-xml/dist/lib/types.js generated vendored Normal file
View File

@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=types.js.map

1
node_modules/@rgrove/parse-xml/dist/lib/types.js.map generated vendored Normal file
View File

@ -0,0 +1 @@
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":""}

62
node_modules/@rgrove/parse-xml/package.json generated vendored Normal file
View File

@ -0,0 +1,62 @@
{
"name": "@rgrove/parse-xml",
"version": "4.2.0",
"description": "A fast, safe, compliant XML parser for Node.js and browsers.",
"keywords": [
"xml",
"xml parser",
"parse-xml",
"parse xml",
"parse",
"parser"
],
"author": "Ryan Grove <ryan@wonko.com>",
"license": "ISC",
"homepage": "https://github.com/rgrove/parse-xml",
"bugs": "https://github.com/rgrove/parse-xml/issues",
"repository": {
"type": "git",
"url": "https://github.com/rgrove/parse-xml.git"
},
"engines": {
"node": ">=14.0.0"
},
"files": [
"dist",
"!dist/tsconfig.tsbuildinfo",
"src",
"LICENSE"
],
"types": "./dist/index.d.ts",
"main": "./dist/index.js",
"browser": "./dist/browser.js",
"devDependencies": {
"@rgrove/eslint-config": "^5.1.0",
"@types/node": "^22.7.9",
"assert": "^2.1.0",
"concurrently": "^9.0.1",
"esbuild": "^0.24.0",
"eslint": "^8.57.1",
"expect-type": "^1.1.0",
"mocha": "^10.7.3",
"nyc": "^17.1.0",
"path-browserify": "^1.0.1",
"process": "^0.11.10",
"typedoc": "^0.26.10",
"typescript": "5.6.3"
},
"scripts": {
"build": "pnpm run build:js && pnpm run build:bundle && pnpm run build:docs",
"build:bundle": "./scripts/esbuild.js",
"build:docs": "typedoc src/index.ts",
"build:js": "tsc",
"clean": "rm -rf .nyc_output coverage dist docs tests/.build",
"coverage": "nyc --reporter html --report-dir coverage pnpm test && open coverage/index.html",
"lint": "pnpm run build:js && pnpm run lint:js",
"lint:js": "eslint .",
"test": "pnpm run build:js && nyc --check-coverage --branches 100 --functions 100 --lines 100 --statements 100 mocha && pnpm run test:types",
"test:browser": "pnpm run build:js && pnpm run build:bundle && scripts/test/browser.js",
"test:types": "pnpm run build:js && tsc --noEmit tests/types.expect.ts",
"test:watch": "pnpm run build:js && concurrently --kill-others-on-fail --names build,mocha 'pnpm run build:js --watch' 'mocha --watch'"
}
}

33
node_modules/@rgrove/parse-xml/src/index.ts generated vendored Normal file
View File

@ -0,0 +1,33 @@
import { Parser } from './lib/Parser.js';
import type { ParserOptions } from './lib/Parser.js';
export * from './lib/types.js';
export { XmlCdata } from './lib/XmlCdata.js';
export { XmlComment } from './lib/XmlComment.js';
export { XmlDeclaration } from './lib/XmlDeclaration.js';
export { XmlDocument } from './lib/XmlDocument.js';
export { XmlDocumentType } from './lib/XmlDocumentType.js';
export { XmlElement } from './lib/XmlElement.js';
export { XmlError } from './lib/XmlError.js';
export { XmlNode } from './lib/XmlNode.js';
export { XmlProcessingInstruction } from './lib/XmlProcessingInstruction.js';
export { XmlText } from './lib/XmlText.js';
export type { ParserOptions } from './lib/Parser.js';
/**
* Parses the given XML string and returns an `XmlDocument` instance
* representing the document tree.
*
* @example
*
* import { parseXml } from '@rgrove/parse-xml';
* let doc = parseXml('<kittens fuzzy="yes">I like fuzzy kittens.</kittens>');
*
* @param xml XML string to parse.
* @param options Parser options.
*/
export function parseXml(xml: string, options?: ParserOptions) {
return (new Parser(xml, options)).document;
}

906
node_modules/@rgrove/parse-xml/src/lib/Parser.ts generated vendored Normal file
View File

@ -0,0 +1,906 @@
import { StringScanner } from './StringScanner.js';
import * as syntax from './syntax.js';
import { XmlCdata } from './XmlCdata.js';
import { XmlComment } from './XmlComment.js';
import { XmlDeclaration } from './XmlDeclaration.js';
import { XmlDocument } from './XmlDocument.js';
import { XmlDocumentType } from './XmlDocumentType.js';
import { XmlElement } from './XmlElement.js';
import { XmlError } from './XmlError.js';
import { XmlNode } from './XmlNode.js';
import { XmlProcessingInstruction } from './XmlProcessingInstruction.js';
import { XmlText } from './XmlText.js';
const emptyString = '';
/**
* Parses an XML string into an `XmlDocument`.
*
* @private
*/
export class Parser {
readonly document: XmlDocument;
private currentNode: XmlDocument | XmlElement;
private readonly options: ParserOptions;
private readonly scanner: StringScanner;
/**
* @param xml XML string to parse.
* @param options Parser options.
*/
constructor(xml: string, options: ParserOptions = {}) {
let doc = this.document = new XmlDocument();
this.currentNode = doc;
this.options = options;
this.scanner = new StringScanner(xml);
if (this.options.includeOffsets) {
doc.start = 0;
doc.end = xml.length;
}
this.parse();
}
/**
* Adds the given `XmlNode` as a child of `this.currentNode`.
*/
addNode(node: XmlNode, charIndex: number) {
node.parent = this.currentNode;
if (this.options.includeOffsets) {
node.start = this.scanner.charIndexToByteIndex(charIndex);
node.end = this.scanner.charIndexToByteIndex();
}
// @ts-expect-error: XmlDocument has a more limited set of possible children
// than XmlElement so TypeScript is unhappy, but we always do the right
// thing.
this.currentNode.children.push(node);
return true;
}
/**
* Adds the given _text_ to the document, either by appending it to a
* preceding `XmlText` node (if possible) or by creating a new `XmlText` node.
*/
addText(text: string, charIndex: number) {
let { children } = this.currentNode;
let { length } = children;
text = normalizeLineBreaks(text);
if (length > 0) {
let prevNode = children[length - 1];
if (prevNode?.type === XmlNode.TYPE_TEXT) {
let textNode = prevNode as XmlText;
// The previous node is a text node, so we can append to it and avoid
// creating another node.
textNode.text += text;
if (this.options.includeOffsets) {
textNode.end = this.scanner.charIndexToByteIndex();
}
return true;
}
}
return this.addNode(new XmlText(text), charIndex);
}
/**
* Consumes element attributes.
*
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#sec-starttags
*/
consumeAttributes(): Record<string, string> {
let attributes = Object.create(null);
while (this.consumeWhitespace()) {
let attrName = this.consumeName();
if (!attrName) {
break;
}
let attrValue = this.consumeEqual() && this.consumeAttributeValue();
if (attrValue === false) {
throw this.error('Attribute value expected');
}
if (attrName in attributes) {
throw this.error(`Duplicate attribute: ${attrName}`);
}
if (attrName === 'xml:space'
&& attrValue !== 'default'
&& attrValue !== 'preserve') {
throw this.error('Value of the `xml:space` attribute must be "default" or "preserve"');
}
attributes[attrName] = attrValue;
}
if (this.options.sortAttributes) {
let attrNames = Object.keys(attributes).sort();
let sortedAttributes = Object.create(null);
for (let i = 0; i < attrNames.length; ++i) {
let attrName = attrNames[i] as string;
sortedAttributes[attrName] = attributes[attrName];
}
attributes = sortedAttributes;
}
return attributes;
}
/**
* Consumes an `AttValue` (attribute value) if possible.
*
* @returns
* Contents of the `AttValue` minus quotes, or `false` if nothing was
* consumed. An empty string indicates that an `AttValue` was consumed but
* was empty.
*
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#NT-AttValue
*/
consumeAttributeValue(): string | false {
let { scanner } = this;
let quote = scanner.peek();
if (quote !== '"' && quote !== "'") {
return false;
}
scanner.advance();
let chars;
let isClosed = false;
let value = emptyString;
let regex = quote === '"'
? syntax.attValueCharDoubleQuote
: syntax.attValueCharSingleQuote;
matchLoop: while (!scanner.isEnd) {
chars = scanner.consumeUntilMatch(regex);
if (chars) {
this.validateChars(chars);
value += chars.replace(syntax.attValueNormalizedWhitespace, ' ');
}
switch (scanner.peek()) {
case quote:
isClosed = true;
break matchLoop;
case '&':
value += this.consumeReference();
continue;
case '<':
throw this.error('Unescaped `<` is not allowed in an attribute value');
default:
break matchLoop;
}
}
if (!isClosed) {
throw this.error('Unclosed attribute');
}
scanner.advance();
return value;
}
/**
* Consumes a CDATA section if possible.
*
* @returns Whether a CDATA section was consumed.
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#sec-cdata-sect
*/
consumeCdataSection(): boolean {
let { scanner } = this;
let startIndex = scanner.charIndex;
if (!scanner.consumeString('<![CDATA[')) {
return false;
}
let text = scanner.consumeUntilString(']]>');
this.validateChars(text);
if (!scanner.consumeString(']]>')) {
throw this.error('Unclosed CDATA section');
}
return this.options.preserveCdata
? this.addNode(new XmlCdata(normalizeLineBreaks(text)), startIndex)
: this.addText(text, startIndex);
}
/**
* Consumes character data if possible.
*
* @returns Whether character data was consumed.
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#dt-chardata
*/
consumeCharData(): boolean {
let { scanner } = this;
let startIndex = scanner.charIndex;
let charData = scanner.consumeUntilMatch(syntax.endCharData);
if (!charData) {
return false;
}
this.validateChars(charData);
if (scanner.peek(3) === ']]>') {
throw this.error('Element content may not contain the CDATA section close delimiter `]]>`');
}
return this.addText(charData, startIndex);
}
/**
* Consumes a comment if possible.
*
* @returns Whether a comment was consumed.
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#NT-Comment
*/
consumeComment(): boolean {
let { scanner } = this;
let startIndex = scanner.charIndex;
if (!scanner.consumeString('<!--')) {
return false;
}
let content = scanner.consumeUntilString('--');
this.validateChars(content);
if (!scanner.consumeString('-->')) {
if (scanner.peek(2) === '--') {
throw this.error("The string `--` isn't allowed inside a comment");
}
throw this.error('Unclosed comment');
}
return this.options.preserveComments
? this.addNode(new XmlComment(normalizeLineBreaks(content)), startIndex)
: true;
}
/**
* Consumes a reference in a content context if possible.
*
* This differs from `consumeReference()` in that a consumed reference will be
* added to the document as a text node instead of returned.
*
* @returns Whether a reference was consumed.
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#entproc
*/
consumeContentReference(): boolean {
let startIndex = this.scanner.charIndex;
let ref = this.consumeReference();
return ref
? this.addText(ref, startIndex)
: false;
}
/**
* Consumes a doctype declaration if possible.
*
* This is a loose implementation since doctype declarations are currently
* discarded without further parsing.
*
* @returns Whether a doctype declaration was consumed.
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#dtd
*/
consumeDoctypeDeclaration(): boolean {
let { scanner } = this;
let startIndex = scanner.charIndex;
if (!scanner.consumeString('<!DOCTYPE')) {
return false;
}
let name = this.consumeWhitespace()
&& this.consumeName();
if (!name) {
throw this.error('Expected a name');
}
let publicId;
let systemId;
if (this.consumeWhitespace()) {
if (scanner.consumeString('PUBLIC')) {
publicId = this.consumeWhitespace()
&& this.consumePubidLiteral();
if (publicId === false) {
throw this.error('Expected a public identifier');
}
this.consumeWhitespace();
}
if (publicId !== undefined || scanner.consumeString('SYSTEM')) {
this.consumeWhitespace();
systemId = this.consumeSystemLiteral();
if (systemId === false) {
throw this.error('Expected a system identifier');
}
this.consumeWhitespace();
}
}
let internalSubset;
if (scanner.consumeString('[')) {
// The internal subset may contain comments that contain `]` characters,
// so we can't use `consumeUntilString()` here.
internalSubset = scanner.consumeUntilMatch(/\][\x20\t\r\n]*>/);
if (!scanner.consumeString(']')) {
throw this.error('Unclosed internal subset');
}
this.consumeWhitespace();
}
if (!scanner.consumeString('>')) {
throw this.error('Unclosed doctype declaration');
}
return this.options.preserveDocumentType
? this.addNode(new XmlDocumentType(name, publicId, systemId, internalSubset), startIndex)
: true;
}
/**
* Consumes an element if possible.
*
* @returns Whether an element was consumed.
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#NT-element
*/
consumeElement(): boolean {
let { scanner } = this;
let startIndex = scanner.charIndex;
if (!scanner.consumeString('<')) {
return false;
}
let name = this.consumeName();
if (!name) {
scanner.reset(startIndex);
return false;
}
let attributes = this.consumeAttributes();
let isEmpty = !!scanner.consumeString('/>');
let element = new XmlElement(name, attributes);
element.parent = this.currentNode;
if (!isEmpty) {
if (!scanner.consumeString('>')) {
throw this.error(`Unclosed start tag for element \`${name}\``);
}
this.currentNode = element;
do {
this.consumeCharData();
} while (
this.consumeElement()
|| this.consumeContentReference()
|| this.consumeCdataSection()
|| this.consumeProcessingInstruction()
|| this.consumeComment()
);
let endTagMark = scanner.charIndex;
let endTagName;
if (!scanner.consumeString('</')
|| !(endTagName = this.consumeName())
|| endTagName !== name) {
scanner.reset(endTagMark);
throw this.error(`Missing end tag for element ${name}`);
}
this.consumeWhitespace();
if (!scanner.consumeString('>')) {
throw this.error(`Unclosed end tag for element ${name}`);
}
this.currentNode = element.parent;
}
return this.addNode(element, startIndex);
}
/**
* Consumes an `Eq` production if possible.
*
* @returns Whether an `Eq` production was consumed.
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#NT-Eq
*/
consumeEqual(): boolean {
this.consumeWhitespace();
if (this.scanner.consumeString('=')) {
this.consumeWhitespace();
return true;
}
return false;
}
/**
* Consumes `Misc` content if possible.
*
* @returns Whether anything was consumed.
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#NT-Misc
*/
consumeMisc(): boolean {
return this.consumeComment()
|| this.consumeProcessingInstruction()
|| this.consumeWhitespace();
}
/**
* Consumes one or more `Name` characters if possible.
*
* @returns `Name` characters, or an empty string if none were consumed.
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#NT-Name
*/
consumeName(): string {
return syntax.isNameStartChar(this.scanner.peek())
? this.scanner.consumeMatchFn(syntax.isNameChar)
: emptyString;
}
/**
* Consumes a processing instruction if possible.
*
* @returns Whether a processing instruction was consumed.
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#sec-pi
*/
consumeProcessingInstruction(): boolean {
let { scanner } = this;
let startIndex = scanner.charIndex;
if (!scanner.consumeString('<?')) {
return false;
}
let name = this.consumeName();
if (name) {
if (name.toLowerCase() === 'xml') {
scanner.reset(startIndex);
throw this.error("XML declaration isn't allowed here");
}
} else {
throw this.error('Invalid processing instruction');
}
if (!this.consumeWhitespace()) {
if (scanner.consumeString('?>')) {
return this.addNode(new XmlProcessingInstruction(name), startIndex);
}
throw this.error('Whitespace is required after a processing instruction name');
}
let content = scanner.consumeUntilString('?>');
this.validateChars(content);
if (!scanner.consumeString('?>')) {
throw this.error('Unterminated processing instruction');
}
return this.addNode(new XmlProcessingInstruction(name, normalizeLineBreaks(content)), startIndex);
}
/**
* Consumes a prolog if possible.
*
* @returns Whether a prolog was consumed.
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#sec-prolog-dtd
*/
consumeProlog(): boolean {
let { scanner } = this;
let startIndex = scanner.charIndex;
this.consumeXmlDeclaration();
while (this.consumeMisc()) {} // eslint-disable-line no-empty
if (this.consumeDoctypeDeclaration()) {
while (this.consumeMisc()) {} // eslint-disable-line no-empty
}
return startIndex < scanner.charIndex;
}
/**
* Consumes a public identifier literal if possible.
*
* @returns
* Value of the public identifier literal minus quotes, or `false` if
* nothing was consumed. An empty string indicates that a public id literal
* was consumed but was empty.
*
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#NT-PubidLiteral
*/
consumePubidLiteral(): string | false {
let startIndex = this.scanner.charIndex;
let value = this.consumeSystemLiteral();
if (value !== false && !/^[-\x20\r\na-zA-Z0-9'()+,./:=?;!*#@$_%]*$/.test(value)) {
this.scanner.reset(startIndex);
throw this.error('Invalid character in public identifier');
}
return value;
}
/**
* Consumes a reference if possible.
*
* This differs from `consumeContentReference()` in that a consumed reference
* will be returned rather than added to the document.
*
* @returns
* Parsed reference value, or `false` if nothing was consumed (to
* distinguish from a reference that resolves to an empty string).
*
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#NT-Reference
*/
consumeReference(): string | false {
let { scanner } = this;
if (!scanner.consumeString('&')) {
return false;
}
let ref = scanner.consumeMatchFn(syntax.isReferenceChar);
if (scanner.consume() !== ';') {
throw this.error('Unterminated reference (a reference must end with `;`)');
}
let parsedValue;
if (ref[0] === '#') {
// This is a character reference.
let codePoint = ref[1] === 'x'
? parseInt(ref.slice(2), 16) // Hex codepoint.
: parseInt(ref.slice(1), 10); // Decimal codepoint.
if (isNaN(codePoint)) {
throw this.error('Invalid character reference');
}
if (!syntax.isXmlCodePoint(codePoint)) {
throw this.error('Character reference resolves to an invalid character');
}
parsedValue = String.fromCodePoint(codePoint);
} else {
// This is an entity reference.
parsedValue = syntax.predefinedEntities[ref];
if (parsedValue === undefined) {
let {
ignoreUndefinedEntities,
resolveUndefinedEntity,
} = this.options;
let wrappedRef = `&${ref};`; // for backcompat with <= 2.x
if (resolveUndefinedEntity) {
let resolvedValue = resolveUndefinedEntity(wrappedRef);
if (resolvedValue !== null && resolvedValue !== undefined) {
let type = typeof resolvedValue;
if (type !== 'string') {
throw new TypeError(`\`resolveUndefinedEntity()\` must return a string, \`null\`, or \`undefined\`, but returned a value of type ${type}`);
}
return resolvedValue;
}
}
if (ignoreUndefinedEntities) {
return wrappedRef;
}
scanner.reset(-wrappedRef.length);
throw this.error(`Named entity isn't defined: ${wrappedRef}`);
}
}
return parsedValue;
}
/**
* Consumes a `SystemLiteral` if possible.
*
* A `SystemLiteral` is similar to an attribute value, but allows the
* characters `<` and `&` and doesn't replace references.
*
* @returns
* Value of the `SystemLiteral` minus quotes, or `false` if nothing was
* consumed. An empty string indicates that a `SystemLiteral` was consumed
* but was empty.
*
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#NT-SystemLiteral
*/
consumeSystemLiteral(): string | false {
let { scanner } = this;
let quote = scanner.consumeString('"') || scanner.consumeString("'");
if (!quote) {
return false;
}
let value = scanner.consumeUntilString(quote);
this.validateChars(value);
if (!scanner.consumeString(quote)) {
throw this.error('Missing end quote');
}
return value;
}
/**
* Consumes one or more whitespace characters if possible.
*
* @returns Whether any whitespace characters were consumed.
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#white
*/
consumeWhitespace(): boolean {
return !!this.scanner.consumeMatchFn(syntax.isWhitespace);
}
/**
* Consumes an XML declaration if possible.
*
* @returns Whether an XML declaration was consumed.
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#NT-XMLDecl
*/
consumeXmlDeclaration(): boolean {
let { scanner } = this;
let startIndex = scanner.charIndex;
if (!scanner.consumeString('<?xml')) {
return false;
}
if (!this.consumeWhitespace()) {
throw this.error('Invalid XML declaration');
}
let version = !!scanner.consumeString('version')
&& this.consumeEqual()
&& this.consumeSystemLiteral();
if (version === false) {
throw this.error('XML version is missing or invalid');
} else if (!/^1\.[0-9]+$/.test(version)) {
throw this.error('Invalid character in version number');
}
let encoding;
let standalone;
if (this.consumeWhitespace()) {
encoding = !!scanner.consumeString('encoding')
&& this.consumeEqual()
&& this.consumeSystemLiteral();
if (encoding) {
if (!/^[A-Za-z][\w.-]*$/.test(encoding)) {
throw this.error('Invalid character in encoding name');
}
this.consumeWhitespace();
}
standalone = !!scanner.consumeString('standalone')
&& this.consumeEqual()
&& this.consumeSystemLiteral();
if (standalone) {
if (standalone !== 'yes' && standalone !== 'no') {
throw this.error('Only "yes" and "no" are permitted as values of `standalone`');
}
this.consumeWhitespace();
}
}
if (!scanner.consumeString('?>')) {
throw this.error('Invalid or unclosed XML declaration');
}
return this.options.preserveXmlDeclaration
? this.addNode(new XmlDeclaration(
version,
encoding || undefined,
(standalone as 'yes' | 'no' | false) || undefined,
), startIndex)
: true;
}
/**
* Returns an `XmlError` for the current scanner position.
*/
error(message: string) {
let { scanner } = this;
return new XmlError(message, scanner.charIndex, scanner.string);
}
/**
* Parses the XML input.
*/
parse() {
this.scanner.consumeString('\uFEFF'); // byte order mark
this.consumeProlog();
if (!this.consumeElement()) {
throw this.error('Root element is missing or invalid');
}
while (this.consumeMisc()) {} // eslint-disable-line no-empty
if (!this.scanner.isEnd) {
throw this.error('Extra content at the end of the document');
}
}
/**
* Throws an invalid character error if any character in the given _string_
* isn't a valid XML character.
*/
validateChars(string: string) {
let { length } = string;
for (let i = 0; i < length; ++i) {
let cp = string.codePointAt(i) as number;
if (!syntax.isXmlCodePoint(cp)) {
this.scanner.reset(-([ ...string ].length - i));
throw this.error('Invalid character');
}
if (cp > 65535) {
i += 1;
}
}
}
}
// -- Private Functions --------------------------------------------------------
/**
* Normalizes line breaks in the given text by replacing CRLF sequences and lone
* CR characters with LF characters.
*/
function normalizeLineBreaks(text: string): string {
let i = 0;
while ((i = text.indexOf('\r', i)) !== -1) {
text = text[i + 1] === '\n'
? text.slice(0, i) + text.slice(i + 1)
: text.slice(0, i) + '\n' + text.slice(i + 1);
}
return text;
}
// -- Types --------------------------------------------------------------------
export type ParserOptions = {
/**
* When `true`, an undefined named entity (like "&bogus;") will be left in the
* output as is instead of causing a parse error.
*
* @default false
*/
ignoreUndefinedEntities?: boolean;
/**
* When `true`, the starting and ending byte offsets of each node in the input
* string will be made available via `start` and `end` properties on the node.
*
* @default false
*/
includeOffsets?: boolean;
/**
* When `true`, CDATA sections will be preserved in the document as `XmlCdata`
* nodes. Otherwise CDATA sections will be represented as `XmlText` nodes,
* which keeps the node tree simpler and easier to work with.
*
* @default false
*/
preserveCdata?: boolean;
/**
* When `true`, comments will be preserved in the document as `XmlComment`
* nodes. Otherwise comments will not be included in the node tree.
*
* @default false
*/
preserveComments?: boolean;
/**
* When `true`, a document type declaration (if present) will be preserved in
* the document as an `XmlDocumentType` node. Otherwise the declaration will
* not be included in the node tree.
*
* Note that when this is `true` and a document type declaration is present,
* the DTD will precede the root node in the node tree (normally the root
* node would be first).
*
* @default false
*/
preserveDocumentType?: boolean;
/**
* When `true`, an XML declaration (if present) will be preserved in the
* document as an `XmlDeclaration` node. Otherwise the declaration will not be
* included in the node tree.
*
* Note that when this is `true` and an XML declaration is present, the
* XML declaration will be the first child of the document (normally the root
* node would be first).
*
* @default false
*/
preserveXmlDeclaration?: boolean;
/**
* When an undefined named entity is encountered, this function will be called
* with the entity as its only argument. It should return a string value with
* which to replace the entity, or `null` or `undefined` to treat the entity
* as undefined (which may result in a parse error depending on the value of
* `ignoreUndefinedEntities`).
*/
resolveUndefinedEntity?: (entity: string) => string | null | undefined;
/**
* When `true`, attributes in an element's `attributes` object will be sorted
* in alphanumeric order by name. Otherwise they'll retain their original
* order as found in the XML.
*
* @default false
*/
sortAttributes?: boolean;
};

217
node_modules/@rgrove/parse-xml/src/lib/StringScanner.ts generated vendored Normal file
View File

@ -0,0 +1,217 @@
const emptyString = '';
const surrogatePair = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
/** @private */
export class StringScanner {
charIndex: number;
readonly string: string;
private readonly charCount: number;
private readonly charsToBytes: number[] | undefined;
private readonly length: number;
private readonly multiByteMode: boolean;
constructor(string: string) {
this.charCount = this.charLength(string, true);
this.charIndex = 0;
this.length = string.length;
this.multiByteMode = this.charCount !== this.length;
this.string = string;
if (this.multiByteMode) {
let charsToBytes = [];
// Create a mapping of character indexes to byte indexes. Since the string
// contains multibyte characters, a byte index may not necessarily align
// with a character index.
for (let byteIndex = 0, charIndex = 0; charIndex < this.charCount; ++charIndex) {
charsToBytes[charIndex] = byteIndex;
byteIndex += (string.codePointAt(byteIndex) as number) > 65535 ? 2 : 1;
}
this.charsToBytes = charsToBytes;
}
}
/**
* Whether the current character index is at the end of the input string.
*/
get isEnd() {
return this.charIndex >= this.charCount;
}
// -- Protected Methods ------------------------------------------------------
/**
* Returns the number of characters in the given string, which may differ from
* the byte length if the string contains multibyte characters.
*/
protected charLength(string: string, multiByteSafe = this.multiByteMode): number {
// We could get the char length with `[ ...string ].length`, but that's
// actually slower than replacing surrogate pairs with single-byte
// characters and then counting the result.
return multiByteSafe
? string.replace(surrogatePair, '_').length
: string.length;
}
// -- Public Methods ---------------------------------------------------------
/**
* Advances the scanner by the given number of characters, stopping if the end
* of the string is reached.
*/
advance(count = 1) {
this.charIndex = Math.min(this.charCount, this.charIndex + count);
}
/**
* Returns the byte index of the given character index in the string. The two
* may differ in strings that contain multibyte characters.
*/
charIndexToByteIndex(charIndex: number = this.charIndex): number {
return this.multiByteMode
? (this.charsToBytes as number[])[charIndex] ?? Infinity
: charIndex;
}
/**
* Consumes and returns the given number of characters if possible, advancing
* the scanner and stopping if the end of the string is reached.
*
* If no characters could be consumed, an empty string will be returned.
*/
consume(charCount = 1): string {
let chars = this.peek(charCount);
this.advance(charCount);
return chars;
}
/**
* Consumes and returns the given number of bytes if possible, advancing the
* scanner and stopping if the end of the string is reached.
*
* It's up to the caller to ensure that the given byte count doesn't split a
* multibyte character.
*
* If no bytes could be consumed, an empty string will be returned.
*/
consumeBytes(byteCount: number): string {
let byteIndex = this.charIndexToByteIndex();
let result = this.string.slice(byteIndex, byteIndex + byteCount);
this.advance(this.charLength(result));
return result;
}
/**
* Consumes and returns all characters for which the given function returns
* `true`, stopping when `false` is returned or the end of the input is
* reached.
*/
consumeMatchFn(fn: (char: string) => boolean): string {
let { length, multiByteMode, string } = this;
let startByteIndex = this.charIndexToByteIndex();
let endByteIndex = startByteIndex;
if (multiByteMode) {
while (endByteIndex < length) {
let char = string[endByteIndex] as string;
let isSurrogatePair = char >= '\uD800' && char <= '\uDBFF';
if (isSurrogatePair) {
char += string[endByteIndex + 1];
}
if (!fn(char)) {
break;
}
endByteIndex += isSurrogatePair ? 2 : 1;
}
} else {
while (endByteIndex < length && fn(string[endByteIndex] as string)) {
++endByteIndex;
}
}
return this.consumeBytes(endByteIndex - startByteIndex);
}
/**
* Consumes the given string if it exists at the current character index, and
* advances the scanner.
*
* If the given string doesn't exist at the current character index, an empty
* string will be returned and the scanner will not be advanced.
*/
consumeString(stringToConsume: string): string {
let { length } = stringToConsume;
let byteIndex = this.charIndexToByteIndex();
if (stringToConsume === this.string.slice(byteIndex, byteIndex + length)) {
this.advance(length === 1 ? 1 : this.charLength(stringToConsume));
return stringToConsume;
}
return emptyString;
}
/**
* Consumes characters until the given global regex is matched, advancing the
* scanner up to (but not beyond) the beginning of the match. If the regex
* doesn't match, nothing will be consumed.
*
* Returns the consumed string, or an empty string if nothing was consumed.
*/
consumeUntilMatch(regex: RegExp): string {
let matchByteIndex = this.string
.slice(this.charIndexToByteIndex())
.search(regex);
return matchByteIndex > 0
? this.consumeBytes(matchByteIndex)
: emptyString;
}
/**
* Consumes characters until the given string is found, advancing the scanner
* up to (but not beyond) that point. If the string is never found, nothing
* will be consumed.
*
* Returns the consumed string, or an empty string if nothing was consumed.
*/
consumeUntilString(searchString: string): string {
let byteIndex = this.charIndexToByteIndex();
let matchByteIndex = this.string.indexOf(searchString, byteIndex);
return matchByteIndex > 0
? this.consumeBytes(matchByteIndex - byteIndex)
: emptyString;
}
/**
* Returns the given number of characters starting at the current character
* index, without advancing the scanner and without exceeding the end of the
* input string.
*/
peek(count = 1): string {
let { charIndex, string } = this;
return this.multiByteMode
? string.slice(this.charIndexToByteIndex(charIndex), this.charIndexToByteIndex(charIndex + count))
: string.slice(charIndex, charIndex + count);
}
/**
* Resets the scanner position to the given character _index_, or to the start
* of the input string if no index is given.
*
* If _index_ is negative, the scanner position will be moved backward by that
* many characters, stopping if the beginning of the string is reached.
*/
reset(index = 0) {
this.charIndex = index >= 0
? Math.min(this.charCount, index)
: Math.max(0, this.charIndex + index);
}
}

11
node_modules/@rgrove/parse-xml/src/lib/XmlCdata.ts generated vendored Normal file
View File

@ -0,0 +1,11 @@
import { XmlNode } from './XmlNode.js';
import { XmlText } from './XmlText.js';
/**
* A CDATA section within an XML document.
*/
export class XmlCdata extends XmlText {
override get type() {
return XmlNode.TYPE_CDATA;
}
}

26
node_modules/@rgrove/parse-xml/src/lib/XmlComment.ts generated vendored Normal file
View File

@ -0,0 +1,26 @@
import { XmlNode } from './XmlNode.js';
/**
* A comment within an XML document.
*/
export class XmlComment extends XmlNode {
/**
* Content of this comment.
*/
content: string;
constructor(content = '') {
super();
this.content = content;
}
override get type() {
return XmlNode.TYPE_COMMENT;
}
override toJSON() {
return Object.assign(XmlNode.prototype.toJSON.call(this), {
content: this.content,
});
}
}

View File

@ -0,0 +1,58 @@
import { XmlNode } from './XmlNode.js';
/**
* An XML declaration within an XML document.
*
* @example
*
* ```xml
* <?xml version="1.0" encoding="UTF-8"?>
* ```
*/
export class XmlDeclaration extends XmlNode {
/**
* Value of the encoding declaration in this XML declaration, or `null` if no
* encoding declaration was present.
*/
encoding: string | null;
/**
* Value of the standalone declaration in this XML declaration, or `null` if
* no standalone declaration was present.
*/
standalone: 'yes' | 'no' | null;
/**
* Value of the version declaration in this XML declaration.
*/
version: string;
constructor(
version: string,
encoding?: string,
standalone?: typeof XmlDeclaration.prototype.standalone,
) {
super();
this.version = version;
this.encoding = encoding ?? null;
this.standalone = standalone ?? null;
}
override get type() {
return XmlNode.TYPE_XML_DECLARATION;
}
override toJSON() {
let json = XmlNode.prototype.toJSON.call(this);
json.version = this.version;
for (let key of ['encoding', 'standalone'] as const) {
if (this[key] !== null) {
json[key] = this[key];
}
}
return json;
}
}

59
node_modules/@rgrove/parse-xml/src/lib/XmlDocument.ts generated vendored Normal file
View File

@ -0,0 +1,59 @@
import { XmlElement } from './XmlElement.js';
import { XmlNode } from './XmlNode.js';
import type { XmlComment } from './XmlComment.js';
import type { XmlDeclaration } from './XmlDeclaration.js';
import type { XmlDocumentType } from './XmlDocumentType.js';
import type { XmlProcessingInstruction } from './XmlProcessingInstruction.js';
/**
* Represents an XML document. All elements within the document are descendants
* of this node.
*/
export class XmlDocument extends XmlNode {
/**
* Child nodes of this document.
*/
readonly children: Array<XmlComment | XmlDeclaration | XmlDocumentType | XmlProcessingInstruction | XmlElement>;
constructor(children: Array<XmlComment | XmlDeclaration | XmlDocumentType | XmlElement | XmlProcessingInstruction> = []) {
super();
this.children = children;
}
override get document() {
return this;
}
/**
* Root element of this document, or `null` if this document is empty.
*/
get root(): XmlElement | null {
for (let child of this.children) {
if (child instanceof XmlElement) {
return child;
}
}
return null;
}
/**
* Text content of this document and all its descendants.
*/
get text(): string {
return this.children
.map(child => 'text' in child ? child.text : '')
.join('');
}
override get type() {
return XmlNode.TYPE_DOCUMENT;
}
override toJSON() {
return Object.assign(XmlNode.prototype.toJSON.call(this), {
children: this.children.map(child => child.toJSON()),
});
}
}

View File

@ -0,0 +1,67 @@
import { XmlNode } from './XmlNode.js';
/**
* A document type declaration within an XML document.
*
* @example
*
* ```xml
* <!DOCTYPE kittens [
* <!ELEMENT kittens (#PCDATA)>
* ]>
* ```
*/
export class XmlDocumentType extends XmlNode {
/**
* Name of the root element described by this document type declaration.
*/
name: string;
/**
* Public identifier of the external subset of this document type declaration,
* or `null` if no public identifier was present.
*/
publicId: string | null;
/**
* System identifier of the external subset of this document type declaration,
* or `null` if no system identifier was present.
*/
systemId: string | null;
/**
* Internal subset of this document type declaration, or `null` if no internal
* subset was present.
*/
internalSubset: string | null;
constructor(
name: string,
publicId?: string,
systemId?: string,
internalSubset?: string,
) {
super();
this.name = name;
this.publicId = publicId ?? null;
this.systemId = systemId ?? null;
this.internalSubset = internalSubset ?? null;
}
override get type() {
return XmlNode.TYPE_DOCUMENT_TYPE;
}
override toJSON() {
let json = XmlNode.prototype.toJSON.call(this);
json.name = this.name;
for (let key of ['publicId', 'systemId', 'internalSubset'] as const) {
if (this[key] !== null) {
json[key] = this[key];
}
}
return json;
}
}

81
node_modules/@rgrove/parse-xml/src/lib/XmlElement.ts generated vendored Normal file
View File

@ -0,0 +1,81 @@
import { XmlNode } from './XmlNode.js';
import type { JsonObject } from './types.js';
import type { XmlCdata } from './XmlCdata.js';
import type { XmlComment } from './XmlComment.js';
import type { XmlProcessingInstruction } from './XmlProcessingInstruction.js';
import type { XmlText } from './XmlText.js';
/**
* Element in an XML document.
*/
export class XmlElement extends XmlNode {
/**
* Attributes on this element.
*/
attributes: {[attrName: string]: string};
/**
* Child nodes of this element.
*/
children: Array<XmlCdata | XmlComment | XmlElement | XmlProcessingInstruction | XmlText>;
/**
* Name of this element.
*/
name: string;
constructor(
name: string,
attributes: {[attrName: string]: string} = Object.create(null),
children: Array<XmlCdata | XmlComment | XmlElement | XmlProcessingInstruction | XmlText> = [],
) {
super();
this.name = name;
this.attributes = attributes;
this.children = children;
}
/**
* Whether this element is empty (meaning it has no children).
*/
get isEmpty(): boolean {
return this.children.length === 0;
}
override get preserveWhitespace(): boolean {
let node: XmlNode | null = this; // eslint-disable-line @typescript-eslint/no-this-alias
while (node instanceof XmlElement) {
if ('xml:space' in node.attributes) {
return node.attributes['xml:space'] === 'preserve';
}
node = node.parent;
}
return false;
}
/**
* Text content of this element and all its descendants.
*/
get text(): string {
return this.children
.map(child => 'text' in child ? child.text : '')
.join('');
}
override get type() {
return XmlNode.TYPE_ELEMENT;
}
override toJSON(): JsonObject {
return Object.assign(XmlNode.prototype.toJSON.call(this), {
name: this.name,
attributes: this.attributes,
children: this.children.map(child => child.toJSON()),
});
}
}

80
node_modules/@rgrove/parse-xml/src/lib/XmlError.ts generated vendored Normal file
View File

@ -0,0 +1,80 @@
/**
* An error that occurred while parsing XML.
*/
export class XmlError extends Error {
/**
* Character column at which this error occurred (1-based).
*/
readonly column: number;
/**
* Short excerpt from the input string that contains the problem.
*/
readonly excerpt: string;
/**
* Line number at which this error occurred (1-based).
*/
readonly line: number;
/**
* Character position at which this error occurred relative to the beginning
* of the input (0-based).
*/
readonly pos: number;
constructor(
message: string,
charIndex: number,
xml: string,
) {
let column = 1;
let excerpt = '';
let line = 1;
// Find the line and column where the error occurred.
for (let i = 0; i < charIndex; ++i) {
let char = xml[i];
if (char === '\n') {
column = 1;
excerpt = '';
line += 1;
} else {
column += 1;
excerpt += char;
}
}
let eol = xml.indexOf('\n', charIndex);
excerpt += eol === -1
? xml.slice(charIndex)
: xml.slice(charIndex, eol);
let excerptStart = 0;
// Keep the excerpt below 50 chars, but always keep the error position in
// view.
if (excerpt.length > 50) {
if (column < 40) {
excerpt = excerpt.slice(0, 50);
} else {
excerptStart = column - 20;
excerpt = excerpt.slice(excerptStart, column + 30);
}
}
super(
`${message} (line ${line}, column ${column})\n`
+ ` ${excerpt}\n`
+ ' '.repeat(column - excerptStart + 1) + '^\n',
);
this.column = column;
this.excerpt = excerpt;
this.line = line;
this.name = 'XmlError';
this.pos = charIndex;
}
}

137
node_modules/@rgrove/parse-xml/src/lib/XmlNode.ts generated vendored Normal file
View File

@ -0,0 +1,137 @@
import type { JsonObject } from './types.js';
import type { XmlDocument } from './XmlDocument.js';
import type { XmlElement } from './XmlElement.js';
/**
* Base interface for a node in an XML document.
*/
export class XmlNode {
/**
* Type value for an `XmlCdata` node.
*/
static readonly TYPE_CDATA = 'cdata';
/**
* Type value for an `XmlComment` node.
*/
static readonly TYPE_COMMENT = 'comment';
/**
* Type value for an `XmlDocument` node.
*/
static readonly TYPE_DOCUMENT = 'document';
/**
* Type value for an `XmlDocumentType` node.
*/
static readonly TYPE_DOCUMENT_TYPE = 'doctype';
/**
* Type value for an `XmlElement` node.
*/
static readonly TYPE_ELEMENT = 'element';
/**
* Type value for an `XmlProcessingInstruction` node.
*/
static readonly TYPE_PROCESSING_INSTRUCTION = 'pi';
/**
* Type value for an `XmlText` node.
*/
static readonly TYPE_TEXT = 'text';
/**
* Type value for an `XmlDeclaration` node.
*/
static readonly TYPE_XML_DECLARATION = 'xmldecl';
/**
* Parent node of this node, or `null` if this node has no parent.
*/
parent: XmlDocument | XmlElement | null = null;
/**
* Starting byte offset of this node in the original XML string, or `-1` if
* the offset is unknown.
*/
start = -1;
/**
* Ending byte offset of this node in the original XML string, or `-1` if the
* offset is unknown.
*/
end = -1;
/**
* Document that contains this node, or `null` if this node is not associated
* with a document.
*/
get document(): XmlDocument | null {
return this.parent?.document ?? null;
}
/**
* Whether this node is the root node of the document (also known as the
* document element).
*/
get isRootNode(): boolean {
return this.parent !== null
&& this.parent === this.document
&& this.type === XmlNode.TYPE_ELEMENT;
}
/**
* Whether whitespace should be preserved in the content of this element and
* its children.
*
* This is influenced by the value of the special `xml:space` attribute, and
* will be `true` for any node whose `xml:space` attribute is set to
* "preserve". If a node has no such attribute, it will inherit the value of
* the nearest ancestor that does (if any).
*
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#sec-white-space
*/
get preserveWhitespace(): boolean {
return !!this.parent?.preserveWhitespace;
}
/**
* Type of this node.
*
* The value of this property is a string that matches one of the static
* `TYPE_*` properties on the `XmlNode` class (e.g. `TYPE_ELEMENT`,
* `TYPE_TEXT`, etc.).
*
* The `XmlNode` class itself is a base class and doesn't have its own type
* name.
*/
get type() {
return '';
}
/**
* Returns a JSON-serializable object representing this node, minus properties
* that could result in circular references.
*/
toJSON(): JsonObject {
let json: JsonObject = {
type: this.type,
};
if (this.isRootNode) {
json.isRootNode = true;
}
if (this.preserveWhitespace) {
json.preserveWhitespace = true;
}
if (this.start !== -1) {
json.start = this.start;
json.end = this.end;
}
return json;
}
}

View File

@ -0,0 +1,35 @@
import { XmlNode } from './XmlNode.js';
/**
* A processing instruction within an XML document.
*/
export class XmlProcessingInstruction extends XmlNode {
/**
* Content of this processing instruction.
*/
content: string;
/**
* Name of this processing instruction. Also sometimes referred to as the
* processing instruction "target".
*/
name: string;
constructor(name: string, content = '') {
super();
this.name = name;
this.content = content;
}
override get type() {
return XmlNode.TYPE_PROCESSING_INSTRUCTION;
}
override toJSON() {
return Object.assign(XmlNode.prototype.toJSON.call(this), {
name: this.name,
content: this.content,
});
}
}

26
node_modules/@rgrove/parse-xml/src/lib/XmlText.ts generated vendored Normal file
View File

@ -0,0 +1,26 @@
import { XmlNode } from './XmlNode.js';
/**
* Text content within an XML document.
*/
export class XmlText extends XmlNode {
/**
* Text content of this node.
*/
text: string;
constructor(text = '') {
super();
this.text = text;
}
override get type() {
return XmlNode.TYPE_TEXT;
}
override toJSON() {
return Object.assign(XmlNode.prototype.toJSON.call(this), {
text: this.text,
});
}
}

130
node_modules/@rgrove/parse-xml/src/lib/syntax.ts generated vendored Normal file
View File

@ -0,0 +1,130 @@
/**
* Regular expression that matches one or more `AttValue` characters in a
* double-quoted attribute value.
*
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#NT-AttValue
*/
export const attValueCharDoubleQuote = /["&<]/;
/**
* Regular expression that matches one or more `AttValue` characters in a
* single-quoted attribute value.
*
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#NT-AttValue
*/
export const attValueCharSingleQuote = /['&<]/;
/**
* Regular expression that matches a whitespace character that should be
* normalized to a space character in an attribute value.
*
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#AVNormalize
*/
export const attValueNormalizedWhitespace = /\r\n|[\n\r\t]/g;
/**
* Regular expression that matches one or more characters that signal the end of
* XML `CharData` content.
*
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#dt-chardata
*/
export const endCharData = /<|&|]]>/;
/**
* Mapping of predefined entity names to their replacement values.
*
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#sec-predefined-ent
*/
export const predefinedEntities: Readonly<{[name: string]: string;}> = Object.freeze(Object.assign(Object.create(null), {
amp: '&',
apos: "'",
gt: '>',
lt: '<',
quot: '"',
}));
/**
* Returns `true` if _char_ is an XML `NameChar`, `false` if it isn't.
*
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#NT-NameChar
*/
export function isNameChar(char: string): boolean {
let cp = char.codePointAt(0) as number;
// Including the most common NameStartChars here improves performance
// slightly.
return (cp >= 0x61 && cp <= 0x7A) // a-z
|| (cp >= 0x41 && cp <= 0x5A) // A-Z
|| (cp >= 0x30 && cp <= 0x39) // 0-9
|| cp === 0x2D // -
|| cp === 0x2E // .
|| cp === 0xB7
|| (cp >= 0x300 && cp <= 0x36F)
|| cp === 0x203F
|| cp === 0x2040
|| isNameStartChar(char, cp);
}
/**
* Returns `true` if _char_ is an XML `NameStartChar`, `false` if it isn't.
*
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#NT-NameStartChar
*/
export function isNameStartChar(char: string, cp = char.codePointAt(0) as number): boolean {
return (cp >= 0x61 && cp <= 0x7A) // a-z
|| (cp >= 0x41 && cp <= 0x5A) // A-Z
|| cp === 0x3A // :
|| cp === 0x5F // _
|| (cp >= 0xC0 && cp <= 0xD6)
|| (cp >= 0xD8 && cp <= 0xF6)
|| (cp >= 0xF8 && cp <= 0x2FF)
|| (cp >= 0x370 && cp <= 0x37D)
|| (cp >= 0x37F && cp <= 0x1FFF)
|| cp === 0x200C
|| cp === 0x200D
|| (cp >= 0x2070 && cp <= 0x218F)
|| (cp >= 0x2C00 && cp <= 0x2FEF)
|| (cp >= 0x3001 && cp <= 0xD7FF)
|| (cp >= 0xF900 && cp <= 0xFDCF)
|| (cp >= 0xFDF0 && cp <= 0xFFFD)
|| (cp >= 0x10000 && cp <= 0xEFFFF);
}
/**
* Returns `true` if _char_ is a valid reference character (which may appear
* between `&` and `;` in a reference), `false` otherwise.
*
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#sec-references
*/
export function isReferenceChar(char: string): boolean {
return char === '#' || isNameChar(char);
}
/**
* Returns `true` if _char_ is an XML whitespace character, `false` otherwise.
*
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#white
*/
export function isWhitespace(char: string): boolean {
let cp = char.codePointAt(0);
return cp === 0x20
|| cp === 0x9
|| cp === 0xA
|| cp === 0xD;
}
/**
* Returns `true` if _codepoint_ is a valid XML `Char` code point, `false`
* otherwise.
*
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#NT-Char
*/
export function isXmlCodePoint(cp: number): boolean {
return (cp >= 0x20 && cp <= 0xD7FF)
|| cp === 0xA
|| cp === 0x9
|| cp === 0xD
|| (cp >= 0xE000 && cp <= 0xFFFD)
|| (cp >= 0x10000 && cp <= 0x10FFFF);
}

2
node_modules/@rgrove/parse-xml/src/lib/types.ts generated vendored Normal file
View File

@ -0,0 +1,2 @@
export type JsonObject = {[key in string]?: JsonValue};
export type JsonValue = string | number | boolean | JsonObject | JsonValue[] | null;