From da5c0c88b139833de2f57c7a621590f0157eb349 Mon Sep 17 00:00:00 2001 From: Jason <59297610+caracal-js@users.noreply.github.com> Date: Tue, 22 Feb 2022 23:31:05 -0500 Subject: [PATCH] Release is almost here! --- client/dom/style.js | 50 + client/index.js | 2 + example/index.js | 94 +- example/index.test.js | 229 - example/static/op.bundle.js | 24795 ----------------------------- example/static/op.handler.js | 765 - example/static/op.sw.js | 304 - example/static/op.test.sw.js | 206 - example/static/test.html | 0 index.js | 27 - lib/uv.bundle.js | 67 +- lib/uv.handler.js | 146 +- lib/uv.handler.test.js | 215 - lib/uv.sw.js | 77 +- rewrite/rewrite.script.test.js | 230 - server/v1/request.js | 33 - server/v1/test/index.js | 29 - server/v1/test/ssl.cert | 22 - server/v1/test/ssl.key | 28 - server/v1/test/static/index.html | 9 - server/v1/test/static/script.js | 8 - server/v1/test/static/sw.js | 28 - server/v1/upgrade.js | 3 - server/v1/util.js | 73 - tomp/EncodeProtocol.mjs | 57 + tomp/Example.mjs | 46 + tomp/HeaderUtil.mjs | 33 + tomp/LICENSE | 674 + tomp/README.md | 48 + tomp/Response.mjs | 34 + tomp/Server.mjs | 136 + tomp/Standalone.mjs | 79 + tomp/V1.mjs | 349 + tomp/package.json | 30 + worker/context.js | 14 - worker/index.js | 10 - 36 files changed, 1762 insertions(+), 27188 deletions(-) create mode 100644 client/dom/style.js delete mode 100644 example/index.test.js delete mode 100644 example/static/op.bundle.js delete mode 100644 example/static/op.handler.js delete mode 100644 example/static/op.sw.js delete mode 100644 example/static/op.test.sw.js delete mode 100644 example/static/test.html delete mode 100644 index.js delete mode 100644 lib/uv.handler.test.js delete mode 100644 rewrite/rewrite.script.test.js delete mode 100644 server/v1/request.js delete mode 100644 server/v1/test/index.js delete mode 100644 server/v1/test/ssl.cert delete mode 100644 server/v1/test/ssl.key delete mode 100644 server/v1/test/static/index.html delete mode 100644 server/v1/test/static/script.js delete mode 100644 server/v1/test/static/sw.js delete mode 100644 server/v1/upgrade.js delete mode 100644 server/v1/util.js create mode 100644 tomp/EncodeProtocol.mjs create mode 100644 tomp/Example.mjs create mode 100644 tomp/HeaderUtil.mjs create mode 100644 tomp/LICENSE create mode 100644 tomp/README.md create mode 100644 tomp/Response.mjs create mode 100644 tomp/Server.mjs create mode 100644 tomp/Standalone.mjs create mode 100644 tomp/V1.mjs create mode 100644 tomp/package.json delete mode 100644 worker/context.js delete mode 100644 worker/index.js diff --git a/client/dom/style.js b/client/dom/style.js new file mode 100644 index 0000000..77e476d --- /dev/null +++ b/client/dom/style.js @@ -0,0 +1,50 @@ +import EventEmitter from "../events.js"; +import HookEvent from "../hook.js"; + +class StyleApi extends EventEmitter { + constructor(ctx) { + super(); + this.ctx = ctx; + this.window = ctx.window; + this.CSSStyleDeclaration = this.window.CSSStyleDeclaration || {}; + this.cssStyleProto = this.CSSStyleDeclaration.prototype || {}; + this.getPropertyValue = this.cssStyleProto.getPropertyValue || null; + this.setProperty = this.cssStyleProto.setProperty || null; + this.urlProps = ['background', 'backgroundImage', 'borderImage', 'borderImageSource', 'listStyle', 'listStyleImage', 'cursor']; + this.dashedUrlProps = ['background', 'background-image', 'border-image', 'border-image-source', 'list-style', 'list-style-image', 'cursor']; + this.propToDashed = { + background: 'background', + backgroundImage: 'background-image', + borderImage: 'border-image', + borderImageSource: 'border-image-source', + listStyle: 'list-style', + listStyleImage: 'list-style-image', + cursor: 'cursor' + }; + }; + overrideSetGetProperty() { + this.ctx.override(this.cssStyleProto, 'getPropertyValue', (target, that, args) => { + if (!args.length) return target.apply(that, args); + + let [ property ] = args; + + const event = new HookEvent({ property }, target, that); + this.emit('getPropertyValue', event); + + if (event.intercepted) return event.returnValue; + return event.target.call(event.that, event.data.property); + }); + this.ctx.override(this.cssStyleProto, 'setProperty', (target, that, args) => { + if (2 > args.length) return target.apply(that, args); + let [ property, value ] = args; + + const event = new HookEvent({ property, value }, target, that); + this.emit('setProperty', event); + + if (event.intercepted) return event.returnValue; + return event.target.call(event.that, event.data.property, event.data.value); + }); + }; +}; + +export default StyleApi; \ No newline at end of file diff --git a/client/index.js b/client/index.js index 4b41a74..4e01903 100644 --- a/client/index.js +++ b/client/index.js @@ -16,6 +16,7 @@ import Workers from "./worker.js"; import URLApi from "./url.js"; import EventEmitter from "./events.js"; import StorageApi from "./storage.js"; +import StyleApi from "./dom/style.js"; class UVClient extends EventEmitter { constructor(window = self, worker = !window.window) { @@ -53,6 +54,7 @@ class UVClient extends EventEmitter { this.workers = new Workers(this); this.location = new LocationApi(this); this.storage = new StorageApi(this); + this.style = new StyleApi(this); }; initLocation(rewriteUrl, sourceUrl) { this.location = new LocationApi(this, sourceUrl, rewriteUrl, this.worker); diff --git a/example/index.js b/example/index.js index 1e56e3d..6ed10fc 100644 --- a/example/index.js +++ b/example/index.js @@ -2,7 +2,7 @@ import https from "https"; import httpStatic from "node-static"; import path from "path"; import { readFileSync, createReadStream, read } from "fs"; -import request from "../server/v1/request.js"; +import { Server as Bare } from '../tomp/Server.mjs'; const __dirname = path.resolve(path.dirname(decodeURI(new URL(import.meta.url).pathname))).slice(3); const config = JSON.parse(readFileSync(path.join(__dirname, './config.json'), 'utf-8')); @@ -13,10 +13,10 @@ const server = https.createServer({ cert: readFileSync(path.join(__dirname, './ssl.cert')), }); +const bare = new Bare('/bare/'); + server.on('request', (req, res) => { - if (req.url.startsWith(config.bare + 'v1/')) { - return request(req, res); - }; + if (bare.route_request(req, res)) return true; if (req.url.startsWith('/uv.handler.js')) { res.writeHead(200, { "Content-Type": "application/javascript" }); @@ -45,91 +45,11 @@ server.on('request', (req, res) => { file.serve(req, res); }); -const impl = { - 'accept-encoding': 'Accept-Encoding', - 'accept-language': 'Accept-Language', - 'accept': 'Accept', - 'sec-websocket-extensions': 'Sec-WebSocket-Extensions', - 'sec-websocket-key': 'Sec-WebSocket-Key', - 'sec-websocket-version': 'Sec-WebSocket-Version' -}; - server.on('upgrade', (req, socket, head) => { - if (!req.url.startsWith('/bare/v1/') || !req.headers['sec-websocket-protocol']) return socket.end(); - try { - const [ bare, data ] = req.headers['sec-websocket-protocol'].split(/,\s*/g); - const { - remote, - headers, - forward_headers: forward, - } = JSON.parse(decodeProtocol(data)); + if (!bare.route_upgrade(req, socket, head)) socket.end(); +}); - for (const header of forward) { - if (req.headers[header]) headers[(impl[header] || header)] = req.headers[header]; - }; - - const url = new URL(remote.protocol + '//' + remote.host + ':' + remote.port + remote.path); - const remoteRequest = (url.protocol === 'https:' ? https : http).request( - url, - { - headers, - method: req.method, - } - ); - - remoteRequest.on('upgrade', (remoteResponse, remoteSocket, remoteHead) => { - let handshake = 'HTTP/1.1 101 Web Socket Protocol Handshake\r\n'; - if (remoteResponse.headers['sec-websocket-accept']) handshake += `Sec-WebSocket-Accept: ${remoteResponse.headers['sec-websocket-accept']}\r\n`; - if (remoteResponse.headers['sec-websocket-extensions']) handshake += `Sec-WebSocket-Extensions: ${remoteResponse.headers['sec-websocket-extensions']}\r\n`; - handshake += `Sec-WebSocket-Protocol: bare\r\n`; - if (remoteResponse.headers['connection']) handshake += `Connection: ${remoteResponse.headers['connection']}\r\n`; - if (remoteResponse.headers['upgrade']) handshake += `Upgrade: ${remoteResponse.headers['upgrade']}\r\n`; - handshake += '\r\n'; - socket.write(handshake); - socket.write(remoteHead); - remoteSocket.on('close', () => socket.end()); - socket.on('close', () => remoteSocket.end()); - remoteSocket.on('error', () => socket.end()); - socket.on('error', () => remoteSocket.end()); - - remoteSocket.pipe(socket); - socket.pipe(remoteSocket); - }); - - remoteRequest.on('error', () => socket.end()); - - remoteRequest.end(); - - } catch(e) { - console.log(e); - socket.end(); - }; -}) - -function decodeProtocol(protocol){ - if(typeof protocol != 'string')throw new TypeError('protocol must be a string'); - - let result = ''; - - for(let i = 0; i < protocol.length; i++){ - const char = protocol[i]; - - if(char == '%'){ - const code = parseInt(protocol.slice(i + 1, i + 3), 16); - const decoded = String.fromCharCode(code); - - result += decoded; - i += 2; - }else{ - result += char; - } - } - - return result; -} - - -server.listen(443); +server.listen(3030); function createUVFileStream(file) { return createReadStream( diff --git a/example/index.test.js b/example/index.test.js deleted file mode 100644 index 1b585d7..0000000 --- a/example/index.test.js +++ /dev/null @@ -1,229 +0,0 @@ -import http from "http"; -import https from "https"; -import httpStatic from "node-static"; -import path from "path"; -import { readFileSync, createReadStream } from "fs"; -import webpack from "webpack"; - -const __dirname = path.resolve(path.dirname(decodeURI(new URL(import.meta.url).pathname))).slice(3); -const file = new httpStatic.Server(path.join(__dirname, './static/')); - -const server = https.createServer({ - key: readFileSync(path.join(__dirname, './ssl.key')), - cert: readFileSync(path.join(__dirname, './ssl.cert')), -}); - -server.on('request', (req, res) => { - - if (req.url.startsWith('/service/')) { - res.writeHead(200, { "Content-Type": "text/html", "Cache-Control": 'no-cache' }); - createReadStream(path.join(__dirname, './load.html')).pipe(res); - return; - }; - - if (!req.url.startsWith('/bare/v1/')) return file.serve(req, res); - - - try { - const headers = JSON.parse(req.headers['x-bare-headers']); - const forward = JSON.parse((req.headers['x-bare-forward-headers'] || '[]')); - const url = new URL(req.headers['x-bare-protocol'] + '//' + req.headers['x-bare-host'] + ':' + req.headers['x-bare-port'] + req.headers['x-bare-path']); - - for (const header of forward) { - if (req.headers[header]) headers[header] = req.headers[header]; - }; - - const remoteRequest = (url.protocol === 'https:' ? https : http).request( - url, - { - headers: headers, - method: req.method, - } - ); - - remoteRequest.on('response', remoteResponse => { - remoteResponse.headers['x-bare-headers'] = JSON.stringify(remoteResponse.headers); - remoteResponse.headers['x-bare-status'] = remoteResponse.statusCode.toString(); - remoteResponse.headers['x-bare-status-text'] = remoteResponse.statusMessage; - remoteResponse.headers['cache-control'] = 'no-cache'; - - const headers = { - 'x-bare-headers': JSON.stringify(remoteResponse.headers), - 'x-bare-status': remoteResponse.statusCode.toString(), - 'x-bare-status-text': remoteResponse.statusMessage, - 'cache-control': 'no-cache', - }; - - if (remoteResponse.headers['content-encoding']) headers['content-encoding'] = remoteResponse.headers['content-encoding']; - if (remoteResponse.headers['content-length']) headers['content-length'] = remoteResponse.headers['content-length']; - - res.writeHead(200, headers); - remoteResponse.pipe(res); - }); - - remoteRequest.on('error', e => { - res.writeHead(500, {}); - res.end(); - }); - - req.pipe(remoteRequest); - } catch(e) { - res.writeHead(500, {}); - res.end(); - }; - -}); - -const impl = { - 'accept-encoding': 'Accept-Encoding', - 'accept-language': 'Accept-Language', - 'accept': 'Accept', - 'sec-websocket-extensions': 'Sec-WebSocket-Extensions', - 'sec-websocket-key': 'Sec-WebSocket-Key', - 'sec-websocket-version': 'Sec-WebSocket-Version' -}; - -server.on('upgrade', (req, socket, head) => { - if (!req.url.startsWith('/bare/v1/') || !req.headers['sec-websocket-protocol']) return socket.end(); - try { - const [ bare, data ] = req.headers['sec-websocket-protocol'].split(/,\s*/g); - const { - remote, - headers, - forward_headers: forward, - } = JSON.parse(decodeProtocol(data)); - - for (const header of forward) { - if (req.headers[header]) headers[(impl[header] || header)] = req.headers[header]; - }; - - const url = new URL(remote.protocol + '//' + remote.host + ':' + remote.port + remote.path); - const remoteRequest = (url.protocol === 'https:' ? https : http).request( - url, - { - headers, - method: req.method, - } - ); - - remoteRequest.on('upgrade', (remoteResponse, remoteSocket, remoteHead) => { - let handshake = 'HTTP/1.1 101 Web Socket Protocol Handshake\r\n'; - if (remoteResponse.headers['sec-websocket-accept']) handshake += `Sec-WebSocket-Accept: ${remoteResponse.headers['sec-websocket-accept']}\r\n`; - if (remoteResponse.headers['sec-websocket-extensions']) handshake += `Sec-WebSocket-Extensions: ${remoteResponse.headers['sec-websocket-extensions']}\r\n`; - handshake += `Sec-WebSocket-Protocol: bare\r\n`; - if (remoteResponse.headers['connection']) handshake += `Connection: ${remoteResponse.headers['connection']}\r\n`; - if (remoteResponse.headers['upgrade']) handshake += `Upgrade: ${remoteResponse.headers['upgrade']}\r\n`; - handshake += '\r\n'; - socket.write(handshake); - socket.write(remoteHead); - remoteSocket.on('close', () => socket.end()); - socket.on('close', () => remoteSocket.end()); - remoteSocket.on('error', () => socket.end()); - socket.on('error', () => remoteSocket.end()); - - remoteSocket.pipe(socket); - socket.pipe(remoteSocket); - }); - - remoteRequest.on('error', () => socket.end()); - - remoteRequest.end(); - - } catch(e) { - console.log(e); - socket.end(); - }; -}); - - -server.listen(443); - - -const valid_chars = "!#$%&'*+-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz|~"; -const reserved_chars = "%"; - -function encodeProtocol(protocol){ - protocol = protocol.toString(); - - let result = ''; - - for(let i = 0; i < protocol.length; i++){ - const char = protocol[i]; - - if(valid_chars.includes(char) && !reserved_chars.includes(char)){ - result += char; - }else{ - const code = char.charCodeAt(); - result += '%' + code.toString(16).padStart(2, 0); - } - } - - return result; -} - -function decodeProtocol(protocol){ - if(typeof protocol != 'string')throw new TypeError('protocol must be a string'); - - let result = ''; - - for(let i = 0; i < protocol.length; i++){ - const char = protocol[i]; - - if(char == '%'){ - const code = parseInt(protocol.slice(i + 1, i + 3), 16); - const decoded = String.fromCharCode(code); - - result += decoded; - i += 2; - }else{ - result += char; - } - } - - return result; -} - - -function parseRawHeaders(rawHeaders = []) { - const obj = {}; - - for (let i = 0; i < rawHeaders.length; i+=2) { - const name = rawHeaders[i] || ''; - const lowerCaseName = name.toLowerCase(); - const value = rawHeaders[i + 1] || ''; - - if (lowerCaseName in obj) { - if (Array.isArray(obj[lowerCaseName].value)) { - obj[lowerCaseName].value.push(value); - } else { - obj[lowerCaseName].value = [ obj[lowerCaseName].value, value ]; - }; - } else { - obj[lowerCaseName] = { name, value }; - }; - }; - - return obj; -}; - -function compileParsedHeaders(headers = {}, prefix = false) { - const compiled = {}; - - for (const key in headers) { - const { name, value } = headers[key]; - compiled[(prefix ? 'x-op-' : '') + name] = value; - }; - - return compiled; -}; - -webpack({ - mode: 'none', - entry: path.join(__dirname, '../lib/index.js'), - output: { - path: __dirname, - filename: './static/op.bundle.js', - } -}, (err, i) => - console.log(!err ? 'Ultraviolet bundled!' : 'Err') -); \ No newline at end of file diff --git a/example/static/op.bundle.js b/example/static/op.bundle.js deleted file mode 100644 index f65c52b..0000000 --- a/example/static/op.bundle.js +++ /dev/null @@ -1,24795 +0,0 @@ -/******/ (() => { // webpackBootstrap -/******/ var __webpack_modules__ = ([ -/* 0 */, -/* 1 */ -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) -/* harmony export */ }); -/* harmony import */ var _events_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); -/* harmony import */ var parse5__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3); - - - -class HTML extends _events_js__WEBPACK_IMPORTED_MODULE_0__["default"] { - constructor(ctx) { - super(); - this.ctx = ctx; - this.rewriteUrl = ctx.rewriteUrl; - this.sourceUrl = ctx.sourceUrl; - }; - rewrite(str, options = {}) { - if (!str) return str; - return this.recast(str, node => { - if (node.tagName) this.emit('element', node, 'rewrite'); - if (node.attr) this.emit('attr', node, 'rewrite'); - if (node.nodeName === '#text') this.emit('text', node, 'rewrite'); - }, options) - }; - source(str, options = {}) { - if (!str) return str; - return this.recast(str, node => { - if (node.tagName) this.emit('element', node, 'source'); - if (node.attr) this.emit('attr', node, 'source'); - if (node.nodeName === '#text') this.emit('text', node, 'source'); - }, options) - }; - recast(str, fn, options = {}) { - try { - const ast = (options.document ? parse5__WEBPACK_IMPORTED_MODULE_1__.parse : parse5__WEBPACK_IMPORTED_MODULE_1__.parseFragment)(new String(str).toString()); - this.iterate(ast, fn, options); - return (0,parse5__WEBPACK_IMPORTED_MODULE_1__.serialize)(ast); - } catch(e) { - return str; - }; - }; - iterate(ast, fn, fnOptions) { - if (!ast) return ast; - - if (ast.tagName) { - const element = new P5Element(ast, false, fnOptions); - fn(element); - if (ast.attrs) { - for (const attr of ast.attrs) { - if (!attr.skip) fn(new AttributeEvent(element, attr, fnOptions)); - }; - }; - }; - - if (ast.childNodes) { - for (const child of ast.childNodes) { - if (!child.skip) this.iterate(child, fn, fnOptions); - }; - }; - - if (ast.nodeName === '#text') { - fn(new TextEvent(ast, new P5Element(ast.parentNode), false, fnOptions)); - }; - - return ast; - }; - wrapSrcset(str, meta = this.ctx.meta) { - return str.split(',').map(src => { - const parts = src.trimStart().split(' '); - if (parts[0]) parts[0] = this.ctx.rewriteUrl(parts[0], meta); - return parts.join(' '); - }).join(', '); - }; - unwrapSrcset(str, meta = this.ctx.meta) { - return str.split(',').map(src => { - const parts = src.trimStart().split(' '); - if (parts[0]) parts[0] = this.ctx.sourceUrl(parts[0], meta); - return parts.join(' '); - }).join(', '); - }; - static parse = parse5__WEBPACK_IMPORTED_MODULE_1__.parse; - static parseFragment = parse5__WEBPACK_IMPORTED_MODULE_1__.parseFragment; - static serialize = parse5__WEBPACK_IMPORTED_MODULE_1__.serialize; -}; - -class P5Element extends _events_js__WEBPACK_IMPORTED_MODULE_0__["default"] { - constructor(node, stream = false, options = {}) { - super(); - this.stream = stream; - this.node = node; - this.options = options; - }; - setAttribute(name, value) { - for (const attr of this.attrs) { - if (attr.name === name) { - attr.value = value; - return true; - }; - }; - - this.attrs.push( - { - name, - value, - } - ); - }; - getAttribute(name) { - const attr = this.attrs.find(attr => attr.name === name) || {}; - return attr.value; - }; - hasAttribute(name) { - return !!this.attrs.find(attr => attr.name === name); - }; - removeAttribute(name) { - const i = this.attrs.findIndex(attr => attr.name === name); - if (typeof i !== 'undefined') this.attrs.splice(i, 1); - }; - get tagName() { - return this.node.tagName; - }; - set tagName(val) { - this.node.tagName = val; - }; - get childNodes() { - return !this.stream ? this.node.childNodes : null; - }; - get innerHTML() { - return !this.stream ? (0,parse5__WEBPACK_IMPORTED_MODULE_1__.serialize)( - { - nodeName: '#document-fragment', - childNodes: this.childNodes, - } - ) : null; - }; - set innerHTML(val) { - if (!this.stream) this.node.childNodes = (0,parse5__WEBPACK_IMPORTED_MODULE_1__.parseFragment)(val).childNodes; - }; - get outerHTML() { - return !this.stream ? (0,parse5__WEBPACK_IMPORTED_MODULE_1__.serialize)( - { - nodeName: '#document-fragment', - childNodes: [ this ], - } - ) : null; - }; - set outerHTML(val) { - if (!this.stream) this.parentNode.childNodes.splice(this.parentNode.childNodes.findIndex(node => node === this.node), 1, ...(0,parse5__WEBPACK_IMPORTED_MODULE_1__.parseFragment)(val).childNodes); - }; - get textContent() { - if (this.stream) return null; - - let str = ''; - iterate(this.node, node => { - if (node.nodeName === '#text') str += node.value; - }); - - return str; - }; - set textContent(val) { - if (!this.stream) this.node.childNodes = [ - { - nodeName: '#text', - value: val, - parentNode: this.node - } - ]; - }; - get nodeName() { - return this.node.nodeName; - } - get parentNode() { - return this.node.parentNode ? new P5Element(this.node.parentNode) : null; - }; - get attrs() { - return this.node.attrs; - } - get namespaceURI() { - return this.node.namespaceURI; - } -}; - -class AttributeEvent { - constructor(node, attr, options = {}) { - this.attr = attr; - this.attrs = node.attrs; - this.node = node; - this.options = options; - }; - delete() { - const i = this.attrs.findIndex(attr => attr === this.attr); - - this.attrs.splice(i, 1); - - Object.defineProperty(this, 'deleted', { - get: () => true, - }); - - return true; - }; - get name() { - return this.attr.name; - }; - - set name(val) { - this.attr.name = val; - }; - get value() { - return this.attr.value; - }; - - set value(val) { - this.attr.value = val; - }; - get deleted() { - return false; - }; -}; - -class TextEvent { - constructor(node, element, stream = false, options = {}) { - this.stream = stream; - this.node = node; - this.element = element; - this.options = options; - }; - get nodeName() { - return this.node.nodeName; - } - get parentNode() { - return this.element; - }; - get value() { - return this.stream ? this.node.text : this.node.value; - }; - set value(val) { - - if (this.stream) this.node.text = val; - else this.node.value = val; - }; -}; - -/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (HTML); - -/***/ }), -/* 2 */ -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) -/* harmony export */ }); -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - - - -var R = typeof Reflect === 'object' ? Reflect : null -var ReflectApply = R && typeof R.apply === 'function' - ? R.apply - : function ReflectApply(target, receiver, args) { - return Function.prototype.apply.call(target, receiver, args); - } - -var ReflectOwnKeys -if (R && typeof R.ownKeys === 'function') { - ReflectOwnKeys = R.ownKeys -} else if (Object.getOwnPropertySymbols) { - ReflectOwnKeys = function ReflectOwnKeys(target) { - return Object.getOwnPropertyNames(target) - .concat(Object.getOwnPropertySymbols(target)); - }; -} else { - ReflectOwnKeys = function ReflectOwnKeys(target) { - return Object.getOwnPropertyNames(target); - }; -} - -function ProcessEmitWarning(warning) { - if (console && console.warn) console.warn(warning); -} - -var NumberIsNaN = Number.isNaN || function NumberIsNaN(value) { - return value !== value; -} - -function EventEmitter() { - EventEmitter.init.call(this); -} - -/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (EventEmitter); - -// Backwards-compat with node 0.10.x -EventEmitter.EventEmitter = EventEmitter; - -EventEmitter.prototype._events = undefined; -EventEmitter.prototype._eventsCount = 0; -EventEmitter.prototype._maxListeners = undefined; - -// By default EventEmitters will print a warning if more than 10 listeners are -// added to it. This is a useful default which helps finding memory leaks. -var defaultMaxListeners = 10; - -function checkListener(listener) { - if (typeof listener !== 'function') { - throw new TypeError('The "listener" argument must be of type Function. Received type ' + typeof listener); - } -} - -Object.defineProperty(EventEmitter, 'defaultMaxListeners', { - enumerable: true, - get: function() { - return defaultMaxListeners; - }, - set: function(arg) { - if (typeof arg !== 'number' || arg < 0 || NumberIsNaN(arg)) { - throw new RangeError('The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received ' + arg + '.'); - } - defaultMaxListeners = arg; - } -}); - -EventEmitter.init = function() { - - if (this._events === undefined || - this._events === Object.getPrototypeOf(this)._events) { - this._events = Object.create(null); - this._eventsCount = 0; - } - - this._maxListeners = this._maxListeners || undefined; -}; - -// Obviously not all Emitters should be limited to 10. This function allows -// that to be increased. Set to zero for unlimited. -EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) { - if (typeof n !== 'number' || n < 0 || NumberIsNaN(n)) { - throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received ' + n + '.'); - } - this._maxListeners = n; - return this; -}; - -function _getMaxListeners(that) { - if (that._maxListeners === undefined) - return EventEmitter.defaultMaxListeners; - return that._maxListeners; -} - -EventEmitter.prototype.getMaxListeners = function getMaxListeners() { - return _getMaxListeners(this); -}; - -EventEmitter.prototype.emit = function emit(type) { - var args = []; - for (var i = 1; i < arguments.length; i++) args.push(arguments[i]); - var doError = (type === 'error'); - - var events = this._events; - if (events !== undefined) - doError = (doError && events.error === undefined); - else if (!doError) - return false; - - // If there is no 'error' event listener then throw. - if (doError) { - var er; - if (args.length > 0) - er = args[0]; - if (er instanceof Error) { - // Note: The comments on the `throw` lines are intentional, they show - // up in Node's output if this results in an unhandled exception. - throw er; // Unhandled 'error' event - } - // At least give some kind of context to the user - var err = new Error('Unhandled error.' + (er ? ' (' + er.message + ')' : '')); - err.context = er; - throw err; // Unhandled 'error' event - } - - var handler = events[type]; - - if (handler === undefined) - return false; - - if (typeof handler === 'function') { - ReflectApply(handler, this, args); - } else { - var len = handler.length; - var listeners = arrayClone(handler, len); - for (var i = 0; i < len; ++i) - ReflectApply(listeners[i], this, args); - } - - return true; -}; - -function _addListener(target, type, listener, prepend) { - var m; - var events; - var existing; - - checkListener(listener); - - events = target._events; - if (events === undefined) { - events = target._events = Object.create(null); - target._eventsCount = 0; - } else { - // To avoid recursion in the case that type === "newListener"! Before - // adding it to the listeners, first emit "newListener". - if (events.newListener !== undefined) { - target.emit('newListener', type, - listener.listener ? listener.listener : listener); - - // Re-assign `events` because a newListener handler could have caused the - // this._events to be assigned to a new object - events = target._events; - } - existing = events[type]; - } - - if (existing === undefined) { - // Optimize the case of one listener. Don't need the extra array object. - existing = events[type] = listener; - ++target._eventsCount; - } else { - if (typeof existing === 'function') { - // Adding the second element, need to change to array. - existing = events[type] = - prepend ? [listener, existing] : [existing, listener]; - // If we've already got an array, just append. - } else if (prepend) { - existing.unshift(listener); - } else { - existing.push(listener); - } - - // Check for listener leak - m = _getMaxListeners(target); - if (m > 0 && existing.length > m && !existing.warned) { - existing.warned = true; - // No error code for this since it is a Warning - // eslint-disable-next-line no-restricted-syntax - var w = new Error('Possible EventEmitter memory leak detected. ' + - existing.length + ' ' + String(type) + ' listeners ' + - 'added. Use emitter.setMaxListeners() to ' + - 'increase limit'); - w.name = 'MaxListenersExceededWarning'; - w.emitter = target; - w.type = type; - w.count = existing.length; - ProcessEmitWarning(w); - } - } - - return target; -} - -EventEmitter.prototype.addListener = function addListener(type, listener) { - return _addListener(this, type, listener, false); -}; - -EventEmitter.prototype.on = EventEmitter.prototype.addListener; - -EventEmitter.prototype.prependListener = - function prependListener(type, listener) { - return _addListener(this, type, listener, true); - }; - -function onceWrapper() { - if (!this.fired) { - this.target.removeListener(this.type, this.wrapFn); - this.fired = true; - if (arguments.length === 0) - return this.listener.call(this.target); - return this.listener.apply(this.target, arguments); - } -} - -function _onceWrap(target, type, listener) { - var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener }; - var wrapped = onceWrapper.bind(state); - wrapped.listener = listener; - state.wrapFn = wrapped; - return wrapped; -} - -EventEmitter.prototype.once = function once(type, listener) { - checkListener(listener); - this.on(type, _onceWrap(this, type, listener)); - return this; -}; - -EventEmitter.prototype.prependOnceListener = - function prependOnceListener(type, listener) { - checkListener(listener); - this.prependListener(type, _onceWrap(this, type, listener)); - return this; - }; - -// Emits a 'removeListener' event if and only if the listener was removed. -EventEmitter.prototype.removeListener = - function removeListener(type, listener) { - var list, events, position, i, originalListener; - - checkListener(listener); - - events = this._events; - if (events === undefined) - return this; - - list = events[type]; - if (list === undefined) - return this; - - if (list === listener || list.listener === listener) { - if (--this._eventsCount === 0) - this._events = Object.create(null); - else { - delete events[type]; - if (events.removeListener) - this.emit('removeListener', type, list.listener || listener); - } - } else if (typeof list !== 'function') { - position = -1; - - for (i = list.length - 1; i >= 0; i--) { - if (list[i] === listener || list[i].listener === listener) { - originalListener = list[i].listener; - position = i; - break; - } - } - - if (position < 0) - return this; - - if (position === 0) - list.shift(); - else { - spliceOne(list, position); - } - - if (list.length === 1) - events[type] = list[0]; - - if (events.removeListener !== undefined) - this.emit('removeListener', type, originalListener || listener); - } - - return this; - }; - -EventEmitter.prototype.off = EventEmitter.prototype.removeListener; - -EventEmitter.prototype.removeAllListeners = - function removeAllListeners(type) { - var listeners, events, i; - - events = this._events; - if (events === undefined) - return this; - - // not listening for removeListener, no need to emit - if (events.removeListener === undefined) { - if (arguments.length === 0) { - this._events = Object.create(null); - this._eventsCount = 0; - } else if (events[type] !== undefined) { - if (--this._eventsCount === 0) - this._events = Object.create(null); - else - delete events[type]; - } - return this; - } - - // emit removeListener for all listeners on all events - if (arguments.length === 0) { - var keys = Object.keys(events); - var key; - for (i = 0; i < keys.length; ++i) { - key = keys[i]; - if (key === 'removeListener') continue; - this.removeAllListeners(key); - } - this.removeAllListeners('removeListener'); - this._events = Object.create(null); - this._eventsCount = 0; - return this; - } - - listeners = events[type]; - - if (typeof listeners === 'function') { - this.removeListener(type, listeners); - } else if (listeners !== undefined) { - // LIFO order - for (i = listeners.length - 1; i >= 0; i--) { - this.removeListener(type, listeners[i]); - } - } - - return this; - }; - -function _listeners(target, type, unwrap) { - var events = target._events; - - if (events === undefined) - return []; - - var evlistener = events[type]; - if (evlistener === undefined) - return []; - - if (typeof evlistener === 'function') - return unwrap ? [evlistener.listener || evlistener] : [evlistener]; - - return unwrap ? - unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length); -} - -EventEmitter.prototype.listeners = function listeners(type) { - return _listeners(this, type, true); -}; - -EventEmitter.prototype.rawListeners = function rawListeners(type) { - return _listeners(this, type, false); -}; - -EventEmitter.listenerCount = function(emitter, type) { - if (typeof emitter.listenerCount === 'function') { - return emitter.listenerCount(type); - } else { - return listenerCount.call(emitter, type); - } -}; - -EventEmitter.prototype.listenerCount = listenerCount; -function listenerCount(type) { - var events = this._events; - - if (events !== undefined) { - var evlistener = events[type]; - - if (typeof evlistener === 'function') { - return 1; - } else if (evlistener !== undefined) { - return evlistener.length; - } - } - - return 0; -} - -EventEmitter.prototype.eventNames = function eventNames() { - return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : []; -}; - -function arrayClone(arr, n) { - var copy = new Array(n); - for (var i = 0; i < n; ++i) - copy[i] = arr[i]; - return copy; -} - -function spliceOne(list, index) { - for (; index + 1 < list.length; index++) - list[index] = list[index + 1]; - list.pop(); -} - -function unwrapListeners(arr) { - var ret = new Array(arr.length); - for (var i = 0; i < ret.length; ++i) { - ret[i] = arr[i].listener || arr[i]; - } - return ret; -} - -function once(emitter, name) { - return new Promise(function (resolve, reject) { - function errorListener(err) { - emitter.removeListener(name, resolver); - reject(err); - } - - function resolver() { - if (typeof emitter.removeListener === 'function') { - emitter.removeListener('error', errorListener); - } - resolve([].slice.call(arguments)); - }; - - eventTargetAgnosticAddListener(emitter, name, resolver, { once: true }); - if (name !== 'error') { - addErrorHandlerIfEventEmitter(emitter, errorListener, { once: true }); - } - }); -} - -function addErrorHandlerIfEventEmitter(emitter, handler, flags) { - if (typeof emitter.on === 'function') { - eventTargetAgnosticAddListener(emitter, 'error', handler, flags); - } -} - -function eventTargetAgnosticAddListener(emitter, name, listener, flags) { - if (typeof emitter.on === 'function') { - if (flags.once) { - emitter.once(name, listener); - } else { - emitter.on(name, listener); - } - } else if (typeof emitter.addEventListener === 'function') { - // EventTarget does not have `error` event semantics like Node - // EventEmitters, we do not listen for `error` events here. - emitter.addEventListener(name, function wrapListener(arg) { - // IE does not have builtin `{ once: true }` support so we - // have to do it manually. - if (flags.once) { - emitter.removeEventListener(name, wrapListener); - } - listener(arg); - }); - } else { - throw new TypeError('The "emitter" argument must be of type EventEmitter. Received type ' + typeof emitter); - } -} - -/***/ }), -/* 3 */ -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - - -const Parser = __webpack_require__(4); -const Serializer = __webpack_require__(26); - -// Shorthands -exports.parse = function parse(html, options) { - const parser = new Parser(options); - - return parser.parse(html); -}; - -exports.parseFragment = function parseFragment(fragmentContext, html, options) { - if (typeof fragmentContext === 'string') { - options = html; - html = fragmentContext; - fragmentContext = null; - } - - const parser = new Parser(options); - - return parser.parseFragment(html, fragmentContext); -}; - -exports.serialize = function(node, options) { - const serializer = new Serializer(node, options); - - return serializer.serialize(); -}; - - -/***/ }), -/* 4 */ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; - - -const Tokenizer = __webpack_require__(5); -const OpenElementStack = __webpack_require__(10); -const FormattingElementList = __webpack_require__(12); -const LocationInfoParserMixin = __webpack_require__(13); -const ErrorReportingParserMixin = __webpack_require__(18); -const Mixin = __webpack_require__(14); -const defaultTreeAdapter = __webpack_require__(22); -const mergeOptions = __webpack_require__(23); -const doctype = __webpack_require__(24); -const foreignContent = __webpack_require__(25); -const ERR = __webpack_require__(8); -const unicode = __webpack_require__(7); -const HTML = __webpack_require__(11); - -//Aliases -const $ = HTML.TAG_NAMES; -const NS = HTML.NAMESPACES; -const ATTRS = HTML.ATTRS; - -const DEFAULT_OPTIONS = { - scriptingEnabled: true, - sourceCodeLocationInfo: false, - onParseError: null, - treeAdapter: defaultTreeAdapter -}; - -//Misc constants -const HIDDEN_INPUT_TYPE = 'hidden'; - -//Adoption agency loops iteration count -const AA_OUTER_LOOP_ITER = 8; -const AA_INNER_LOOP_ITER = 3; - -//Insertion modes -const INITIAL_MODE = 'INITIAL_MODE'; -const BEFORE_HTML_MODE = 'BEFORE_HTML_MODE'; -const BEFORE_HEAD_MODE = 'BEFORE_HEAD_MODE'; -const IN_HEAD_MODE = 'IN_HEAD_MODE'; -const IN_HEAD_NO_SCRIPT_MODE = 'IN_HEAD_NO_SCRIPT_MODE'; -const AFTER_HEAD_MODE = 'AFTER_HEAD_MODE'; -const IN_BODY_MODE = 'IN_BODY_MODE'; -const TEXT_MODE = 'TEXT_MODE'; -const IN_TABLE_MODE = 'IN_TABLE_MODE'; -const IN_TABLE_TEXT_MODE = 'IN_TABLE_TEXT_MODE'; -const IN_CAPTION_MODE = 'IN_CAPTION_MODE'; -const IN_COLUMN_GROUP_MODE = 'IN_COLUMN_GROUP_MODE'; -const IN_TABLE_BODY_MODE = 'IN_TABLE_BODY_MODE'; -const IN_ROW_MODE = 'IN_ROW_MODE'; -const IN_CELL_MODE = 'IN_CELL_MODE'; -const IN_SELECT_MODE = 'IN_SELECT_MODE'; -const IN_SELECT_IN_TABLE_MODE = 'IN_SELECT_IN_TABLE_MODE'; -const IN_TEMPLATE_MODE = 'IN_TEMPLATE_MODE'; -const AFTER_BODY_MODE = 'AFTER_BODY_MODE'; -const IN_FRAMESET_MODE = 'IN_FRAMESET_MODE'; -const AFTER_FRAMESET_MODE = 'AFTER_FRAMESET_MODE'; -const AFTER_AFTER_BODY_MODE = 'AFTER_AFTER_BODY_MODE'; -const AFTER_AFTER_FRAMESET_MODE = 'AFTER_AFTER_FRAMESET_MODE'; - -//Insertion mode reset map -const INSERTION_MODE_RESET_MAP = { - [$.TR]: IN_ROW_MODE, - [$.TBODY]: IN_TABLE_BODY_MODE, - [$.THEAD]: IN_TABLE_BODY_MODE, - [$.TFOOT]: IN_TABLE_BODY_MODE, - [$.CAPTION]: IN_CAPTION_MODE, - [$.COLGROUP]: IN_COLUMN_GROUP_MODE, - [$.TABLE]: IN_TABLE_MODE, - [$.BODY]: IN_BODY_MODE, - [$.FRAMESET]: IN_FRAMESET_MODE -}; - -//Template insertion mode switch map -const TEMPLATE_INSERTION_MODE_SWITCH_MAP = { - [$.CAPTION]: IN_TABLE_MODE, - [$.COLGROUP]: IN_TABLE_MODE, - [$.TBODY]: IN_TABLE_MODE, - [$.TFOOT]: IN_TABLE_MODE, - [$.THEAD]: IN_TABLE_MODE, - [$.COL]: IN_COLUMN_GROUP_MODE, - [$.TR]: IN_TABLE_BODY_MODE, - [$.TD]: IN_ROW_MODE, - [$.TH]: IN_ROW_MODE -}; - -//Token handlers map for insertion modes -const TOKEN_HANDLERS = { - [INITIAL_MODE]: { - [Tokenizer.CHARACTER_TOKEN]: tokenInInitialMode, - [Tokenizer.NULL_CHARACTER_TOKEN]: tokenInInitialMode, - [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: ignoreToken, - [Tokenizer.COMMENT_TOKEN]: appendComment, - [Tokenizer.DOCTYPE_TOKEN]: doctypeInInitialMode, - [Tokenizer.START_TAG_TOKEN]: tokenInInitialMode, - [Tokenizer.END_TAG_TOKEN]: tokenInInitialMode, - [Tokenizer.EOF_TOKEN]: tokenInInitialMode - }, - [BEFORE_HTML_MODE]: { - [Tokenizer.CHARACTER_TOKEN]: tokenBeforeHtml, - [Tokenizer.NULL_CHARACTER_TOKEN]: tokenBeforeHtml, - [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: ignoreToken, - [Tokenizer.COMMENT_TOKEN]: appendComment, - [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, - [Tokenizer.START_TAG_TOKEN]: startTagBeforeHtml, - [Tokenizer.END_TAG_TOKEN]: endTagBeforeHtml, - [Tokenizer.EOF_TOKEN]: tokenBeforeHtml - }, - [BEFORE_HEAD_MODE]: { - [Tokenizer.CHARACTER_TOKEN]: tokenBeforeHead, - [Tokenizer.NULL_CHARACTER_TOKEN]: tokenBeforeHead, - [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: ignoreToken, - [Tokenizer.COMMENT_TOKEN]: appendComment, - [Tokenizer.DOCTYPE_TOKEN]: misplacedDoctype, - [Tokenizer.START_TAG_TOKEN]: startTagBeforeHead, - [Tokenizer.END_TAG_TOKEN]: endTagBeforeHead, - [Tokenizer.EOF_TOKEN]: tokenBeforeHead - }, - [IN_HEAD_MODE]: { - [Tokenizer.CHARACTER_TOKEN]: tokenInHead, - [Tokenizer.NULL_CHARACTER_TOKEN]: tokenInHead, - [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters, - [Tokenizer.COMMENT_TOKEN]: appendComment, - [Tokenizer.DOCTYPE_TOKEN]: misplacedDoctype, - [Tokenizer.START_TAG_TOKEN]: startTagInHead, - [Tokenizer.END_TAG_TOKEN]: endTagInHead, - [Tokenizer.EOF_TOKEN]: tokenInHead - }, - [IN_HEAD_NO_SCRIPT_MODE]: { - [Tokenizer.CHARACTER_TOKEN]: tokenInHeadNoScript, - [Tokenizer.NULL_CHARACTER_TOKEN]: tokenInHeadNoScript, - [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters, - [Tokenizer.COMMENT_TOKEN]: appendComment, - [Tokenizer.DOCTYPE_TOKEN]: misplacedDoctype, - [Tokenizer.START_TAG_TOKEN]: startTagInHeadNoScript, - [Tokenizer.END_TAG_TOKEN]: endTagInHeadNoScript, - [Tokenizer.EOF_TOKEN]: tokenInHeadNoScript - }, - [AFTER_HEAD_MODE]: { - [Tokenizer.CHARACTER_TOKEN]: tokenAfterHead, - [Tokenizer.NULL_CHARACTER_TOKEN]: tokenAfterHead, - [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters, - [Tokenizer.COMMENT_TOKEN]: appendComment, - [Tokenizer.DOCTYPE_TOKEN]: misplacedDoctype, - [Tokenizer.START_TAG_TOKEN]: startTagAfterHead, - [Tokenizer.END_TAG_TOKEN]: endTagAfterHead, - [Tokenizer.EOF_TOKEN]: tokenAfterHead - }, - [IN_BODY_MODE]: { - [Tokenizer.CHARACTER_TOKEN]: characterInBody, - [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken, - [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: whitespaceCharacterInBody, - [Tokenizer.COMMENT_TOKEN]: appendComment, - [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, - [Tokenizer.START_TAG_TOKEN]: startTagInBody, - [Tokenizer.END_TAG_TOKEN]: endTagInBody, - [Tokenizer.EOF_TOKEN]: eofInBody - }, - [TEXT_MODE]: { - [Tokenizer.CHARACTER_TOKEN]: insertCharacters, - [Tokenizer.NULL_CHARACTER_TOKEN]: insertCharacters, - [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters, - [Tokenizer.COMMENT_TOKEN]: ignoreToken, - [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, - [Tokenizer.START_TAG_TOKEN]: ignoreToken, - [Tokenizer.END_TAG_TOKEN]: endTagInText, - [Tokenizer.EOF_TOKEN]: eofInText - }, - [IN_TABLE_MODE]: { - [Tokenizer.CHARACTER_TOKEN]: characterInTable, - [Tokenizer.NULL_CHARACTER_TOKEN]: characterInTable, - [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: characterInTable, - [Tokenizer.COMMENT_TOKEN]: appendComment, - [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, - [Tokenizer.START_TAG_TOKEN]: startTagInTable, - [Tokenizer.END_TAG_TOKEN]: endTagInTable, - [Tokenizer.EOF_TOKEN]: eofInBody - }, - [IN_TABLE_TEXT_MODE]: { - [Tokenizer.CHARACTER_TOKEN]: characterInTableText, - [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken, - [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: whitespaceCharacterInTableText, - [Tokenizer.COMMENT_TOKEN]: tokenInTableText, - [Tokenizer.DOCTYPE_TOKEN]: tokenInTableText, - [Tokenizer.START_TAG_TOKEN]: tokenInTableText, - [Tokenizer.END_TAG_TOKEN]: tokenInTableText, - [Tokenizer.EOF_TOKEN]: tokenInTableText - }, - [IN_CAPTION_MODE]: { - [Tokenizer.CHARACTER_TOKEN]: characterInBody, - [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken, - [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: whitespaceCharacterInBody, - [Tokenizer.COMMENT_TOKEN]: appendComment, - [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, - [Tokenizer.START_TAG_TOKEN]: startTagInCaption, - [Tokenizer.END_TAG_TOKEN]: endTagInCaption, - [Tokenizer.EOF_TOKEN]: eofInBody - }, - [IN_COLUMN_GROUP_MODE]: { - [Tokenizer.CHARACTER_TOKEN]: tokenInColumnGroup, - [Tokenizer.NULL_CHARACTER_TOKEN]: tokenInColumnGroup, - [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters, - [Tokenizer.COMMENT_TOKEN]: appendComment, - [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, - [Tokenizer.START_TAG_TOKEN]: startTagInColumnGroup, - [Tokenizer.END_TAG_TOKEN]: endTagInColumnGroup, - [Tokenizer.EOF_TOKEN]: eofInBody - }, - [IN_TABLE_BODY_MODE]: { - [Tokenizer.CHARACTER_TOKEN]: characterInTable, - [Tokenizer.NULL_CHARACTER_TOKEN]: characterInTable, - [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: characterInTable, - [Tokenizer.COMMENT_TOKEN]: appendComment, - [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, - [Tokenizer.START_TAG_TOKEN]: startTagInTableBody, - [Tokenizer.END_TAG_TOKEN]: endTagInTableBody, - [Tokenizer.EOF_TOKEN]: eofInBody - }, - [IN_ROW_MODE]: { - [Tokenizer.CHARACTER_TOKEN]: characterInTable, - [Tokenizer.NULL_CHARACTER_TOKEN]: characterInTable, - [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: characterInTable, - [Tokenizer.COMMENT_TOKEN]: appendComment, - [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, - [Tokenizer.START_TAG_TOKEN]: startTagInRow, - [Tokenizer.END_TAG_TOKEN]: endTagInRow, - [Tokenizer.EOF_TOKEN]: eofInBody - }, - [IN_CELL_MODE]: { - [Tokenizer.CHARACTER_TOKEN]: characterInBody, - [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken, - [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: whitespaceCharacterInBody, - [Tokenizer.COMMENT_TOKEN]: appendComment, - [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, - [Tokenizer.START_TAG_TOKEN]: startTagInCell, - [Tokenizer.END_TAG_TOKEN]: endTagInCell, - [Tokenizer.EOF_TOKEN]: eofInBody - }, - [IN_SELECT_MODE]: { - [Tokenizer.CHARACTER_TOKEN]: insertCharacters, - [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken, - [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters, - [Tokenizer.COMMENT_TOKEN]: appendComment, - [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, - [Tokenizer.START_TAG_TOKEN]: startTagInSelect, - [Tokenizer.END_TAG_TOKEN]: endTagInSelect, - [Tokenizer.EOF_TOKEN]: eofInBody - }, - [IN_SELECT_IN_TABLE_MODE]: { - [Tokenizer.CHARACTER_TOKEN]: insertCharacters, - [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken, - [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters, - [Tokenizer.COMMENT_TOKEN]: appendComment, - [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, - [Tokenizer.START_TAG_TOKEN]: startTagInSelectInTable, - [Tokenizer.END_TAG_TOKEN]: endTagInSelectInTable, - [Tokenizer.EOF_TOKEN]: eofInBody - }, - [IN_TEMPLATE_MODE]: { - [Tokenizer.CHARACTER_TOKEN]: characterInBody, - [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken, - [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: whitespaceCharacterInBody, - [Tokenizer.COMMENT_TOKEN]: appendComment, - [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, - [Tokenizer.START_TAG_TOKEN]: startTagInTemplate, - [Tokenizer.END_TAG_TOKEN]: endTagInTemplate, - [Tokenizer.EOF_TOKEN]: eofInTemplate - }, - [AFTER_BODY_MODE]: { - [Tokenizer.CHARACTER_TOKEN]: tokenAfterBody, - [Tokenizer.NULL_CHARACTER_TOKEN]: tokenAfterBody, - [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: whitespaceCharacterInBody, - [Tokenizer.COMMENT_TOKEN]: appendCommentToRootHtmlElement, - [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, - [Tokenizer.START_TAG_TOKEN]: startTagAfterBody, - [Tokenizer.END_TAG_TOKEN]: endTagAfterBody, - [Tokenizer.EOF_TOKEN]: stopParsing - }, - [IN_FRAMESET_MODE]: { - [Tokenizer.CHARACTER_TOKEN]: ignoreToken, - [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken, - [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters, - [Tokenizer.COMMENT_TOKEN]: appendComment, - [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, - [Tokenizer.START_TAG_TOKEN]: startTagInFrameset, - [Tokenizer.END_TAG_TOKEN]: endTagInFrameset, - [Tokenizer.EOF_TOKEN]: stopParsing - }, - [AFTER_FRAMESET_MODE]: { - [Tokenizer.CHARACTER_TOKEN]: ignoreToken, - [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken, - [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters, - [Tokenizer.COMMENT_TOKEN]: appendComment, - [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, - [Tokenizer.START_TAG_TOKEN]: startTagAfterFrameset, - [Tokenizer.END_TAG_TOKEN]: endTagAfterFrameset, - [Tokenizer.EOF_TOKEN]: stopParsing - }, - [AFTER_AFTER_BODY_MODE]: { - [Tokenizer.CHARACTER_TOKEN]: tokenAfterAfterBody, - [Tokenizer.NULL_CHARACTER_TOKEN]: tokenAfterAfterBody, - [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: whitespaceCharacterInBody, - [Tokenizer.COMMENT_TOKEN]: appendCommentToDocument, - [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, - [Tokenizer.START_TAG_TOKEN]: startTagAfterAfterBody, - [Tokenizer.END_TAG_TOKEN]: tokenAfterAfterBody, - [Tokenizer.EOF_TOKEN]: stopParsing - }, - [AFTER_AFTER_FRAMESET_MODE]: { - [Tokenizer.CHARACTER_TOKEN]: ignoreToken, - [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken, - [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: whitespaceCharacterInBody, - [Tokenizer.COMMENT_TOKEN]: appendCommentToDocument, - [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, - [Tokenizer.START_TAG_TOKEN]: startTagAfterAfterFrameset, - [Tokenizer.END_TAG_TOKEN]: ignoreToken, - [Tokenizer.EOF_TOKEN]: stopParsing - } -}; - -//Parser -class Parser { - constructor(options) { - this.options = mergeOptions(DEFAULT_OPTIONS, options); - - this.treeAdapter = this.options.treeAdapter; - this.pendingScript = null; - - if (this.options.sourceCodeLocationInfo) { - Mixin.install(this, LocationInfoParserMixin); - } - - if (this.options.onParseError) { - Mixin.install(this, ErrorReportingParserMixin, { onParseError: this.options.onParseError }); - } - } - - // API - parse(html) { - const document = this.treeAdapter.createDocument(); - - this._bootstrap(document, null); - this.tokenizer.write(html, true); - this._runParsingLoop(null); - - return document; - } - - parseFragment(html, fragmentContext) { - //NOTE: use