first commit
This commit is contained in:
3
node_modules/@xmldom/xmldom/lib/.eslintrc.yml
generated
vendored
Normal file
3
node_modules/@xmldom/xmldom/lib/.eslintrc.yml
generated
vendored
Normal 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
429
node_modules/@xmldom/xmldom/lib/conventions.js
generated
vendored
Normal 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
586
node_modules/@xmldom/xmldom/lib/dom-parser.js
generated
vendored
Normal 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
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
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
202
node_modules/@xmldom/xmldom/lib/errors.js
generated
vendored
Normal 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
533
node_modules/@xmldom/xmldom/lib/grammar.js
generated
vendored
Normal 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
41
node_modules/@xmldom/xmldom/lib/index.js
generated
vendored
Normal 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
929
node_modules/@xmldom/xmldom/lib/sax.js
generated
vendored
Normal 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;
|
||||
Reference in New Issue
Block a user