From 775fb33f99f7c40dbfac957c42ecdcad5be25cdb Mon Sep 17 00:00:00 2001 From: "${Mr.DJA}" <42304709+iMrDJAi@users.noreply.github.com> Date: Sat, 22 Oct 2022 22:03:21 +0100 Subject: [PATCH 01/13] =?UTF-8?q?=E2=9C=A8=20Make=20parseFormString=20acce?= =?UTF-8?q?pts=20streams=20as=20input?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .eslintrc.json | 1 + cjs/dom/parser.js | 5 +- cjs/shared/parse-from-string.js | 47 +- esm/dom/parser.js | 5 +- esm/shared/parse-from-string.js | 47 +- package-lock.json | 13 +- package.json | 3 +- test/stream/test.js | 35 + types/commonjs/canvas-shim.d.cts | 9 + types/esm/dom/parser.d.ts | 15 +- types/esm/index.d.ts | 2 +- types/esm/shared/node.d.ts | 2 +- types/esm/shared/parse-from-string.d.ts | 5 +- worker.js | 5394 +++++++++++------------ 14 files changed, 2620 insertions(+), 2963 deletions(-) create mode 100644 test/stream/test.js create mode 100644 types/commonjs/canvas-shim.d.cts diff --git a/.eslintrc.json b/.eslintrc.json index cfe1e0b3..cc691a0c 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,6 +1,7 @@ { "env": { "browser": true, + "node": true, "es2021": true }, "extends": "eslint:recommended", diff --git a/cjs/dom/parser.js b/cjs/dom/parser.js index ecb31781..c5a02a24 100644 --- a/cjs/dom/parser.js +++ b/cjs/dom/parser.js @@ -13,10 +13,11 @@ class DOMParser { /** @typedef {{ "text/html": HTMLDocument, "image/svg+xml": SVGDocument, "text/xml": XMLDocument }} MimeToDoc */ /** + * @template {string|NodeJS.ReadableStream} INPUT * @template {keyof MimeToDoc} MIME - * @param {string} markupLanguage + * @param {INPUT} markupLanguage * @param {MIME} mimeType - * @returns {MimeToDoc[MIME]} + * @returns {INPUT extends string ? MimeToDoc[MIME] : Promise} */ parseFromString(markupLanguage, mimeType, globals = null) { let isHTML = false, document; diff --git a/cjs/shared/parse-from-string.js b/cjs/shared/parse-from-string.js index 04eb852c..238eeafa 100644 --- a/cjs/shared/parse-from-string.js +++ b/cjs/shared/parse-from-string.js @@ -1,5 +1,5 @@ 'use strict'; -const HTMLParser2 = require('htmlparser2'); +const HTMLParser2 = require('htmlparser2/lib/WritableStream'); const {ELEMENT_NODE, SVG_NAMESPACE} = require('./constants.js'); const {CUSTOM_ELEMENTS, PREV, END, VALUE} = require('./symbols.js'); @@ -8,7 +8,7 @@ const {keys} = require('./object.js'); const {knownBoundaries, knownSiblings} = require('./utils.js'); const {attributeChangedCallback, connectedCallback} = require('../interface/custom-element-registry.js'); -const {Parser} = HTMLParser2; +const {WritableStream} = HTMLParser2; // import {Mime} from './mime.js'; // const VOID_SOURCE = Mime['text/html'].voidElements.source.slice(4, -2); @@ -16,6 +16,12 @@ const {Parser} = HTMLParser2; // const VOID_SANITIZER = (_, $1, $2) => `<${$1}${$2}${/\/$/.test($2) ? '' : ' /'}>`; // const voidSanitizer = html => html.replace(VOID_ELEMENTS, VOID_SANITIZER); +/** + * @typedef {import('../html/document.js').HTMLDocument} HTMLDocument + * @typedef {import('../svg/document.js').SVGDocument} SVGDocument + * @typedef {import('../xml/document.js').XMLDocument} XMLDocument + */ + let notParsing = true; const append = (self, node, active) => { @@ -40,6 +46,14 @@ const attribute = (element, end, attribute, value, active) => { const isNotParsing = () => notParsing; exports.isNotParsing = isNotParsing; +/** + * @template {HTMLDocument|SVGDocument|XMLDocument} DOC + * @template {string|NodeJS.ReadableStream} INPUT + * @param {DOC} document + * @param {Boolean} isHTML + * @param {INPUT} markupLanguage + * @returns {INPUT extends string ? DOC : Promise} + */ const parseFromString = (document, isHTML, markupLanguage) => { const {active, registry} = document[CUSTOM_ELEMENTS]; @@ -48,7 +62,7 @@ const parseFromString = (document, isHTML, markupLanguage) => { notParsing = false; - const content = new Parser({ + const content = new WritableStream({ // onprocessinginstruction(name, data) { if (name.toLowerCase() === '!doctype') @@ -104,11 +118,26 @@ const parseFromString = (document, isHTML, markupLanguage) => { xmlMode: !isHTML }); - content.write(markupLanguage); - content.end(); - - notParsing = true; - - return document; + if (typeof markupLanguage === 'string') { + content.write(markupLanguage); + content.end(); + notParsing = true; + return document; + } else { + return new Promise((resolve, reject) => { + markupLanguage.pipe(content); + markupLanguage.once('end', () => { + notParsing = true; + resolve(document); + }); + const errorCb = err => { + content.end(); + notParsing = true; + reject(err); + } + markupLanguage.once('error', errorCb); + content.once('error', errorCb); + }); + } }; exports.parseFromString = parseFromString; diff --git a/esm/dom/parser.js b/esm/dom/parser.js index 1ca423d0..5d060639 100644 --- a/esm/dom/parser.js +++ b/esm/dom/parser.js @@ -12,10 +12,11 @@ export class DOMParser { /** @typedef {{ "text/html": HTMLDocument, "image/svg+xml": SVGDocument, "text/xml": XMLDocument }} MimeToDoc */ /** + * @template {string|NodeJS.ReadableStream} INPUT * @template {keyof MimeToDoc} MIME - * @param {string} markupLanguage + * @param {INPUT} markupLanguage * @param {MIME} mimeType - * @returns {MimeToDoc[MIME]} + * @returns {INPUT extends string ? MimeToDoc[MIME] : Promise} */ parseFromString(markupLanguage, mimeType, globals = null) { let isHTML = false, document; diff --git a/esm/shared/parse-from-string.js b/esm/shared/parse-from-string.js index edc901d4..d6c335d5 100644 --- a/esm/shared/parse-from-string.js +++ b/esm/shared/parse-from-string.js @@ -1,4 +1,4 @@ -import * as HTMLParser2 from 'htmlparser2'; +import * as HTMLParser2 from 'htmlparser2/lib/WritableStream'; import {ELEMENT_NODE, SVG_NAMESPACE} from './constants.js'; import {CUSTOM_ELEMENTS, PREV, END, VALUE} from './symbols.js'; @@ -7,7 +7,7 @@ import {keys} from './object.js'; import {knownBoundaries, knownSiblings} from './utils.js'; import {attributeChangedCallback, connectedCallback} from '../interface/custom-element-registry.js'; -const {Parser} = HTMLParser2; +const {WritableStream} = HTMLParser2; // import {Mime} from './mime.js'; // const VOID_SOURCE = Mime['text/html'].voidElements.source.slice(4, -2); @@ -15,6 +15,12 @@ const {Parser} = HTMLParser2; // const VOID_SANITIZER = (_, $1, $2) => `<${$1}${$2}${/\/$/.test($2) ? '' : ' /'}>`; // const voidSanitizer = html => html.replace(VOID_ELEMENTS, VOID_SANITIZER); +/** + * @typedef {import('../html/document.js').HTMLDocument} HTMLDocument + * @typedef {import('../svg/document.js').SVGDocument} SVGDocument + * @typedef {import('../xml/document.js').XMLDocument} XMLDocument + */ + let notParsing = true; const append = (self, node, active) => { @@ -38,6 +44,14 @@ const attribute = (element, end, attribute, value, active) => { export const isNotParsing = () => notParsing; +/** + * @template {HTMLDocument|SVGDocument|XMLDocument} DOC + * @template {string|NodeJS.ReadableStream} INPUT + * @param {DOC} document + * @param {Boolean} isHTML + * @param {INPUT} markupLanguage + * @returns {INPUT extends string ? DOC : Promise} + */ export const parseFromString = (document, isHTML, markupLanguage) => { const {active, registry} = document[CUSTOM_ELEMENTS]; @@ -46,7 +60,7 @@ export const parseFromString = (document, isHTML, markupLanguage) => { notParsing = false; - const content = new Parser({ + const content = new WritableStream({ // onprocessinginstruction(name, data) { if (name.toLowerCase() === '!doctype') @@ -102,10 +116,25 @@ export const parseFromString = (document, isHTML, markupLanguage) => { xmlMode: !isHTML }); - content.write(markupLanguage); - content.end(); - - notParsing = true; - - return document; + if (typeof markupLanguage === 'string') { + content.write(markupLanguage); + content.end(); + notParsing = true; + return document; + } else { + return new Promise((resolve, reject) => { + markupLanguage.pipe(content); + markupLanguage.once('end', () => { + notParsing = true; + resolve(document); + }); + const errorCb = err => { + content.end(); + notParsing = true; + reject(err); + } + markupLanguage.once('error', errorCb); + content.once('error', errorCb); + }); + } }; diff --git a/package-lock.json b/package-lock.json index 8e5a182c..8abb2343 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "@rollup/plugin-commonjs": "^22.0.0", "@rollup/plugin-json": "^4.1.0", "@rollup/plugin-node-resolve": "^13.3.0", + "@types/node": "^18.11.0", "ascjs": "^5.0.1", "c8": "^7.11.2", "eslint": "^8.15.0", @@ -207,9 +208,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "17.0.31", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.31.tgz", - "integrity": "sha512-AR0x5HbXGqkEx9CadRH3EBYx/VkiUgZIhP4wvPn/+5KIsgpNoyFaRlVe0Zlx9gRtg8fA06a9tskE2MSN7TcG4Q==", + "version": "18.11.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.3.tgz", + "integrity": "sha512-fNjDQzzOsZeKZu5NATgXUPsaFaTxeRgFXoosrHivTl8RGeV733OLawXsGfEk9a8/tySyZUyiZ6E8LcjPFZ2y1A==", "dev": true }, "node_modules/@types/resolve": { @@ -1919,9 +1920,9 @@ "dev": true }, "@types/node": { - "version": "17.0.31", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.31.tgz", - "integrity": "sha512-AR0x5HbXGqkEx9CadRH3EBYx/VkiUgZIhP4wvPn/+5KIsgpNoyFaRlVe0Zlx9gRtg8fA06a9tskE2MSN7TcG4Q==", + "version": "18.11.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.3.tgz", + "integrity": "sha512-fNjDQzzOsZeKZu5NATgXUPsaFaTxeRgFXoosrHivTl8RGeV733OLawXsGfEk9a8/tySyZUyiZ6E8LcjPFZ2y1A==", "dev": true }, "@types/resolve": { diff --git a/package.json b/package.json index e94722e4..f3c56aef 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "0.14.19", "description": "A triple-linked lists based DOM implementation", "main": "./cjs/index.js", - "types": "./types/index.d.ts", + "types": "./types/esm/index.d.ts", "scripts": { "benchmark": "node test/benchmark/linkedom.js", "benchmark:w3c": "node test/benchmark/linkedom.js --w3c; node test/benchmark/linkedom-cached.js --w3c; node test/benchmark/jsdom.js --w3c; node test/benchmark/basichtml.js --w3c", @@ -34,6 +34,7 @@ "@rollup/plugin-commonjs": "^22.0.0", "@rollup/plugin-json": "^4.1.0", "@rollup/plugin-node-resolve": "^13.3.0", + "@types/node": "^18.11.0", "ascjs": "^5.0.1", "c8": "^7.11.2", "eslint": "^8.15.0", diff --git a/test/stream/test.js b/test/stream/test.js new file mode 100644 index 00000000..24fe407f --- /dev/null +++ b/test/stream/test.js @@ -0,0 +1,35 @@ +const fs = require('fs'); +const {join} = require('path'); +const {memoryUsage} = require('process'); +const {DOMParser} = require('../../cjs/index.js'); + +const parser = new DOMParser; +let length = 0 + +const logStatus = (message = 'total heap memory') => { + const used = memoryUsage().heapUsed / 1024 / 1024; + const processed = length / 1024 / 1024; + console.log( + `\x1b[1m${message}:\x1b[0m ${Math.round(used * 100) / 100} MB`, + `\x1b[1mtotal processed:\x1b[0m ${Math.round(processed * 100) / 100} MB` + ); +}; + +logStatus('initial heap') + +const src = fs.createReadStream(join(__dirname, '../benchmark/html.html')); +src.on('data', chunk => { + length += chunk.length; + logStatus(); +}); + +console.time(' parsing \x1b[2mcold\x1b[0m'); +parser.parseFromString(src, 'text/html').then(doc => { + console.timeEnd(' parsing \x1b[2mcold\x1b[0m'); + console.log(); + logStatus('document heap'); + console.log(doc); +}).catch((o_O) => { + console.error(o_O); + console.warn(`⚠ \x1b[1merror\x1b[0m - unable to parse the document: ${o_O.message}`); +}); diff --git a/types/commonjs/canvas-shim.d.cts b/types/commonjs/canvas-shim.d.cts new file mode 100644 index 00000000..ac6e4324 --- /dev/null +++ b/types/commonjs/canvas-shim.d.cts @@ -0,0 +1,9 @@ +declare class Canvas { + constructor(width: any, height: any); + width: any; + height: any; + getContext(): any; + toDataURL(): string; +} +export function createCanvas(width: any, height: any): Canvas; +export {}; diff --git a/types/esm/dom/parser.d.ts b/types/esm/dom/parser.d.ts index e5146792..e3572266 100644 --- a/types/esm/dom/parser.d.ts +++ b/types/esm/dom/parser.d.ts @@ -4,20 +4,25 @@ export class DOMParser implements globalThis.DOMParser { /** @typedef {{ "text/html": HTMLDocument, "image/svg+xml": SVGDocument, "text/xml": XMLDocument }} MimeToDoc */ /** + * @template {string|NodeJS.ReadableStream} INPUT * @template {keyof MimeToDoc} MIME - * @param {string} markupLanguage + * @param {INPUT} markupLanguage * @param {MIME} mimeType - * @returns {MimeToDoc[MIME]} + * @returns {INPUT extends string ? MimeToDoc[MIME] : Promise} */ - parseFromString(markupLanguage: string, mimeType: MIME, globals?: any): { + }>(markupLanguage: INPUT, mimeType: MIME, globals?: any): INPUT extends string ? { "text/html": HTMLDocument; "image/svg+xml": SVGDocument; "text/xml": XMLDocument; - }[MIME]; + }[MIME] : Promise<{ + "text/html": HTMLDocument; + "image/svg+xml": SVGDocument; + "text/xml": XMLDocument; + }[MIME]>; } import { HTMLDocument } from "../html/document.js"; import { SVGDocument } from "../svg/document.js"; diff --git a/types/esm/index.d.ts b/types/esm/index.d.ts index bf72536a..9c89d4a6 100644 --- a/types/esm/index.d.ts +++ b/types/esm/index.d.ts @@ -8,6 +8,6 @@ export { EventTarget } from "./interface/event-target.js"; export { InputEvent } from "./interface/input-event.js"; export { NodeList } from "./interface/node-list.js"; export { NodeFilter } from "./interface/node-filter.js"; -export function parseHTML(html: any, globals?: any): Window & typeof globalThis; +export function parseHTML(html: any, globals?: any): any; import { DOMParser } from "./dom/parser.js"; export { parseJSON, toJSON } from "./shared/parse-json.js"; diff --git a/types/esm/shared/node.d.ts b/types/esm/shared/node.d.ts index 9a2ce017..8c941567 100644 --- a/types/esm/shared/node.d.ts +++ b/types/esm/shared/node.d.ts @@ -6,7 +6,7 @@ export function parentElement({ parentNode }: { parentNode: any; }): any; export function previousSibling({ [PREV]: prev }: { - "__@PREV@38498": any; + "__@PREV@39422": any; }): any; export function nextSibling(node: any): any; import { PREV } from "./symbols.js"; diff --git a/types/esm/shared/parse-from-string.d.ts b/types/esm/shared/parse-from-string.d.ts index 1cda3495..afd90851 100644 --- a/types/esm/shared/parse-from-string.d.ts +++ b/types/esm/shared/parse-from-string.d.ts @@ -1,2 +1,5 @@ export function isNotParsing(): boolean; -export function parseFromString(document: any, isHTML: any, markupLanguage: any): any; +export function parseFromString(document: DOC, isHTML: boolean, markupLanguage: INPUT): INPUT extends string ? DOC : Promise; +export type HTMLDocument = import('../html/document.js').HTMLDocument; +export type SVGDocument = import('../svg/document.js').SVGDocument; +export type XMLDocument = import('../xml/document.js').XMLDocument; diff --git a/worker.js b/worker.js index d4c8a938..d2d2706a 100644 --- a/worker.js +++ b/worker.js @@ -1,3 +1,6 @@ +import { Writable } from 'stream'; +import { StringDecoder } from 'string_decoder'; + // used in Attr to signal changes const CHANGED = Symbol('changed'); @@ -1160,7 +1163,7 @@ const htmlIntegrationElements = new Set([ "title", ]); const reNameEnd = /\s|\//; -class Parser$1 { +class Parser { constructor(cbs, options = {}) { var _a, _b, _c, _d, _e; this.options = options; @@ -1551,3145 +1554,2683 @@ class Parser$1 { } } -/** Types of elements found in htmlparser2's DOM */ -var ElementType; -(function (ElementType) { - /** Type for the root element of a document */ - ElementType["Root"] = "root"; - /** Type for Text */ - ElementType["Text"] = "text"; - /** Type for */ - ElementType["Directive"] = "directive"; - /** Type for */ - ElementType["Comment"] = "comment"; - /** Type for + +fdsf + diff --git a/test/stream/test.js b/test/stream/test-domparser.js similarity index 73% rename from test/stream/test.js rename to test/stream/test-domparser.js index 24fe407f..997ba9cc 100644 --- a/test/stream/test.js +++ b/test/stream/test-domparser.js @@ -3,8 +3,9 @@ const {join} = require('path'); const {memoryUsage} = require('process'); const {DOMParser} = require('../../cjs/index.js'); + const parser = new DOMParser; -let length = 0 +let length = 0; const logStatus = (message = 'total heap memory') => { const used = memoryUsage().heapUsed / 1024 / 1024; @@ -13,23 +14,26 @@ const logStatus = (message = 'total heap memory') => { `\x1b[1m${message}:\x1b[0m ${Math.round(used * 100) / 100} MB`, `\x1b[1mtotal processed:\x1b[0m ${Math.round(processed * 100) / 100} MB` ); -}; +} -logStatus('initial heap') +logStatus('initial heap'); -const src = fs.createReadStream(join(__dirname, '../benchmark/html.html')); +// const src = fs.createReadStream(join(__dirname, '../benchmark/html.html')); +const src = fs.createReadStream(join(__dirname, './GB.xml')); src.on('data', chunk => { length += chunk.length; logStatus(); }); console.time(' parsing \x1b[2mcold\x1b[0m'); -parser.parseFromString(src, 'text/html').then(doc => { +parser.parseFromString(src, 'text/xml').then(doc => { console.timeEnd(' parsing \x1b[2mcold\x1b[0m'); console.log(); logStatus('document heap'); - console.log(doc); + console.log(doc.childElementCount) }).catch((o_O) => { console.error(o_O); console.warn(`⚠ \x1b[1merror\x1b[0m - unable to parse the document: ${o_O.message}`); }); + +setInterval(() => {}, 2000000) diff --git a/test/stream/test-domstream.js b/test/stream/test-domstream.js new file mode 100644 index 00000000..0b6b425d --- /dev/null +++ b/test/stream/test-domstream.js @@ -0,0 +1,42 @@ +const fs = require('fs'); +const {join} = require('path'); +const {memoryUsage} = require('process'); +const DOMStream = require('../../cjs/dom/stream.js'); + + +let length = 0; + +const logStatus = (message = 'total heap memory') => { + const used = memoryUsage().heapUsed / 1024 / 1024; + const processed = length / 1024 / 1024; + console.log( + `\x1b[1m${message}:\x1b[0m ${Math.round(used * 100) / 100} MB`, + `\x1b[1mtotal processed:\x1b[0m ${Math.round(processed * 100) / 100} MB` + ); +} + +logStatus('initial heap'); + +const domStream = new DOMStream('text/xml', (name) => { + return name === 'hotelName'; +}); + +const src = fs.createReadStream(join(__dirname, './GB.xml')); +src.on('data', chunk => { + length += chunk.length; + logStatus(); +}); + +console.time(' parsing \x1b[2mcold\x1b[0m'); +src.on('end', () => { + console.timeEnd(' parsing \x1b[2mcold\x1b[0m'); + console.log(); + logStatus('end heap'); +}) + +src.pipe(domStream).on('document', doc => { + console.log(doc.documentElement.outerHTML); + logStatus('doc heap'); +}); + +setInterval(() => {}, 2000000); diff --git a/worker.js b/worker.js index d2d2706a..1dfa76a3 100644 --- a/worker.js +++ b/worker.js @@ -1563,7 +1563,7 @@ function isBuffer(_chunk, encoding) { * * @see Parser */ -class WritableStream$1 extends Writable { +class WritableStream extends Writable { constructor(cbs, options) { super({ decodeStrings: false }); this._decoder = new StringDecoder(); @@ -1579,11 +1579,6 @@ class WritableStream$1 extends Writable { } } -var HTMLParser2 = /*#__PURE__*/Object.freeze({ - __proto__: null, - WritableStream: WritableStream$1 -}); - // Internal const NODE_END = -1; @@ -1854,8 +1849,6 @@ class CustomElementRegistry { } } -const {WritableStream} = HTMLParser2; - const append$2 = (self, node, active) => { const end = self[END]; node.parentNode = self; From 2e7018194299f82d10b8b5fa0bb337919b926263 Mon Sep 17 00:00:00 2001 From: "${Mr.DJA}" <42304709+iMrDJAi@users.noreply.github.com> Date: Sun, 23 Oct 2022 22:09:24 +0100 Subject: [PATCH 03/13] =?UTF-8?q?=F0=9F=A9=B9=20Replaced=20Transform=20str?= =?UTF-8?q?eam=20by=20Writable?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cjs/dom/stream.js | 8 ++++---- esm/dom/stream.js | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cjs/dom/stream.js b/cjs/dom/stream.js index 37605aef..b1e141c7 100644 --- a/cjs/dom/stream.js +++ b/cjs/dom/stream.js @@ -1,5 +1,5 @@ 'use strict'; -const { Transform } = require('stream'); +const { Writable } = require('stream'); const { WritableStream } = require('htmlparser2/lib/WritableStream'); const {ELEMENT_NODE, SVG_NAMESPACE} = require('../shared/constants'); @@ -36,9 +36,9 @@ const {XMLDocument} = require('../xml/document.js') * @property {MIME extends 'text/html' ? true : false} isHTML * @property {StackItem[]} stack * @property {string} doctype - * @extends {Transform} + * @extends {Writable} */ -class DOMStream extends Transform { +class DOMStream extends Writable { /** * @param {MIME} mimeType * @param {FILTER} filter @@ -148,7 +148,7 @@ class DOMStream extends Transform { * @param {string} encoding * @param {() => void} callback */ - _transform(chunk, encoding, callback) { + _write(chunk, encoding, callback) { this.content._write(chunk, encoding, callback) } diff --git a/esm/dom/stream.js b/esm/dom/stream.js index a1c5c06c..281673fc 100644 --- a/esm/dom/stream.js +++ b/esm/dom/stream.js @@ -1,4 +1,4 @@ -import { Transform } from 'stream'; +import { Writable } from 'stream'; import { WritableStream } from 'htmlparser2/lib/WritableStream'; import {ELEMENT_NODE, SVG_NAMESPACE} from '../shared/constants'; @@ -35,9 +35,9 @@ import {XMLDocument} from '../xml/document.js' * @property {MIME extends 'text/html' ? true : false} isHTML * @property {StackItem[]} stack * @property {string} doctype - * @extends {Transform} + * @extends {Writable} */ -class DOMStream extends Transform { +class DOMStream extends Writable { /** * @param {MIME} mimeType * @param {FILTER} filter @@ -147,7 +147,7 @@ class DOMStream extends Transform { * @param {string} encoding * @param {() => void} callback */ - _transform(chunk, encoding, callback) { + _write(chunk, encoding, callback) { this.content._write(chunk, encoding, callback) } From cd53ed1d1d12712977c39881507470198889cde8 Mon Sep 17 00:00:00 2001 From: "${Mr.DJA}" <42304709+iMrDJAi@users.noreply.github.com> Date: Mon, 24 Oct 2022 09:49:26 +0100 Subject: [PATCH 04/13] =?UTF-8?q?=F0=9F=8F=B7=EF=B8=8F=20Added=20types=20f?= =?UTF-8?q?or=20`document`=20event?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cjs/dom/stream.js | 20 ++++++++++++++++++++ esm/dom/stream.js | 20 ++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/cjs/dom/stream.js b/cjs/dom/stream.js index b1e141c7..146e777a 100644 --- a/cjs/dom/stream.js +++ b/cjs/dom/stream.js @@ -29,6 +29,8 @@ const {XMLDocument} = require('../xml/document.js') * ownerSVGElement: SVGElement|undefined * rootNode: Node * }} StackItem + * @template {Writable['on'] & (name: 'document', listener: (doc: MimeToDoc[MIME]) => void) => this} Listener + * @template {Writable['emit'] & (name: 'document', doc: MimeToDoc[MIME]) => boolean} Emitter * * @property {MIME} mimeType * @property {FILTER} filter @@ -52,6 +54,24 @@ class DOMStream extends Writable { this.stack = [] this.init = this.init.bind(this) this.init() + + // EVENTS + /** @type {Listener} */ + this.addListener = super.addListener; + /** @type {Emitter} */ + this.emit = super.emit; + /** @type {Listener} */ + this.on = super.on; + /** @type {Listener} */ + this.once = super.once; + /** @type {Listener} */ + this.prependListener = super.prependListener; + /** @type {Listener} */ + this.prependOnceListener = super.prependOnceListener; + /** @type {Listener} */ + this.removeListener = super.removeListener; + /** @type {Listener} */ + this.off = super.off; } newDocument () { diff --git a/esm/dom/stream.js b/esm/dom/stream.js index 281673fc..c8d0f8ac 100644 --- a/esm/dom/stream.js +++ b/esm/dom/stream.js @@ -28,6 +28,8 @@ import {XMLDocument} from '../xml/document.js' * ownerSVGElement: SVGElement|undefined * rootNode: Node * }} StackItem + * @template {Writable['on'] & (name: 'document', listener: (doc: MimeToDoc[MIME]) => void) => this} Listener + * @template {Writable['emit'] & (name: 'document', doc: MimeToDoc[MIME]) => boolean} Emitter * * @property {MIME} mimeType * @property {FILTER} filter @@ -51,6 +53,24 @@ class DOMStream extends Writable { this.stack = [] this.init = this.init.bind(this) this.init() + + // EVENTS + /** @type {Listener} */ + this.addListener = super.addListener; + /** @type {Emitter} */ + this.emit = super.emit; + /** @type {Listener} */ + this.on = super.on; + /** @type {Listener} */ + this.once = super.once; + /** @type {Listener} */ + this.prependListener = super.prependListener; + /** @type {Listener} */ + this.prependOnceListener = super.prependOnceListener; + /** @type {Listener} */ + this.removeListener = super.removeListener; + /** @type {Listener} */ + this.off = super.off; } newDocument () { From d7eaf9ad899941958124fe37723da03aab01e258 Mon Sep 17 00:00:00 2001 From: "${Mr.DJA}" <42304709+iMrDJAi@users.noreply.github.com> Date: Mon, 24 Oct 2022 09:55:32 +0100 Subject: [PATCH 05/13] =?UTF-8?q?=F0=9F=93=84=20Upadated=20README=20:3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e1b3eac7..467aeef9 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ **Social Media Photo by [JJ Ying](https://unsplash.com/@jjying) on [Unsplash](https://unsplash.com/)** -### This is not a crawler! +### This is ~~not a~~ better than a crawler! :3 LinkeDOM is a [triple-linked list](#data-structure) based DOM-like namespace, for DOM-less environments, with the following goals: From c75925d3cb1c700304ce832b9de837f3bc73c9de Mon Sep 17 00:00:00 2001 From: "${Mr.DJA}" <42304709+iMrDJAi@users.noreply.github.com> Date: Mon, 24 Oct 2022 10:12:40 +0100 Subject: [PATCH 06/13] =?UTF-8?q?=F0=9F=9A=9A=20Provide=20correct=20export?= =?UTF-8?q?=20for=20DOMStream?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cjs/dom/stream.js | 43 ++++---- cjs/index.js | 2 + esm/dom/stream.js | 44 ++++---- esm/index.js | 2 + test/stream/test-domstream.js | 2 +- types/esm/dom/stream.d.ts | 78 ++++++++++++++ types/esm/index.d.ts | 3 +- worker.js | 188 +++++++++++++++++++++++++++++++++- 8 files changed, 314 insertions(+), 48 deletions(-) create mode 100644 types/esm/dom/stream.d.ts diff --git a/cjs/dom/stream.js b/cjs/dom/stream.js index 146e777a..bc9d10ca 100644 --- a/cjs/dom/stream.js +++ b/cjs/dom/stream.js @@ -9,9 +9,9 @@ const {keys} = require('../shared/object'); const {knownBoundaries, knownSiblings} = require('../shared/utils'); const {attributeChangedCallback, connectedCallback} = require('../interface/custom-element-registry.js'); -const {HTMLDocument} = require('../html/document.js') -const {SVGDocument} = require('../svg/document.js') -const {XMLDocument} = require('../xml/document.js') +const {HTMLDocument} = require('../html/document.js'); +const {SVGDocument} = require('../svg/document.js'); +const {XMLDocument} = require('../xml/document.js'); /** * @typedef {import('../interface/node').Node} Node @@ -46,14 +46,14 @@ class DOMStream extends Writable { * @param {FILTER} filter */ constructor (mimeType, filter) { - super() - this.mimeType = mimeType - if (mimeType === 'text/html') this.isHTML = true - this.filter = filter + super(); + this.mimeType = mimeType; + if (mimeType === 'text/html') this.isHTML = true; + this.filter = filter; /** @type {StackItem[]} */ - this.stack = [] - this.init = this.init.bind(this) - this.init() + this.stack = []; + this.init = this.init.bind(this); + this.init(); // EVENTS /** @type {Listener} */ @@ -75,16 +75,16 @@ class DOMStream extends Writable { } newDocument () { - let document + let document; if (this.mimeType === 'text/html') { - document = new HTMLDocument() + document = new HTMLDocument(); } else if (this.mimeType === 'image/svg+xml') { - document = new SVGDocument() + document = new SVGDocument(); } else { - document = new XMLDocument() + document = new XMLDocument(); } - if (this.doctype) document.doctype = this.doctype - this.stack.push({ document, node: document }) + if (this.doctype) document.doctype = this.doctype; + this.stack.push({ document, node: document }); } init () { @@ -99,7 +99,7 @@ class DOMStream extends Writable { onopentag: (name, attributes) => { if (this.filter(name, attributes)) this.newDocument() for (const item of this.stack) { - const { document } = item + const { document } = item; const { active, registry } = document[CUSTOM_ELEMENTS]; let create = true; if (this.isHTML) { @@ -126,7 +126,7 @@ class DOMStream extends Writable { for (const name of keys(attributes)) { this.attribute(item.node, end, document.createAttribute(name), attributes[name], active); } - if (!item.rootNode) item.rootNode = item.node + if (!item.rootNode) item.rootNode = item.node; } }, // #text, #comment @@ -169,14 +169,14 @@ class DOMStream extends Writable { * @param {() => void} callback */ _write(chunk, encoding, callback) { - this.content._write(chunk, encoding, callback) + this.content._write(chunk, encoding, callback); } /** * @param {() => void} callback */ _final(callback) { - this.content._final(callback) + this.content._final(callback); } append (self, node, active) { @@ -198,5 +198,4 @@ class DOMStream extends Writable { attributeChangedCallback(element, attribute.name, null, value); } } - -module.exports = DOMStream +exports.DOMStream = DOMStream diff --git a/cjs/index.js b/cjs/index.js index 3960b91a..37e6e31a 100644 --- a/cjs/index.js +++ b/cjs/index.js @@ -1,5 +1,6 @@ 'use strict'; const {DOMParser} = require('./dom/parser.js'); +const {DOMStream} = require('./dom/stream.js'); const {Document: _Document} = require('./interface/document.js'); const {illegalConstructor} = require('./shared/facades.js'); @@ -15,6 +16,7 @@ const {setPrototypeOf} = require('./shared/object.js'); (require('./shared/html-classes.js')); exports.DOMParser = DOMParser; +exports.DOMStream = DOMStream; (m => { exports.CustomEvent = m.CustomEvent; diff --git a/esm/dom/stream.js b/esm/dom/stream.js index c8d0f8ac..a278c520 100644 --- a/esm/dom/stream.js +++ b/esm/dom/stream.js @@ -8,9 +8,9 @@ import {keys} from '../shared/object'; import {knownBoundaries, knownSiblings} from '../shared/utils'; import {attributeChangedCallback, connectedCallback} from '../interface/custom-element-registry.js'; -import {HTMLDocument} from '../html/document.js' -import {SVGDocument} from '../svg/document.js' -import {XMLDocument} from '../xml/document.js' +import {HTMLDocument} from '../html/document.js'; +import {SVGDocument} from '../svg/document.js'; +import {XMLDocument} from '../xml/document.js'; /** * @typedef {import('../interface/node').Node} Node @@ -39,20 +39,20 @@ import {XMLDocument} from '../xml/document.js' * @property {string} doctype * @extends {Writable} */ -class DOMStream extends Writable { +export class DOMStream extends Writable { /** * @param {MIME} mimeType * @param {FILTER} filter */ constructor (mimeType, filter) { - super() - this.mimeType = mimeType - if (mimeType === 'text/html') this.isHTML = true - this.filter = filter + super(); + this.mimeType = mimeType; + if (mimeType === 'text/html') this.isHTML = true; + this.filter = filter; /** @type {StackItem[]} */ - this.stack = [] - this.init = this.init.bind(this) - this.init() + this.stack = []; + this.init = this.init.bind(this); + this.init(); // EVENTS /** @type {Listener} */ @@ -74,16 +74,16 @@ class DOMStream extends Writable { } newDocument () { - let document + let document; if (this.mimeType === 'text/html') { - document = new HTMLDocument() + document = new HTMLDocument(); } else if (this.mimeType === 'image/svg+xml') { - document = new SVGDocument() + document = new SVGDocument(); } else { - document = new XMLDocument() + document = new XMLDocument(); } - if (this.doctype) document.doctype = this.doctype - this.stack.push({ document, node: document }) + if (this.doctype) document.doctype = this.doctype; + this.stack.push({ document, node: document }); } init () { @@ -98,7 +98,7 @@ class DOMStream extends Writable { onopentag: (name, attributes) => { if (this.filter(name, attributes)) this.newDocument() for (const item of this.stack) { - const { document } = item + const { document } = item; const { active, registry } = document[CUSTOM_ELEMENTS]; let create = true; if (this.isHTML) { @@ -125,7 +125,7 @@ class DOMStream extends Writable { for (const name of keys(attributes)) { this.attribute(item.node, end, document.createAttribute(name), attributes[name], active); } - if (!item.rootNode) item.rootNode = item.node + if (!item.rootNode) item.rootNode = item.node; } }, // #text, #comment @@ -168,14 +168,14 @@ class DOMStream extends Writable { * @param {() => void} callback */ _write(chunk, encoding, callback) { - this.content._write(chunk, encoding, callback) + this.content._write(chunk, encoding, callback); } /** * @param {() => void} callback */ _final(callback) { - this.content._final(callback) + this.content._final(callback); } append (self, node, active) { @@ -197,5 +197,3 @@ class DOMStream extends Writable { attributeChangedCallback(element, attribute.name, null, value); } } - -export default DOMStream diff --git a/esm/index.js b/esm/index.js index 9a34dc75..d420b45d 100644 --- a/esm/index.js +++ b/esm/index.js @@ -1,4 +1,5 @@ import {DOMParser} from './dom/parser.js'; +import {DOMStream} from './dom/stream.js'; import {Document as _Document} from './interface/document.js'; import {illegalConstructor} from './shared/facades.js'; @@ -9,6 +10,7 @@ export * from './shared/facades.js'; export * from './shared/html-classes.js'; export {DOMParser}; +export {DOMStream}; export {CustomEvent} from './interface/custom-event.js'; export {Event} from './interface/event.js'; diff --git a/test/stream/test-domstream.js b/test/stream/test-domstream.js index 0b6b425d..bcb61db8 100644 --- a/test/stream/test-domstream.js +++ b/test/stream/test-domstream.js @@ -1,7 +1,7 @@ const fs = require('fs'); const {join} = require('path'); const {memoryUsage} = require('process'); -const DOMStream = require('../../cjs/dom/stream.js'); +const {DOMStream} = require('../../cjs/index.js'); let length = 0; diff --git a/types/esm/dom/stream.d.ts b/types/esm/dom/stream.d.ts new file mode 100644 index 00000000..4331265f --- /dev/null +++ b/types/esm/dom/stream.d.ts @@ -0,0 +1,78 @@ +/// +/** + * @typedef {import('../interface/node').Node} Node + * @typedef {import('../svg/element').SVGElement} SVGElement + * @typedef {{ "text/html": HTMLDocument, "image/svg+xml": SVGDocument, "text/xml": XMLDocument }} MimeToDoc + * @typedef {(name: string, attributes: Record) => boolean} Filter + */ +/** + * @template {keyof MimeToDoc} MIME + * @template {Filter} FILTER + * @template {{ + * document: MimeToDoc[MIME] + * node: MimeToDoc[MIME]|Node + * ownerSVGElement: SVGElement|undefined + * rootNode: Node + * }} StackItem + * @template {Writable['on'] & (name: 'document', listener: (doc: MimeToDoc[MIME]) => void) => this} Listener + * @template {Writable['emit'] & (name: 'document', doc: MimeToDoc[MIME]) => boolean} Emitter + * + * @property {MIME} mimeType + * @property {FILTER} filter + * + * @property {MIME extends 'text/html' ? true : false} isHTML + * @property {StackItem[]} stack + * @property {string} doctype + * @extends {Writable} + */ +export class DOMStream void): Writable; + (event: "drain", listener: () => void): Writable; + (event: "error", listener: (err: Error) => void): Writable; + (event: "finish", listener: () => void): Writable; + (event: "pipe", listener: (src: import("stream").Readable) => void): Writable; + (event: "unpipe", listener: (src: import("stream").Readable) => void): Writable; + (event: string | symbol, listener: (...args: any[]) => void): Writable; +} & ((name: 'document', listener: (doc: MimeToDoc[MIME]) => void) => any), Emitter extends { + (event: "close"): boolean; + (event: "drain"): boolean; + (event: "error", err: Error): boolean; + (event: "finish"): boolean; + (event: "pipe", src: import("stream").Readable): boolean; + (event: "unpipe", src: import("stream").Readable): boolean; + (event: string | symbol, ...args: any[]): boolean; +} & ((name: 'document', doc: MimeToDoc[MIME]) => boolean)> extends Writable { + /** + * @param {MIME} mimeType + * @param {FILTER} filter + */ + constructor(mimeType: MIME, filter: FILTER); + mimeType: MIME; + isHTML: boolean; + filter: FILTER; + /** @type {StackItem[]} */ + stack: StackItem[]; + init(): void; + newDocument(): void; + content: any; + doctype: any; + append(self: any, node: any, active: any): any; + attribute(element: any, end: any, attribute: any, value: any, active: any): void; +} +export type Node = import('../interface/node').Node; +export type SVGElement = import('../svg/element').SVGElement; +export type MimeToDoc = { + "text/html": HTMLDocument; + "image/svg+xml": SVGDocument; + "text/xml": XMLDocument; +}; +export type Filter = (name: string, attributes: Record) => boolean; +import { Writable } from "stream"; +import { HTMLDocument } from "../html/document.js"; +import { SVGDocument } from "../svg/document.js"; +import { XMLDocument } from "../xml/document.js"; diff --git a/types/esm/index.d.ts b/types/esm/index.d.ts index 9c89d4a6..27ad2e8d 100644 --- a/types/esm/index.d.ts +++ b/types/esm/index.d.ts @@ -1,7 +1,6 @@ export function Document(): void; export * from "./shared/facades.js"; export * from "./shared/html-classes.js"; -export { DOMParser }; export { CustomEvent } from "./interface/custom-event.js"; export { Event } from "./interface/event.js"; export { EventTarget } from "./interface/event-target.js"; @@ -10,4 +9,6 @@ export { NodeList } from "./interface/node-list.js"; export { NodeFilter } from "./interface/node-filter.js"; export function parseHTML(html: any, globals?: any): any; import { DOMParser } from "./dom/parser.js"; +import { DOMStream } from "./dom/stream.js"; +export { DOMParser, DOMStream }; export { parseJSON, toJSON } from "./shared/parse-json.js"; diff --git a/worker.js b/worker.js index 1dfa76a3..98834c0b 100644 --- a/worker.js +++ b/worker.js @@ -11397,6 +11397,192 @@ class DOMParser { } } +/** + * @typedef {import('../interface/node').Node} Node + * @typedef {import('../svg/element').SVGElement} SVGElement + * @typedef {{ "text/html": HTMLDocument, "image/svg+xml": SVGDocument, "text/xml": XMLDocument }} MimeToDoc + * @typedef {(name: string, attributes: Record) => boolean} Filter + */ + +/** + * @template {keyof MimeToDoc} MIME + * @template {Filter} FILTER + * @template {{ + * document: MimeToDoc[MIME] + * node: MimeToDoc[MIME]|Node + * ownerSVGElement: SVGElement|undefined + * rootNode: Node + * }} StackItem + * @template {Writable['on'] & (name: 'document', listener: (doc: MimeToDoc[MIME]) => void) => this} Listener + * @template {Writable['emit'] & (name: 'document', doc: MimeToDoc[MIME]) => boolean} Emitter + * + * @property {MIME} mimeType + * @property {FILTER} filter + * + * @property {MIME extends 'text/html' ? true : false} isHTML + * @property {StackItem[]} stack + * @property {string} doctype + * @extends {Writable} + */ +class DOMStream extends Writable { + /** + * @param {MIME} mimeType + * @param {FILTER} filter + */ + constructor (mimeType, filter) { + super(); + this.mimeType = mimeType; + if (mimeType === 'text/html') this.isHTML = true; + this.filter = filter; + /** @type {StackItem[]} */ + this.stack = []; + this.init = this.init.bind(this); + this.init(); + + // EVENTS + /** @type {Listener} */ + this.addListener = super.addListener; + /** @type {Emitter} */ + this.emit = super.emit; + /** @type {Listener} */ + this.on = super.on; + /** @type {Listener} */ + this.once = super.once; + /** @type {Listener} */ + this.prependListener = super.prependListener; + /** @type {Listener} */ + this.prependOnceListener = super.prependOnceListener; + /** @type {Listener} */ + this.removeListener = super.removeListener; + /** @type {Listener} */ + this.off = super.off; + } + + newDocument () { + let document; + if (this.mimeType === 'text/html') { + document = new HTMLDocument(); + } else if (this.mimeType === 'image/svg+xml') { + document = new SVGDocument(); + } else { + document = new XMLDocument(); + } + if (this.doctype) document.doctype = this.doctype; + this.stack.push({ document, node: document }); + } + + init () { + this.content = new WritableStream({ + // + onprocessinginstruction: (name, data) => { + if (name.toLowerCase() === '!doctype') { + this.doctype = data.slice(name.length).trim(); + } + }, + // + onopentag: (name, attributes) => { + if (this.filter(name, attributes)) this.newDocument(); + for (const item of this.stack) { + const { document } = item; + const { active, registry } = document[CUSTOM_ELEMENTS]; + let create = true; + if (this.isHTML) { + if (item.ownerSVGElement) { + item.node = this.append(item.node, document.createElementNS(SVG_NAMESPACE, name), active); + item.node.ownerSVGElement = item.ownerSVGElement; + create = false; + } else if (name === 'svg' || name === 'SVG') { + item.ownerSVGElement = document.createElementNS(SVG_NAMESPACE, name); + item.node = this.append(item.node, item.ownerSVGElement, active); + create = false; + } else if (active) { + const ce = name.includes('-') ? name : (attributes.is || ''); + if (ce && registry.has(ce)) { + const {Class} = registry.get(ce); + item.node = this.append(item.node, new Class, active); + delete attributes.is; + create = false; + } + } + } + if (create) item.node = this.append(item.node, document.createElement(name), false); + let end = item.node[END]; + for (const name of keys(attributes)) { + this.attribute(item.node, end, document.createAttribute(name), attributes[name], active); + } + if (!item.rootNode) item.rootNode = item.node; + } + }, + // #text, #comment + oncomment: (data) => { + for (const { document, node } of this.stack) { + const { active } = document[CUSTOM_ELEMENTS]; + this.append(node, document.createComment(data), active); + } + }, + ontext: (text) => { + for (const { document, node } of this.stack) { + const { active } = document[CUSTOM_ELEMENTS]; + this.append(node, document.createTextNode(text), active); + } + }, + // + onclosetag: () => { + for (const item of this.stack) { + const { document } = item; + if (this.isHTML && item.node === item.ownerSVGElement) { + item.ownerSVGElement = undefined; + } + if (item.node === item.rootNode) { + this.emit('document', document); + this.stack.length -= 1; + } + item.node = item.node.parentNode; + } + } + }, { + lowerCaseAttributeNames: false, + decodeEntities: true, + xmlMode: !this.isHTML + }); + } + + /** + * @param {string|Buffer} chunk + * @param {string} encoding + * @param {() => void} callback + */ + _write(chunk, encoding, callback) { + this.content._write(chunk, encoding, callback); + } + + /** + * @param {() => void} callback + */ + _final(callback) { + this.content._final(callback); + } + + append (self, node, active) { + const end = self[END]; + node.parentNode = self; + knownBoundaries(end[PREV], node, end); + if (active && node.nodeType === ELEMENT_NODE) + connectedCallback(node); + return node; + } + + attribute (element, end, attribute, value, active) { + attribute[VALUE] = value; + attribute.ownerElement = element; + knownSiblings(end[PREV], attribute, end); + if (attribute.name === 'class') + element.className = value; + if (active) + attributeChangedCallback$1(element, attribute.name, null, value); + } +} + const {parse} = JSON; const append = (parentNode, node, end) => { @@ -11516,4 +11702,4 @@ function Document() { setPrototypeOf(Document, Document$1).prototype = Document$1.prototype; -export { Attr, CharacterData, Comment, GlobalCustomEvent as CustomEvent, DOMParser, Document, DocumentFragment, DocumentType, Element, GlobalEvent as Event, DOMEventTarget as EventTarget, Facades, HTMLAnchorElement, HTMLAreaElement, HTMLAudioElement, HTMLBRElement, HTMLBaseElement, HTMLBodyElement, HTMLButtonElement, HTMLCanvasElement, HTMLClasses, HTMLDListElement, HTMLDataElement, HTMLDataListElement, HTMLDetailsElement, HTMLDirectoryElement, HTMLDivElement, HTMLElement, HTMLEmbedElement, HTMLFieldSetElement, HTMLFontElement, HTMLFormElement, HTMLFrameElement, HTMLFrameSetElement, HTMLHRElement, HTMLHeadElement, HTMLHeadingElement, HTMLHtmlElement, HTMLIFrameElement, HTMLImageElement, HTMLInputElement, HTMLLIElement, HTMLLabelElement, HTMLLegendElement, HTMLLinkElement, HTMLMapElement, HTMLMarqueeElement, HTMLMediaElement, HTMLMenuElement, HTMLMetaElement, HTMLMeterElement, HTMLModElement, HTMLOListElement, HTMLObjectElement, HTMLOptGroupElement, HTMLOptionElement, HTMLOutputElement, HTMLParagraphElement, HTMLParamElement, HTMLPictureElement, HTMLPreElement, HTMLProgressElement, HTMLQuoteElement, HTMLScriptElement, HTMLSelectElement, HTMLSlotElement, HTMLSourceElement, HTMLSpanElement, HTMLStyleElement, HTMLTableCaptionElement, HTMLTableCellElement, HTMLTableElement, HTMLTableRowElement, HTMLTemplateElement, HTMLTextAreaElement, HTMLTimeElement, HTMLTitleElement, HTMLTrackElement, HTMLUListElement, HTMLUnknownElement, HTMLVideoElement, InputEvent, Node, NodeFilter, NodeList, SVGElement, ShadowRoot, Text, illegalConstructor, parseHTML, parseJSON, toJSON }; +export { Attr, CharacterData, Comment, GlobalCustomEvent as CustomEvent, DOMParser, DOMStream, Document, DocumentFragment, DocumentType, Element, GlobalEvent as Event, DOMEventTarget as EventTarget, Facades, HTMLAnchorElement, HTMLAreaElement, HTMLAudioElement, HTMLBRElement, HTMLBaseElement, HTMLBodyElement, HTMLButtonElement, HTMLCanvasElement, HTMLClasses, HTMLDListElement, HTMLDataElement, HTMLDataListElement, HTMLDetailsElement, HTMLDirectoryElement, HTMLDivElement, HTMLElement, HTMLEmbedElement, HTMLFieldSetElement, HTMLFontElement, HTMLFormElement, HTMLFrameElement, HTMLFrameSetElement, HTMLHRElement, HTMLHeadElement, HTMLHeadingElement, HTMLHtmlElement, HTMLIFrameElement, HTMLImageElement, HTMLInputElement, HTMLLIElement, HTMLLabelElement, HTMLLegendElement, HTMLLinkElement, HTMLMapElement, HTMLMarqueeElement, HTMLMediaElement, HTMLMenuElement, HTMLMetaElement, HTMLMeterElement, HTMLModElement, HTMLOListElement, HTMLObjectElement, HTMLOptGroupElement, HTMLOptionElement, HTMLOutputElement, HTMLParagraphElement, HTMLParamElement, HTMLPictureElement, HTMLPreElement, HTMLProgressElement, HTMLQuoteElement, HTMLScriptElement, HTMLSelectElement, HTMLSlotElement, HTMLSourceElement, HTMLSpanElement, HTMLStyleElement, HTMLTableCaptionElement, HTMLTableCellElement, HTMLTableElement, HTMLTableRowElement, HTMLTemplateElement, HTMLTextAreaElement, HTMLTimeElement, HTMLTitleElement, HTMLTrackElement, HTMLUListElement, HTMLUnknownElement, HTMLVideoElement, InputEvent, Node, NodeFilter, NodeList, SVGElement, ShadowRoot, Text, illegalConstructor, parseHTML, parseJSON, toJSON }; From 8e6208f9e2212733ab397b3d03dd42769dee4714 Mon Sep 17 00:00:00 2001 From: "${Mr.DJA}" <42304709+iMrDJAi@users.noreply.github.com> Date: Mon, 24 Oct 2022 10:20:56 +0100 Subject: [PATCH 07/13] =?UTF-8?q?=F0=9F=8F=B7=EF=B8=8F=20Fixed=20stream.d.?= =?UTF-8?q?ts=20(maybe=3F)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cjs/dom/stream.js | 10 ++++++++++ esm/dom/stream.js | 10 ++++++++++ types/esm/dom/stream.d.ts | 10 ++++++++++ worker.js | 10 ++++++++++ 4 files changed, 40 insertions(+) diff --git a/cjs/dom/stream.js b/cjs/dom/stream.js index bc9d10ca..6f32e244 100644 --- a/cjs/dom/stream.js +++ b/cjs/dom/stream.js @@ -38,6 +38,16 @@ const {XMLDocument} = require('../xml/document.js'); * @property {MIME extends 'text/html' ? true : false} isHTML * @property {StackItem[]} stack * @property {string} doctype + * + * @property {Listener} addListener + * @property {Emitter} emit + * @property {Listener} on + * @property {Listener} once + * @property {Listener} prependListener + * @property {Listener} prependOnceListener + * @property {Listener} removeListener + * @property {Listener} off + * @extends {Writable} */ class DOMStream extends Writable { diff --git a/esm/dom/stream.js b/esm/dom/stream.js index a278c520..81cc499b 100644 --- a/esm/dom/stream.js +++ b/esm/dom/stream.js @@ -37,6 +37,16 @@ import {XMLDocument} from '../xml/document.js'; * @property {MIME extends 'text/html' ? true : false} isHTML * @property {StackItem[]} stack * @property {string} doctype + * + * @property {Listener} addListener + * @property {Emitter} emit + * @property {Listener} on + * @property {Listener} once + * @property {Listener} prependListener + * @property {Listener} prependOnceListener + * @property {Listener} removeListener + * @property {Listener} off + * @extends {Writable} */ export class DOMStream extends Writable { diff --git a/types/esm/dom/stream.d.ts b/types/esm/dom/stream.d.ts index 4331265f..6eda3172 100644 --- a/types/esm/dom/stream.d.ts +++ b/types/esm/dom/stream.d.ts @@ -23,6 +23,16 @@ * @property {MIME extends 'text/html' ? true : false} isHTML * @property {StackItem[]} stack * @property {string} doctype + * + * @property {Listener} addListener + * @property {Emitter} emit + * @property {Listener} on + * @property {Listener} once + * @property {Listener} prependListener + * @property {Listener} prependOnceListener + * @property {Listener} removeListener + * @property {Listener} off + * @extends {Writable} */ export class DOMStream Date: Mon, 24 Oct 2022 16:19:04 +0100 Subject: [PATCH 08/13] =?UTF-8?q?=E2=9D=8C=20Removed=20`@property`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cjs/dom/stream.js | 16 ---------------- esm/dom/stream.js | 16 ---------------- test/stream/index.html | 19 ------------------- test/stream/test-domparser.js | 3 +-- test/stream/test-domstream.js | 2 +- types/esm/dom/stream.d.ts | 16 ---------------- worker.js | 16 ---------------- 7 files changed, 2 insertions(+), 86 deletions(-) delete mode 100644 test/stream/index.html diff --git a/cjs/dom/stream.js b/cjs/dom/stream.js index 6f32e244..f7408d63 100644 --- a/cjs/dom/stream.js +++ b/cjs/dom/stream.js @@ -32,22 +32,6 @@ const {XMLDocument} = require('../xml/document.js'); * @template {Writable['on'] & (name: 'document', listener: (doc: MimeToDoc[MIME]) => void) => this} Listener * @template {Writable['emit'] & (name: 'document', doc: MimeToDoc[MIME]) => boolean} Emitter * - * @property {MIME} mimeType - * @property {FILTER} filter - * - * @property {MIME extends 'text/html' ? true : false} isHTML - * @property {StackItem[]} stack - * @property {string} doctype - * - * @property {Listener} addListener - * @property {Emitter} emit - * @property {Listener} on - * @property {Listener} once - * @property {Listener} prependListener - * @property {Listener} prependOnceListener - * @property {Listener} removeListener - * @property {Listener} off - * @extends {Writable} */ class DOMStream extends Writable { diff --git a/esm/dom/stream.js b/esm/dom/stream.js index 81cc499b..67a58643 100644 --- a/esm/dom/stream.js +++ b/esm/dom/stream.js @@ -31,22 +31,6 @@ import {XMLDocument} from '../xml/document.js'; * @template {Writable['on'] & (name: 'document', listener: (doc: MimeToDoc[MIME]) => void) => this} Listener * @template {Writable['emit'] & (name: 'document', doc: MimeToDoc[MIME]) => boolean} Emitter * - * @property {MIME} mimeType - * @property {FILTER} filter - * - * @property {MIME extends 'text/html' ? true : false} isHTML - * @property {StackItem[]} stack - * @property {string} doctype - * - * @property {Listener} addListener - * @property {Emitter} emit - * @property {Listener} on - * @property {Listener} once - * @property {Listener} prependListener - * @property {Listener} prependOnceListener - * @property {Listener} removeListener - * @property {Listener} off - * @extends {Writable} */ export class DOMStream extends Writable { diff --git a/test/stream/index.html b/test/stream/index.html deleted file mode 100644 index 3cefb589..00000000 --- a/test/stream/index.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - linkedom - - -fdsf - diff --git a/test/stream/test-domparser.js b/test/stream/test-domparser.js index 997ba9cc..5bf4bea2 100644 --- a/test/stream/test-domparser.js +++ b/test/stream/test-domparser.js @@ -18,8 +18,7 @@ const logStatus = (message = 'total heap memory') => { logStatus('initial heap'); -// const src = fs.createReadStream(join(__dirname, '../benchmark/html.html')); -const src = fs.createReadStream(join(__dirname, './GB.xml')); +const src = fs.createReadStream(join(__dirname, './big.xml')); src.on('data', chunk => { length += chunk.length; logStatus(); diff --git a/test/stream/test-domstream.js b/test/stream/test-domstream.js index bcb61db8..ac817182 100644 --- a/test/stream/test-domstream.js +++ b/test/stream/test-domstream.js @@ -21,7 +21,7 @@ const domStream = new DOMStream('text/xml', (name) => { return name === 'hotelName'; }); -const src = fs.createReadStream(join(__dirname, './GB.xml')); +const src = fs.createReadStream(join(__dirname, './big.xml')); src.on('data', chunk => { length += chunk.length; logStatus(); diff --git a/types/esm/dom/stream.d.ts b/types/esm/dom/stream.d.ts index 6eda3172..fd9a5f24 100644 --- a/types/esm/dom/stream.d.ts +++ b/types/esm/dom/stream.d.ts @@ -17,22 +17,6 @@ * @template {Writable['on'] & (name: 'document', listener: (doc: MimeToDoc[MIME]) => void) => this} Listener * @template {Writable['emit'] & (name: 'document', doc: MimeToDoc[MIME]) => boolean} Emitter * - * @property {MIME} mimeType - * @property {FILTER} filter - * - * @property {MIME extends 'text/html' ? true : false} isHTML - * @property {StackItem[]} stack - * @property {string} doctype - * - * @property {Listener} addListener - * @property {Emitter} emit - * @property {Listener} on - * @property {Listener} once - * @property {Listener} prependListener - * @property {Listener} prependOnceListener - * @property {Listener} removeListener - * @property {Listener} off - * @extends {Writable} */ export class DOMStream void) => this} Listener * @template {Writable['emit'] & (name: 'document', doc: MimeToDoc[MIME]) => boolean} Emitter * - * @property {MIME} mimeType - * @property {FILTER} filter - * - * @property {MIME extends 'text/html' ? true : false} isHTML - * @property {StackItem[]} stack - * @property {string} doctype - * - * @property {Listener} addListener - * @property {Emitter} emit - * @property {Listener} on - * @property {Listener} once - * @property {Listener} prependListener - * @property {Listener} prependOnceListener - * @property {Listener} removeListener - * @property {Listener} off - * @extends {Writable} */ class DOMStream extends Writable { From 64aeae7d0a7196d40d20d8ca9bc697a3dfb4838a Mon Sep 17 00:00:00 2001 From: "${Mr.DJA}" <42304709+iMrDJAi@users.noreply.github.com> Date: Tue, 25 Oct 2022 10:57:37 +0100 Subject: [PATCH 09/13] =?UTF-8?q?=F0=9F=8F=B7=EF=B8=8F=20Types=20improveme?= =?UTF-8?q?nts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cjs/dom/stream.js | 59 +++++++++++---------------- esm/dom/stream.js | 59 +++++++++++---------------- test/stream/test-domparser.js | 5 +-- test/stream/test-domstream.js | 4 +- tsconfig.json | 2 +- types/esm/dom/stream.d.ts | 68 ++++++++++++-------------------- types/esm/interface/element.d.ts | 2 +- types/esm/interface/image.d.ts | 2 +- types/esm/shared/matches.d.ts | 4 +- types/esm/shared/node.d.ts | 2 +- worker.js | 55 ++++++++++---------------- 11 files changed, 102 insertions(+), 160 deletions(-) diff --git a/cjs/dom/stream.js b/cjs/dom/stream.js index f7408d63..678e17df 100644 --- a/cjs/dom/stream.js +++ b/cjs/dom/stream.js @@ -1,6 +1,6 @@ 'use strict'; -const { Writable } = require('stream'); -const { WritableStream } = require('htmlparser2/lib/WritableStream'); +const {Writable} = require('stream'); +const {WritableStream} = require('htmlparser2/lib/WritableStream'); const {ELEMENT_NODE, SVG_NAMESPACE} = require('../shared/constants'); const {CUSTOM_ELEMENTS, PREV, END, VALUE} = require('../shared/symbols'); @@ -17,55 +17,33 @@ const {XMLDocument} = require('../xml/document.js'); * @typedef {import('../interface/node').Node} Node * @typedef {import('../svg/element').SVGElement} SVGElement * @typedef {{ "text/html": HTMLDocument, "image/svg+xml": SVGDocument, "text/xml": XMLDocument }} MimeToDoc - * @typedef {(name: string, attributes: Record) => boolean} Filter */ /** * @template {keyof MimeToDoc} MIME - * @template {Filter} FILTER - * @template {{ - * document: MimeToDoc[MIME] - * node: MimeToDoc[MIME]|Node - * ownerSVGElement: SVGElement|undefined - * rootNode: Node - * }} StackItem - * @template {Writable['on'] & (name: 'document', listener: (doc: MimeToDoc[MIME]) => void) => this} Listener - * @template {Writable['emit'] & (name: 'document', doc: MimeToDoc[MIME]) => boolean} Emitter - * * @extends {Writable} */ class DOMStream extends Writable { /** * @param {MIME} mimeType - * @param {FILTER} filter + * @param {(name: string, attributes: Record) => boolean} filter */ constructor (mimeType, filter) { super(); this.mimeType = mimeType; if (mimeType === 'text/html') this.isHTML = true; this.filter = filter; - /** @type {StackItem[]} */ + /** + * @type {{ + * document: MimeToDoc[MIME] + * node: MimeToDoc[MIME]|Node + * ownerSVGElement: SVGElement|undefined + * rootNode: Node + * }[]} + */ this.stack = []; this.init = this.init.bind(this); this.init(); - - // EVENTS - /** @type {Listener} */ - this.addListener = super.addListener; - /** @type {Emitter} */ - this.emit = super.emit; - /** @type {Listener} */ - this.on = super.on; - /** @type {Listener} */ - this.once = super.once; - /** @type {Listener} */ - this.prependListener = super.prependListener; - /** @type {Listener} */ - this.prependOnceListener = super.prependOnceListener; - /** @type {Listener} */ - this.removeListener = super.removeListener; - /** @type {Listener} */ - this.off = super.off; } newDocument () { @@ -82,7 +60,7 @@ class DOMStream extends Writable { } init () { - this.content = new WritableStream({ + this.parserStream = new WritableStream({ // onprocessinginstruction: (name, data) => { if (name.toLowerCase() === '!doctype') { @@ -163,14 +141,23 @@ class DOMStream extends Writable { * @param {() => void} callback */ _write(chunk, encoding, callback) { - this.content._write(chunk, encoding, callback); + this.parserStream._write(chunk, encoding, callback); } /** * @param {() => void} callback */ _final(callback) { - this.content._final(callback); + this.parserStream._final(callback); + } + + /** + * An alias for `docStream.on('document', doc => {...})` + * @param {(doc: MimeToDoc[MIME]) => void} listener + */ + ondocument (listener) { + this.on('document', listener) + return this } append (self, node, active) { diff --git a/esm/dom/stream.js b/esm/dom/stream.js index 67a58643..3e8d4817 100644 --- a/esm/dom/stream.js +++ b/esm/dom/stream.js @@ -1,5 +1,5 @@ -import { Writable } from 'stream'; -import { WritableStream } from 'htmlparser2/lib/WritableStream'; +import {Writable} from 'stream'; +import {WritableStream} from 'htmlparser2/lib/WritableStream'; import {ELEMENT_NODE, SVG_NAMESPACE} from '../shared/constants'; import {CUSTOM_ELEMENTS, PREV, END, VALUE} from '../shared/symbols'; @@ -16,55 +16,33 @@ import {XMLDocument} from '../xml/document.js'; * @typedef {import('../interface/node').Node} Node * @typedef {import('../svg/element').SVGElement} SVGElement * @typedef {{ "text/html": HTMLDocument, "image/svg+xml": SVGDocument, "text/xml": XMLDocument }} MimeToDoc - * @typedef {(name: string, attributes: Record) => boolean} Filter */ /** * @template {keyof MimeToDoc} MIME - * @template {Filter} FILTER - * @template {{ - * document: MimeToDoc[MIME] - * node: MimeToDoc[MIME]|Node - * ownerSVGElement: SVGElement|undefined - * rootNode: Node - * }} StackItem - * @template {Writable['on'] & (name: 'document', listener: (doc: MimeToDoc[MIME]) => void) => this} Listener - * @template {Writable['emit'] & (name: 'document', doc: MimeToDoc[MIME]) => boolean} Emitter - * * @extends {Writable} */ export class DOMStream extends Writable { /** * @param {MIME} mimeType - * @param {FILTER} filter + * @param {(name: string, attributes: Record) => boolean} filter */ constructor (mimeType, filter) { super(); this.mimeType = mimeType; if (mimeType === 'text/html') this.isHTML = true; this.filter = filter; - /** @type {StackItem[]} */ + /** + * @type {{ + * document: MimeToDoc[MIME] + * node: MimeToDoc[MIME]|Node + * ownerSVGElement: SVGElement|undefined + * rootNode: Node + * }[]} + */ this.stack = []; this.init = this.init.bind(this); this.init(); - - // EVENTS - /** @type {Listener} */ - this.addListener = super.addListener; - /** @type {Emitter} */ - this.emit = super.emit; - /** @type {Listener} */ - this.on = super.on; - /** @type {Listener} */ - this.once = super.once; - /** @type {Listener} */ - this.prependListener = super.prependListener; - /** @type {Listener} */ - this.prependOnceListener = super.prependOnceListener; - /** @type {Listener} */ - this.removeListener = super.removeListener; - /** @type {Listener} */ - this.off = super.off; } newDocument () { @@ -81,7 +59,7 @@ export class DOMStream extends Writable { } init () { - this.content = new WritableStream({ + this.parserStream = new WritableStream({ // onprocessinginstruction: (name, data) => { if (name.toLowerCase() === '!doctype') { @@ -162,14 +140,23 @@ export class DOMStream extends Writable { * @param {() => void} callback */ _write(chunk, encoding, callback) { - this.content._write(chunk, encoding, callback); + this.parserStream._write(chunk, encoding, callback); } /** * @param {() => void} callback */ _final(callback) { - this.content._final(callback); + this.parserStream._final(callback); + } + + /** + * An alias for `docStream.on('document', doc => {...})` + * @param {(doc: MimeToDoc[MIME]) => void} listener + */ + ondocument (listener) { + this.on('document', listener) + return this } append (self, node, active) { diff --git a/test/stream/test-domparser.js b/test/stream/test-domparser.js index 5bf4bea2..70008bdc 100644 --- a/test/stream/test-domparser.js +++ b/test/stream/test-domparser.js @@ -29,10 +29,9 @@ parser.parseFromString(src, 'text/xml').then(doc => { console.timeEnd(' parsing \x1b[2mcold\x1b[0m'); console.log(); logStatus('document heap'); - console.log(doc.childElementCount) + const hotels = doc.querySelectorAll('hotelName') + console.log('Num of hotels:', hotels.length) }).catch((o_O) => { console.error(o_O); console.warn(`⚠ \x1b[1merror\x1b[0m - unable to parse the document: ${o_O.message}`); }); - -setInterval(() => {}, 2000000) diff --git a/test/stream/test-domstream.js b/test/stream/test-domstream.js index ac817182..49da61fd 100644 --- a/test/stream/test-domstream.js +++ b/test/stream/test-domstream.js @@ -34,9 +34,7 @@ src.on('end', () => { logStatus('end heap'); }) -src.pipe(domStream).on('document', doc => { +src.pipe(domStream).ondocument(doc => { console.log(doc.documentElement.outerHTML); logStatus('doc heap'); }); - -setInterval(() => {}, 2000000); diff --git a/tsconfig.json b/tsconfig.json index 4626cf48..323472c6 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,7 +2,7 @@ "compilerOptions": { "module": "ES2020", "target": "ES2020", - "moduleResolution": "Classic", + "moduleResolution": "Node", "allowJs": true, "declaration": true, "emitDeclarationOnly": true, diff --git a/types/esm/dom/stream.d.ts b/types/esm/dom/stream.d.ts index fd9a5f24..61e38b6e 100644 --- a/types/esm/dom/stream.d.ts +++ b/types/esm/dom/stream.d.ts @@ -1,60 +1,44 @@ -/// /** * @typedef {import('../interface/node').Node} Node * @typedef {import('../svg/element').SVGElement} SVGElement * @typedef {{ "text/html": HTMLDocument, "image/svg+xml": SVGDocument, "text/xml": XMLDocument }} MimeToDoc - * @typedef {(name: string, attributes: Record) => boolean} Filter */ /** * @template {keyof MimeToDoc} MIME - * @template {Filter} FILTER - * @template {{ - * document: MimeToDoc[MIME] - * node: MimeToDoc[MIME]|Node - * ownerSVGElement: SVGElement|undefined - * rootNode: Node - * }} StackItem - * @template {Writable['on'] & (name: 'document', listener: (doc: MimeToDoc[MIME]) => void) => this} Listener - * @template {Writable['emit'] & (name: 'document', doc: MimeToDoc[MIME]) => boolean} Emitter - * * @extends {Writable} */ -export class DOMStream void): Writable; - (event: "drain", listener: () => void): Writable; - (event: "error", listener: (err: Error) => void): Writable; - (event: "finish", listener: () => void): Writable; - (event: "pipe", listener: (src: import("stream").Readable) => void): Writable; - (event: "unpipe", listener: (src: import("stream").Readable) => void): Writable; - (event: string | symbol, listener: (...args: any[]) => void): Writable; -} & ((name: 'document', listener: (doc: MimeToDoc[MIME]) => void) => any), Emitter extends { - (event: "close"): boolean; - (event: "drain"): boolean; - (event: "error", err: Error): boolean; - (event: "finish"): boolean; - (event: "pipe", src: import("stream").Readable): boolean; - (event: "unpipe", src: import("stream").Readable): boolean; - (event: string | symbol, ...args: any[]): boolean; -} & ((name: 'document', doc: MimeToDoc[MIME]) => boolean)> extends Writable { +export class DOMStream extends Writable { /** * @param {MIME} mimeType - * @param {FILTER} filter + * @param {(name: string, attributes: Record) => boolean} filter */ - constructor(mimeType: MIME, filter: FILTER); + constructor(mimeType: MIME, filter: (name: string, attributes: Record) => boolean); mimeType: MIME; isHTML: boolean; - filter: FILTER; - /** @type {StackItem[]} */ - stack: StackItem[]; + filter: (name: string, attributes: Record) => boolean; + /** + * @type {{ + * document: MimeToDoc[MIME] + * node: MimeToDoc[MIME]|Node + * ownerSVGElement: SVGElement|undefined + * rootNode: Node + * }[]} + */ + stack: { + document: MimeToDoc[MIME]; + node: MimeToDoc[MIME] | Node; + ownerSVGElement: SVGElement | undefined; + rootNode: Node; + }[]; init(): void; newDocument(): void; - content: any; - doctype: any; + parserStream: WritableStream; + doctype: string; + /** + * An alias for `docStream.on('document', doc => {...})` + * @param {(doc: MimeToDoc[MIME]) => void} listener + */ + ondocument(listener: (doc: MimeToDoc[MIME]) => void): DOMStream; append(self: any, node: any, active: any): any; attribute(element: any, end: any, attribute: any, value: any, active: any): void; } @@ -65,8 +49,8 @@ export type MimeToDoc = { "image/svg+xml": SVGDocument; "text/xml": XMLDocument; }; -export type Filter = (name: string, attributes: Record) => boolean; import { Writable } from "stream"; +import { WritableStream } from "htmlparser2/lib/WritableStream"; import { HTMLDocument } from "../html/document.js"; import { SVGDocument } from "../svg/document.js"; import { XMLDocument } from "../xml/document.js"; diff --git a/types/esm/interface/element.d.ts b/types/esm/interface/element.d.ts index 53645783..42790f91 100644 --- a/types/esm/interface/element.d.ts +++ b/types/esm/interface/element.d.ts @@ -38,7 +38,7 @@ export class Element extends ParentNode implements globalThis.Element { toggleAttribute(name: any, force: any, ...args: any[]): boolean; get shadowRoot(): any; attachShadow(init: any): ShadowRoot; - matches(selectors: any): any; + matches(selectors: any): boolean; closest(selectors: any): Element; insertAdjacentElement(position: any, element: any): any; insertAdjacentHTML(position: any, html: any): void; diff --git a/types/esm/interface/image.d.ts b/types/esm/interface/image.d.ts index f99edbf1..b8d07bdb 100644 --- a/types/esm/interface/image.d.ts +++ b/types/esm/interface/image.d.ts @@ -127,7 +127,7 @@ export function ImageClass(ownerDocument: any): { toggleAttribute(name: any, force: any, ...args: any[]): boolean; readonly shadowRoot: any; attachShadow(init: any): import("./shadow-root.js").ShadowRoot; - matches(selectors: any): any; + matches(selectors: any): boolean; closest(selectors: any): any; insertAdjacentElement(position: any, element: any): any; insertAdjacentHTML(position: any, html: any): void; diff --git a/types/esm/shared/matches.d.ts b/types/esm/shared/matches.d.ts index 3f592e26..7ee6cc17 100644 --- a/types/esm/shared/matches.d.ts +++ b/types/esm/shared/matches.d.ts @@ -1,2 +1,2 @@ -export function prepareMatch(element: any, selectors: any): any; -export function matches(element: any, selectors: any): any; +export function prepareMatch(element: any, selectors: any): import("css-select/lib/types").CompiledQuery; +export function matches(element: any, selectors: any): boolean; diff --git a/types/esm/shared/node.d.ts b/types/esm/shared/node.d.ts index 8c941567..251a50ad 100644 --- a/types/esm/shared/node.d.ts +++ b/types/esm/shared/node.d.ts @@ -6,7 +6,7 @@ export function parentElement({ parentNode }: { parentNode: any; }): any; export function previousSibling({ [PREV]: prev }: { - "__@PREV@39422": any; + "__@PREV@39945": any; }): any; export function nextSibling(node: any): any; import { PREV } from "./symbols.js"; diff --git a/worker.js b/worker.js index 9d78a474..11c10971 100644 --- a/worker.js +++ b/worker.js @@ -11401,55 +11401,33 @@ class DOMParser { * @typedef {import('../interface/node').Node} Node * @typedef {import('../svg/element').SVGElement} SVGElement * @typedef {{ "text/html": HTMLDocument, "image/svg+xml": SVGDocument, "text/xml": XMLDocument }} MimeToDoc - * @typedef {(name: string, attributes: Record) => boolean} Filter */ /** * @template {keyof MimeToDoc} MIME - * @template {Filter} FILTER - * @template {{ - * document: MimeToDoc[MIME] - * node: MimeToDoc[MIME]|Node - * ownerSVGElement: SVGElement|undefined - * rootNode: Node - * }} StackItem - * @template {Writable['on'] & (name: 'document', listener: (doc: MimeToDoc[MIME]) => void) => this} Listener - * @template {Writable['emit'] & (name: 'document', doc: MimeToDoc[MIME]) => boolean} Emitter - * * @extends {Writable} */ class DOMStream extends Writable { /** * @param {MIME} mimeType - * @param {FILTER} filter + * @param {(name: string, attributes: Record) => boolean} filter */ constructor (mimeType, filter) { super(); this.mimeType = mimeType; if (mimeType === 'text/html') this.isHTML = true; this.filter = filter; - /** @type {StackItem[]} */ + /** + * @type {{ + * document: MimeToDoc[MIME] + * node: MimeToDoc[MIME]|Node + * ownerSVGElement: SVGElement|undefined + * rootNode: Node + * }[]} + */ this.stack = []; this.init = this.init.bind(this); this.init(); - - // EVENTS - /** @type {Listener} */ - this.addListener = super.addListener; - /** @type {Emitter} */ - this.emit = super.emit; - /** @type {Listener} */ - this.on = super.on; - /** @type {Listener} */ - this.once = super.once; - /** @type {Listener} */ - this.prependListener = super.prependListener; - /** @type {Listener} */ - this.prependOnceListener = super.prependOnceListener; - /** @type {Listener} */ - this.removeListener = super.removeListener; - /** @type {Listener} */ - this.off = super.off; } newDocument () { @@ -11466,7 +11444,7 @@ class DOMStream extends Writable { } init () { - this.content = new WritableStream({ + this.parserStream = new WritableStream({ // onprocessinginstruction: (name, data) => { if (name.toLowerCase() === '!doctype') { @@ -11547,14 +11525,23 @@ class DOMStream extends Writable { * @param {() => void} callback */ _write(chunk, encoding, callback) { - this.content._write(chunk, encoding, callback); + this.parserStream._write(chunk, encoding, callback); } /** * @param {() => void} callback */ _final(callback) { - this.content._final(callback); + this.parserStream._final(callback); + } + + /** + * An alias for `docStream.on('document', doc => {...})` + * @param {(doc: MimeToDoc[MIME]) => void} listener + */ + ondocument (listener) { + this.on('document', listener); + return this } append (self, node, active) { From fb47894366ead5664a503f7d6e37fb5207d97187 Mon Sep 17 00:00:00 2001 From: "${Mr.DJA}" <42304709+iMrDJAi@users.noreply.github.com> Date: Thu, 27 Oct 2022 10:23:42 +0100 Subject: [PATCH 10/13] =?UTF-8?q?=E2=9C=85=20Improved=20code=20coverage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cjs/dom/stream.js | 52 +- cjs/shared/parse-from-string.js | 2 + esm/dom/stream.js | 52 +- esm/shared/parse-from-string.js | 4 +- package-lock.json | 1255 ++++++++++++++++- package.json | 14 +- test/benchmark/content.js | 14 +- .../domstream.js} | 16 +- test/benchmark/html.html | 2 +- test/benchmark/index.js | 17 +- test/index.js | 1 + test/stream/document.js | 19 + test/stream/domstream.js | 18 + test/stream/test-domparser.js | 37 - types/esm/dom/stream.d.ts | 10 +- types/esm/shared/parse-from-string.d.ts | 2 + worker.js | 278 ++-- 17 files changed, 1508 insertions(+), 285 deletions(-) rename test/{stream/test-domstream.js => benchmark/domstream.js} (62%) create mode 100644 test/stream/document.js create mode 100644 test/stream/domstream.js delete mode 100644 test/stream/test-domparser.js diff --git a/cjs/dom/stream.js b/cjs/dom/stream.js index 678e17df..ba1ae108 100644 --- a/cjs/dom/stream.js +++ b/cjs/dom/stream.js @@ -2,17 +2,16 @@ const {Writable} = require('stream'); const {WritableStream} = require('htmlparser2/lib/WritableStream'); -const {ELEMENT_NODE, SVG_NAMESPACE} = require('../shared/constants'); -const {CUSTOM_ELEMENTS, PREV, END, VALUE} = require('../shared/symbols'); +const {append, attribute} = require('../shared/parse-from-string'); +const {SVG_NAMESPACE} = require('../shared/constants'); +const {CUSTOM_ELEMENTS, END} = require('../shared/symbols'); const {keys} = require('../shared/object'); -const {knownBoundaries, knownSiblings} = require('../shared/utils'); -const {attributeChangedCallback, connectedCallback} = require('../interface/custom-element-registry.js'); - const {HTMLDocument} = require('../html/document.js'); const {SVGDocument} = require('../svg/document.js'); const {XMLDocument} = require('../xml/document.js'); + /** * @typedef {import('../interface/node').Node} Node * @typedef {import('../svg/element').SVGElement} SVGElement @@ -42,7 +41,6 @@ class DOMStream extends Writable { * }[]} */ this.stack = []; - this.init = this.init.bind(this); this.init(); } @@ -76,27 +74,27 @@ class DOMStream extends Writable { let create = true; if (this.isHTML) { if (item.ownerSVGElement) { - item.node = this.append(item.node, document.createElementNS(SVG_NAMESPACE, name), active); + item.node = append(item.node, document.createElementNS(SVG_NAMESPACE, name), active); item.node.ownerSVGElement = item.ownerSVGElement; create = false; } else if (name === 'svg' || name === 'SVG') { item.ownerSVGElement = document.createElementNS(SVG_NAMESPACE, name); - item.node = this.append(item.node, item.ownerSVGElement, active); + item.node = append(item.node, item.ownerSVGElement, active); create = false; } else if (active) { const ce = name.includes('-') ? name : (attributes.is || ''); if (ce && registry.has(ce)) { const {Class} = registry.get(ce); - item.node = this.append(item.node, new Class, active); + item.node = append(item.node, new Class, active); delete attributes.is; create = false; } } } - if (create) item.node = this.append(item.node, document.createElement(name), false); + if (create) item.node = append(item.node, document.createElement(name), false); let end = item.node[END]; for (const name of keys(attributes)) { - this.attribute(item.node, end, document.createAttribute(name), attributes[name], active); + attribute(item.node, end, document.createAttribute(name), attributes[name], active); } if (!item.rootNode) item.rootNode = item.node; } @@ -105,13 +103,13 @@ class DOMStream extends Writable { oncomment: (data) => { for (const { document, node } of this.stack) { const { active } = document[CUSTOM_ELEMENTS]; - this.append(node, document.createComment(data), active); + append(node, document.createComment(data), active); } }, ontext: (text) => { for (const { document, node } of this.stack) { const { active } = document[CUSTOM_ELEMENTS]; - this.append(node, document.createTextNode(text), active); + append(node, document.createTextNode(text), active); } }, // @@ -133,6 +131,7 @@ class DOMStream extends Writable { decodeEntities: true, xmlMode: !this.isHTML }) + this.parserStream.on('error', err => this.emit('error', err)) } /** @@ -160,23 +159,14 @@ class DOMStream extends Writable { return this } - append (self, node, active) { - const end = self[END]; - node.parentNode = self; - knownBoundaries(end[PREV], node, end); - if (active && node.nodeType === ELEMENT_NODE) - connectedCallback(node); - return node; - } - - attribute (element, end, attribute, value, active) { - attribute[VALUE] = value; - attribute.ownerElement = element; - knownSiblings(end[PREV], attribute, end); - if (attribute.name === 'class') - element.className = value; - if (active) - attributeChangedCallback(element, attribute.name, null, value); - } + /** + * An alias for `docStream.on('error', err => {...})` + * or `docStream.parserStream.on('error', err => {...})` + * @param {(err: Error) => void} listener + */ + onerror (listener) { + this.on('error', listener) + return this + } } exports.DOMStream = DOMStream diff --git a/cjs/shared/parse-from-string.js b/cjs/shared/parse-from-string.js index 8b7ed8f1..4209efcf 100644 --- a/cjs/shared/parse-from-string.js +++ b/cjs/shared/parse-from-string.js @@ -31,6 +31,7 @@ const append = (self, node, active) => { connectedCallback(node); return node; }; +exports.append = append; const attribute = (element, end, attribute, value, active) => { attribute[VALUE] = value; @@ -41,6 +42,7 @@ const attribute = (element, end, attribute, value, active) => { if (active) attributeChangedCallback(element, attribute.name, null, value); }; +exports.attribute = attribute; const isNotParsing = () => notParsing; exports.isNotParsing = isNotParsing; diff --git a/esm/dom/stream.js b/esm/dom/stream.js index 3e8d4817..c862872c 100644 --- a/esm/dom/stream.js +++ b/esm/dom/stream.js @@ -1,17 +1,16 @@ import {Writable} from 'stream'; import {WritableStream} from 'htmlparser2/lib/WritableStream'; -import {ELEMENT_NODE, SVG_NAMESPACE} from '../shared/constants'; -import {CUSTOM_ELEMENTS, PREV, END, VALUE} from '../shared/symbols'; +import {append, attribute} from '../shared/parse-from-string'; +import {SVG_NAMESPACE} from '../shared/constants'; +import {CUSTOM_ELEMENTS, END} from '../shared/symbols'; import {keys} from '../shared/object'; -import {knownBoundaries, knownSiblings} from '../shared/utils'; -import {attributeChangedCallback, connectedCallback} from '../interface/custom-element-registry.js'; - import {HTMLDocument} from '../html/document.js'; import {SVGDocument} from '../svg/document.js'; import {XMLDocument} from '../xml/document.js'; + /** * @typedef {import('../interface/node').Node} Node * @typedef {import('../svg/element').SVGElement} SVGElement @@ -41,7 +40,6 @@ export class DOMStream extends Writable { * }[]} */ this.stack = []; - this.init = this.init.bind(this); this.init(); } @@ -75,27 +73,27 @@ export class DOMStream extends Writable { let create = true; if (this.isHTML) { if (item.ownerSVGElement) { - item.node = this.append(item.node, document.createElementNS(SVG_NAMESPACE, name), active); + item.node = append(item.node, document.createElementNS(SVG_NAMESPACE, name), active); item.node.ownerSVGElement = item.ownerSVGElement; create = false; } else if (name === 'svg' || name === 'SVG') { item.ownerSVGElement = document.createElementNS(SVG_NAMESPACE, name); - item.node = this.append(item.node, item.ownerSVGElement, active); + item.node = append(item.node, item.ownerSVGElement, active); create = false; } else if (active) { const ce = name.includes('-') ? name : (attributes.is || ''); if (ce && registry.has(ce)) { const {Class} = registry.get(ce); - item.node = this.append(item.node, new Class, active); + item.node = append(item.node, new Class, active); delete attributes.is; create = false; } } } - if (create) item.node = this.append(item.node, document.createElement(name), false); + if (create) item.node = append(item.node, document.createElement(name), false); let end = item.node[END]; for (const name of keys(attributes)) { - this.attribute(item.node, end, document.createAttribute(name), attributes[name], active); + attribute(item.node, end, document.createAttribute(name), attributes[name], active); } if (!item.rootNode) item.rootNode = item.node; } @@ -104,13 +102,13 @@ export class DOMStream extends Writable { oncomment: (data) => { for (const { document, node } of this.stack) { const { active } = document[CUSTOM_ELEMENTS]; - this.append(node, document.createComment(data), active); + append(node, document.createComment(data), active); } }, ontext: (text) => { for (const { document, node } of this.stack) { const { active } = document[CUSTOM_ELEMENTS]; - this.append(node, document.createTextNode(text), active); + append(node, document.createTextNode(text), active); } }, // @@ -132,6 +130,7 @@ export class DOMStream extends Writable { decodeEntities: true, xmlMode: !this.isHTML }) + this.parserStream.on('error', err => this.emit('error', err)) } /** @@ -159,22 +158,13 @@ export class DOMStream extends Writable { return this } - append (self, node, active) { - const end = self[END]; - node.parentNode = self; - knownBoundaries(end[PREV], node, end); - if (active && node.nodeType === ELEMENT_NODE) - connectedCallback(node); - return node; - } - - attribute (element, end, attribute, value, active) { - attribute[VALUE] = value; - attribute.ownerElement = element; - knownSiblings(end[PREV], attribute, end); - if (attribute.name === 'class') - element.className = value; - if (active) - attributeChangedCallback(element, attribute.name, null, value); - } + /** + * An alias for `docStream.on('error', err => {...})` + * or `docStream.parserStream.on('error', err => {...})` + * @param {(err: Error) => void} listener + */ + onerror (listener) { + this.on('error', listener) + return this + } } diff --git a/esm/shared/parse-from-string.js b/esm/shared/parse-from-string.js index e44eaba3..17e43f0a 100644 --- a/esm/shared/parse-from-string.js +++ b/esm/shared/parse-from-string.js @@ -22,7 +22,7 @@ import {attributeChangedCallback, connectedCallback} from '../interface/custom-e let notParsing = true; -const append = (self, node, active) => { +export const append = (self, node, active) => { const end = self[END]; node.parentNode = self; knownBoundaries(end[PREV], node, end); @@ -31,7 +31,7 @@ const append = (self, node, active) => { return node; }; -const attribute = (element, end, attribute, value, active) => { +export const attribute = (element, end, attribute, value, active) => { attribute[VALUE] = value; attribute.ownerElement = element; knownSiblings(end[PREV], attribute, end); diff --git a/package-lock.json b/package-lock.json index 8abb2343..f1be4557 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,10 +21,17 @@ "@rollup/plugin-node-resolve": "^13.3.0", "@types/node": "^18.11.0", "ascjs": "^5.0.1", + "basichtml": "^2.4.9", "c8": "^7.11.2", "eslint": "^8.15.0", + "jsdom": "^20.0.1", + "jsdon": "^0.1.15", "rollup": "^2.72.0", "typescript": "4.5" + }, + "optionalDependencies": { + "basichtml": "^2.4.9", + "jsdon": "^0.1.15" } }, "node_modules/@babel/parser": { @@ -195,6 +202,15 @@ "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", "dev": true }, + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, "node_modules/@types/estree": { "version": "0.0.39", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", @@ -222,10 +238,22 @@ "@types/node": "*" } }, + "node_modules/@webreflection/interface": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@webreflection/interface/-/interface-0.1.1.tgz", + "integrity": "sha512-n5t7JLDaLzAPqCWIqC2i+i0RXoxUjXvcpYmTYQ6cR2XyyCL5jTqDh6th21FuZzfi5j+PFvpeYxFPv5b4/vnJzA==", + "dev": true + }, + "node_modules/abab": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", + "dev": true + }, "node_modules/acorn": { - "version": "8.7.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", - "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", + "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -234,6 +262,16 @@ "node": ">=0.4.0" } }, + "node_modules/acorn-globals": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz", + "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==", + "dev": true, + "dependencies": { + "acorn": "^8.1.0", + "acorn-walk": "^8.0.2" + } + }, "node_modules/acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", @@ -243,6 +281,27 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, + "node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -301,12 +360,125 @@ "ascjs": "bin.js" } }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/basichtml": { + "version": "2.4.9", + "resolved": "https://registry.npmjs.org/basichtml/-/basichtml-2.4.9.tgz", + "integrity": "sha512-/vz9qpgCBp7sCjlsxisCaMX6KPzy1ncEzyAQjofWiOY9U0y9VXH+EV2iYjaOmIYXXSAcZaugdYKBml2dmkW0vQ==", + "deprecated": "The effort has moved into LinkeDOM module: https://www.npmjs.com/package/linkedom", + "dev": true, + "dependencies": { + "@webreflection/interface": "^0.1.1", + "broadcast": "^3.0.0", + "html-escaper": "^3.0.0", + "htmlparser2": "^4.1.0" + } + }, + "node_modules/basichtml/node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dev": true, + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/basichtml/node_modules/dom-serializer/node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dev": true, + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/basichtml/node_modules/domhandler": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-3.3.0.tgz", + "integrity": "sha512-J1C5rIANUbuYK+FuFL98650rihynUOEzRLxW+90bKZRWB6A1X1Tf82GxR1qAWLyfNPRvjqfip3Q5tdYlmAa9lA==", + "dev": true, + "dependencies": { + "domelementtype": "^2.0.1" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/basichtml/node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dev": true, + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/basichtml/node_modules/domutils/node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dev": true, + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/basichtml/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/basichtml/node_modules/htmlparser2": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-4.1.0.tgz", + "integrity": "sha512-4zDq1a1zhE4gQso/c5LP1OtrhYTncXNSpvJYtWJBtXAETPlMfi3IFNjGuQbYLuVY4ZR0QMqRVvo4Pdy9KLyP8Q==", + "dev": true, + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^3.0.0", + "domutils": "^2.0.0", + "entities": "^2.0.0" + } + }, "node_modules/boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", @@ -322,6 +494,12 @@ "concat-map": "0.0.1" } }, + "node_modules/broadcast": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/broadcast/-/broadcast-3.0.0.tgz", + "integrity": "sha512-q//26zihgUvAtvSBRD1xtk/9KBVNfiUrS8Phz8dN95Y5mqINO/gFT6181b4Yvhoeal3Aa9+rsFnKzA6a6UTHfg==", + "dev": true + }, "node_modules/builtin-modules": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.2.0.tgz", @@ -414,6 +592,18 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", @@ -480,6 +670,38 @@ "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==" }, + "node_modules/cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "dev": true, + "dependencies": { + "cssom": "~0.3.6" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cssstyle/node_modules/cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true + }, + "node_modules/data-urls": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz", + "integrity": "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==", + "dev": true, + "dependencies": { + "abab": "^2.0.6", + "whatwg-mimetype": "^3.0.0", + "whatwg-url": "^11.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -497,6 +719,12 @@ } } }, + "node_modules/decimal.js": { + "version": "10.4.2", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.2.tgz", + "integrity": "sha512-ic1yEvwT6GuvaYwBLLY6/aFFgjZdySKTE8en/fkU3QICTmRtgtSlFn0u0BXN06InZwtfCelR7j8LRiDI/02iGA==", + "dev": true + }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -512,6 +740,15 @@ "node": ">=0.10.0" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -548,6 +785,18 @@ } ] }, + "node_modules/domexception": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", + "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", + "dev": true, + "dependencies": { + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/domhandler": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", @@ -582,9 +831,9 @@ "dev": true }, "node_modules/entities": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.3.0.tgz", - "integrity": "sha512-/iP1rZrSEJ0DTlPiX+jbzlA3eVkY/e8L8SozroF395fIqE3TYF/Nz7YOMAawta+vLmyJ/hkGNNPcSbMADCCXbg==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", + "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==", "engines": { "node": ">=0.12" }, @@ -613,6 +862,79 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/escodegen": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", + "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", + "dev": true, + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/escodegen/node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "dev": true, + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/escodegen/node_modules/optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "dependencies": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/escodegen/node_modules/prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/escodegen/node_modules/type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "dev": true, + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/eslint": { "version": "8.15.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.15.0.tgz", @@ -728,6 +1050,19 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/esquery": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", @@ -854,6 +1189,20 @@ "node": ">=8.0.0" } }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -963,6 +1312,18 @@ "node": ">=8" } }, + "node_modules/html-encoding-sniffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", + "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", + "dev": true, + "dependencies": { + "whatwg-encoding": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/html-escaper": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-3.0.3.tgz", @@ -986,6 +1347,45 @@ "entities": "^4.3.0" } }, + "node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dev": true, + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/ignore": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", @@ -1096,6 +1496,12 @@ "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=", "dev": true }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true + }, "node_modules/is-reference": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", @@ -1165,6 +1571,57 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsdom": { + "version": "20.0.1", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.1.tgz", + "integrity": "sha512-pksjj7Rqoa+wdpkKcLzQRHhJCEE42qQhl/xLMUKHgoSejaKOdaXEAnqs6uDNwMl/fciHTzKeR8Wm8cw7N+g98A==", + "dev": true, + "dependencies": { + "abab": "^2.0.6", + "acorn": "^8.8.0", + "acorn-globals": "^7.0.0", + "cssom": "^0.5.0", + "cssstyle": "^2.3.0", + "data-urls": "^3.0.2", + "decimal.js": "^10.4.1", + "domexception": "^4.0.0", + "escodegen": "^2.0.0", + "form-data": "^4.0.0", + "html-encoding-sniffer": "^3.0.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.1", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.2", + "parse5": "^7.1.1", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.1.2", + "w3c-xmlserializer": "^3.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^2.0.0", + "whatwg-mimetype": "^3.0.0", + "whatwg-url": "^11.0.0", + "ws": "^8.9.0", + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "canvas": "^2.5.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jsdon": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/jsdon/-/jsdon-0.1.15.tgz", + "integrity": "sha512-3ZrE0EfFIJVgCggM3H81xN7KN8BLWmiYiSSErMKo5w6xJUi0JkdbOQs3lQ8cPBcF01JAIIve7JqXfJHLFbifPg==", + "dev": true + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -1235,6 +1692,27 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -1270,6 +1748,12 @@ "url": "https://github.com/fb55/nth-check?sponsor=1" } }, + "node_modules/nwsapi": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.2.tgz", + "integrity": "sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw==", + "dev": true + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -1338,6 +1822,18 @@ "node": ">=6" } }, + "node_modules/parse5": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.1.tgz", + "integrity": "sha512-kwpuwzB+px5WUg9pyK0IcK/shltJN5/OVhQagxhCQNtT9Y9QRZqNY2e1cmbu/paRh5LMnz/oVTVLBpjFmMZhSg==", + "dev": true, + "dependencies": { + "entities": "^4.4.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -1392,6 +1888,12 @@ "node": ">= 0.8.0" } }, + "node_modules/psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", + "dev": true + }, "node_modules/punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -1401,6 +1903,12 @@ "node": ">=6" } }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "dev": true + }, "node_modules/regexpp": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", @@ -1422,6 +1930,12 @@ "node": ">=0.10.0" } }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "dev": true + }, "node_modules/resolve": { "version": "1.22.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", @@ -1484,6 +1998,24 @@ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dev": true, + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" + } + }, "node_modules/semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", @@ -1520,6 +2052,16 @@ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/sourcemap-codec": { "version": "1.4.8", "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", @@ -1588,26 +2130,59 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true + }, "node_modules/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", "dev": true, "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "node_modules/tough-cookie": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.2.tgz", + "integrity": "sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==", + "dev": true, + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tr46": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "dev": true, + "dependencies": { + "punycode": "^2.1.1" }, "engines": { - "node": ">=8" + "node": ">=12" } }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -1650,6 +2225,15 @@ "resolved": "https://registry.npmjs.org/uhyphen/-/uhyphen-0.1.0.tgz", "integrity": "sha512-o0QVGuFg24FK765Qdd5kk0zU/U4dEsCtN/GSiwNI9i8xsSVtjIAOdTaVhLwZ1nrbWxFVMxNDDl+9fednsOMsBw==" }, + "node_modules/universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -1659,6 +2243,16 @@ "punycode": "^2.1.0" } }, + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "dev": true, + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, "node_modules/v8-compile-cache": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", @@ -1679,6 +2273,61 @@ "node": ">=10.12.0" } }, + "node_modules/w3c-xmlserializer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-3.0.0.tgz", + "integrity": "sha512-3WFqGEgSXIyGhOmAFtlicJNMjEps8b1MG31NCA0/vOF9+nKMUW1ckhi9cnNHmf88Rzw5V+dwIwsm2C7X8k9aQg==", + "dev": true, + "dependencies": { + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", + "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", + "dev": true, + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-mimetype": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", + "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-url": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "dev": true, + "dependencies": { + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -1726,6 +2375,42 @@ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, + "node_modules/ws": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.10.0.tgz", + "integrity": "sha512-+s49uSmZpvtAsd2h37vIPy1RBusaLawVe8of+GyEPsaJTCMpj/2v8NpeK1SHXjBlQ95lQTmQofOJnFiLoaN3yw==", + "dev": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xml-name-validator": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", + "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -1907,6 +2592,12 @@ } } }, + "@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "dev": true + }, "@types/estree": { "version": "0.0.39", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", @@ -1934,12 +2625,34 @@ "@types/node": "*" } }, + "@webreflection/interface": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@webreflection/interface/-/interface-0.1.1.tgz", + "integrity": "sha512-n5t7JLDaLzAPqCWIqC2i+i0RXoxUjXvcpYmTYQ6cR2XyyCL5jTqDh6th21FuZzfi5j+PFvpeYxFPv5b4/vnJzA==", + "dev": true + }, + "abab": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", + "dev": true + }, "acorn": { - "version": "8.7.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", - "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", + "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", "dev": true }, + "acorn-globals": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz", + "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==", + "dev": true, + "requires": { + "acorn": "^8.1.0", + "acorn-walk": "^8.0.2" + } + }, "acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", @@ -1947,6 +2660,21 @@ "dev": true, "requires": {} }, + "acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true + }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "requires": { + "debug": "4" + } + }, "ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -1989,12 +2717,103 @@ "@babel/parser": "^7.12.5" } }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true + }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "basichtml": { + "version": "2.4.9", + "resolved": "https://registry.npmjs.org/basichtml/-/basichtml-2.4.9.tgz", + "integrity": "sha512-/vz9qpgCBp7sCjlsxisCaMX6KPzy1ncEzyAQjofWiOY9U0y9VXH+EV2iYjaOmIYXXSAcZaugdYKBml2dmkW0vQ==", + "dev": true, + "requires": { + "@webreflection/interface": "^0.1.1", + "broadcast": "^3.0.0", + "html-escaper": "^3.0.0", + "htmlparser2": "^4.1.0" + }, + "dependencies": { + "dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "dependencies": { + "domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dev": true, + "requires": { + "domelementtype": "^2.2.0" + } + } + } + }, + "domhandler": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-3.3.0.tgz", + "integrity": "sha512-J1C5rIANUbuYK+FuFL98650rihynUOEzRLxW+90bKZRWB6A1X1Tf82GxR1qAWLyfNPRvjqfip3Q5tdYlmAa9lA==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1" + } + }, + "domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dev": true, + "requires": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "dependencies": { + "domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dev": true, + "requires": { + "domelementtype": "^2.2.0" + } + } + } + }, + "entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true + }, + "htmlparser2": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-4.1.0.tgz", + "integrity": "sha512-4zDq1a1zhE4gQso/c5LP1OtrhYTncXNSpvJYtWJBtXAETPlMfi3IFNjGuQbYLuVY4ZR0QMqRVvo4Pdy9KLyP8Q==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^3.0.0", + "domutils": "^2.0.0", + "entities": "^2.0.0" + } + } + } + }, "boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", @@ -2010,6 +2829,12 @@ "concat-map": "0.0.1" } }, + "broadcast": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/broadcast/-/broadcast-3.0.0.tgz", + "integrity": "sha512-q//26zihgUvAtvSBRD1xtk/9KBVNfiUrS8Phz8dN95Y5mqINO/gFT6181b4Yvhoeal3Aa9+rsFnKzA6a6UTHfg==", + "dev": true + }, "builtin-modules": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.2.0.tgz", @@ -2078,6 +2903,15 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, "commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", @@ -2132,6 +2966,34 @@ "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==" }, + "cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "dev": true, + "requires": { + "cssom": "~0.3.6" + }, + "dependencies": { + "cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true + } + } + }, + "data-urls": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz", + "integrity": "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==", + "dev": true, + "requires": { + "abab": "^2.0.6", + "whatwg-mimetype": "^3.0.0", + "whatwg-url": "^11.0.0" + } + }, "debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -2141,6 +3003,12 @@ "ms": "2.1.2" } }, + "decimal.js": { + "version": "10.4.2", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.2.tgz", + "integrity": "sha512-ic1yEvwT6GuvaYwBLLY6/aFFgjZdySKTE8en/fkU3QICTmRtgtSlFn0u0BXN06InZwtfCelR7j8LRiDI/02iGA==", + "dev": true + }, "deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -2153,6 +3021,12 @@ "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", "dev": true }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true + }, "doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -2177,6 +3051,15 @@ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" }, + "domexception": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", + "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", + "dev": true, + "requires": { + "webidl-conversions": "^7.0.0" + } + }, "domhandler": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", @@ -2202,9 +3085,9 @@ "dev": true }, "entities": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.3.0.tgz", - "integrity": "sha512-/iP1rZrSEJ0DTlPiX+jbzlA3eVkY/e8L8SozroF395fIqE3TYF/Nz7YOMAawta+vLmyJ/hkGNNPcSbMADCCXbg==" + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", + "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==" }, "escalade": { "version": "3.1.1", @@ -2218,6 +3101,60 @@ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true }, + "escodegen": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", + "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", + "dev": true, + "requires": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + }, + "dependencies": { + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "dev": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + } + } + }, "eslint": { "version": "8.15.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.15.0.tgz", @@ -2305,6 +3242,12 @@ "eslint-visitor-keys": "^3.3.0" } }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, "esquery": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", @@ -2404,6 +3347,17 @@ "signal-exit": "^3.0.2" } }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -2482,6 +3436,15 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, + "html-encoding-sniffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", + "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", + "dev": true, + "requires": { + "whatwg-encoding": "^2.0.0" + } + }, "html-escaper": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-3.0.3.tgz", @@ -2498,6 +3461,36 @@ "entities": "^4.3.0" } }, + "http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dev": true, + "requires": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + } + }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4" + } + }, + "iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + }, "ignore": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", @@ -2581,6 +3574,12 @@ "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=", "dev": true }, + "is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true + }, "is-reference": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", @@ -2640,6 +3639,46 @@ "argparse": "^2.0.1" } }, + "jsdom": { + "version": "20.0.1", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.1.tgz", + "integrity": "sha512-pksjj7Rqoa+wdpkKcLzQRHhJCEE42qQhl/xLMUKHgoSejaKOdaXEAnqs6uDNwMl/fciHTzKeR8Wm8cw7N+g98A==", + "dev": true, + "requires": { + "abab": "^2.0.6", + "acorn": "^8.8.0", + "acorn-globals": "^7.0.0", + "cssom": "^0.5.0", + "cssstyle": "^2.3.0", + "data-urls": "^3.0.2", + "decimal.js": "^10.4.1", + "domexception": "^4.0.0", + "escodegen": "^2.0.0", + "form-data": "^4.0.0", + "html-encoding-sniffer": "^3.0.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.1", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.2", + "parse5": "^7.1.1", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.1.2", + "w3c-xmlserializer": "^3.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^2.0.0", + "whatwg-mimetype": "^3.0.0", + "whatwg-url": "^11.0.0", + "ws": "^8.9.0", + "xml-name-validator": "^4.0.0" + } + }, + "jsdon": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/jsdon/-/jsdon-0.1.15.tgz", + "integrity": "sha512-3ZrE0EfFIJVgCggM3H81xN7KN8BLWmiYiSSErMKo5w6xJUi0JkdbOQs3lQ8cPBcF01JAIIve7JqXfJHLFbifPg==", + "dev": true + }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -2695,6 +3734,21 @@ "semver": "^6.0.0" } }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "requires": { + "mime-db": "1.52.0" + } + }, "minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -2724,6 +3778,12 @@ "boolbase": "^1.0.0" } }, + "nwsapi": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.2.tgz", + "integrity": "sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw==", + "dev": true + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -2774,6 +3834,15 @@ "callsites": "^3.0.0" } }, + "parse5": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.1.tgz", + "integrity": "sha512-kwpuwzB+px5WUg9pyK0IcK/shltJN5/OVhQagxhCQNtT9Y9QRZqNY2e1cmbu/paRh5LMnz/oVTVLBpjFmMZhSg==", + "dev": true, + "requires": { + "entities": "^4.4.0" + } + }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -2810,12 +3879,24 @@ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true }, + "psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", + "dev": true + }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "dev": true }, + "querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "dev": true + }, "regexpp": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", @@ -2828,6 +3909,12 @@ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "dev": true + }, "resolve": { "version": "1.22.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", @@ -2869,6 +3956,21 @@ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dev": true, + "requires": { + "xmlchars": "^2.2.0" + } + }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", @@ -2896,6 +3998,13 @@ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true + }, "sourcemap-codec": { "version": "1.4.8", "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", @@ -2943,6 +4052,12 @@ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true }, + "symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true + }, "test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", @@ -2960,6 +4075,27 @@ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, + "tough-cookie": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.2.tgz", + "integrity": "sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==", + "dev": true, + "requires": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + } + }, + "tr46": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "dev": true, + "requires": { + "punycode": "^2.1.1" + } + }, "type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -2986,6 +4122,12 @@ "resolved": "https://registry.npmjs.org/uhyphen/-/uhyphen-0.1.0.tgz", "integrity": "sha512-o0QVGuFg24FK765Qdd5kk0zU/U4dEsCtN/GSiwNI9i8xsSVtjIAOdTaVhLwZ1nrbWxFVMxNDDl+9fednsOMsBw==" }, + "universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "dev": true + }, "uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -2995,6 +4137,16 @@ "punycode": "^2.1.0" } }, + "url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "dev": true, + "requires": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, "v8-compile-cache": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", @@ -3012,6 +4164,46 @@ "convert-source-map": "^1.6.0" } }, + "w3c-xmlserializer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-3.0.0.tgz", + "integrity": "sha512-3WFqGEgSXIyGhOmAFtlicJNMjEps8b1MG31NCA0/vOF9+nKMUW1ckhi9cnNHmf88Rzw5V+dwIwsm2C7X8k9aQg==", + "dev": true, + "requires": { + "xml-name-validator": "^4.0.0" + } + }, + "webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true + }, + "whatwg-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", + "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", + "dev": true, + "requires": { + "iconv-lite": "0.6.3" + } + }, + "whatwg-mimetype": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", + "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", + "dev": true + }, + "whatwg-url": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "dev": true, + "requires": { + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + } + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -3044,6 +4236,25 @@ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, + "ws": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.10.0.tgz", + "integrity": "sha512-+s49uSmZpvtAsd2h37vIPy1RBusaLawVe8of+GyEPsaJTCMpj/2v8NpeK1SHXjBlQ95lQTmQofOJnFiLoaN3yw==", + "dev": true, + "requires": {} + }, + "xml-name-validator": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", + "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", + "dev": true + }, + "xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true + }, "y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", diff --git a/package.json b/package.json index f3c56aef..67ab975f 100644 --- a/package.json +++ b/package.json @@ -11,14 +11,17 @@ "benchmark:dom": "node test/benchmark/linkedom.js --dom; node test/benchmark/linkedom-cached.js --dom; node test/benchmark/jsdom.js --dom; node test/benchmark/basichtml.js --dom", "benchmark:dom:ce": "node test/benchmark/linkedom.js --dom --custom-elements; node test/benchmark/linkedom-cached.js --dom --custom-elements; node test/benchmark/jsdom.js --dom --custom-elements; node test/benchmark/basichtml.js --dom --custom-elements", "benchmark:html": "node test/benchmark/jsdon.js --html; node test/benchmark/linkedom.js --html; node test/benchmark/linkedom-cached.js --html; #node test/benchmark/jsdom.js --html", + "benchmark:html:st": "node test/benchmark/linkedom.js --html; node test/benchmark/linkedom.js --html --html-as-stream", "benchmark:html:ce": "node test/benchmark/linkedom.js --html --custom-elements; node test/benchmark/linkedom-cached.js --html --custom-elements; #node test/benchmark/jsdom.js --html --custom-elements", "benchmark:html:mo": "node test/benchmark/linkedom.js --html --mutation-observer --custom-elements; node test/benchmark/linkedom-cached.js --html --mutation-observer --custom-elements", "benchmark:html:nc": "node test/benchmark/linkedom.js --html --no-clone; node test/benchmark/linkedom-cached.js --html --no-clone; #node test/benchmark/jsdom.js --html --no-clone", + "domstream": "node test/benchmark/domstream.js", "build": "npm run tsc && npm run cjs && rollup -c rollup/es.config.js && npm run test", "cjs": "ascjs --no-default esm cjs", "tsc": "tsc -p .", "hello": "if [[ \"$(node --version)\" =~ ^v1[^2] ]]; then node --input-type=module -e \"import {DOMParser} from './esm/index.js';console.log('\\x1b[7m\\x1b[1m',(new DOMParser).parseFromString('LinkeDOM','text/html').querySelectorAll('html')[0].firstChild.toString(),'\\x1b[0m')\"; fi", - "test": "eslint esm/ && npm run hello && node test/benchmark/linkedom.js --w3c --mutation-observer --custom-elements && c8 node test/index.js && c8 report -r html", + "test": "eslint esm/ && npm run hello && node test/benchmark/linkedom.js --w3c --mutation-observer --custom-elements && node test/benchmark/linkedom.js --w3c --mutation-observer --custom-elements --html-as-stream && node test/benchmark/domstream.js --silent && npm run c8", + "c8": "c8 node test/index.js && c8 report -r html", "coverage": "mkdir -p ./coverage; c8 report --reporter=text-lcov > ./coverage/lcov.info" }, "keywords": [ @@ -36,8 +39,11 @@ "@rollup/plugin-node-resolve": "^13.3.0", "@types/node": "^18.11.0", "ascjs": "^5.0.1", + "basichtml": "^2.4.9", "c8": "^7.11.2", "eslint": "^8.15.0", + "jsdom": "^20.0.1", + "jsdon": "^0.1.15", "rollup": "^2.72.0", "typescript": "4.5" }, @@ -70,5 +76,9 @@ "bugs": { "url": "https://github.com/WebReflection/linkedom/issues" }, - "homepage": "https://github.com/WebReflection/linkedom#readme" + "homepage": "https://github.com/WebReflection/linkedom#readme", + "optionalDependencies": { + "basichtml": "^2.4.9", + "jsdon": "^0.1.15" + } } diff --git a/test/benchmark/content.js b/test/benchmark/content.js index ba482205..ea65acf4 100644 --- a/test/benchmark/content.js +++ b/test/benchmark/content.js @@ -15,6 +15,7 @@ const bench = (name, count, times) => { return total; }; +// eslint-disable-next-line no-control-regex const clean = str => browser ? str.replace(/\x1b\[\dm/g, '') : str; const crawl = (element, kind) => { @@ -28,7 +29,15 @@ const crawl = (element, kind) => { const sleep = ms => new Promise($ => setTimeout($, ms)); -const onContent = async (createDocument, html, times, logHeap = () => {}, cloneBench = true, customElements = false, mutationObserver = false) => { +const onContent = async ({ + createDocument, + html, + times, + logHeap = () => {}, + cloneBench = true, + customElements = false, + mutationObserver = false +}) => { console.time(clean('\x1b[1mtotal benchmark time\x1b[0m')); @@ -38,7 +47,7 @@ const onContent = async (createDocument, html, times, logHeap = () => {}, cloneB let document; try { console.time(clean(' parsing \x1b[2mcold\x1b[0m')); - document = createDocument(html.toString()); + document = await createDocument(html); console.timeEnd(clean(' parsing \x1b[2mcold\x1b[0m')); console.log(); logHeap('document heap'); @@ -221,6 +230,7 @@ const onContent = async (createDocument, html, times, logHeap = () => {}, cloneB if (cloneBench) { await sleep(100); console.time(' html.innerHTML'); + // eslint-disable-next-line no-self-assign document.documentElement.innerHTML = document.documentElement.innerHTML; console.timeEnd(' html.innerHTML'); } diff --git a/test/stream/test-domstream.js b/test/benchmark/domstream.js similarity index 62% rename from test/stream/test-domstream.js rename to test/benchmark/domstream.js index 49da61fd..3ee0efcc 100644 --- a/test/stream/test-domstream.js +++ b/test/benchmark/domstream.js @@ -3,6 +3,7 @@ const {join} = require('path'); const {memoryUsage} = require('process'); const {DOMStream} = require('../../cjs/index.js'); +let silent = process.argv.some(arg => arg === '--silent'); let length = 0; @@ -15,13 +16,17 @@ const logStatus = (message = 'total heap memory') => { ); } +console.log(''); +console.log(`\x1b[7m\x1b[1m DOMStream \x1b[0m\x1b[7m\x1b[2m benchmark for \x1b[0m\x1b[7m ./html/html\x1b[0m`); +console.log(''); + logStatus('initial heap'); -const domStream = new DOMStream('text/xml', (name) => { - return name === 'hotelName'; +const domStream = new DOMStream('text/html', (name) => { + return name === 'span'; }); -const src = fs.createReadStream(join(__dirname, './big.xml')); +const src = fs.createReadStream(join(__dirname, './html.html')); src.on('data', chunk => { length += chunk.length; logStatus(); @@ -35,6 +40,7 @@ src.on('end', () => { }) src.pipe(domStream).ondocument(doc => { - console.log(doc.documentElement.outerHTML); - logStatus('doc heap'); + const html = doc.documentElement.outerHTML + if (!silent) console.log(html); + if (!silent) logStatus('doc heap'); }); diff --git a/test/benchmark/html.html b/test/benchmark/html.html index a89f67d3..2c6b4099 100644 --- a/test/benchmark/html.html +++ b/test/benchmark/html.html @@ -17,7 +17,7 @@