first commit

This commit is contained in:
Missdrop
2025-07-16 16:30:56 +00:00
commit 7ee33927cb
11326 changed files with 1230901 additions and 0 deletions

3
node_modules/@xmldom/xmldom/lib/.eslintrc.yml generated vendored Normal file
View File

@@ -0,0 +1,3 @@
extends:
- 'plugin:es5/no-es2015'
- 'plugin:n/recommended'

429
node_modules/@xmldom/xmldom/lib/conventions.js generated vendored Normal file
View File

@@ -0,0 +1,429 @@
'use strict';
/**
* Ponyfill for `Array.prototype.find` which is only available in ES6 runtimes.
*
* Works with anything that has a `length` property and index access properties,
* including NodeList.
*
* @param {T[] | { length: number; [number]: T }} list
* @param {function (item: T, index: number, list:T[]):boolean} predicate
* @param {Partial<Pick<ArrayConstructor['prototype'], 'find'>>?} ac
* Allows injecting a custom implementation in tests (`Array.prototype` by default).
* @returns {T | undefined}
* @template {unknown} T
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find
* @see https://tc39.es/ecma262/multipage/indexed-collections.html#sec-array.prototype.find
*/
function find(list, predicate, ac) {
if (ac === undefined) {
ac = Array.prototype;
}
if (list && typeof ac.find === 'function') {
return ac.find.call(list, predicate);
}
for (var i = 0; i < list.length; i++) {
if (hasOwn(list, i)) {
var item = list[i];
if (predicate.call(undefined, item, i, list)) {
return item;
}
}
}
}
/**
* "Shallow freezes" an object to render it immutable.
* Uses `Object.freeze` if available,
* otherwise the immutability is only in the type.
*
* Is used to create "enum like" objects.
*
* If `Object.getOwnPropertyDescriptors` is available,
* a new object with all properties of object but without any prototype is created and returned
* after freezing it.
*
* @param {T} object
* The object to freeze.
* @param {Pick<ObjectConstructor, 'create' | 'freeze' | 'getOwnPropertyDescriptors'>} [oc=Object]
* `Object` by default,
* allows to inject custom object constructor for tests.
* @returns {Readonly<T>}
* @template {Object} T
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze
* @prettierignore
*/
function freeze(object, oc) {
if (oc === undefined) {
oc = Object;
}
if (oc && typeof oc.getOwnPropertyDescriptors === 'function') {
object = oc.create(null, oc.getOwnPropertyDescriptors(object));
}
return oc && typeof oc.freeze === 'function' ? oc.freeze(object) : object;
}
/**
* Implementation for `Object.hasOwn` but ES5 compatible.
*
* @param {any} object
* @param {string | number} key
* @returns {boolean}
*/
function hasOwn(object, key) {
return Object.prototype.hasOwnProperty.call(object, key);
}
/**
* Since xmldom can not rely on `Object.assign`,
* it uses/provides a simplified version that is sufficient for its needs.
*
* @param {Object} target
* @param {Object | null | undefined} source
* @returns {Object}
* The target with the merged/overridden properties.
* @throws {TypeError}
* If target is not an object.
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
* @see https://tc39.es/ecma262/multipage/fundamental-objects.html#sec-object.assign
*/
function assign(target, source) {
if (target === null || typeof target !== 'object') {
throw new TypeError('target is not an object');
}
for (var key in source) {
if (hasOwn(source, key)) {
target[key] = source[key];
}
}
return target;
}
/**
* A number of attributes are boolean attributes.
* The presence of a boolean attribute on an element represents the `true` value,
* and the absence of the attribute represents the `false` value.
*
* If the attribute is present, its value must either be the empty string, or a value that is
* an ASCII case-insensitive match for the attribute's canonical name,
* with no leading or trailing whitespace.
*
* Note: The values `"true"` and `"false"` are not allowed on boolean attributes.
* To represent a `false` value, the attribute has to be omitted altogether.
*
* @see https://html.spec.whatwg.org/#boolean-attributes
* @see https://html.spec.whatwg.org/#attributes-3
*/
var HTML_BOOLEAN_ATTRIBUTES = freeze({
allowfullscreen: true,
async: true,
autofocus: true,
autoplay: true,
checked: true,
controls: true,
default: true,
defer: true,
disabled: true,
formnovalidate: true,
hidden: true,
ismap: true,
itemscope: true,
loop: true,
multiple: true,
muted: true,
nomodule: true,
novalidate: true,
open: true,
playsinline: true,
readonly: true,
required: true,
reversed: true,
selected: true,
});
/**
* Check if `name` is matching one of the HTML boolean attribute names.
* This method doesn't check if such attributes are allowed in the context of the current
* document/parsing.
*
* @param {string} name
* @returns {boolean}
* @see {@link HTML_BOOLEAN_ATTRIBUTES}
* @see https://html.spec.whatwg.org/#boolean-attributes
* @see https://html.spec.whatwg.org/#attributes-3
*/
function isHTMLBooleanAttribute(name) {
return hasOwn(HTML_BOOLEAN_ATTRIBUTES, name.toLowerCase());
}
/**
* Void elements only have a start tag; end tags must not be specified for void elements.
* These elements should be written as self-closing like this: `<area />`.
* This should not be confused with optional tags that HTML allows to omit the end tag for
* (like `li`, `tr` and others), which can have content after them,
* so they can not be written as self-closing.
* xmldom does not have any logic for optional end tags cases,
* and will report them as a warning.
* Content that would go into the unopened element,
* will instead be added as a sibling text node.
*
* @type {Readonly<{
* area: boolean;
* col: boolean;
* img: boolean;
* wbr: boolean;
* link: boolean;
* hr: boolean;
* source: boolean;
* br: boolean;
* input: boolean;
* param: boolean;
* meta: boolean;
* embed: boolean;
* track: boolean;
* base: boolean;
* }>}
* @see https://html.spec.whatwg.org/#void-elements
* @see https://html.spec.whatwg.org/#optional-tags
*/
var HTML_VOID_ELEMENTS = freeze({
area: true,
base: true,
br: true,
col: true,
embed: true,
hr: true,
img: true,
input: true,
link: true,
meta: true,
param: true,
source: true,
track: true,
wbr: true,
});
/**
* Check if `tagName` is matching one of the HTML void element names.
* This method doesn't check if such tags are allowed in the context of the current
* document/parsing.
*
* @param {string} tagName
* @returns {boolean}
* @see {@link HTML_VOID_ELEMENTS}
* @see https://html.spec.whatwg.org/#void-elements
*/
function isHTMLVoidElement(tagName) {
return hasOwn(HTML_VOID_ELEMENTS, tagName.toLowerCase());
}
/**
* Tag names that are raw text elements according to HTML spec.
* The value denotes whether they are escapable or not.
*
* @see {@link isHTMLEscapableRawTextElement}
* @see {@link isHTMLRawTextElement}
* @see https://html.spec.whatwg.org/#raw-text-elements
* @see https://html.spec.whatwg.org/#escapable-raw-text-elements
*/
var HTML_RAW_TEXT_ELEMENTS = freeze({
script: false,
style: false,
textarea: true,
title: true,
});
/**
* Check if `tagName` is matching one of the HTML raw text element names.
* This method doesn't check if such tags are allowed in the context of the current
* document/parsing.
*
* @param {string} tagName
* @returns {boolean}
* @see {@link isHTMLEscapableRawTextElement}
* @see {@link HTML_RAW_TEXT_ELEMENTS}
* @see https://html.spec.whatwg.org/#raw-text-elements
* @see https://html.spec.whatwg.org/#escapable-raw-text-elements
*/
function isHTMLRawTextElement(tagName) {
var key = tagName.toLowerCase();
return hasOwn(HTML_RAW_TEXT_ELEMENTS, key) && !HTML_RAW_TEXT_ELEMENTS[key];
}
/**
* Check if `tagName` is matching one of the HTML escapable raw text element names.
* This method doesn't check if such tags are allowed in the context of the current
* document/parsing.
*
* @param {string} tagName
* @returns {boolean}
* @see {@link isHTMLRawTextElement}
* @see {@link HTML_RAW_TEXT_ELEMENTS}
* @see https://html.spec.whatwg.org/#raw-text-elements
* @see https://html.spec.whatwg.org/#escapable-raw-text-elements
*/
function isHTMLEscapableRawTextElement(tagName) {
var key = tagName.toLowerCase();
return hasOwn(HTML_RAW_TEXT_ELEMENTS, key) && HTML_RAW_TEXT_ELEMENTS[key];
}
/**
* Only returns true if `value` matches MIME_TYPE.HTML, which indicates an HTML document.
*
* @param {string} mimeType
* @returns {mimeType is 'text/html'}
* @see https://www.iana.org/assignments/media-types/text/html
* @see https://en.wikipedia.org/wiki/HTML
* @see https://developer.mozilla.org/en-US/docs/Web/API/DOMParser/parseFromString
* @see https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#dom-domparser-parsefromstring
*/
function isHTMLMimeType(mimeType) {
return mimeType === MIME_TYPE.HTML;
}
/**
* For both the `text/html` and the `application/xhtml+xml` namespace the spec defines that the
* HTML namespace is provided as the default.
*
* @param {string} mimeType
* @returns {boolean}
* @see https://dom.spec.whatwg.org/#dom-document-createelement
* @see https://dom.spec.whatwg.org/#dom-domimplementation-createdocument
* @see https://dom.spec.whatwg.org/#dom-domimplementation-createhtmldocument
*/
function hasDefaultHTMLNamespace(mimeType) {
return isHTMLMimeType(mimeType) || mimeType === MIME_TYPE.XML_XHTML_APPLICATION;
}
/**
* All mime types that are allowed as input to `DOMParser.parseFromString`
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/DOMParser/parseFromString#Argument02
* MDN
* @see https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#domparsersupportedtype
* WHATWG HTML Spec
* @see {@link DOMParser.prototype.parseFromString}
*/
var MIME_TYPE = freeze({
/**
* `text/html`, the only mime type that triggers treating an XML document as HTML.
*
* @see https://www.iana.org/assignments/media-types/text/html IANA MimeType registration
* @see https://en.wikipedia.org/wiki/HTML Wikipedia
* @see https://developer.mozilla.org/en-US/docs/Web/API/DOMParser/parseFromString MDN
* @see https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#dom-domparser-parsefromstring
* WHATWG HTML Spec
*/
HTML: 'text/html',
/**
* `application/xml`, the standard mime type for XML documents.
*
* @see https://www.iana.org/assignments/media-types/application/xml IANA MimeType
* registration
* @see https://tools.ietf.org/html/rfc7303#section-9.1 RFC 7303
* @see https://en.wikipedia.org/wiki/XML_and_MIME Wikipedia
*/
XML_APPLICATION: 'application/xml',
/**
* `text/xml`, an alias for `application/xml`.
*
* @see https://tools.ietf.org/html/rfc7303#section-9.2 RFC 7303
* @see https://www.iana.org/assignments/media-types/text/xml IANA MimeType registration
* @see https://en.wikipedia.org/wiki/XML_and_MIME Wikipedia
*/
XML_TEXT: 'text/xml',
/**
* `application/xhtml+xml`, indicates an XML document that has the default HTML namespace,
* but is parsed as an XML document.
*
* @see https://www.iana.org/assignments/media-types/application/xhtml+xml IANA MimeType
* registration
* @see https://dom.spec.whatwg.org/#dom-domimplementation-createdocument WHATWG DOM Spec
* @see https://en.wikipedia.org/wiki/XHTML Wikipedia
*/
XML_XHTML_APPLICATION: 'application/xhtml+xml',
/**
* `image/svg+xml`,
*
* @see https://www.iana.org/assignments/media-types/image/svg+xml IANA MimeType registration
* @see https://www.w3.org/TR/SVG11/ W3C SVG 1.1
* @see https://en.wikipedia.org/wiki/Scalable_Vector_Graphics Wikipedia
*/
XML_SVG_IMAGE: 'image/svg+xml',
});
/**
* @typedef {'application/xhtml+xml' | 'application/xml' | 'image/svg+xml' | 'text/html' | 'text/xml'}
* MimeType
*/
/**
* @type {MimeType[]}
* @private
* Basically `Object.values`, which is not available in ES5.
*/
var _MIME_TYPES = Object.keys(MIME_TYPE).map(function (key) {
return MIME_TYPE[key];
});
/**
* Only returns true if `mimeType` is one of the allowed values for
* `DOMParser.parseFromString`.
*
* @param {string} mimeType
* @returns {mimeType is 'application/xhtml+xml' | 'application/xml' | 'image/svg+xml' | 'text/html' | 'text/xml'}
*
*/
function isValidMimeType(mimeType) {
return _MIME_TYPES.indexOf(mimeType) > -1;
}
/**
* Namespaces that are used in this code base.
*
* @see http://www.w3.org/TR/REC-xml-names
*/
var NAMESPACE = freeze({
/**
* The XHTML namespace.
*
* @see http://www.w3.org/1999/xhtml
*/
HTML: 'http://www.w3.org/1999/xhtml',
/**
* The SVG namespace.
*
* @see http://www.w3.org/2000/svg
*/
SVG: 'http://www.w3.org/2000/svg',
/**
* The `xml:` namespace.
*
* @see http://www.w3.org/XML/1998/namespace
*/
XML: 'http://www.w3.org/XML/1998/namespace',
/**
* The `xmlns:` namespace.
*
* @see https://www.w3.org/2000/xmlns/
*/
XMLNS: 'http://www.w3.org/2000/xmlns/',
});
exports.assign = assign;
exports.find = find;
exports.freeze = freeze;
exports.HTML_BOOLEAN_ATTRIBUTES = HTML_BOOLEAN_ATTRIBUTES;
exports.HTML_RAW_TEXT_ELEMENTS = HTML_RAW_TEXT_ELEMENTS;
exports.HTML_VOID_ELEMENTS = HTML_VOID_ELEMENTS;
exports.hasDefaultHTMLNamespace = hasDefaultHTMLNamespace;
exports.hasOwn = hasOwn;
exports.isHTMLBooleanAttribute = isHTMLBooleanAttribute;
exports.isHTMLRawTextElement = isHTMLRawTextElement;
exports.isHTMLEscapableRawTextElement = isHTMLEscapableRawTextElement;
exports.isHTMLMimeType = isHTMLMimeType;
exports.isHTMLVoidElement = isHTMLVoidElement;
exports.isValidMimeType = isValidMimeType;
exports.MIME_TYPE = MIME_TYPE;
exports.NAMESPACE = NAMESPACE;

586
node_modules/@xmldom/xmldom/lib/dom-parser.js generated vendored Normal file
View File

@@ -0,0 +1,586 @@
'use strict';
var conventions = require('./conventions');
var dom = require('./dom');
var errors = require('./errors');
var entities = require('./entities');
var sax = require('./sax');
var DOMImplementation = dom.DOMImplementation;
var hasDefaultHTMLNamespace = conventions.hasDefaultHTMLNamespace;
var isHTMLMimeType = conventions.isHTMLMimeType;
var isValidMimeType = conventions.isValidMimeType;
var MIME_TYPE = conventions.MIME_TYPE;
var NAMESPACE = conventions.NAMESPACE;
var ParseError = errors.ParseError;
var XMLReader = sax.XMLReader;
/**
* Normalizes line ending according to <https://www.w3.org/TR/xml11/#sec-line-ends>,
* including some Unicode "newline" characters:
*
* > XML parsed entities are often stored in computer files which,
* > for editing convenience, are organized into lines.
* > These lines are typically separated by some combination
* > of the characters CARRIAGE RETURN (#xD) and LINE FEED (#xA).
* >
* > To simplify the tasks of applications, the XML processor must behave
* > as if it normalized all line breaks in external parsed entities (including the document entity)
* > on input, before parsing, by translating the following to a single #xA character:
* >
* > 1. the two-character sequence #xD #xA,
* > 2. the two-character sequence #xD #x85,
* > 3. the single character #x85,
* > 4. the single character #x2028,
* > 5. the single character #x2029,
* > 6. any #xD character that is not immediately followed by #xA or #x85.
*
* @param {string} input
* @returns {string}
* @prettierignore
*/
function normalizeLineEndings(input) {
return input.replace(/\r[\n\u0085]/g, '\n').replace(/[\r\u0085\u2028\u2029]/g, '\n');
}
/**
* @typedef Locator
* @property {number} [columnNumber]
* @property {number} [lineNumber]
*/
/**
* @typedef DOMParserOptions
* @property {typeof assign} [assign]
* The method to use instead of `conventions.assign`, which is used to copy values from
* `options` before they are used for parsing.
* @property {typeof DOMHandler} [domHandler]
* For internal testing: The class for creating an instance for handling events from the SAX
* parser.
* *****Warning: By configuring a faulty implementation, the specified behavior can completely
* be broken.*****.
* @property {Function} [errorHandler]
* DEPRECATED! use `onError` instead.
* @property {function(level:ErrorLevel, message:string, context: DOMHandler):void}
* [onError]
* A function invoked for every error that occurs during parsing.
*
* If it is not provided, all errors are reported to `console.error`
* and only `fatalError`s are thrown as a `ParseError`,
* which prevents any further processing.
* If the provided method throws, a `ParserError` is thrown,
* which prevents any further processing.
*
* Be aware that many `warning`s are considered an error that prevents further processing in
* most implementations.
* @property {boolean} [locator=true]
* Configures if the nodes created during parsing will have a `lineNumber` and a `columnNumber`
* attribute describing their location in the XML string.
* Default is true.
* @property {(string) => string} [normalizeLineEndings]
* used to replace line endings before parsing, defaults to exported `normalizeLineEndings`,
* which normalizes line endings according to <https://www.w3.org/TR/xml11/#sec-line-ends>,
* including some Unicode "newline" characters.
* @property {Object} [xmlns]
* The XML namespaces that should be assumed when parsing.
* The default namespace can be provided by the key that is the empty string.
* When the `mimeType` for HTML, XHTML or SVG are passed to `parseFromString`,
* the default namespace that will be used,
* will be overridden according to the specification.
* @see {@link normalizeLineEndings}
*/
/**
* The DOMParser interface provides the ability to parse XML or HTML source code from a string
* into a DOM `Document`.
*
* ***xmldom is different from the spec in that it allows an `options` parameter,
* to control the behavior***.
*
* @class
* @param {DOMParserOptions} [options]
* @see https://developer.mozilla.org/en-US/docs/Web/API/DOMParser
* @see https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#dom-parsing-and-serialization
*/
function DOMParser(options) {
options = options || {};
if (options.locator === undefined) {
options.locator = true;
}
/**
* The method to use instead of `conventions.assign`, which is used to copy values from
* `options`
* before they are used for parsing.
*
* @type {conventions.assign}
* @private
* @see {@link conventions.assign}
* @readonly
*/
this.assign = options.assign || conventions.assign;
/**
* For internal testing: The class for creating an instance for handling events from the SAX
* parser.
* *****Warning: By configuring a faulty implementation, the specified behavior can completely
* be broken*****.
*
* @type {typeof DOMHandler}
* @private
* @readonly
*/
this.domHandler = options.domHandler || DOMHandler;
/**
* A function that is invoked for every error that occurs during parsing.
*
* If it is not provided, all errors are reported to `console.error`
* and only `fatalError`s are thrown as a `ParseError`,
* which prevents any further processing.
* If the provided method throws, a `ParserError` is thrown,
* which prevents any further processing.
*
* Be aware that many `warning`s are considered an error that prevents further processing in
* most implementations.
*
* @type {function(level:ErrorLevel, message:string, context: DOMHandler):void}
* @see {@link onErrorStopParsing}
* @see {@link onWarningStopParsing}
*/
this.onError = options.onError || options.errorHandler;
if (options.errorHandler && typeof options.errorHandler !== 'function') {
throw new TypeError('errorHandler object is no longer supported, switch to onError!');
} else if (options.errorHandler) {
options.errorHandler('warning', 'The `errorHandler` option has been deprecated, use `onError` instead!', this);
}
/**
* used to replace line endings before parsing, defaults to `normalizeLineEndings`
*
* @type {(string) => string}
* @readonly
*/
this.normalizeLineEndings = options.normalizeLineEndings || normalizeLineEndings;
/**
* Configures if the nodes created during parsing will have a `lineNumber` and a
* `columnNumber`
* attribute describing their location in the XML string.
* Default is true.
*
* @type {boolean}
* @readonly
*/
this.locator = !!options.locator;
/**
* The default namespace can be provided by the key that is the empty string.
* When the `mimeType` for HTML, XHTML or SVG are passed to `parseFromString`,
* the default namespace that will be used,
* will be overridden according to the specification.
*
* @type {Readonly<Object>}
* @readonly
*/
this.xmlns = this.assign(Object.create(null), options.xmlns);
}
/**
* Parses `source` using the options in the way configured by the `DOMParserOptions` of `this`
* `DOMParser`. If `mimeType` is `text/html` an HTML `Document` is created,
* otherwise an XML `Document` is created.
*
* __It behaves different from the description in the living standard__:
* - Uses the `options` passed to the `DOMParser` constructor to modify the behavior.
* - Any unexpected input is reported to `onError` with either a `warning`,
* `error` or `fatalError` level.
* - Any `fatalError` throws a `ParseError` which prevents further processing.
* - Any error thrown by `onError` is converted to a `ParseError` which prevents further
* processing - If no `Document` was created during parsing it is reported as a `fatalError`.
* *****Warning: By configuring a faulty DOMHandler implementation,
* the specified behavior can completely be broken*****.
*
* @param {string} source
* The XML mime type only allows string input!
* @param {string} [mimeType='application/xml']
* the mimeType or contentType of the document to be created determines the `type` of document
* created (XML or HTML)
* @returns {Document}
* The `Document` node.
* @throws {ParseError}
* for any `fatalError` or anything that is thrown by `onError`
* @throws {TypeError}
* for any invalid `mimeType`
* @see https://developer.mozilla.org/en-US/docs/Web/API/DOMParser/parseFromString
* @see https://html.spec.whatwg.org/#dom-domparser-parsefromstring-dev
*/
DOMParser.prototype.parseFromString = function (source, mimeType) {
if (!isValidMimeType(mimeType)) {
throw new TypeError('DOMParser.parseFromString: the provided mimeType "' + mimeType + '" is not valid.');
}
var defaultNSMap = this.assign(Object.create(null), this.xmlns);
var entityMap = entities.XML_ENTITIES;
var defaultNamespace = defaultNSMap[''] || null;
if (hasDefaultHTMLNamespace(mimeType)) {
entityMap = entities.HTML_ENTITIES;
defaultNamespace = NAMESPACE.HTML;
} else if (mimeType === MIME_TYPE.XML_SVG_IMAGE) {
defaultNamespace = NAMESPACE.SVG;
}
defaultNSMap[''] = defaultNamespace;
defaultNSMap.xml = defaultNSMap.xml || NAMESPACE.XML;
var domBuilder = new this.domHandler({
mimeType: mimeType,
defaultNamespace: defaultNamespace,
onError: this.onError,
});
var locator = this.locator ? {} : undefined;
if (this.locator) {
domBuilder.setDocumentLocator(locator);
}
var sax = new XMLReader();
sax.errorHandler = domBuilder;
sax.domBuilder = domBuilder;
var isXml = !conventions.isHTMLMimeType(mimeType);
if (isXml && typeof source !== 'string') {
sax.errorHandler.fatalError('source is not a string');
}
sax.parse(this.normalizeLineEndings(String(source)), defaultNSMap, entityMap);
if (!domBuilder.doc.documentElement) {
sax.errorHandler.fatalError('missing root element');
}
return domBuilder.doc;
};
/**
* @typedef DOMHandlerOptions
* @property {string} [mimeType=MIME_TYPE.XML_APPLICATION]
* @property {string | null} [defaultNamespace=null]
*/
/**
* The class that is used to handle events from the SAX parser to create the related DOM
* elements.
*
* Some methods are only implemented as an empty function,
* since they are (at least currently) not relevant for xmldom.
*
* @class
* @param {DOMHandlerOptions} [options]
* @see http://www.saxproject.org/apidoc/org/xml/sax/ext/DefaultHandler2.html
*/
function DOMHandler(options) {
var opt = options || {};
/**
* The mime type is used to determine if the DOM handler will create an XML or HTML document.
* Only if it is set to `text/html` it will create an HTML document.
* It defaults to MIME_TYPE.XML_APPLICATION.
*
* @type {string}
* @see {@link MIME_TYPE}
* @readonly
*/
this.mimeType = opt.mimeType || MIME_TYPE.XML_APPLICATION;
/**
* The namespace to use to create an XML document.
* For the following reasons this is required:
* - The SAX API for `startDocument` doesn't offer any way to pass a namespace,
* since at that point there is no way for the parser to know what the default namespace from
* the document will be.
* - When creating using `DOMImplementation.createDocument` it is required to pass a
* namespace,
* to determine the correct `Document.contentType`, which should match `this.mimeType`.
* - When parsing an XML document with the `application/xhtml+xml` mimeType,
* the HTML namespace needs to be the default namespace.
*
* @type {string | null}
* @private
* @readonly
*/
this.defaultNamespace = opt.defaultNamespace || null;
/**
* @type {boolean}
* @private
*/
this.cdata = false;
/**
* The last `Element` that was created by `startElement`.
* `endElement` sets it to the `currentElement.parentNode`.
*
* Note: The sax parser currently sets it to white space text nodes between tags.
*
* @type {Element | Node | undefined}
* @private
*/
this.currentElement = undefined;
/**
* The Document that is created as part of `startDocument`,
* and returned by `DOMParser.parseFromString`.
*
* @type {Document | undefined}
* @readonly
*/
this.doc = undefined;
/**
* The locator is stored as part of setDocumentLocator.
* It is controlled and mutated by the SAX parser to store the current parsing position.
* It is used by DOMHandler to set `columnNumber` and `lineNumber`
* on the DOM nodes.
*
* @type {Readonly<Locator> | undefined}
* @private
* @readonly (the
* sax parser currently sometimes set's it)
*/
this.locator = undefined;
/**
* @type {function (level:ErrorLevel ,message:string, context:DOMHandler):void}
* @readonly
*/
this.onError = opt.onError;
}
function position(locator, node) {
node.lineNumber = locator.lineNumber;
node.columnNumber = locator.columnNumber;
}
DOMHandler.prototype = {
/**
* Either creates an XML or an HTML document and stores it under `this.doc`.
* If it is an XML document, `this.defaultNamespace` is used to create it,
* and it will not contain any `childNodes`.
* If it is an HTML document, it will be created without any `childNodes`.
*
* @see http://www.saxproject.org/apidoc/org/xml/sax/ContentHandler.html
*/
startDocument: function () {
var impl = new DOMImplementation();
this.doc = isHTMLMimeType(this.mimeType) ? impl.createHTMLDocument(false) : impl.createDocument(this.defaultNamespace, '');
},
startElement: function (namespaceURI, localName, qName, attrs) {
var doc = this.doc;
var el = doc.createElementNS(namespaceURI, qName || localName);
var len = attrs.length;
appendElement(this, el);
this.currentElement = el;
this.locator && position(this.locator, el);
for (var i = 0; i < len; i++) {
var namespaceURI = attrs.getURI(i);
var value = attrs.getValue(i);
var qName = attrs.getQName(i);
var attr = doc.createAttributeNS(namespaceURI, qName);
this.locator && position(attrs.getLocator(i), attr);
attr.value = attr.nodeValue = value;
el.setAttributeNode(attr);
}
},
endElement: function (namespaceURI, localName, qName) {
this.currentElement = this.currentElement.parentNode;
},
startPrefixMapping: function (prefix, uri) {},
endPrefixMapping: function (prefix) {},
processingInstruction: function (target, data) {
var ins = this.doc.createProcessingInstruction(target, data);
this.locator && position(this.locator, ins);
appendElement(this, ins);
},
ignorableWhitespace: function (ch, start, length) {},
characters: function (chars, start, length) {
chars = _toString.apply(this, arguments);
//console.log(chars)
if (chars) {
if (this.cdata) {
var charNode = this.doc.createCDATASection(chars);
} else {
var charNode = this.doc.createTextNode(chars);
}
if (this.currentElement) {
this.currentElement.appendChild(charNode);
} else if (/^\s*$/.test(chars)) {
this.doc.appendChild(charNode);
//process xml
}
this.locator && position(this.locator, charNode);
}
},
skippedEntity: function (name) {},
endDocument: function () {
this.doc.normalize();
},
/**
* Stores the locator to be able to set the `columnNumber` and `lineNumber`
* on the created DOM nodes.
*
* @param {Locator} locator
*/
setDocumentLocator: function (locator) {
if (locator) {
locator.lineNumber = 0;
}
this.locator = locator;
},
//LexicalHandler
comment: function (chars, start, length) {
chars = _toString.apply(this, arguments);
var comm = this.doc.createComment(chars);
this.locator && position(this.locator, comm);
appendElement(this, comm);
},
startCDATA: function () {
//used in characters() methods
this.cdata = true;
},
endCDATA: function () {
this.cdata = false;
},
startDTD: function (name, publicId, systemId, internalSubset) {
var impl = this.doc.implementation;
if (impl && impl.createDocumentType) {
var dt = impl.createDocumentType(name, publicId, systemId, internalSubset);
this.locator && position(this.locator, dt);
appendElement(this, dt);
this.doc.doctype = dt;
}
},
reportError: function (level, message) {
if (typeof this.onError === 'function') {
try {
this.onError(level, message, this);
} catch (e) {
throw new ParseError('Reporting ' + level + ' "' + message + '" caused ' + e, this.locator);
}
} else {
console.error('[xmldom ' + level + ']\t' + message, _locator(this.locator));
}
},
/**
* @see http://www.saxproject.org/apidoc/org/xml/sax/ErrorHandler.html
*/
warning: function (message) {
this.reportError('warning', message);
},
error: function (message) {
this.reportError('error', message);
},
/**
* This function reports a fatal error and throws a ParseError.
*
* @param {string} message
* - The message to be used for reporting and throwing the error.
* @returns {never}
* This function always throws an error and never returns a value.
* @throws {ParseError}
* Always throws a ParseError with the provided message.
*/
fatalError: function (message) {
this.reportError('fatalError', message);
throw new ParseError(message, this.locator);
},
};
function _locator(l) {
if (l) {
return '\n@#[line:' + l.lineNumber + ',col:' + l.columnNumber + ']';
}
}
function _toString(chars, start, length) {
if (typeof chars == 'string') {
return chars.substr(start, length);
} else {
//java sax connect width xmldom on rhino(what about: "? && !(chars instanceof String)")
if (chars.length >= start + length || start) {
return new java.lang.String(chars, start, length) + '';
}
return chars;
}
}
/*
* @link http://www.saxproject.org/apidoc/org/xml/sax/ext/LexicalHandler.html
* used method of org.xml.sax.ext.LexicalHandler:
* #comment(chars, start, length)
* #startCDATA()
* #endCDATA()
* #startDTD(name, publicId, systemId)
*
*
* IGNORED method of org.xml.sax.ext.LexicalHandler:
* #endDTD()
* #startEntity(name)
* #endEntity(name)
*
*
* @link http://www.saxproject.org/apidoc/org/xml/sax/ext/DeclHandler.html
* IGNORED method of org.xml.sax.ext.DeclHandler
* #attributeDecl(eName, aName, type, mode, value)
* #elementDecl(name, model)
* #externalEntityDecl(name, publicId, systemId)
* #internalEntityDecl(name, value)
* @link http://www.saxproject.org/apidoc/org/xml/sax/ext/EntityResolver2.html
* IGNORED method of org.xml.sax.EntityResolver2
* #resolveEntity(String name,String publicId,String baseURI,String systemId)
* #resolveEntity(publicId, systemId)
* #getExternalSubset(name, baseURI)
* @link http://www.saxproject.org/apidoc/org/xml/sax/DTDHandler.html
* IGNORED method of org.xml.sax.DTDHandler
* #notationDecl(name, publicId, systemId) {};
* #unparsedEntityDecl(name, publicId, systemId, notationName) {};
*/
'endDTD,startEntity,endEntity,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,resolveEntity,getExternalSubset,notationDecl,unparsedEntityDecl'.replace(
/\w+/g,
function (key) {
DOMHandler.prototype[key] = function () {
return null;
};
}
);
/* Private static helpers treated below as private instance methods, so don't need to add these to the public API; we might use a Relator to also get rid of non-standard public properties */
function appendElement(handler, node) {
if (!handler.currentElement) {
handler.doc.appendChild(node);
} else {
handler.currentElement.appendChild(node);
}
}
/**
* A method that prevents any further parsing when an `error`
* with level `error` is reported during parsing.
*
* @see {@link DOMParserOptions.onError}
* @see {@link onWarningStopParsing}
*/
function onErrorStopParsing(level) {
if (level === 'error') throw 'onErrorStopParsing';
}
/**
* A method that prevents any further parsing when any `error` is reported during parsing.
*
* @see {@link DOMParserOptions.onError}
* @see {@link onErrorStopParsing}
*/
function onWarningStopParsing() {
throw 'onWarningStopParsing';
}
exports.__DOMHandler = DOMHandler;
exports.DOMParser = DOMParser;
exports.normalizeLineEndings = normalizeLineEndings;
exports.onErrorStopParsing = onErrorStopParsing;
exports.onWarningStopParsing = onWarningStopParsing;

3135
node_modules/@xmldom/xmldom/lib/dom.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

2171
node_modules/@xmldom/xmldom/lib/entities.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

202
node_modules/@xmldom/xmldom/lib/errors.js generated vendored Normal file
View File

@@ -0,0 +1,202 @@
'use strict';
var conventions = require('./conventions');
function extendError(constructor, writableName) {
constructor.prototype = Object.create(Error.prototype, {
constructor: { value: constructor },
name: { value: constructor.name, enumerable: true, writable: writableName },
});
}
var DOMExceptionName = conventions.freeze({
/**
* the default value as defined by the spec
*/
Error: 'Error',
/**
* @deprecated
* Use RangeError instead.
*/
IndexSizeError: 'IndexSizeError',
/**
* @deprecated
* Just to match the related static code, not part of the spec.
*/
DomstringSizeError: 'DomstringSizeError',
HierarchyRequestError: 'HierarchyRequestError',
WrongDocumentError: 'WrongDocumentError',
InvalidCharacterError: 'InvalidCharacterError',
/**
* @deprecated
* Just to match the related static code, not part of the spec.
*/
NoDataAllowedError: 'NoDataAllowedError',
NoModificationAllowedError: 'NoModificationAllowedError',
NotFoundError: 'NotFoundError',
NotSupportedError: 'NotSupportedError',
InUseAttributeError: 'InUseAttributeError',
InvalidStateError: 'InvalidStateError',
SyntaxError: 'SyntaxError',
InvalidModificationError: 'InvalidModificationError',
NamespaceError: 'NamespaceError',
/**
* @deprecated
* Use TypeError for invalid arguments,
* "NotSupportedError" DOMException for unsupported operations,
* and "NotAllowedError" DOMException for denied requests instead.
*/
InvalidAccessError: 'InvalidAccessError',
/**
* @deprecated
* Just to match the related static code, not part of the spec.
*/
ValidationError: 'ValidationError',
/**
* @deprecated
* Use TypeError instead.
*/
TypeMismatchError: 'TypeMismatchError',
SecurityError: 'SecurityError',
NetworkError: 'NetworkError',
AbortError: 'AbortError',
/**
* @deprecated
* Just to match the related static code, not part of the spec.
*/
URLMismatchError: 'URLMismatchError',
QuotaExceededError: 'QuotaExceededError',
TimeoutError: 'TimeoutError',
InvalidNodeTypeError: 'InvalidNodeTypeError',
DataCloneError: 'DataCloneError',
EncodingError: 'EncodingError',
NotReadableError: 'NotReadableError',
UnknownError: 'UnknownError',
ConstraintError: 'ConstraintError',
DataError: 'DataError',
TransactionInactiveError: 'TransactionInactiveError',
ReadOnlyError: 'ReadOnlyError',
VersionError: 'VersionError',
OperationError: 'OperationError',
NotAllowedError: 'NotAllowedError',
OptOutError: 'OptOutError',
});
var DOMExceptionNames = Object.keys(DOMExceptionName);
function isValidDomExceptionCode(value) {
return typeof value === 'number' && value >= 1 && value <= 25;
}
function endsWithError(value) {
return typeof value === 'string' && value.substring(value.length - DOMExceptionName.Error.length) === DOMExceptionName.Error;
}
/**
* DOM operations only raise exceptions in "exceptional" circumstances, i.e., when an operation
* is impossible to perform (either for logical reasons, because data is lost, or because the
* implementation has become unstable). In general, DOM methods return specific error values in
* ordinary processing situations, such as out-of-bound errors when using NodeList.
*
* Implementations should raise other exceptions under other circumstances. For example,
* implementations should raise an implementation-dependent exception if a null argument is
* passed when null was not expected.
*
* This implementation supports the following usages:
* 1. according to the living standard (both arguments are optional):
* ```
* new DOMException("message (can be empty)", DOMExceptionNames.HierarchyRequestError)
* ```
* 2. according to previous xmldom implementation (only the first argument is required):
* ```
* new DOMException(DOMException.HIERARCHY_REQUEST_ERR, "optional message")
* ```
* both result in the proper name being set.
*
* @class DOMException
* @param {number | string} messageOrCode
* The reason why an operation is not acceptable.
* If it is a number, it is used to determine the `name`, see
* {@link https://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-258A00AF ExceptionCode}
* @param {string | keyof typeof DOMExceptionName | Error} [nameOrMessage]
* The `name` to use for the error.
* If `messageOrCode` is a number, this arguments is used as the `message` instead.
* @augments Error
* @see https://webidl.spec.whatwg.org/#idl-DOMException
* @see https://webidl.spec.whatwg.org/#dfn-error-names-table
* @see https://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-17189187
* @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/ecma-script-binding.html
* @see http://www.w3.org/TR/REC-DOM-Level-1/ecma-script-language-binding.html
*/
function DOMException(messageOrCode, nameOrMessage) {
// support old way of passing arguments: first argument is a valid number
if (isValidDomExceptionCode(messageOrCode)) {
this.name = DOMExceptionNames[messageOrCode];
this.message = nameOrMessage || '';
} else {
this.message = messageOrCode;
this.name = endsWithError(nameOrMessage) ? nameOrMessage : DOMExceptionName.Error;
}
if (Error.captureStackTrace) Error.captureStackTrace(this, DOMException);
}
extendError(DOMException, true);
Object.defineProperties(DOMException.prototype, {
code: {
enumerable: true,
get: function () {
var code = DOMExceptionNames.indexOf(this.name);
if (isValidDomExceptionCode(code)) return code;
return 0;
},
},
});
var ExceptionCode = {
INDEX_SIZE_ERR: 1,
DOMSTRING_SIZE_ERR: 2,
HIERARCHY_REQUEST_ERR: 3,
WRONG_DOCUMENT_ERR: 4,
INVALID_CHARACTER_ERR: 5,
NO_DATA_ALLOWED_ERR: 6,
NO_MODIFICATION_ALLOWED_ERR: 7,
NOT_FOUND_ERR: 8,
NOT_SUPPORTED_ERR: 9,
INUSE_ATTRIBUTE_ERR: 10,
INVALID_STATE_ERR: 11,
SYNTAX_ERR: 12,
INVALID_MODIFICATION_ERR: 13,
NAMESPACE_ERR: 14,
INVALID_ACCESS_ERR: 15,
VALIDATION_ERR: 16,
TYPE_MISMATCH_ERR: 17,
SECURITY_ERR: 18,
NETWORK_ERR: 19,
ABORT_ERR: 20,
URL_MISMATCH_ERR: 21,
QUOTA_EXCEEDED_ERR: 22,
TIMEOUT_ERR: 23,
INVALID_NODE_TYPE_ERR: 24,
DATA_CLONE_ERR: 25,
};
var entries = Object.entries(ExceptionCode);
for (var i = 0; i < entries.length; i++) {
var key = entries[i][0];
DOMException[key] = entries[i][1];
}
/**
* Creates an error that will not be caught by XMLReader aka the SAX parser.
*
* @class
* @param {string} message
* @param {any} [locator]
*/
function ParseError(message, locator) {
this.message = message;
this.locator = locator;
if (Error.captureStackTrace) Error.captureStackTrace(this, ParseError);
}
extendError(ParseError);
exports.DOMException = DOMException;
exports.DOMExceptionName = DOMExceptionName;
exports.ExceptionCode = ExceptionCode;
exports.ParseError = ParseError;

533
node_modules/@xmldom/xmldom/lib/grammar.js generated vendored Normal file
View File

@@ -0,0 +1,533 @@
'use strict';
/**
* Detects relevant unicode support for regular expressions in the runtime.
* Should the runtime not accepts the flag `u` or unicode ranges,
* character classes without unicode handling will be used.
*
* @param {typeof RegExp} [RegExpImpl=RegExp]
* For testing: the RegExp class.
* @returns {boolean}
* @see https://node.green/#ES2015-syntax-RegExp--y--and--u--flags
*/
function detectUnicodeSupport(RegExpImpl) {
try {
if (typeof RegExpImpl !== 'function') {
RegExpImpl = RegExp;
}
// eslint-disable-next-line es5/no-unicode-regex,es5/no-unicode-code-point-escape
var match = new RegExpImpl('\u{1d306}', 'u').exec('𝌆');
return !!match && match[0].length === 2;
} catch (error) {}
return false;
}
var UNICODE_SUPPORT = detectUnicodeSupport();
/**
* Removes `[`, `]` and any trailing quantifiers from the source of a RegExp.
*
* @param {RegExp} regexp
*/
function chars(regexp) {
if (regexp.source[0] !== '[') {
throw new Error(regexp + ' can not be used with chars');
}
return regexp.source.slice(1, regexp.source.lastIndexOf(']'));
}
/**
* Creates a new character list regular expression,
* by removing `search` from the source of `regexp`.
*
* @param {RegExp} regexp
* @param {string} search
* The character(s) to remove.
* @returns {RegExp}
*/
function chars_without(regexp, search) {
if (regexp.source[0] !== '[') {
throw new Error('/' + regexp.source + '/ can not be used with chars_without');
}
if (!search || typeof search !== 'string') {
throw new Error(JSON.stringify(search) + ' is not a valid search');
}
if (regexp.source.indexOf(search) === -1) {
throw new Error('"' + search + '" is not is /' + regexp.source + '/');
}
if (search === '-' && regexp.source.indexOf(search) !== 1) {
throw new Error('"' + search + '" is not at the first postion of /' + regexp.source + '/');
}
return new RegExp(regexp.source.replace(search, ''), UNICODE_SUPPORT ? 'u' : '');
}
/**
* Combines and Regular expressions correctly by using `RegExp.source`.
*
* @param {...(RegExp | string)[]} args
* @returns {RegExp}
*/
function reg(args) {
var self = this;
return new RegExp(
Array.prototype.slice
.call(arguments)
.map(function (part) {
var isStr = typeof part === 'string';
if (isStr && self === undefined && part === '|') {
throw new Error('use regg instead of reg to wrap expressions with `|`!');
}
return isStr ? part : part.source;
})
.join(''),
UNICODE_SUPPORT ? 'mu' : 'm'
);
}
/**
* Like `reg` but wraps the expression in `(?:`,`)` to create a non tracking group.
*
* @param {...(RegExp | string)[]} args
* @returns {RegExp}
*/
function regg(args) {
if (arguments.length === 0) {
throw new Error('no parameters provided');
}
return reg.apply(regg, ['(?:'].concat(Array.prototype.slice.call(arguments), [')']));
}
// /**
// * Append ^ to the beginning of the expression.
// * @param {...(RegExp | string)[]} args
// * @returns {RegExp}
// */
// function reg_start(args) {
// if (arguments.length === 0) {
// throw new Error('no parameters provided');
// }
// return reg.apply(reg_start, ['^'].concat(Array.prototype.slice.call(arguments)));
// }
// https://www.w3.org/TR/xml/#document
// `[1] document ::= prolog element Misc*`
// https://www.w3.org/TR/xml11/#NT-document
// `[1] document ::= ( prolog element Misc* ) - ( Char* RestrictedChar Char* )`
/**
* A character usually appearing in wrongly converted strings.
*
* @type {string}
* @see https://en.wikipedia.org/wiki/Specials_(Unicode_block)#Replacement_character
* @see https://nodejs.dev/en/api/v18/buffer/#buffers-and-character-encodings
* @see https://www.unicode.org/faq/utf_bom.html#BOM
* @readonly
*/
var UNICODE_REPLACEMENT_CHARACTER = '\uFFFD';
// https://www.w3.org/TR/xml/#NT-Char
// any Unicode character, excluding the surrogate blocks, FFFE, and FFFF.
// `[2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]`
// https://www.w3.org/TR/xml11/#NT-Char
// `[2] Char ::= [#x1-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]`
// https://www.w3.org/TR/xml11/#NT-RestrictedChar
// `[2a] RestrictedChar ::= [#x1-#x8] | [#xB-#xC] | [#xE-#x1F] | [#x7F-#x84] | [#x86-#x9F]`
// https://www.w3.org/TR/xml11/#charsets
var Char = /[-\x09\x0A\x0D\x20-\x2C\x2E-\uD7FF\uE000-\uFFFD]/; // without \u10000-\uEFFFF
if (UNICODE_SUPPORT) {
// eslint-disable-next-line es5/no-unicode-code-point-escape
Char = reg('[', chars(Char), '\\u{10000}-\\u{10FFFF}', ']');
}
var _SChar = /[\x20\x09\x0D\x0A]/;
var SChar_s = chars(_SChar);
// https://www.w3.org/TR/xml11/#NT-S
// `[3] S ::= (#x20 | #x9 | #xD | #xA)+`
var S = reg(_SChar, '+');
// optional whitespace described as `S?` in the grammar,
// simplified to 0-n occurrences of the character class
// instead of 0-1 occurrences of a non-capturing group around S
var S_OPT = reg(_SChar, '*');
// https://www.w3.org/TR/xml11/#NT-NameStartChar
// `[4] NameStartChar ::= ":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF]`
var NameStartChar =
/[:_a-zA-Z\xC0-\xD6\xD8-\xF6\xF8-\u02FF\u0370-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]/; // without \u10000-\uEFFFF
if (UNICODE_SUPPORT) {
// eslint-disable-next-line es5/no-unicode-code-point-escape
NameStartChar = reg('[', chars(NameStartChar), '\\u{10000}-\\u{10FFFF}', ']');
}
var NameStartChar_s = chars(NameStartChar);
// https://www.w3.org/TR/xml11/#NT-NameChar
// `[4a] NameChar ::= NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040]`
var NameChar = reg('[', NameStartChar_s, chars(/[-.0-9\xB7]/), chars(/[\u0300-\u036F\u203F-\u2040]/), ']');
// https://www.w3.org/TR/xml11/#NT-Name
// `[5] Name ::= NameStartChar (NameChar)*`
var Name = reg(NameStartChar, NameChar, '*');
/*
https://www.w3.org/TR/xml11/#NT-Names
`[6] Names ::= Name (#x20 Name)*`
*/
// https://www.w3.org/TR/xml11/#NT-Nmtoken
// `[7] Nmtoken ::= (NameChar)+`
var Nmtoken = reg(NameChar, '+');
/*
https://www.w3.org/TR/xml11/#NT-Nmtokens
`[8] Nmtokens ::= Nmtoken (#x20 Nmtoken)*`
var Nmtokens = reg(Nmtoken, regg(/\x20/, Nmtoken), '*');
*/
// https://www.w3.org/TR/xml11/#NT-EntityRef
// `[68] EntityRef ::= '&' Name ';'` [WFC: Entity Declared] [VC: Entity Declared] [WFC: Parsed Entity] [WFC: No Recursion]
var EntityRef = reg('&', Name, ';');
// https://www.w3.org/TR/xml11/#NT-CharRef
// `[66] CharRef ::= '&#' [0-9]+ ';' | '&#x' [0-9a-fA-F]+ ';'` [WFC: Legal Character]
var CharRef = regg(/&#[0-9]+;|&#x[0-9a-fA-F]+;/);
/*
https://www.w3.org/TR/xml11/#NT-Reference
- `[67] Reference ::= EntityRef | CharRef`
- `[66] CharRef ::= '&#' [0-9]+ ';' | '&#x' [0-9a-fA-F]+ ';'` [WFC: Legal Character]
- `[68] EntityRef ::= '&' Name ';'` [WFC: Entity Declared] [VC: Entity Declared] [WFC: Parsed Entity] [WFC: No Recursion]
*/
var Reference = regg(EntityRef, '|', CharRef);
// https://www.w3.org/TR/xml11/#NT-PEReference
// `[69] PEReference ::= '%' Name ';'`
// [VC: Entity Declared] [WFC: No Recursion] [WFC: In DTD]
var PEReference = reg('%', Name, ';');
// https://www.w3.org/TR/xml11/#NT-EntityValue
// `[9] EntityValue ::= '"' ([^%&"] | PEReference | Reference)* '"' | "'" ([^%&'] | PEReference | Reference)* "'"`
var EntityValue = regg(
reg('"', regg(/[^%&"]/, '|', PEReference, '|', Reference), '*', '"'),
'|',
reg("'", regg(/[^%&']/, '|', PEReference, '|', Reference), '*', "'")
);
// https://www.w3.org/TR/xml11/#NT-AttValue
// `[10] AttValue ::= '"' ([^<&"] | Reference)* '"' | "'" ([^<&'] | Reference)* "'"`
var AttValue = regg('"', regg(/[^<&"]/, '|', Reference), '*', '"', '|', "'", regg(/[^<&']/, '|', Reference), '*', "'");
// https://www.w3.org/TR/xml-names/#ns-decl
// https://www.w3.org/TR/xml-names/#ns-qualnames
// NameStartChar without ":"
var NCNameStartChar = chars_without(NameStartChar, ':');
// https://www.w3.org/TR/xml-names/#orphans
// `[5] NCNameChar ::= NameChar - ':'`
// An XML NameChar, minus the ":"
var NCNameChar = chars_without(NameChar, ':');
// https://www.w3.org/TR/xml-names/#NT-NCName
// `[4] NCName ::= Name - (Char* ':' Char*)`
// An XML Name, minus the ":"
var NCName = reg(NCNameStartChar, NCNameChar, '*');
/**
https://www.w3.org/TR/xml-names/#ns-qualnames
```
[7] QName ::= PrefixedName | UnprefixedName
=== (NCName ':' NCName) | NCName
=== NCName (':' NCName)?
[8] PrefixedName ::= Prefix ':' LocalPart
=== NCName ':' NCName
[9] UnprefixedName ::= LocalPart
=== NCName
[10] Prefix ::= NCName
[11] LocalPart ::= NCName
```
*/
var QName = reg(NCName, regg(':', NCName), '?');
var QName_exact = reg('^', QName, '$');
var QName_group = reg('(', QName, ')');
// https://www.w3.org/TR/xml11/#NT-SystemLiteral
// `[11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'")`
var SystemLiteral = regg(/"[^"]*"|'[^']*'/);
/*
https://www.w3.org/TR/xml11/#NT-PI
```
[17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l'))
[16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
```
target /xml/i is not excluded!
*/
var PI = reg(/^<\?/, '(', Name, ')', regg(S, '(', Char, '*?)'), '?', /\?>/);
// https://www.w3.org/TR/xml11/#NT-PubidChar
// `[13] PubidChar ::= #x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%]`
var PubidChar = /[\x20\x0D\x0Aa-zA-Z0-9-'()+,./:=?;!*#@$_%]/;
// https://www.w3.org/TR/xml11/#NT-PubidLiteral
// `[12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'"`
var PubidLiteral = regg('"', PubidChar, '*"', '|', "'", chars_without(PubidChar, "'"), "*'");
// https://www.w3.org/TR/xml11/#NT-CharData
// `[14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*)`
var COMMENT_START = '<!--';
var COMMENT_END = '-->';
// https://www.w3.org/TR/xml11/#NT-Comment
// `[15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'`
var Comment = reg(COMMENT_START, regg(chars_without(Char, '-'), '|', reg('-', chars_without(Char, '-'))), '*', COMMENT_END);
var PCDATA = '#PCDATA';
// https://www.w3.org/TR/xml11/#NT-Mixed
// `[51] Mixed ::= '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*' | '(' S? '#PCDATA' S? ')'`
// https://www.w3.org/TR/xml-names/#NT-Mixed
// `[51] Mixed ::= '(' S? '#PCDATA' (S? '|' S? QName)* S? ')*' | '(' S? '#PCDATA' S? ')'`
// [VC: Proper Group/PE Nesting] [VC: No Duplicate Types]
var Mixed = regg(
reg(/\(/, S_OPT, PCDATA, regg(S_OPT, /\|/, S_OPT, QName), '*', S_OPT, /\)\*/),
'|',
reg(/\(/, S_OPT, PCDATA, S_OPT, /\)/)
);
var _children_quantity = /[?*+]?/;
/*
`[49] choice ::= '(' S? cp ( S? '|' S? cp )+ S? ')'` [VC: Proper Group/PE Nesting]
`[50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'` [VC: Proper Group/PE Nesting]
simplification to solve circular referencing, but doesn't check validity constraint "Proper Group/PE Nesting"
var _choice_or_seq = reg('[', NameChar_s, SChar_s, chars(_children_quantity), '()|,]*');
```
[48] cp ::= (Name | choice | seq) ('?' | '*' | '+')?
=== (Name | '(' S? cp ( S? '|' S? cp )+ S? ')' | '(' S? cp ( S? ',' S? cp )* S? ')') ('?' | '*' | '+')?
!== (Name | [_choice_or_seq]*) ('?' | '*' | '+')?
```
simplification to solve circular referencing, but doesn't check validity constraint "Proper Group/PE Nesting"
var cp = reg(regg(Name, '|', _choice_or_seq), _children_quantity);
*/
/*
Inefficient regular expression (High)
This part of the regular expression may cause exponential backtracking on strings starting with '(|' and containing many repetitions of '|'.
https://github.com/xmldom/xmldom/security/code-scanning/91
var choice = regg(/\(/, S_OPT, cp, regg(S_OPT, /\|/, S_OPT, cp), '+', S_OPT, /\)/);
*/
/*
Inefficient regular expression (High)
This part of the regular expression may cause exponential backtracking on strings starting with '(,' and containing many repetitions of ','.
https://github.com/xmldom/xmldom/security/code-scanning/92
var seq = regg(/\(/, S_OPT, cp, regg(S_OPT, /,/, S_OPT, cp), '*', S_OPT, /\)/);
*/
// `[47] children ::= (choice | seq) ('?' | '*' | '+')?`
// simplification to solve circular referencing, but doesn't check validity constraint "Proper Group/PE Nesting"
var children = reg(/\([^>]+\)/, _children_quantity /*regg(choice, '|', seq), _children_quantity*/);
// https://www.w3.org/TR/xml11/#NT-contentspec
// `[46] contentspec ::= 'EMPTY' | 'ANY' | Mixed | children`
var contentspec = regg('EMPTY', '|', 'ANY', '|', Mixed, '|', children);
var ELEMENTDECL_START = '<!ELEMENT';
// https://www.w3.org/TR/xml11/#NT-elementdecl
// `[45] elementdecl ::= '<!ELEMENT' S Name S contentspec S? '>'`
// https://www.w3.org/TR/xml-names/#NT-elementdecl
// `[17] elementdecl ::= '<!ELEMENT' S QName S contentspec S? '>'`
// because of https://www.w3.org/TR/xml11/#NT-PEReference
// since xmldom is not supporting replacements of PEReferences in the DTD
// this also supports PEReference in the possible places
var elementdecl = reg(ELEMENTDECL_START, S, regg(QName, '|', PEReference), S, regg(contentspec, '|', PEReference), S_OPT, '>');
// https://www.w3.org/TR/xml11/#NT-NotationType
// `[58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'`
// [VC: Notation Attributes] [VC: One Notation Per Element Type] [VC: No Notation on Empty Element] [VC: No Duplicate Tokens]
var NotationType = reg('NOTATION', S, /\(/, S_OPT, Name, regg(S_OPT, /\|/, S_OPT, Name), '*', S_OPT, /\)/);
// https://www.w3.org/TR/xml11/#NT-Enumeration
// `[59] Enumeration ::= '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')'`
// [VC: Enumeration] [VC: No Duplicate Tokens]
var Enumeration = reg(/\(/, S_OPT, Nmtoken, regg(S_OPT, /\|/, S_OPT, Nmtoken), '*', S_OPT, /\)/);
// https://www.w3.org/TR/xml11/#NT-EnumeratedType
// `[57] EnumeratedType ::= NotationType | Enumeration`
var EnumeratedType = regg(NotationType, '|', Enumeration);
/*
```
[55] StringType ::= 'CDATA'
[56] TokenizedType ::= 'ID' [VC: ID] [VC: One ID per Element Type] [VC: ID Attribute Default]
| 'IDREF' [VC: IDREF]
| 'IDREFS' [VC: IDREF]
| 'ENTITY' [VC: Entity Name]
| 'ENTITIES' [VC: Entity Name]
| 'NMTOKEN' [VC: Name Token]
| 'NMTOKENS' [VC: Name Token]
[54] AttType ::= StringType | TokenizedType | EnumeratedType
```*/
var AttType = regg(/CDATA|ID|IDREF|IDREFS|ENTITY|ENTITIES|NMTOKEN|NMTOKENS/, '|', EnumeratedType);
// `[60] DefaultDecl ::= '#REQUIRED' | '#IMPLIED' | (('#FIXED' S)? AttValue)`
// [WFC: No < in Attribute Values] [WFC: No External Entity References]
// [VC: Fixed Attribute Default] [VC: Required Attribute] [VC: Attribute Default Value Syntactically Correct]
var DefaultDecl = regg(/#REQUIRED|#IMPLIED/, '|', regg(regg('#FIXED', S), '?', AttValue));
// https://www.w3.org/TR/xml11/#NT-AttDef
// [53] AttDef ::= S Name S AttType S DefaultDecl
// https://www.w3.org/TR/xml-names/#NT-AttDef
// [1] NSAttName ::= PrefixedAttName | DefaultAttName
// [2] PrefixedAttName ::= 'xmlns:' NCName [NSC: Reserved Prefixes and Namespace Names]
// [3] DefaultAttName ::= 'xmlns'
// [21] AttDef ::= S (QName | NSAttName) S AttType S DefaultDecl
// === S Name S AttType S DefaultDecl
// xmldom is not distinguishing between QName and NSAttName on this level
// to support XML without namespaces in DTD we can not restrict it to QName
var AttDef = regg(S, Name, S, AttType, S, DefaultDecl);
var ATTLIST_DECL_START = '<!ATTLIST';
// https://www.w3.org/TR/xml11/#NT-AttlistDecl
// `[52] AttlistDecl ::= '<!ATTLIST' S Name AttDef* S? '>'`
// https://www.w3.org/TR/xml-names/#NT-AttlistDecl
// `[20] AttlistDecl ::= '<!ATTLIST' S QName AttDef* S? '>'`
// to support XML without namespaces in DTD we can not restrict it to QName
var AttlistDecl = reg(ATTLIST_DECL_START, S, Name, AttDef, '*', S_OPT, '>');
// https://html.spec.whatwg.org/multipage/urls-and-fetching.html#about:legacy-compat
var ABOUT_LEGACY_COMPAT = 'about:legacy-compat';
var ABOUT_LEGACY_COMPAT_SystemLiteral = regg('"' + ABOUT_LEGACY_COMPAT + '"', '|', "'" + ABOUT_LEGACY_COMPAT + "'");
var SYSTEM = 'SYSTEM';
var PUBLIC = 'PUBLIC';
// https://www.w3.org/TR/xml11/#NT-ExternalID
// `[75] ExternalID ::= 'SYSTEM' S SystemLiteral | 'PUBLIC' S PubidLiteral S SystemLiteral`
var ExternalID = regg(regg(SYSTEM, S, SystemLiteral), '|', regg(PUBLIC, S, PubidLiteral, S, SystemLiteral));
var ExternalID_match = reg(
'^',
regg(
regg(SYSTEM, S, '(?<SystemLiteralOnly>', SystemLiteral, ')'),
'|',
regg(PUBLIC, S, '(?<PubidLiteral>', PubidLiteral, ')', S, '(?<SystemLiteral>', SystemLiteral, ')')
)
);
// https://www.w3.org/TR/xml11/#NT-NDataDecl
// `[76] NDataDecl ::= S 'NDATA' S Name` [VC: Notation Declared]
var NDataDecl = regg(S, 'NDATA', S, Name);
// https://www.w3.org/TR/xml11/#NT-EntityDef
// `[73] EntityDef ::= EntityValue | (ExternalID NDataDecl?)`
var EntityDef = regg(EntityValue, '|', regg(ExternalID, NDataDecl, '?'));
var ENTITY_DECL_START = '<!ENTITY';
// https://www.w3.org/TR/xml11/#NT-GEDecl
// `[71] GEDecl ::= '<!ENTITY' S Name S EntityDef S? '>'`
var GEDecl = reg(ENTITY_DECL_START, S, Name, S, EntityDef, S_OPT, '>');
// https://www.w3.org/TR/xml11/#NT-PEDef
// `[74] PEDef ::= EntityValue | ExternalID`
var PEDef = regg(EntityValue, '|', ExternalID);
// https://www.w3.org/TR/xml11/#NT-PEDecl
// `[72] PEDecl ::= '<!ENTITY' S '%' S Name S PEDef S? '>'`
var PEDecl = reg(ENTITY_DECL_START, S, '%', S, Name, S, PEDef, S_OPT, '>');
// https://www.w3.org/TR/xml11/#NT-EntityDecl
// `[70] EntityDecl ::= GEDecl | PEDecl`
var EntityDecl = regg(GEDecl, '|', PEDecl);
// https://www.w3.org/TR/xml11/#NT-PublicID
// `[83] PublicID ::= 'PUBLIC' S PubidLiteral`
var PublicID = reg(PUBLIC, S, PubidLiteral);
// https://www.w3.org/TR/xml11/#NT-NotationDecl
// `[82] NotationDecl ::= '<!NOTATION' S Name S (ExternalID | PublicID) S? '>'` [VC: Unique Notation Name]
var NotationDecl = reg('<!NOTATION', S, Name, S, regg(ExternalID, '|', PublicID), S_OPT, '>');
// https://www.w3.org/TR/xml11/#NT-Eq
// `[25] Eq ::= S? '=' S?`
var Eq = reg(S_OPT, '=', S_OPT);
// https://www.w3.org/TR/xml/#NT-VersionNum
// `[26] VersionNum ::= '1.' [0-9]+`
// https://www.w3.org/TR/xml11/#NT-VersionNum
// `[26] VersionNum ::= '1.1'`
var VersionNum = /1[.]\d+/;
// https://www.w3.org/TR/xml11/#NT-VersionInfo
// `[24] VersionInfo ::= S 'version' Eq ("'" VersionNum "'" | '"' VersionNum '"')`
var VersionInfo = reg(S, 'version', Eq, regg("'", VersionNum, "'", '|', '"', VersionNum, '"'));
// https://www.w3.org/TR/xml11/#NT-EncName
// `[81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*`
var EncName = /[A-Za-z][-A-Za-z0-9._]*/;
// https://www.w3.org/TR/xml11/#NT-EncDecl
// `[80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' | "'" EncName "'" )`
var EncodingDecl = regg(S, 'encoding', Eq, regg('"', EncName, '"', '|', "'", EncName, "'"));
// https://www.w3.org/TR/xml11/#NT-SDDecl
// `[32] SDDecl ::= S 'standalone' Eq (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no') '"'))`
var SDDecl = regg(S, 'standalone', Eq, regg("'", regg('yes', '|', 'no'), "'", '|', '"', regg('yes', '|', 'no'), '"'));
// https://www.w3.org/TR/xml11/#NT-XMLDecl
// [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
var XMLDecl = reg(/^<\?xml/, VersionInfo, EncodingDecl, '?', SDDecl, '?', S_OPT, /\?>/);
/*
https://www.w3.org/TR/xml/#NT-markupdecl
https://www.w3.org/TR/xml11/#NT-markupdecl
`[29] markupdecl ::= elementdecl | AttlistDecl | EntityDecl | NotationDecl | PI | Comment`
var markupdecl = regg(elementdecl, '|', AttlistDecl, '|', EntityDecl, '|', NotationDecl, '|', PI_unsafe, '|', Comment);
*/
/*
https://www.w3.org/TR/xml-names/#NT-doctypedecl
`[28a] DeclSep ::= PEReference | S`
https://www.w3.org/TR/xml11/#NT-intSubset
```
[28b] intSubset ::= (markupdecl | DeclSep)*
=== (markupdecl | PEReference | S)*
```
[WFC: PE Between Declarations]
var intSubset = reg(regg(markupdecl, '|', PEReference, '|', S), '*');
*/
var DOCTYPE_DECL_START = '<!DOCTYPE';
/*
https://www.w3.org/TR/xml11/#NT-doctypedecl
`[28] doctypedecl ::= '<!DOCTYPE' S Name (S ExternalID)? S? ('[' intSubset ']' S?)? '>'`
https://www.afterwardsw3.org/TR/xml-names/#NT-doctypedecl
`[16] doctypedecl ::= '<!DOCTYPE' S QName (S ExternalID)? S? ('[' (markupdecl | PEReference | S)* ']' S?)? '>'`
var doctypedecl = reg('<!DOCTYPE', S, Name, regg(S, ExternalID), '?', S_OPT, regg(/\[/, intSubset, /]/, S_OPT), '?', '>');
*/
var CDATA_START = '<![CDATA[';
var CDATA_END = ']]>';
var CDStart = /<!\[CDATA\[/;
var CDEnd = /\]\]>/;
var CData = reg(Char, '*?', CDEnd);
/*
https://www.w3.org/TR/xml/#dt-cdsection
`[18] CDSect ::= CDStart CData CDEnd`
`[19] CDStart ::= '<![CDATA['`
`[20] CData ::= (Char* - (Char* ']]>' Char*))`
`[21] CDEnd ::= ']]>'`
*/
var CDSect = reg(CDStart, CData);
// unit tested
exports.chars = chars;
exports.chars_without = chars_without;
exports.detectUnicodeSupport = detectUnicodeSupport;
exports.reg = reg;
exports.regg = regg;
exports.ABOUT_LEGACY_COMPAT = ABOUT_LEGACY_COMPAT;
exports.ABOUT_LEGACY_COMPAT_SystemLiteral = ABOUT_LEGACY_COMPAT_SystemLiteral;
exports.AttlistDecl = AttlistDecl;
exports.CDATA_START = CDATA_START;
exports.CDATA_END = CDATA_END;
exports.CDSect = CDSect;
exports.Char = Char;
exports.Comment = Comment;
exports.COMMENT_START = COMMENT_START;
exports.COMMENT_END = COMMENT_END;
exports.DOCTYPE_DECL_START = DOCTYPE_DECL_START;
exports.elementdecl = elementdecl;
exports.EntityDecl = EntityDecl;
exports.EntityValue = EntityValue;
exports.ExternalID = ExternalID;
exports.ExternalID_match = ExternalID_match;
exports.Name = Name;
exports.NotationDecl = NotationDecl;
exports.Reference = Reference;
exports.PEReference = PEReference;
exports.PI = PI;
exports.PUBLIC = PUBLIC;
exports.PubidLiteral = PubidLiteral;
exports.QName = QName;
exports.QName_exact = QName_exact;
exports.QName_group = QName_group;
exports.S = S;
exports.SChar_s = SChar_s;
exports.S_OPT = S_OPT;
exports.SYSTEM = SYSTEM;
exports.SystemLiteral = SystemLiteral;
exports.UNICODE_REPLACEMENT_CHARACTER = UNICODE_REPLACEMENT_CHARACTER;
exports.UNICODE_SUPPORT = UNICODE_SUPPORT;
exports.XMLDecl = XMLDecl;

41
node_modules/@xmldom/xmldom/lib/index.js generated vendored Normal file
View File

@@ -0,0 +1,41 @@
'use strict';
var conventions = require('./conventions');
exports.assign = conventions.assign;
exports.hasDefaultHTMLNamespace = conventions.hasDefaultHTMLNamespace;
exports.isHTMLMimeType = conventions.isHTMLMimeType;
exports.isValidMimeType = conventions.isValidMimeType;
exports.MIME_TYPE = conventions.MIME_TYPE;
exports.NAMESPACE = conventions.NAMESPACE;
var errors = require('./errors');
exports.DOMException = errors.DOMException;
exports.DOMExceptionName = errors.DOMExceptionName;
exports.ExceptionCode = errors.ExceptionCode;
exports.ParseError = errors.ParseError;
var dom = require('./dom');
exports.Attr = dom.Attr;
exports.CDATASection = dom.CDATASection;
exports.CharacterData = dom.CharacterData;
exports.Comment = dom.Comment;
exports.Document = dom.Document;
exports.DocumentFragment = dom.DocumentFragment;
exports.DocumentType = dom.DocumentType;
exports.DOMImplementation = dom.DOMImplementation;
exports.Element = dom.Element;
exports.Entity = dom.Entity;
exports.EntityReference = dom.EntityReference;
exports.LiveNodeList = dom.LiveNodeList;
exports.NamedNodeMap = dom.NamedNodeMap;
exports.Node = dom.Node;
exports.NodeList = dom.NodeList;
exports.Notation = dom.Notation;
exports.ProcessingInstruction = dom.ProcessingInstruction;
exports.Text = dom.Text;
exports.XMLSerializer = dom.XMLSerializer;
var domParser = require('./dom-parser');
exports.DOMParser = domParser.DOMParser;
exports.normalizeLineEndings = domParser.normalizeLineEndings;
exports.onErrorStopParsing = domParser.onErrorStopParsing;
exports.onWarningStopParsing = domParser.onWarningStopParsing;

929
node_modules/@xmldom/xmldom/lib/sax.js generated vendored Normal file
View File

@@ -0,0 +1,929 @@
'use strict';
var conventions = require('./conventions');
var g = require('./grammar');
var errors = require('./errors');
var isHTMLEscapableRawTextElement = conventions.isHTMLEscapableRawTextElement;
var isHTMLMimeType = conventions.isHTMLMimeType;
var isHTMLRawTextElement = conventions.isHTMLRawTextElement;
var hasOwn = conventions.hasOwn;
var NAMESPACE = conventions.NAMESPACE;
var ParseError = errors.ParseError;
var DOMException = errors.DOMException;
//var handlers = 'resolveEntity,getExternalSubset,characters,endDocument,endElement,endPrefixMapping,ignorableWhitespace,processingInstruction,setDocumentLocator,skippedEntity,startDocument,startElement,startPrefixMapping,notationDecl,unparsedEntityDecl,error,fatalError,warning,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,comment,endCDATA,endDTD,endEntity,startCDATA,startDTD,startEntity'.split(',')
//S_TAG, S_ATTR, S_EQ, S_ATTR_NOQUOT_VALUE
//S_ATTR_SPACE, S_ATTR_END, S_TAG_SPACE, S_TAG_CLOSE
var S_TAG = 0; //tag name offerring
var S_ATTR = 1; //attr name offerring
var S_ATTR_SPACE = 2; //attr name end and space offer
var S_EQ = 3; //=space?
var S_ATTR_NOQUOT_VALUE = 4; //attr value(no quot value only)
var S_ATTR_END = 5; //attr value end and no space(quot end)
var S_TAG_SPACE = 6; //(attr value end || tag end ) && (space offer)
var S_TAG_CLOSE = 7; //closed el<el />
function XMLReader() {}
XMLReader.prototype = {
parse: function (source, defaultNSMap, entityMap) {
var domBuilder = this.domBuilder;
domBuilder.startDocument();
_copy(defaultNSMap, (defaultNSMap = Object.create(null)));
parse(source, defaultNSMap, entityMap, domBuilder, this.errorHandler);
domBuilder.endDocument();
},
};
/**
* Detecting everything that might be a reference,
* including those without ending `;`, since those are allowed in HTML.
* The entityReplacer takes care of verifying and transforming each occurrence,
* and reports to the errorHandler on those that are not OK,
* depending on the context.
*/
var ENTITY_REG = /&#?\w+;?/g;
function parse(source, defaultNSMapCopy, entityMap, domBuilder, errorHandler) {
var isHTML = isHTMLMimeType(domBuilder.mimeType);
if (source.indexOf(g.UNICODE_REPLACEMENT_CHARACTER) >= 0) {
errorHandler.warning('Unicode replacement character detected, source encoding issues?');
}
function fixedFromCharCode(code) {
// String.prototype.fromCharCode does not supports
// > 2 bytes unicode chars directly
if (code > 0xffff) {
code -= 0x10000;
var surrogate1 = 0xd800 + (code >> 10),
surrogate2 = 0xdc00 + (code & 0x3ff);
return String.fromCharCode(surrogate1, surrogate2);
} else {
return String.fromCharCode(code);
}
}
function entityReplacer(a) {
var complete = a[a.length - 1] === ';' ? a : a + ';';
if (!isHTML && complete !== a) {
errorHandler.error('EntityRef: expecting ;');
return a;
}
var match = g.Reference.exec(complete);
if (!match || match[0].length !== complete.length) {
errorHandler.error('entity not matching Reference production: ' + a);
return a;
}
var k = complete.slice(1, -1);
if (hasOwn(entityMap, k)) {
return entityMap[k];
} else if (k.charAt(0) === '#') {
return fixedFromCharCode(parseInt(k.substring(1).replace('x', '0x')));
} else {
errorHandler.error('entity not found:' + a);
return a;
}
}
function appendText(end) {
//has some bugs
if (end > start) {
var xt = source.substring(start, end).replace(ENTITY_REG, entityReplacer);
locator && position(start);
domBuilder.characters(xt, 0, end - start);
start = end;
}
}
var lineStart = 0;
var lineEnd = 0;
var linePattern = /\r\n?|\n|$/g;
var locator = domBuilder.locator;
function position(p, m) {
while (p >= lineEnd && (m = linePattern.exec(source))) {
lineStart = lineEnd;
lineEnd = m.index + m[0].length;
locator.lineNumber++;
}
locator.columnNumber = p - lineStart + 1;
}
var parseStack = [{ currentNSMap: defaultNSMapCopy }];
var unclosedTags = [];
var start = 0;
while (true) {
try {
var tagStart = source.indexOf('<', start);
if (tagStart < 0) {
if (!isHTML && unclosedTags.length > 0) {
return errorHandler.fatalError('unclosed xml tag(s): ' + unclosedTags.join(', '));
}
if (!source.substring(start).match(/^\s*$/)) {
var doc = domBuilder.doc;
var text = doc.createTextNode(source.substring(start));
if (doc.documentElement) {
return errorHandler.error('Extra content at the end of the document');
}
doc.appendChild(text);
domBuilder.currentElement = text;
}
return;
}
if (tagStart > start) {
var fromSource = source.substring(start, tagStart);
if (!isHTML && unclosedTags.length === 0) {
fromSource = fromSource.replace(new RegExp(g.S_OPT.source, 'g'), '');
fromSource && errorHandler.error("Unexpected content outside root element: '" + fromSource + "'");
}
appendText(tagStart);
}
switch (source.charAt(tagStart + 1)) {
case '/':
var end = source.indexOf('>', tagStart + 2);
var tagNameRaw = source.substring(tagStart + 2, end > 0 ? end : undefined);
if (!tagNameRaw) {
return errorHandler.fatalError('end tag name missing');
}
var tagNameMatch = end > 0 && g.reg('^', g.QName_group, g.S_OPT, '$').exec(tagNameRaw);
if (!tagNameMatch) {
return errorHandler.fatalError('end tag name contains invalid characters: "' + tagNameRaw + '"');
}
if (!domBuilder.currentElement && !domBuilder.doc.documentElement) {
// not enough information to provide a helpful error message,
// but parsing will throw since there is no root element
return;
}
var currentTagName =
unclosedTags[unclosedTags.length - 1] ||
domBuilder.currentElement.tagName ||
domBuilder.doc.documentElement.tagName ||
'';
if (currentTagName !== tagNameMatch[1]) {
var tagNameLower = tagNameMatch[1].toLowerCase();
if (!isHTML || currentTagName.toLowerCase() !== tagNameLower) {
return errorHandler.fatalError('Opening and ending tag mismatch: "' + currentTagName + '" != "' + tagNameRaw + '"');
}
}
var config = parseStack.pop();
unclosedTags.pop();
var localNSMap = config.localNSMap;
domBuilder.endElement(config.uri, config.localName, currentTagName);
if (localNSMap) {
for (var prefix in localNSMap) {
if (hasOwn(localNSMap, prefix)) {
domBuilder.endPrefixMapping(prefix);
}
}
}
end++;
break;
// end element
case '?': // <?...?>
locator && position(tagStart);
end = parseProcessingInstruction(source, tagStart, domBuilder, errorHandler);
break;
case '!': // <!doctype,<![CDATA,<!--
locator && position(tagStart);
end = parseDoctypeCommentOrCData(source, tagStart, domBuilder, errorHandler, isHTML);
break;
default:
locator && position(tagStart);
var el = new ElementAttributes();
var currentNSMap = parseStack[parseStack.length - 1].currentNSMap;
//elStartEnd
var end = parseElementStartPart(source, tagStart, el, currentNSMap, entityReplacer, errorHandler, isHTML);
var len = el.length;
if (!el.closed) {
if (isHTML && conventions.isHTMLVoidElement(el.tagName)) {
el.closed = true;
} else {
unclosedTags.push(el.tagName);
}
}
if (locator && len) {
var locator2 = copyLocator(locator, {});
//try{//attribute position fixed
for (var i = 0; i < len; i++) {
var a = el[i];
position(a.offset);
a.locator = copyLocator(locator, {});
}
domBuilder.locator = locator2;
if (appendElement(el, domBuilder, currentNSMap)) {
parseStack.push(el);
}
domBuilder.locator = locator;
} else {
if (appendElement(el, domBuilder, currentNSMap)) {
parseStack.push(el);
}
}
if (isHTML && !el.closed) {
end = parseHtmlSpecialContent(source, end, el.tagName, entityReplacer, domBuilder);
} else {
end++;
}
}
} catch (e) {
if (e instanceof ParseError) {
throw e;
} else if (e instanceof DOMException) {
throw new ParseError(e.name + ': ' + e.message, domBuilder.locator, e);
}
errorHandler.error('element parse error: ' + e);
end = -1;
}
if (end > start) {
start = end;
} else {
//Possible sax fallback here, risk of positional error
appendText(Math.max(tagStart, start) + 1);
}
}
}
function copyLocator(f, t) {
t.lineNumber = f.lineNumber;
t.columnNumber = f.columnNumber;
return t;
}
/**
* @returns
* end of the elementStartPart(end of elementEndPart for selfClosed el)
* @see {@link #appendElement}
*/
function parseElementStartPart(source, start, el, currentNSMap, entityReplacer, errorHandler, isHTML) {
/**
* @param {string} qname
* @param {string} value
* @param {number} startIndex
*/
function addAttribute(qname, value, startIndex) {
if (hasOwn(el.attributeNames, qname)) {
return errorHandler.fatalError('Attribute ' + qname + ' redefined');
}
if (!isHTML && value.indexOf('<') >= 0) {
return errorHandler.fatalError("Unescaped '<' not allowed in attributes values");
}
el.addValue(
qname,
// @see https://www.w3.org/TR/xml/#AVNormalize
// since the xmldom sax parser does not "interpret" DTD the following is not implemented:
// - recursive replacement of (DTD) entity references
// - trimming and collapsing multiple spaces into a single one for attributes that are not of type CDATA
value.replace(/[\t\n\r]/g, ' ').replace(ENTITY_REG, entityReplacer),
startIndex
);
}
var attrName;
var value;
var p = ++start;
var s = S_TAG; //status
while (true) {
var c = source.charAt(p);
switch (c) {
case '=':
if (s === S_ATTR) {
//attrName
attrName = source.slice(start, p);
s = S_EQ;
} else if (s === S_ATTR_SPACE) {
s = S_EQ;
} else {
//fatalError: equal must after attrName or space after attrName
throw new Error('attribute equal must after attrName'); // No known test case
}
break;
case "'":
case '"':
if (
s === S_EQ ||
s === S_ATTR //|| s == S_ATTR_SPACE
) {
//equal
if (s === S_ATTR) {
errorHandler.warning('attribute value must after "="');
attrName = source.slice(start, p);
}
start = p + 1;
p = source.indexOf(c, start);
if (p > 0) {
value = source.slice(start, p);
addAttribute(attrName, value, start - 1);
s = S_ATTR_END;
} else {
//fatalError: no end quot match
throw new Error("attribute value no end '" + c + "' match");
}
} else if (s == S_ATTR_NOQUOT_VALUE) {
value = source.slice(start, p);
addAttribute(attrName, value, start);
errorHandler.warning('attribute "' + attrName + '" missed start quot(' + c + ')!!');
start = p + 1;
s = S_ATTR_END;
} else {
//fatalError: no equal before
throw new Error('attribute value must after "="'); // No known test case
}
break;
case '/':
switch (s) {
case S_TAG:
el.setTagName(source.slice(start, p));
case S_ATTR_END:
case S_TAG_SPACE:
case S_TAG_CLOSE:
s = S_TAG_CLOSE;
el.closed = true;
case S_ATTR_NOQUOT_VALUE:
case S_ATTR:
break;
case S_ATTR_SPACE:
el.closed = true;
break;
//case S_EQ:
default:
throw new Error("attribute invalid close char('/')"); // No known test case
}
break;
case '': //end document
errorHandler.error('unexpected end of input');
if (s == S_TAG) {
el.setTagName(source.slice(start, p));
}
return p;
case '>':
switch (s) {
case S_TAG:
el.setTagName(source.slice(start, p));
case S_ATTR_END:
case S_TAG_SPACE:
case S_TAG_CLOSE:
break; //normal
case S_ATTR_NOQUOT_VALUE: //Compatible state
case S_ATTR:
value = source.slice(start, p);
if (value.slice(-1) === '/') {
el.closed = true;
value = value.slice(0, -1);
}
case S_ATTR_SPACE:
if (s === S_ATTR_SPACE) {
value = attrName;
}
if (s == S_ATTR_NOQUOT_VALUE) {
errorHandler.warning('attribute "' + value + '" missed quot(")!');
addAttribute(attrName, value, start);
} else {
if (!isHTML) {
errorHandler.warning('attribute "' + value + '" missed value!! "' + value + '" instead!!');
}
addAttribute(value, value, start);
}
break;
case S_EQ:
if (!isHTML) {
return errorHandler.fatalError('AttValue: \' or " expected');
}
}
return p;
/*xml space '\x20' | #x9 | #xD | #xA; */
case '\u0080':
c = ' ';
default:
if (c <= ' ') {
//space
switch (s) {
case S_TAG:
el.setTagName(source.slice(start, p)); //tagName
s = S_TAG_SPACE;
break;
case S_ATTR:
attrName = source.slice(start, p);
s = S_ATTR_SPACE;
break;
case S_ATTR_NOQUOT_VALUE:
var value = source.slice(start, p);
errorHandler.warning('attribute "' + value + '" missed quot(")!!');
addAttribute(attrName, value, start);
case S_ATTR_END:
s = S_TAG_SPACE;
break;
//case S_TAG_SPACE:
//case S_EQ:
//case S_ATTR_SPACE:
// void();break;
//case S_TAG_CLOSE:
//ignore warning
}
} else {
//not space
//S_TAG, S_ATTR, S_EQ, S_ATTR_NOQUOT_VALUE
//S_ATTR_SPACE, S_ATTR_END, S_TAG_SPACE, S_TAG_CLOSE
switch (s) {
//case S_TAG:void();break;
//case S_ATTR:void();break;
//case S_ATTR_NOQUOT_VALUE:void();break;
case S_ATTR_SPACE:
if (!isHTML) {
errorHandler.warning('attribute "' + attrName + '" missed value!! "' + attrName + '" instead2!!');
}
addAttribute(attrName, attrName, start);
start = p;
s = S_ATTR;
break;
case S_ATTR_END:
errorHandler.warning('attribute space is required"' + attrName + '"!!');
case S_TAG_SPACE:
s = S_ATTR;
start = p;
break;
case S_EQ:
s = S_ATTR_NOQUOT_VALUE;
start = p;
break;
case S_TAG_CLOSE:
throw new Error("elements closed character '/' and '>' must be connected to");
}
}
} //end outer switch
p++;
}
}
/**
* @returns
* `true` if a new namespace has been defined.
*/
function appendElement(el, domBuilder, currentNSMap) {
var tagName = el.tagName;
var localNSMap = null;
var i = el.length;
while (i--) {
var a = el[i];
var qName = a.qName;
var value = a.value;
var nsp = qName.indexOf(':');
if (nsp > 0) {
var prefix = (a.prefix = qName.slice(0, nsp));
var localName = qName.slice(nsp + 1);
var nsPrefix = prefix === 'xmlns' && localName;
} else {
localName = qName;
prefix = null;
nsPrefix = qName === 'xmlns' && '';
}
//can not set prefix,because prefix !== ''
a.localName = localName;
//prefix == null for no ns prefix attribute
if (nsPrefix !== false) {
//hack!!
if (localNSMap == null) {
localNSMap = Object.create(null);
_copy(currentNSMap, (currentNSMap = Object.create(null)));
}
currentNSMap[nsPrefix] = localNSMap[nsPrefix] = value;
a.uri = NAMESPACE.XMLNS;
domBuilder.startPrefixMapping(nsPrefix, value);
}
}
var i = el.length;
while (i--) {
a = el[i];
if (a.prefix) {
//no prefix attribute has no namespace
if (a.prefix === 'xml') {
a.uri = NAMESPACE.XML;
}
if (a.prefix !== 'xmlns') {
a.uri = currentNSMap[a.prefix];
}
}
}
var nsp = tagName.indexOf(':');
if (nsp > 0) {
prefix = el.prefix = tagName.slice(0, nsp);
localName = el.localName = tagName.slice(nsp + 1);
} else {
prefix = null; //important!!
localName = el.localName = tagName;
}
//no prefix element has default namespace
var ns = (el.uri = currentNSMap[prefix || '']);
domBuilder.startElement(ns, localName, tagName, el);
//endPrefixMapping and startPrefixMapping have not any help for dom builder
//localNSMap = null
if (el.closed) {
domBuilder.endElement(ns, localName, tagName);
if (localNSMap) {
for (prefix in localNSMap) {
if (hasOwn(localNSMap, prefix)) {
domBuilder.endPrefixMapping(prefix);
}
}
}
} else {
el.currentNSMap = currentNSMap;
el.localNSMap = localNSMap;
//parseStack.push(el);
return true;
}
}
function parseHtmlSpecialContent(source, elStartEnd, tagName, entityReplacer, domBuilder) {
// https://html.spec.whatwg.org/#raw-text-elements
// https://html.spec.whatwg.org/#escapable-raw-text-elements
// https://html.spec.whatwg.org/#cdata-rcdata-restrictions:raw-text-elements
// TODO: https://html.spec.whatwg.org/#cdata-rcdata-restrictions
var isEscapableRaw = isHTMLEscapableRawTextElement(tagName);
if (isEscapableRaw || isHTMLRawTextElement(tagName)) {
var elEndStart = source.indexOf('</' + tagName + '>', elStartEnd);
var text = source.substring(elStartEnd + 1, elEndStart);
if (isEscapableRaw) {
text = text.replace(ENTITY_REG, entityReplacer);
}
domBuilder.characters(text, 0, text.length);
return elEndStart;
}
return elStartEnd + 1;
}
function _copy(source, target) {
for (var n in source) {
if (hasOwn(source, n)) {
target[n] = source[n];
}
}
}
/**
* @typedef ParseUtils
* @property {function(relativeIndex: number?): string | undefined} char
* Provides look ahead access to a singe character relative to the current index.
* @property {function(): number} getIndex
* Provides read-only access to the current index.
* @property {function(reg: RegExp): string | null} getMatch
* Applies the provided regular expression enforcing that it starts at the current index and
* returns the complete matching string,
* and moves the current index by the length of the matching string.
* @property {function(): string} getSource
* Provides read-only access to the complete source.
* @property {function(places: number?): void} skip
* moves the current index by places (defaults to 1)
* @property {function(): number} skipBlanks
* Moves the current index by the amount of white space that directly follows the current index
* and returns the amount of whitespace chars skipped (0..n),
* or -1 if the end of the source was reached.
* @property {function(): string} substringFromIndex
* creates a substring from the current index to the end of `source`
* @property {function(compareWith: string): boolean} substringStartsWith
* Checks if `source` contains `compareWith`, starting from the current index.
* @property {function(compareWith: string): boolean} substringStartsWithCaseInsensitive
* Checks if `source` contains `compareWith`, starting from the current index,
* comparing the upper case of both sides.
* @see {@link parseUtils}
*/
/**
* A temporary scope for parsing and look ahead operations in `source`,
* starting from index `start`.
*
* Some operations move the current index by a number of positions,
* after which `getIndex` returns the new index.
*
* @param {string} source
* @param {number} start
* @returns {ParseUtils}
*/
function parseUtils(source, start) {
var index = start;
function char(n) {
n = n || 0;
return source.charAt(index + n);
}
function skip(n) {
n = n || 1;
index += n;
}
function skipBlanks() {
var blanks = 0;
while (index < source.length) {
var c = char();
if (c !== ' ' && c !== '\n' && c !== '\t' && c !== '\r') {
return blanks;
}
blanks++;
skip();
}
return -1;
}
function substringFromIndex() {
return source.substring(index);
}
function substringStartsWith(text) {
return source.substring(index, index + text.length) === text;
}
function substringStartsWithCaseInsensitive(text) {
return source.substring(index, index + text.length).toUpperCase() === text.toUpperCase();
}
function getMatch(args) {
var expr = g.reg('^', args);
var match = expr.exec(substringFromIndex());
if (match) {
skip(match[0].length);
return match[0];
}
return null;
}
return {
char: char,
getIndex: function () {
return index;
},
getMatch: getMatch,
getSource: function () {
return source;
},
skip: skip,
skipBlanks: skipBlanks,
substringFromIndex: substringFromIndex,
substringStartsWith: substringStartsWith,
substringStartsWithCaseInsensitive: substringStartsWithCaseInsensitive,
};
}
/**
* @param {ParseUtils} p
* @param {DOMHandler} errorHandler
* @returns {string}
*/
function parseDoctypeInternalSubset(p, errorHandler) {
/**
* @param {ParseUtils} p
* @param {DOMHandler} errorHandler
* @returns {string}
*/
function parsePI(p, errorHandler) {
var match = g.PI.exec(p.substringFromIndex());
if (!match) {
return errorHandler.fatalError('processing instruction is not well-formed at position ' + p.getIndex());
}
if (match[1].toLowerCase() === 'xml') {
return errorHandler.fatalError(
'xml declaration is only allowed at the start of the document, but found at position ' + p.getIndex()
);
}
p.skip(match[0].length);
return match[0];
}
// Parse internal subset
var source = p.getSource();
if (p.char() === '[') {
p.skip(1);
var intSubsetStart = p.getIndex();
while (p.getIndex() < source.length) {
p.skipBlanks();
if (p.char() === ']') {
var internalSubset = source.substring(intSubsetStart, p.getIndex());
p.skip(1);
return internalSubset;
}
var current = null;
// Only in external subset
// if (char() === '<' && char(1) === '!' && char(2) === '[') {
// parseConditionalSections(p, errorHandler);
// } else
if (p.char() === '<' && p.char(1) === '!') {
switch (p.char(2)) {
case 'E': // ELEMENT | ENTITY
if (p.char(3) === 'L') {
current = p.getMatch(g.elementdecl);
} else if (p.char(3) === 'N') {
current = p.getMatch(g.EntityDecl);
}
break;
case 'A': // ATTRIBUTE
current = p.getMatch(g.AttlistDecl);
break;
case 'N': // NOTATION
current = p.getMatch(g.NotationDecl);
break;
case '-': // COMMENT
current = p.getMatch(g.Comment);
break;
}
} else if (p.char() === '<' && p.char(1) === '?') {
current = parsePI(p, errorHandler);
} else if (p.char() === '%') {
current = p.getMatch(g.PEReference);
} else {
return errorHandler.fatalError('Error detected in Markup declaration');
}
if (!current) {
return errorHandler.fatalError('Error in internal subset at position ' + p.getIndex());
}
}
return errorHandler.fatalError('doctype internal subset is not well-formed, missing ]');
}
}
/**
* Called when the parser encounters an element starting with '<!'.
*
* @param {string} source
* The xml.
* @param {number} start
* the start index of the '<!'
* @param {DOMHandler} domBuilder
* @param {DOMHandler} errorHandler
* @param {boolean} isHTML
* @returns {number | never}
* The end index of the element.
* @throws {ParseError}
* In case the element is not well-formed.
*/
function parseDoctypeCommentOrCData(source, start, domBuilder, errorHandler, isHTML) {
var p = parseUtils(source, start);
switch (isHTML ? p.char(2).toUpperCase() : p.char(2)) {
case '-':
// should be a comment
var comment = p.getMatch(g.Comment);
if (comment) {
domBuilder.comment(comment, g.COMMENT_START.length, comment.length - g.COMMENT_START.length - g.COMMENT_END.length);
return p.getIndex();
} else {
return errorHandler.fatalError('comment is not well-formed at position ' + p.getIndex());
}
case '[':
// should be CDATA
var cdata = p.getMatch(g.CDSect);
if (cdata) {
if (!isHTML && !domBuilder.currentElement) {
return errorHandler.fatalError('CDATA outside of element');
}
domBuilder.startCDATA();
domBuilder.characters(cdata, g.CDATA_START.length, cdata.length - g.CDATA_START.length - g.CDATA_END.length);
domBuilder.endCDATA();
return p.getIndex();
} else {
return errorHandler.fatalError('Invalid CDATA starting at position ' + start);
}
case 'D': {
// should be DOCTYPE
if (domBuilder.doc && domBuilder.doc.documentElement) {
return errorHandler.fatalError('Doctype not allowed inside or after documentElement at position ' + p.getIndex());
}
if (isHTML ? !p.substringStartsWithCaseInsensitive(g.DOCTYPE_DECL_START) : !p.substringStartsWith(g.DOCTYPE_DECL_START)) {
return errorHandler.fatalError('Expected ' + g.DOCTYPE_DECL_START + ' at position ' + p.getIndex());
}
p.skip(g.DOCTYPE_DECL_START.length);
if (p.skipBlanks() < 1) {
return errorHandler.fatalError('Expected whitespace after ' + g.DOCTYPE_DECL_START + ' at position ' + p.getIndex());
}
var doctype = {
name: undefined,
publicId: undefined,
systemId: undefined,
internalSubset: undefined,
};
// Parse the DOCTYPE name
doctype.name = p.getMatch(g.Name);
if (!doctype.name)
return errorHandler.fatalError('doctype name missing or contains unexpected characters at position ' + p.getIndex());
if (isHTML && doctype.name.toLowerCase() !== 'html') {
errorHandler.warning('Unexpected DOCTYPE in HTML document at position ' + p.getIndex());
}
p.skipBlanks();
// Check for ExternalID
if (p.substringStartsWith(g.PUBLIC) || p.substringStartsWith(g.SYSTEM)) {
var match = g.ExternalID_match.exec(p.substringFromIndex());
if (!match) {
return errorHandler.fatalError('doctype external id is not well-formed at position ' + p.getIndex());
}
if (match.groups.SystemLiteralOnly !== undefined) {
doctype.systemId = match.groups.SystemLiteralOnly;
} else {
doctype.systemId = match.groups.SystemLiteral;
doctype.publicId = match.groups.PubidLiteral;
}
p.skip(match[0].length);
} else if (isHTML && p.substringStartsWithCaseInsensitive(g.SYSTEM)) {
// https://html.spec.whatwg.org/multipage/syntax.html#doctype-legacy-string
p.skip(g.SYSTEM.length);
if (p.skipBlanks() < 1) {
return errorHandler.fatalError('Expected whitespace after ' + g.SYSTEM + ' at position ' + p.getIndex());
}
doctype.systemId = p.getMatch(g.ABOUT_LEGACY_COMPAT_SystemLiteral);
if (!doctype.systemId) {
return errorHandler.fatalError(
'Expected ' + g.ABOUT_LEGACY_COMPAT + ' in single or double quotes after ' + g.SYSTEM + ' at position ' + p.getIndex()
);
}
}
if (isHTML && doctype.systemId && !g.ABOUT_LEGACY_COMPAT_SystemLiteral.test(doctype.systemId)) {
errorHandler.warning('Unexpected doctype.systemId in HTML document at position ' + p.getIndex());
}
if (!isHTML) {
p.skipBlanks();
doctype.internalSubset = parseDoctypeInternalSubset(p, errorHandler);
}
p.skipBlanks();
if (p.char() !== '>') {
return errorHandler.fatalError('doctype not terminated with > at position ' + p.getIndex());
}
p.skip(1);
domBuilder.startDTD(doctype.name, doctype.publicId, doctype.systemId, doctype.internalSubset);
domBuilder.endDTD();
return p.getIndex();
}
default:
return errorHandler.fatalError('Not well-formed XML starting with "<!" at position ' + start);
}
}
function parseProcessingInstruction(source, start, domBuilder, errorHandler) {
var match = source.substring(start).match(g.PI);
if (!match) {
return errorHandler.fatalError('Invalid processing instruction starting at position ' + start);
}
if (match[1].toLowerCase() === 'xml') {
if (start > 0) {
return errorHandler.fatalError(
'processing instruction at position ' + start + ' is an xml declaration which is only at the start of the document'
);
}
if (!g.XMLDecl.test(source.substring(start))) {
return errorHandler.fatalError('xml declaration is not well-formed');
}
}
domBuilder.processingInstruction(match[1], match[2]);
return start + match[0].length;
}
function ElementAttributes() {
this.attributeNames = Object.create(null);
}
ElementAttributes.prototype = {
setTagName: function (tagName) {
if (!g.QName_exact.test(tagName)) {
throw new Error('invalid tagName:' + tagName);
}
this.tagName = tagName;
},
addValue: function (qName, value, offset) {
if (!g.QName_exact.test(qName)) {
throw new Error('invalid attribute:' + qName);
}
this.attributeNames[qName] = this.length;
this[this.length++] = { qName: qName, value: value, offset: offset };
},
length: 0,
getLocalName: function (i) {
return this[i].localName;
},
getLocator: function (i) {
return this[i].locator;
},
getQName: function (i) {
return this[i].qName;
},
getURI: function (i) {
return this[i].uri;
},
getValue: function (i) {
return this[i].value;
},
// ,getIndex:function(uri, localName)){
// if(localName){
//
// }else{
// var qName = uri
// }
// },
// getValue:function(){return this.getValue(this.getIndex.apply(this,arguments))},
// getType:function(uri,localName){}
// getType:function(i){},
};
exports.XMLReader = XMLReader;
exports.parseUtils = parseUtils;
exports.parseDoctypeCommentOrCData = parseDoctypeCommentOrCData;