This commit is contained in:
darenhsu
2022-07-17 13:16:16 +08:00
parent 84759556ff
commit befd344ab0
28070 changed files with 4008428 additions and 1 deletions
+3
View File
@@ -0,0 +1,3 @@
test/
dist/
node_modules/
+142
View File
@@ -0,0 +1,142 @@
module.exports = {
"env": {
"browser": true,
"es6": true,
"node": true
},
"extends": [
"plugin:@typescript-eslint/recommended",
"plugin:@typescript-eslint/recommended-requiring-type-checking"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": "tsconfig.json",
"sourceType": "module"
},
"plugins": [
"@typescript-eslint",
"@typescript-eslint/tslint"
],
"rules": {
"@typescript-eslint/prefer-includes": "off",
"@typescript-eslint/unbound-method": "off",
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/member-delimiter-style": "error",
"@typescript-eslint/no-misused-promises": "error",
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/camelcase": "off",
"@typescript-eslint/adjacent-overload-signatures": "error",
"@typescript-eslint/array-type": "error",
"@typescript-eslint/ban-types": "error",
"@typescript-eslint/class-name-casing": "error",
"@typescript-eslint/consistent-type-assertions": "error",
"@typescript-eslint/indent": [
"error",
"tab",
{
"ArrayExpression": "first",
"ObjectExpression": "first"
}
],
"@typescript-eslint/interface-name-prefix": "off",
"@typescript-eslint/no-empty-function": "off",
"@typescript-eslint/no-empty-interface": "error",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-misused-new": "error",
"@typescript-eslint/no-namespace": "error",
"@typescript-eslint/no-parameter-properties": "off",
"@typescript-eslint/no-use-before-define": "off",
"@typescript-eslint/no-var-requires": "error",
"@typescript-eslint/prefer-for-of": "error",
"@typescript-eslint/prefer-function-type": "error",
"@typescript-eslint/prefer-namespace-keyword": "error",
"@typescript-eslint/quotes": [
"error",
"single",
{
"avoidEscape": true
}
],
"@typescript-eslint/triple-slash-reference": "error",
"@typescript-eslint/unified-signatures": "off",
"camelcase": "off",
"comma-dangle": "error",
"complexity": "off",
"constructor-super": "error",
"dot-notation": "error",
"eqeqeq": [
"error",
"smart"
],
"guard-for-in": "off",
"id-blacklist": [
"error",
"any",
"Number",
"number",
"String",
"string",
"Boolean",
"boolean",
"Undefined"
],
"id-match": "error",
"max-classes-per-file": [
"error",
1
],
"max-len": "off",
"new-parens": "error",
"no-bitwise": "off",
"no-caller": "error",
"no-cond-assign": "off",
"no-console": "off",
"no-debugger": "error",
"no-empty": "off",
"no-eval": "error",
"no-fallthrough": "off",
"no-invalid-this": "off",
"no-multiple-empty-lines": "off",
"no-new-wrappers": "error",
"no-shadow": [
"error",
{
"hoist": "all"
}
],
"no-throw-literal": "error",
"no-trailing-spaces": "error",
"no-undef-init": "error",
"no-underscore-dangle": "off",
"no-unsafe-finally": "error",
"no-unused-expressions": "error",
"no-unused-labels": "error",
"no-var": "error",
"object-shorthand": "error",
"one-var": [
"error",
"never"
],
"prefer-arrow/prefer-arrow-functions": "off",
"prefer-const": "error",
"radix": "error",
"spaced-comment": "error",
"use-isnan": "error",
"valid-typeof": "off",
"@typescript-eslint/tslint/config": [
"error",
{
"rules": {
"jsdoc-format": true,
"no-reference-import": true,
"no-unsafe-any": true,
"whitespace": [
true,
"check-branch",
"check-operator"
]
}
}
]
}
};
+1
View File
@@ -0,0 +1 @@
require: blanket,should,spec
+7
View File
@@ -0,0 +1,7 @@
Copyright 2019 Tao Qiufeng
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.
+165
View File
@@ -0,0 +1,165 @@
# Fast HTML Parser [![NPM version](https://badge.fury.io/js/node-html-parser.png)](http://badge.fury.io/js/node-html-parser) [![Build Status](https://travis-ci.org/taoqf/node-html-parser.svg?branch=master)](https://travis-ci.org/taoqf/node-html-parser)
Fast HTML Parser is a _very fast_ HTML parser. Which will generate a simplified
DOM tree, with basic element query support.
Per the design, it intends to parse massive HTML files in lowest price, thus the
performance is the top priority. For this reason, some malformatted HTML may not
be able to parse correctly, but most usual errors are covered (eg. HTML4 style
no closing `<li>`, `<td>` etc).
## Install
```shell
npm install --save node-html-parser
```
## Performance
Faster than htmlparser2!
```shell
node-html-parser:1.94548 ms/file ± 2.15709
libxmljs :5.28893 ms/file ± 3.69863
htmlparser :24.9625 ms/file ± 168.380
htmlparser2 :3.34011 ms/file ± 4.76959
parse5 :13.9589 ms/file ± 9.84068
high5 :6.98078 ms/file ± 4.47575
```
Tested with [htmlparser-benchmark](https://github.com/AndreasMadsen/htmlparser-benchmark).
## Usage
```ts
import { parse } from 'node-html-parser';
const root = parse('<ul id="list"><li>Hello World</li></ul>');
console.log(root.firstChild.structure);
// ul#list
// li
// #text
console.log(root.querySelector('#list'));
// { tagName: 'ul',
// rawAttrs: 'id="list"',
// childNodes:
// [ { tagName: 'li',
// rawAttrs: '',
// childNodes: [Object],
// classNames: [] } ],
// id: 'list',
// classNames: [] }
console.log(root.toString());
// <ul id="list"><li>Hello World</li></ul>
root.set_content('<li>Hello World</li>');
root.toString(); // <li>Hello World</li>
```
```js
var HTMLParser = require('node-html-parser');
var root = HTMLParser.parse('<ul id="list"><li>Hello World</li></ul>');
```
## API
### parse(data[, options])
Parse given data, and return root of the generated DOM.
- **data**, data to parse
- **options**, parse options
```js
{
lowerCaseTagName: false, // convert tag name to lower case (hurt performance heavily)
script: false, // retrieve content in <script> (hurt performance slightly)
style: false, // retrieve content in <style> (hurt performance slightly)
pre: false, // retrieve content in <pre> (hurt performance slightly)
comment: false // retrieve comments (hurt performance slightly)
}
```
### HTMLElement#text
Get unescaped text value of current node and its children. Like `innerText`.
(slow for the first time)
### HTMLElement#rawText
Get escpaed (as-it) text value of current node and its children. May have
`&amp;` in it. (fast)
### HTMLElement#structuredText
Get structured Text
### HTMLElement#trimRight()
Trim element from right (in block) after seeing pattern in a TextNode.
### HTMLElement#structure
Get DOM structure
### HTMLElement#removeWhitespace()
Remove whitespaces in this sub tree.
### HTMLElement#querySelectorAll(selector)
Query CSS selector to find matching nodes.
Note: only `tagName`, `#id`, `.class` selectors supported. And not behave the
same as standard `querySelectorAll()` as it will _stop_ searching sub tree after
find a match.
### HTMLElement#querySelector(selector)
Query CSS Selector to find matching node.
### HTMLElement#appendChild(node)
Append a child node to childNodes
### HTMLElement#insertAdjacentHTML(where, html)
parses the specified text as HTML and inserts the resulting nodes into the DOM tree at a specified position.
### HTMLElement#firstChild
Get first child node
### HTMLElement#lastChild
Get last child node
### HTMLElement#setAttribute(key: string, value: string)
Set `value` to `key` attribute.
### HTMLElement#removeAttribute(key: string)
Remove `key` attribute.
### HTMLElement#getAttribute(key: string)
Get `key` attrubte.
### HTMLElement#toString()
Same as [outerHTML](#htmlelementouterhtml)
### HTMLElement#innerHTML
Get innerHTML.
### HTMLElement#outerHTML
Get outerHTML.
### HTMLElement#set_content(content: string | Node | Node[])
Set content. **Notice**: Do not set content of the **root** node.
+1
View File
@@ -0,0 +1 @@
export default function arr_back<T>(arr: T[]): T;
+6
View File
@@ -0,0 +1,6 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
function arr_back(arr) {
return arr[arr.length - 1];
}
exports.default = arr_back;
+5
View File
@@ -0,0 +1,5 @@
export { default as CommentNode } from './nodes/comment';
export { default as HTMLElement, parse, parse as default, Options } from './nodes/html';
export { default as Node } from './nodes/node';
export { default as TextNode } from './nodes/text';
export { default as NodeType } from './nodes/type';
+14
View File
@@ -0,0 +1,14 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var comment_1 = require("./nodes/comment");
exports.CommentNode = comment_1.default;
var html_1 = require("./nodes/html");
exports.HTMLElement = html_1.default;
exports.parse = html_1.parse;
exports.default = html_1.parse;
var node_1 = require("./nodes/node");
exports.Node = node_1.default;
var text_1 = require("./nodes/text");
exports.TextNode = text_1.default;
var type_1 = require("./nodes/type");
exports.NodeType = type_1.default;
+1184
View File
File diff suppressed because it is too large Load Diff
+41
View File
@@ -0,0 +1,41 @@
import HTMLElement from './nodes/html';
/**
* Matcher class to make CSS match
*
* @class Matcher
*/
export default class Matcher {
private matchers;
private nextMatch;
/**
* Creates an instance of Matcher.
* @param {string} selector
*
* @memberof Matcher
*/
constructor(selector: string);
/**
* Trying to advance match pointer
* @param {HTMLElement} el element to make the match
* @return {bool} true when pointer advanced.
*/
advance(el: HTMLElement): boolean;
/**
* Rewind the match pointer
*/
rewind(): void;
/**
* Trying to determine if match made.
* @return {bool} true when the match is made
*/
get matched(): boolean;
/**
* Rest match pointer.
* @return {[type]} [description]
*/
reset(): void;
/**
* flush cache to free memory
*/
flushCache(): void;
}
+248
View File
@@ -0,0 +1,248 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/**
* Cache to store generated match functions
* @type {Object}
*/
var pMatchFunctionCache = {};
/**
* Function cache
*/
var functionCache = {
f145: function (el, tagName, classes) {
'use strict';
tagName = tagName || '';
classes = classes || [];
if (el.id !== tagName.substr(1)) {
return false;
}
for (var cls = classes, i = 0; i < cls.length; i++) {
if (el.classNames.indexOf(cls[i]) === -1) {
return false;
}
}
return true;
},
f45: function (el, tagName, classes) {
'use strict';
tagName = tagName || '';
classes = classes || [];
for (var cls = classes, i = 0; i < cls.length; i++) {
if (el.classNames.indexOf(cls[i]) === -1) {
return false;
}
}
return true;
},
f15: function (el, tagName) {
'use strict';
tagName = tagName || '';
if (el.id !== tagName.substr(1)) {
return false;
}
return true;
},
f1: function (el, tagName) {
'use strict';
tagName = tagName || '';
if (el.id !== tagName.substr(1)) {
return false;
}
},
f5: function () {
'use strict';
return true;
},
f55: function (el, tagName, classes, attr_key) {
'use strict';
tagName = tagName || '';
classes = classes || [];
attr_key = attr_key || '';
var attrs = el.attributes;
return attrs.hasOwnProperty(attr_key);
},
f245: function (el, tagName, classes, attr_key, value) {
'use strict';
tagName = tagName || '';
classes = classes || [];
attr_key = attr_key || '';
value = value || '';
var attrs = el.attributes;
return Object.keys(attrs).some(function (key) {
var val = attrs[key];
return key === attr_key && val === value;
});
// for (let cls = classes, i = 0; i < cls.length; i++) {if (el.classNames.indexOf(cls[i]) === -1){ return false;}}
// return true;
},
f25: function (el, tagName, classes, attr_key, value) {
'use strict';
tagName = tagName || '';
classes = classes || [];
attr_key = attr_key || '';
value = value || '';
var attrs = el.attributes;
return Object.keys(attrs).some(function (key) {
var val = attrs[key];
return key === attr_key && val === value;
});
// return true;
},
f2: function (el, tagName, classes, attr_key, value) {
'use strict';
tagName = tagName || '';
classes = classes || [];
attr_key = attr_key || '';
value = value || '';
var attrs = el.attributes;
return Object.keys(attrs).some(function (key) {
var val = attrs[key];
return key === attr_key && val === value;
});
},
f345: function (el, tagName, classes) {
'use strict';
tagName = tagName || '';
classes = classes || [];
if (el.tagName !== tagName) {
return false;
}
for (var cls = classes, i = 0; i < cls.length; i++) {
if (el.classNames.indexOf(cls[i]) === -1) {
return false;
}
}
return true;
},
f35: function (el, tagName) {
'use strict';
tagName = tagName || '';
return el.tagName === tagName;
},
f3: function (el, tagName) {
'use strict';
tagName = tagName || '';
if (el.tagName !== tagName) {
return false;
}
}
};
/**
* Matcher class to make CSS match
*
* @class Matcher
*/
var Matcher = /** @class */ (function () {
/**
* Creates an instance of Matcher.
* @param {string} selector
*
* @memberof Matcher
*/
function Matcher(selector) {
this.nextMatch = 0;
functionCache.f5 = functionCache.f5;
this.matchers = selector.split(' ').map(function (matcher) {
if (pMatchFunctionCache[matcher])
return pMatchFunctionCache[matcher];
var parts = matcher.split('.');
var tagName = parts[0];
var classes = parts.slice(1).sort();
// let source = '"use strict";';
var function_name = 'f';
var attr_key = '';
var value = '';
if (tagName && tagName !== '*') {
var reg = void 0;
if (tagName.startsWith('#')) {
// source += 'if (el.id != ' + JSON.stringify(tagName.substr(1)) + ') return false;';// 1
function_name += '1';
}
else {
reg = /^\[\s*(\S+)\s*(=|!=)\s*((((["'])([^\6]*)\6))|(\S*?))\]\s*/.exec(tagName);
if (reg) {
attr_key = reg[1];
var method = reg[2];
if (method !== '=' && method !== '!=') {
throw new Error('Selector not supported, Expect [key${op}value].op must be =,!=');
}
if (method === '=') {
method = '==';
}
value = reg[7] || reg[8];
// source += `let attrs = el.attributes;for (let key in attrs){const val = attrs[key]; if (key == "${attr_key}" && val == "${value}"){return true;}} return false;`;// 2
function_name += '2';
}
else if (reg = /^\[(.*?)\]/.exec(tagName)) {
attr_key = reg[1];
function_name += '5';
}
else {
// source += 'if (el.tagName != ' + JSON.stringify(tagName) + ') return false;';// 3
function_name += '3';
}
}
}
if (classes.length > 0) {
// source += 'for (let cls = ' + JSON.stringify(classes) + ', i = 0; i < cls.length; i++) if (el.classNames.indexOf(cls[i]) === -1) return false;';// 4
function_name += '4';
}
// source += 'return true;';// 5
function_name += '5';
var obj = {
func: functionCache[function_name],
tagName: tagName || '',
classes: classes || '',
attr_key: attr_key || '',
value: value || ''
};
// source = source || '';
return pMatchFunctionCache[matcher] = obj;
});
}
/**
* Trying to advance match pointer
* @param {HTMLElement} el element to make the match
* @return {bool} true when pointer advanced.
*/
Matcher.prototype.advance = function (el) {
if (this.nextMatch < this.matchers.length &&
this.matchers[this.nextMatch].func(el, this.matchers[this.nextMatch].tagName, this.matchers[this.nextMatch].classes, this.matchers[this.nextMatch].attr_key, this.matchers[this.nextMatch].value)) {
this.nextMatch++;
return true;
}
return false;
};
/**
* Rewind the match pointer
*/
Matcher.prototype.rewind = function () {
this.nextMatch--;
};
Object.defineProperty(Matcher.prototype, "matched", {
/**
* Trying to determine if match made.
* @return {bool} true when the match is made
*/
get: function () {
return this.nextMatch === this.matchers.length;
},
enumerable: true,
configurable: true
});
/**
* Rest match pointer.
* @return {[type]} [description]
*/
Matcher.prototype.reset = function () {
this.nextMatch = 0;
};
/**
* flush cache to free memory
*/
Matcher.prototype.flushCache = function () {
pMatchFunctionCache = {};
};
return Matcher;
}());
exports.default = Matcher;
+16
View File
@@ -0,0 +1,16 @@
import Node from './node';
import NodeType from './type';
export default class CommentNode extends Node {
constructor(value: string);
/**
* Node Type declaration.
* @type {Number}
*/
nodeType: NodeType;
/**
* Get unescaped text value of current node and its children.
* @return {string} text content
*/
get text(): string;
toString(): string;
}
+49
View File
@@ -0,0 +1,49 @@
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
var node_1 = __importDefault(require("./node"));
var type_1 = __importDefault(require("./type"));
var CommentNode = /** @class */ (function (_super) {
__extends(CommentNode, _super);
function CommentNode(value) {
var _this = _super.call(this) || this;
/**
* Node Type declaration.
* @type {Number}
*/
_this.nodeType = type_1.default.COMMENT_NODE;
_this.rawText = value;
return _this;
}
Object.defineProperty(CommentNode.prototype, "text", {
/**
* Get unescaped text value of current node and its children.
* @return {string} text content
*/
get: function () {
return this.rawText;
},
enumerable: true,
configurable: true
});
CommentNode.prototype.toString = function () {
return "<!--" + this.rawText + "-->";
};
return CommentNode;
}(node_1.default));
exports.default = CommentNode;
+176
View File
@@ -0,0 +1,176 @@
import Node from './node';
import NodeType from './type';
import TextNode from './text';
import Matcher from '../matcher';
export interface KeyAttributes {
id?: string;
class?: string;
}
export interface Attributes {
[key: string]: string;
}
export interface RawAttributes {
[key: string]: string;
}
export declare type InsertPosition = 'beforebegin' | 'afterbegin' | 'beforeend' | 'afterend';
/**
* HTMLElement, which contains a set of children.
*
* Note: this is a minimalist implementation, no complete tree
* structure provided (no parentNode, nextSibling,
* previousSibling etc).
* @class HTMLElement
* @extends {Node}
*/
export default class HTMLElement extends Node {
tagName: string;
private rawAttrs;
parentNode: Node;
private _attrs;
private _rawAttrs;
id: string;
classNames: string[];
/**
* Node Type declaration.
*/
nodeType: NodeType;
/**
* Creates an instance of HTMLElement.
* @param keyAttrs id and class attribute
* @param [rawAttrs] attributes in string
*
* @memberof HTMLElement
*/
constructor(tagName: string, keyAttrs: KeyAttributes, rawAttrs?: string, parentNode?: Node);
/**
* Remove Child element from childNodes array
* @param {HTMLElement} node node to remove
*/
removeChild(node: Node): void;
/**
* Exchanges given child with new child
* @param {HTMLElement} oldNode node to exchange
* @param {HTMLElement} newNode new node
*/
exchangeChild(oldNode: Node, newNode: Node): void;
/**
* Get escpaed (as-it) text value of current node and its children.
* @return {string} text content
*/
get rawText(): string;
/**
* Get unescaped text value of current node and its children.
* @return {string} text content
*/
get text(): string;
/**
* Get structured Text (with '\n' etc.)
* @return {string} structured text
*/
get structuredText(): string;
toString(): string;
get innerHTML(): string;
set_content(content: string | Node | Node[], options?: Options): void;
get outerHTML(): string;
/**
* Trim element from right (in block) after seeing pattern in a TextNode.
* @param {RegExp} pattern pattern to find
* @return {HTMLElement} reference to current node
*/
trimRight(pattern: RegExp): this;
/**
* Get DOM structure
* @return {string} strucutre
*/
get structure(): string;
/**
* Remove whitespaces in this sub tree.
* @return {HTMLElement} pointer to this
*/
removeWhitespace(): this;
/**
* Query CSS selector to find matching nodes.
* @param {string} selector Simplified CSS selector
* @param {Matcher} selector A Matcher instance
* @return {HTMLElement[]} matching elements
*/
querySelectorAll(selector: string | Matcher): HTMLElement[];
/**
* Query CSS Selector to find matching node.
* @param {string} selector Simplified CSS selector
* @param {Matcher} selector A Matcher instance
* @return {HTMLElement} matching node
*/
querySelector(selector: string | Matcher): HTMLElement;
/**
* Append a child node to childNodes
* @param {Node} node node to append
* @return {Node} node appended
*/
appendChild<T extends Node = Node>(node: T): T;
/**
* Get first child node
* @return {Node} first child node
*/
get firstChild(): Node;
/**
* Get last child node
* @return {Node} last child node
*/
get lastChild(): Node;
/**
* Get attributes
* @return {Object} parsed and unescaped attributes
*/
get attributes(): Attributes;
/**
* Get escaped (as-it) attributes
* @return {Object} parsed attributes
*/
get rawAttributes(): RawAttributes;
removeAttribute(key: string): void;
hasAttribute(key: string): boolean;
/**
* Get an attribute
* @return {string} value of the attribute
*/
getAttribute(key: string): string | undefined;
/**
* Set an attribute value to the HTMLElement
* @param {string} key The attribute name
* @param {string} value The value to set, or null / undefined to remove an attribute
*/
setAttribute(key: string, value: string): void;
/**
* Replace all the attributes of the HTMLElement by the provided attributes
* @param {Attributes} attributes the new attribute set
*/
setAttributes(attributes: Attributes): void;
insertAdjacentHTML(where: InsertPosition, html: string): void;
}
export interface Options {
lowerCaseTagName?: boolean;
script?: boolean;
style?: boolean;
pre?: boolean;
comment?: boolean;
}
/**
* Parses HTML and returns a root element
* Parse a chuck of HTML source.
* @param {string} data html
* @return {HTMLElement} root element
*/
export declare function parse(data: string, options?: Options): HTMLElement & {
valid: boolean;
};
export declare function parse(data: string, options?: Options & {
noFix: false;
}): HTMLElement & {
valid: boolean;
};
export declare function parse(data: string, options?: Options & {
noFix: true;
}): (HTMLElement | TextNode) & {
valid: boolean;
};
+804
View File
@@ -0,0 +1,804 @@
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
var he_1 = require("he");
var node_1 = __importDefault(require("./node"));
var type_1 = __importDefault(require("./type"));
var text_1 = __importDefault(require("./text"));
var matcher_1 = __importDefault(require("../matcher"));
var back_1 = __importDefault(require("../back"));
var comment_1 = __importDefault(require("./comment"));
var kBlockElements = {
div: true,
p: true,
// ul: true,
// ol: true,
li: true,
// table: true,
// tr: true,
td: true,
section: true,
br: true
};
/**
* HTMLElement, which contains a set of children.
*
* Note: this is a minimalist implementation, no complete tree
* structure provided (no parentNode, nextSibling,
* previousSibling etc).
* @class HTMLElement
* @extends {Node}
*/
var HTMLElement = /** @class */ (function (_super) {
__extends(HTMLElement, _super);
/**
* Creates an instance of HTMLElement.
* @param keyAttrs id and class attribute
* @param [rawAttrs] attributes in string
*
* @memberof HTMLElement
*/
function HTMLElement(tagName, keyAttrs, rawAttrs, parentNode) {
if (rawAttrs === void 0) { rawAttrs = ''; }
if (parentNode === void 0) { parentNode = null; }
var _this = _super.call(this) || this;
_this.tagName = tagName;
_this.rawAttrs = rawAttrs;
_this.parentNode = parentNode;
_this.classNames = [];
/**
* Node Type declaration.
*/
_this.nodeType = type_1.default.ELEMENT_NODE;
_this.rawAttrs = rawAttrs || '';
_this.parentNode = parentNode || null;
_this.childNodes = [];
if (keyAttrs.id) {
_this.id = keyAttrs.id;
if (!rawAttrs) {
_this.rawAttrs = "id=\"" + keyAttrs.id + "\"";
}
}
if (keyAttrs.class) {
_this.classNames = keyAttrs.class.split(/\s+/);
if (!rawAttrs) {
var cls = "class=\"" + _this.classNames.join(' ') + "\"";
if (_this.rawAttrs) {
_this.rawAttrs += " " + cls;
}
else {
_this.rawAttrs = cls;
}
}
}
return _this;
}
/**
* Remove Child element from childNodes array
* @param {HTMLElement} node node to remove
*/
HTMLElement.prototype.removeChild = function (node) {
this.childNodes = this.childNodes.filter(function (child) {
return (child !== node);
});
};
/**
* Exchanges given child with new child
* @param {HTMLElement} oldNode node to exchange
* @param {HTMLElement} newNode new node
*/
HTMLElement.prototype.exchangeChild = function (oldNode, newNode) {
var idx = -1;
for (var i = 0; i < this.childNodes.length; i++) {
if (this.childNodes[i] === oldNode) {
idx = i;
break;
}
}
this.childNodes[idx] = newNode;
};
Object.defineProperty(HTMLElement.prototype, "rawText", {
/**
* Get escpaed (as-it) text value of current node and its children.
* @return {string} text content
*/
get: function () {
return this.childNodes.reduce(function (pre, cur) {
return pre += cur.rawText;
}, '');
},
enumerable: true,
configurable: true
});
Object.defineProperty(HTMLElement.prototype, "text", {
/**
* Get unescaped text value of current node and its children.
* @return {string} text content
*/
get: function () {
return he_1.decode(this.rawText);
},
enumerable: true,
configurable: true
});
Object.defineProperty(HTMLElement.prototype, "structuredText", {
/**
* Get structured Text (with '\n' etc.)
* @return {string} structured text
*/
get: function () {
var currentBlock = [];
var blocks = [currentBlock];
function dfs(node) {
if (node.nodeType === type_1.default.ELEMENT_NODE) {
if (kBlockElements[node.tagName]) {
if (currentBlock.length > 0) {
blocks.push(currentBlock = []);
}
node.childNodes.forEach(dfs);
if (currentBlock.length > 0) {
blocks.push(currentBlock = []);
}
}
else {
node.childNodes.forEach(dfs);
}
}
else if (node.nodeType === type_1.default.TEXT_NODE) {
if (node.isWhitespace) {
// Whitespace node, postponed output
currentBlock.prependWhitespace = true;
}
else {
var text = node.text;
if (currentBlock.prependWhitespace) {
text = ' ' + text;
currentBlock.prependWhitespace = false;
}
currentBlock.push(text);
}
}
}
dfs(this);
return blocks
.map(function (block) {
// Normalize each line's whitespace
return block.join('').trim().replace(/\s{2,}/g, ' ');
})
.join('\n').replace(/\s+$/, ''); // trimRight;
},
enumerable: true,
configurable: true
});
HTMLElement.prototype.toString = function () {
var tag = this.tagName;
if (tag) {
var is_void = /^(area|base|br|col|embed|hr|img|input|link|meta|param|source|track|wbr)$/i.test(tag);
var attrs = this.rawAttrs ? ' ' + this.rawAttrs : '';
if (is_void) {
return "<" + tag + attrs + ">";
}
else {
return "<" + tag + attrs + ">" + this.innerHTML + "</" + tag + ">";
}
}
else {
return this.innerHTML;
}
};
Object.defineProperty(HTMLElement.prototype, "innerHTML", {
get: function () {
return this.childNodes.map(function (child) {
return child.toString();
}).join('');
},
enumerable: true,
configurable: true
});
HTMLElement.prototype.set_content = function (content, options) {
if (options === void 0) { options = {}; }
if (content instanceof node_1.default) {
content = [content];
}
else if (typeof content == 'string') {
var r = parse(content, options);
content = r.childNodes.length ? r.childNodes : [new text_1.default(content)];
}
this.childNodes = content;
};
Object.defineProperty(HTMLElement.prototype, "outerHTML", {
get: function () {
return this.toString();
},
enumerable: true,
configurable: true
});
/**
* Trim element from right (in block) after seeing pattern in a TextNode.
* @param {RegExp} pattern pattern to find
* @return {HTMLElement} reference to current node
*/
HTMLElement.prototype.trimRight = function (pattern) {
for (var i = 0; i < this.childNodes.length; i++) {
var childNode = this.childNodes[i];
if (childNode.nodeType === type_1.default.ELEMENT_NODE) {
childNode.trimRight(pattern);
}
else {
var index = childNode.rawText.search(pattern);
if (index > -1) {
childNode.rawText = childNode.rawText.substr(0, index);
// trim all following nodes.
this.childNodes.length = i + 1;
}
}
}
return this;
};
Object.defineProperty(HTMLElement.prototype, "structure", {
/**
* Get DOM structure
* @return {string} strucutre
*/
get: function () {
var res = [];
var indention = 0;
function write(str) {
res.push(' '.repeat(indention) + str);
}
function dfs(node) {
var idStr = node.id ? ('#' + node.id) : '';
var classStr = node.classNames.length ? ('.' + node.classNames.join('.')) : '';
write(node.tagName + idStr + classStr);
indention++;
node.childNodes.forEach(function (childNode) {
if (childNode.nodeType === type_1.default.ELEMENT_NODE) {
dfs(childNode);
}
else if (childNode.nodeType === type_1.default.TEXT_NODE) {
if (!childNode.isWhitespace)
write('#text');
}
});
indention--;
}
dfs(this);
return res.join('\n');
},
enumerable: true,
configurable: true
});
/**
* Remove whitespaces in this sub tree.
* @return {HTMLElement} pointer to this
*/
HTMLElement.prototype.removeWhitespace = function () {
var _this = this;
var o = 0;
this.childNodes.forEach(function (node) {
if (node.nodeType === type_1.default.TEXT_NODE) {
if (node.isWhitespace) {
return;
}
node.rawText = node.rawText.trim();
}
else if (node.nodeType === type_1.default.ELEMENT_NODE) {
node.removeWhitespace();
}
_this.childNodes[o++] = node;
});
this.childNodes.length = o;
return this;
};
/**
* Query CSS selector to find matching nodes.
* @param {string} selector Simplified CSS selector
* @param {Matcher} selector A Matcher instance
* @return {HTMLElement[]} matching elements
*/
HTMLElement.prototype.querySelectorAll = function (selector) {
var _this = this;
var matcher;
if (selector instanceof matcher_1.default) {
matcher = selector;
matcher.reset();
}
else {
if (selector.includes(',')) {
var selectors = selector.split(',');
return Array.from(selectors.reduce(function (pre, cur) {
var result = _this.querySelectorAll(cur.trim());
return result.reduce(function (p, c) {
return p.add(c);
}, pre);
}, new Set()));
}
matcher = new matcher_1.default(selector);
}
var stack = [];
return this.childNodes.reduce(function (res, cur) {
stack.push([cur, 0, false]);
while (stack.length) {
var state = back_1.default(stack); // get last element
var el = state[0];
if (state[1] === 0) {
// Seen for first time.
if (el.nodeType !== type_1.default.ELEMENT_NODE) {
stack.pop();
continue;
}
var html_el = el;
state[2] = matcher.advance(html_el);
if (state[2]) {
if (matcher.matched) {
res.push(html_el);
res.push.apply(res, (html_el.querySelectorAll(selector)));
// no need to go further.
matcher.rewind();
stack.pop();
continue;
}
}
}
if (state[1] < el.childNodes.length) {
stack.push([el.childNodes[state[1]++], 0, false]);
}
else {
if (state[2]) {
matcher.rewind();
}
stack.pop();
}
}
return res;
}, []);
};
/**
* Query CSS Selector to find matching node.
* @param {string} selector Simplified CSS selector
* @param {Matcher} selector A Matcher instance
* @return {HTMLElement} matching node
*/
HTMLElement.prototype.querySelector = function (selector) {
var matcher;
if (selector instanceof matcher_1.default) {
matcher = selector;
matcher.reset();
}
else {
matcher = new matcher_1.default(selector);
}
var stack = [];
for (var _i = 0, _a = this.childNodes; _i < _a.length; _i++) {
var node = _a[_i];
stack.push([node, 0, false]);
while (stack.length) {
var state = back_1.default(stack);
var el = state[0];
if (state[1] === 0) {
// Seen for first time.
if (el.nodeType !== type_1.default.ELEMENT_NODE) {
stack.pop();
continue;
}
state[2] = matcher.advance(el);
if (state[2]) {
if (matcher.matched) {
return el;
}
}
}
if (state[1] < el.childNodes.length) {
stack.push([el.childNodes[state[1]++], 0, false]);
}
else {
if (state[2])
matcher.rewind();
stack.pop();
}
}
}
return null;
};
/**
* Append a child node to childNodes
* @param {Node} node node to append
* @return {Node} node appended
*/
HTMLElement.prototype.appendChild = function (node) {
// node.parentNode = this;
this.childNodes.push(node);
if (node instanceof HTMLElement) {
node.parentNode = this;
}
return node;
};
Object.defineProperty(HTMLElement.prototype, "firstChild", {
/**
* Get first child node
* @return {Node} first child node
*/
get: function () {
return this.childNodes[0];
},
enumerable: true,
configurable: true
});
Object.defineProperty(HTMLElement.prototype, "lastChild", {
/**
* Get last child node
* @return {Node} last child node
*/
get: function () {
return back_1.default(this.childNodes);
},
enumerable: true,
configurable: true
});
Object.defineProperty(HTMLElement.prototype, "attributes", {
/**
* Get attributes
* @return {Object} parsed and unescaped attributes
*/
get: function () {
if (this._attrs) {
return this._attrs;
}
this._attrs = {};
var attrs = this.rawAttributes;
for (var key in attrs) {
var val = attrs[key] || '';
this._attrs[key] = he_1.decode(val);
}
return this._attrs;
},
enumerable: true,
configurable: true
});
Object.defineProperty(HTMLElement.prototype, "rawAttributes", {
/**
* Get escaped (as-it) attributes
* @return {Object} parsed attributes
*/
get: function () {
if (this._rawAttrs)
return this._rawAttrs;
var attrs = {};
if (this.rawAttrs) {
var re = /\b([a-z][a-z0-9\-]*)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|(\S+)))?/ig;
var match = void 0;
while (match = re.exec(this.rawAttrs)) {
attrs[match[1]] = match[2] || match[3] || match[4] || null;
}
}
this._rawAttrs = attrs;
return attrs;
},
enumerable: true,
configurable: true
});
HTMLElement.prototype.removeAttribute = function (key) {
var attrs = this.rawAttributes;
delete attrs[key];
// Update this.attribute
if (this._attrs) {
delete this._attrs[key];
}
// Update rawString
this.rawAttrs = Object.keys(attrs).map(function (name) {
var val = JSON.stringify(attrs[name]);
if (val === undefined || val === 'null') {
return name;
}
else {
return name + '=' + val;
}
}).join(' ');
};
HTMLElement.prototype.hasAttribute = function (key) {
return key in this.attributes;
};
/**
* Get an attribute
* @return {string} value of the attribute
*/
HTMLElement.prototype.getAttribute = function (key) {
return this.attributes[key];
};
/**
* Set an attribute value to the HTMLElement
* @param {string} key The attribute name
* @param {string} value The value to set, or null / undefined to remove an attribute
*/
HTMLElement.prototype.setAttribute = function (key, value) {
if (arguments.length < 2) {
throw new Error('Failed to execute \'setAttribute\' on \'Element\'');
}
var attrs = this.rawAttributes;
attrs[key] = String(value);
if (this._attrs) {
this._attrs[key] = he_1.decode(attrs[key]);
}
// Update rawString
this.rawAttrs = Object.keys(attrs).map(function (name) {
var val = JSON.stringify(attrs[name]);
if (val === 'null' || val === '""') {
return name;
}
else {
return name + '=' + val;
}
}).join(' ');
};
/**
* Replace all the attributes of the HTMLElement by the provided attributes
* @param {Attributes} attributes the new attribute set
*/
HTMLElement.prototype.setAttributes = function (attributes) {
// Invalidate current this.attributes
if (this._attrs) {
delete this._attrs;
}
// Invalidate current this.rawAttributes
if (this._rawAttrs) {
delete this._rawAttrs;
}
// Update rawString
this.rawAttrs = Object.keys(attributes).map(function (name) {
var val = attributes[name];
if (val === 'null' || val === '""') {
return name;
}
else {
return name + '=' + JSON.stringify(String(val));
}
}).join(' ');
};
HTMLElement.prototype.insertAdjacentHTML = function (where, html) {
var _a, _b;
var _this = this;
if (arguments.length < 2) {
throw new Error('2 arguments required');
}
var p = parse(html);
if (where === 'afterend') {
p.childNodes.forEach(function (n) {
_this.parentNode.appendChild(n);
});
}
else if (where === 'afterbegin') {
(_a = this.childNodes).unshift.apply(_a, p.childNodes);
}
else if (where === 'beforeend') {
p.childNodes.forEach(function (n) {
_this.appendChild(n);
});
}
else if (where === 'beforebegin') {
(_b = this.parentNode.childNodes).unshift.apply(_b, p.childNodes);
}
else {
throw new Error("The value provided ('" + where + "') is not one of 'beforebegin', 'afterbegin', 'beforeend', or 'afterend'");
}
if (!where || html === undefined || html === null) {
return;
}
};
return HTMLElement;
}(node_1.default));
exports.default = HTMLElement;
// https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name
var kMarkupPattern = /<!--[^]*?(?=-->)-->|<(\/?)([a-z][-.:0-9_a-z]*)\s*([^>]*?)(\/?)>/ig;
var kAttributePattern = /(^|\s)(id|class)\s*=\s*("([^"]+)"|'([^']+)'|(\S+))/ig;
var kSelfClosingElements = {
area: true,
base: true,
br: true,
col: true,
hr: true,
img: true,
input: true,
link: true,
meta: true,
source: true
};
var kElementsClosedByOpening = {
li: { li: true },
p: { p: true, div: true },
b: { div: true },
td: { td: true, th: true },
th: { td: true, th: true },
h1: { h1: true },
h2: { h2: true },
h3: { h3: true },
h4: { h4: true },
h5: { h5: true },
h6: { h6: true }
};
var kElementsClosedByClosing = {
li: { ul: true, ol: true },
a: { div: true },
b: { div: true },
i: { div: true },
p: { div: true },
td: { tr: true, table: true },
th: { tr: true, table: true }
};
var kBlockTextElements = {
script: true,
noscript: true,
style: true,
pre: true
};
var frameflag = 'documentfragmentcontainer';
function parse(data, options) {
if (options === void 0) { options = {}; }
var root = new HTMLElement(null, {});
var currentParent = root;
var stack = [root];
var lastTextPos = -1;
var match;
// https://github.com/taoqf/node-html-parser/issues/38
data = "<" + frameflag + ">" + data + "</" + frameflag + ">";
var _loop_1 = function () {
if (lastTextPos > -1) {
if (lastTextPos + match[0].length < kMarkupPattern.lastIndex) {
// if has content
var text = data.substring(lastTextPos, kMarkupPattern.lastIndex - match[0].length);
currentParent.appendChild(new text_1.default(text));
}
}
lastTextPos = kMarkupPattern.lastIndex;
if (match[2] === frameflag) {
return "continue";
}
if (match[0][1] === '!') {
// this is a comment
if (options.comment) {
// Only keep what is in between <!-- and -->
var text = data.substring(lastTextPos - 3, lastTextPos - match[0].length + 4);
currentParent.appendChild(new comment_1.default(text));
}
return "continue";
}
if (options.lowerCaseTagName) {
match[2] = match[2].toLowerCase();
}
if (!match[1]) {
// not </ tags
var attrs = {};
for (var attMatch = void 0; attMatch = kAttributePattern.exec(match[3]);) {
attrs[attMatch[2]] = attMatch[4] || attMatch[5] || attMatch[6];
}
var tagName = currentParent.tagName;
if (!match[4] && kElementsClosedByOpening[tagName]) {
if (kElementsClosedByOpening[tagName][match[2]]) {
stack.pop();
currentParent = back_1.default(stack);
}
}
// ignore container tag we add above
// https://github.com/taoqf/node-html-parser/issues/38
currentParent = currentParent.appendChild(new HTMLElement(match[2], attrs, match[3]));
stack.push(currentParent);
if (kBlockTextElements[match[2]]) {
// a little test to find next </script> or </style> ...
var closeMarkup_1 = '</' + match[2] + '>';
var index = (function () {
if (options.lowerCaseTagName) {
return data.toLocaleLowerCase().indexOf(closeMarkup_1, kMarkupPattern.lastIndex);
}
else {
return data.indexOf(closeMarkup_1, kMarkupPattern.lastIndex);
}
})();
if (options[match[2]]) {
var text = void 0;
if (index === -1) {
// there is no matching ending for the text element.
text = data.substr(kMarkupPattern.lastIndex);
}
else {
text = data.substring(kMarkupPattern.lastIndex, index);
}
if (text.length > 0) {
currentParent.appendChild(new text_1.default(text));
}
}
if (index === -1) {
lastTextPos = kMarkupPattern.lastIndex = data.length + 1;
}
else {
lastTextPos = kMarkupPattern.lastIndex = index + closeMarkup_1.length;
match[1] = 'true';
}
}
}
if (match[1] || match[4] || kSelfClosingElements[match[2]]) {
// </ or /> or <br> etc.
while (true) {
if (currentParent.tagName === match[2]) {
stack.pop();
currentParent = back_1.default(stack);
break;
}
else {
var tagName = currentParent.tagName;
// Trying to close current tag, and move on
if (kElementsClosedByClosing[tagName]) {
if (kElementsClosedByClosing[tagName][match[2]]) {
stack.pop();
currentParent = back_1.default(stack);
continue;
}
}
// Use aggressive strategy to handle unmatching markups.
break;
}
}
}
};
while (match = kMarkupPattern.exec(data)) {
_loop_1();
}
var valid = !!(stack.length === 1);
if (!options.noFix) {
var response = root;
response.valid = valid;
var _loop_2 = function () {
// Handle each error elements.
var last = stack.pop();
var oneBefore = back_1.default(stack);
if (last.parentNode && last.parentNode.parentNode) {
if (last.parentNode === oneBefore && last.tagName === oneBefore.tagName) {
// Pair error case <h3> <h3> handle : Fixes to <h3> </h3>
oneBefore.removeChild(last);
last.childNodes.forEach(function (child) {
oneBefore.parentNode.appendChild(child);
});
stack.pop();
}
else {
// Single error <div> <h3> </div> handle: Just removes <h3>
oneBefore.removeChild(last);
last.childNodes.forEach(function (child) {
oneBefore.appendChild(child);
});
}
}
else {
// If it's final element just skip.
}
};
while (stack.length > 1) {
_loop_2();
}
response.childNodes.forEach(function (node) {
if (node instanceof HTMLElement) {
node.parentNode = null;
}
});
return response;
}
else {
var response = new text_1.default(data);
response.valid = valid;
return response;
}
}
exports.parse = parse;
+11
View File
@@ -0,0 +1,11 @@
import NodeType from './type';
/**
* Node Class as base class for TextNode and HTMLElement.
*/
export default abstract class Node {
nodeType: NodeType;
childNodes: Node[];
text: string;
rawText: string;
abstract toString(): string;
}
+12
View File
@@ -0,0 +1,12 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/**
* Node Class as base class for TextNode and HTMLElement.
*/
var Node = /** @class */ (function () {
function Node() {
this.childNodes = [];
}
return Node;
}());
exports.default = Node;
+25
View File
@@ -0,0 +1,25 @@
import NodeType from './type';
import Node from './node';
/**
* TextNode to contain a text element in DOM tree.
* @param {string} value [description]
*/
export default class TextNode extends Node {
constructor(value: string);
/**
* Node Type declaration.
* @type {Number}
*/
nodeType: NodeType;
/**
* Get unescaped text value of current node and its children.
* @return {string} text content
*/
get text(): string;
/**
* Detect if the node contains only white space.
* @return {bool}
*/
get isWhitespace(): boolean;
toString(): string;
}
+64
View File
@@ -0,0 +1,64 @@
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
var type_1 = __importDefault(require("./type"));
var node_1 = __importDefault(require("./node"));
/**
* TextNode to contain a text element in DOM tree.
* @param {string} value [description]
*/
var TextNode = /** @class */ (function (_super) {
__extends(TextNode, _super);
function TextNode(value) {
var _this = _super.call(this) || this;
/**
* Node Type declaration.
* @type {Number}
*/
_this.nodeType = type_1.default.TEXT_NODE;
_this.rawText = value;
return _this;
}
Object.defineProperty(TextNode.prototype, "text", {
/**
* Get unescaped text value of current node and its children.
* @return {string} text content
*/
get: function () {
return this.rawText;
},
enumerable: true,
configurable: true
});
Object.defineProperty(TextNode.prototype, "isWhitespace", {
/**
* Detect if the node contains only white space.
* @return {bool}
*/
get: function () {
return /^(\s|&nbsp;)*$/.test(this.rawText);
},
enumerable: true,
configurable: true
});
TextNode.prototype.toString = function () {
return this.text;
};
return TextNode;
}(node_1.default));
exports.default = TextNode;
+6
View File
@@ -0,0 +1,6 @@
declare enum NodeType {
ELEMENT_NODE = 1,
TEXT_NODE = 3,
COMMENT_NODE = 8
}
export default NodeType;
+9
View File
@@ -0,0 +1,9 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var NodeType;
(function (NodeType) {
NodeType[NodeType["ELEMENT_NODE"] = 1] = "ELEMENT_NODE";
NodeType[NodeType["TEXT_NODE"] = 3] = "TEXT_NODE";
NodeType[NodeType["COMMENT_NODE"] = 8] = "COMMENT_NODE";
})(NodeType || (NodeType = {}));
exports.default = NodeType;
+1
View File
@@ -0,0 +1 @@
../he/bin/he
+20
View File
@@ -0,0 +1,20 @@
Copyright Mathias Bynens <https://mathiasbynens.be/>
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.
+379
View File
@@ -0,0 +1,379 @@
# he [![Build status](https://travis-ci.org/mathiasbynens/he.svg?branch=master)](https://travis-ci.org/mathiasbynens/he) [![Code coverage status](https://codecov.io/github/mathiasbynens/he/coverage.svg?branch=master)](https://codecov.io/github/mathiasbynens/he?branch=master) [![Dependency status](https://gemnasium.com/mathiasbynens/he.svg)](https://gemnasium.com/mathiasbynens/he)
_he_ (for “HTML entities”) is a robust HTML entity encoder/decoder written in JavaScript. It supports [all standardized named character references as per HTML](https://html.spec.whatwg.org/multipage/syntax.html#named-character-references), handles [ambiguous ampersands](https://mathiasbynens.be/notes/ambiguous-ampersands) and other edge cases [just like a browser would](https://html.spec.whatwg.org/multipage/syntax.html#tokenizing-character-references), has an extensive test suite, and — contrary to many other JavaScript solutions — _he_ handles astral Unicode symbols just fine. [An online demo is available.](https://mothereff.in/html-entities)
## Installation
Via [npm](https://www.npmjs.com/):
```bash
npm install he
```
Via [Bower](http://bower.io/):
```bash
bower install he
```
Via [Component](https://github.com/component/component):
```bash
component install mathiasbynens/he
```
In a browser:
```html
<script src="he.js"></script>
```
In [Node.js](https://nodejs.org/), [io.js](https://iojs.org/), [Narwhal](http://narwhaljs.org/), and [RingoJS](http://ringojs.org/):
```js
var he = require('he');
```
In [Rhino](http://www.mozilla.org/rhino/):
```js
load('he.js');
```
Using an AMD loader like [RequireJS](http://requirejs.org/):
```js
require(
{
'paths': {
'he': 'path/to/he'
}
},
['he'],
function(he) {
console.log(he);
}
);
```
## API
### `he.version`
A string representing the semantic version number.
### `he.encode(text, options)`
This function takes a string of text and encodes (by default) any symbols that arent printable ASCII symbols and `&`, `<`, `>`, `"`, `'`, and `` ` ``, replacing them with character references.
```js
he.encode('foo © bar ≠ baz 𝌆 qux');
// → 'foo &#xA9; bar &#x2260; baz &#x1D306; qux'
```
As long as the input string contains [allowed code points](https://html.spec.whatwg.org/multipage/parsing.html#preprocessing-the-input-stream) only, the return value of this function is always valid HTML. Any [(invalid) code points that cannot be represented using a character reference](https://html.spec.whatwg.org/multipage/syntax.html#table-charref-overrides) in the input are not encoded:
```js
he.encode('foo \0 bar');
// → 'foo \0 bar'
```
However, enabling [the `strict` option](https://github.com/mathiasbynens/he#strict) causes invalid code points to throw an exception. With `strict` enabled, `he.encode` either throws (if the input contains invalid code points) or returns a string of valid HTML.
The `options` object is optional. It recognizes the following properties:
#### `useNamedReferences`
The default value for the `useNamedReferences` option is `false`. This means that `encode()` will not use any named character references (e.g. `&copy;`) in the output — hexadecimal escapes (e.g. `&#xA9;`) will be used instead. Set it to `true` to enable the use of named references.
**Note that if compatibility with older browsers is a concern, this option should remain disabled.**
```js
// Using the global default setting (defaults to `false`):
he.encode('foo © bar ≠ baz 𝌆 qux');
// → 'foo &#xA9; bar &#x2260; baz &#x1D306; qux'
// Passing an `options` object to `encode`, to explicitly disallow named references:
he.encode('foo © bar ≠ baz 𝌆 qux', {
'useNamedReferences': false
});
// → 'foo &#xA9; bar &#x2260; baz &#x1D306; qux'
// Passing an `options` object to `encode`, to explicitly allow named references:
he.encode('foo © bar ≠ baz 𝌆 qux', {
'useNamedReferences': true
});
// → 'foo &copy; bar &ne; baz &#x1D306; qux'
```
#### `decimal`
The default value for the `decimal` option is `false`. If the option is enabled, `encode` will generally use decimal escapes (e.g. `&#169;`) rather than hexadecimal escapes (e.g. `&#xA9;`). Beside of this replacement, the basic behavior remains the same when combined with other options. For example: if both options `useNamedReferences` and `decimal` are enabled, named references (e.g. `&copy;`) are used over decimal escapes. HTML entities without a named reference are encoded using decimal escapes.
```js
// Using the global default setting (defaults to `false`):
he.encode('foo © bar ≠ baz 𝌆 qux');
// → 'foo &#xA9; bar &#x2260; baz &#x1D306; qux'
// Passing an `options` object to `encode`, to explicitly disable decimal escapes:
he.encode('foo © bar ≠ baz 𝌆 qux', {
'decimal': false
});
// → 'foo &#xA9; bar &#x2260; baz &#x1D306; qux'
// Passing an `options` object to `encode`, to explicitly enable decimal escapes:
he.encode('foo © bar ≠ baz 𝌆 qux', {
'decimal': true
});
// → 'foo &#169; bar &#8800; baz &#119558; qux'
// Passing an `options` object to `encode`, to explicitly allow named references and decimal escapes:
he.encode('foo © bar ≠ baz 𝌆 qux', {
'useNamedReferences': true,
'decimal': true
});
// → 'foo &copy; bar &ne; baz &#119558; qux'
```
#### `encodeEverything`
The default value for the `encodeEverything` option is `false`. This means that `encode()` will not use any character references for printable ASCII symbols that dont need escaping. Set it to `true` to encode every symbol in the input string. When set to `true`, this option takes precedence over `allowUnsafeSymbols` (i.e. setting the latter to `true` in such a case has no effect).
```js
// Using the global default setting (defaults to `false`):
he.encode('foo © bar ≠ baz 𝌆 qux');
// → 'foo &#xA9; bar &#x2260; baz &#x1D306; qux'
// Passing an `options` object to `encode`, to explicitly encode all symbols:
he.encode('foo © bar ≠ baz 𝌆 qux', {
'encodeEverything': true
});
// → '&#x66;&#x6F;&#x6F;&#x20;&#xA9;&#x20;&#x62;&#x61;&#x72;&#x20;&#x2260;&#x20;&#x62;&#x61;&#x7A;&#x20;&#x1D306;&#x20;&#x71;&#x75;&#x78;'
// This setting can be combined with the `useNamedReferences` option:
he.encode('foo © bar ≠ baz 𝌆 qux', {
'encodeEverything': true,
'useNamedReferences': true
});
// → '&#x66;&#x6F;&#x6F;&#x20;&copy;&#x20;&#x62;&#x61;&#x72;&#x20;&ne;&#x20;&#x62;&#x61;&#x7A;&#x20;&#x1D306;&#x20;&#x71;&#x75;&#x78;'
```
#### `strict`
The default value for the `strict` option is `false`. This means that `encode()` will encode any HTML text content you feed it, even if it contains any symbols that cause [parse errors](https://html.spec.whatwg.org/multipage/parsing.html#preprocessing-the-input-stream). To throw an error when such invalid HTML is encountered, set the `strict` option to `true`. This option makes it possible to use _he_ as part of HTML parsers and HTML validators.
```js
// Using the global default setting (defaults to `false`, i.e. error-tolerant mode):
he.encode('\x01');
// → '&#x1;'
// Passing an `options` object to `encode`, to explicitly enable error-tolerant mode:
he.encode('\x01', {
'strict': false
});
// → '&#x1;'
// Passing an `options` object to `encode`, to explicitly enable strict mode:
he.encode('\x01', {
'strict': true
});
// → Parse error
```
#### `allowUnsafeSymbols`
The default value for the `allowUnsafeSymbols` option is `false`. This means that characters that are unsafe for use in HTML content (`&`, `<`, `>`, `"`, `'`, and `` ` ``) will be encoded. When set to `true`, only non-ASCII characters will be encoded. If the `encodeEverything` option is set to `true`, this option will be ignored.
```js
he.encode('foo © and & ampersand', {
'allowUnsafeSymbols': true
});
// → 'foo &#xA9; and & ampersand'
```
#### Overriding default `encode` options globally
The global default setting can be overridden by modifying the `he.encode.options` object. This saves you from passing in an `options` object for every call to `encode` if you want to use the non-default setting.
```js
// Read the global default setting:
he.encode.options.useNamedReferences;
// → `false` by default
// Override the global default setting:
he.encode.options.useNamedReferences = true;
// Using the global default setting, which is now `true`:
he.encode('foo © bar ≠ baz 𝌆 qux');
// → 'foo &copy; bar &ne; baz &#x1D306; qux'
```
### `he.decode(html, options)`
This function takes a string of HTML and decodes any named and numerical character references in it using [the algorithm described in section 12.2.4.69 of the HTML spec](https://html.spec.whatwg.org/multipage/syntax.html#tokenizing-character-references).
```js
he.decode('foo &copy; bar &ne; baz &#x1D306; qux');
// → 'foo © bar ≠ baz 𝌆 qux'
```
The `options` object is optional. It recognizes the following properties:
#### `isAttributeValue`
The default value for the `isAttributeValue` option is `false`. This means that `decode()` will decode the string as if it were used in [a text context in an HTML document](https://html.spec.whatwg.org/multipage/syntax.html#data-state). HTML has different rules for [parsing character references in attribute values](https://html.spec.whatwg.org/multipage/syntax.html#character-reference-in-attribute-value-state) — set this option to `true` to treat the input string as if it were used as an attribute value.
```js
// Using the global default setting (defaults to `false`, i.e. HTML text context):
he.decode('foo&ampbar');
// → 'foo&bar'
// Passing an `options` object to `decode`, to explicitly assume an HTML text context:
he.decode('foo&ampbar', {
'isAttributeValue': false
});
// → 'foo&bar'
// Passing an `options` object to `decode`, to explicitly assume an HTML attribute value context:
he.decode('foo&ampbar', {
'isAttributeValue': true
});
// → 'foo&ampbar'
```
#### `strict`
The default value for the `strict` option is `false`. This means that `decode()` will decode any HTML text content you feed it, even if it contains any entities that cause [parse errors](https://html.spec.whatwg.org/multipage/syntax.html#tokenizing-character-references). To throw an error when such invalid HTML is encountered, set the `strict` option to `true`. This option makes it possible to use _he_ as part of HTML parsers and HTML validators.
```js
// Using the global default setting (defaults to `false`, i.e. error-tolerant mode):
he.decode('foo&ampbar');
// → 'foo&bar'
// Passing an `options` object to `decode`, to explicitly enable error-tolerant mode:
he.decode('foo&ampbar', {
'strict': false
});
// → 'foo&bar'
// Passing an `options` object to `decode`, to explicitly enable strict mode:
he.decode('foo&ampbar', {
'strict': true
});
// → Parse error
```
#### Overriding default `decode` options globally
The global default settings for the `decode` function can be overridden by modifying the `he.decode.options` object. This saves you from passing in an `options` object for every call to `decode` if you want to use a non-default setting.
```js
// Read the global default setting:
he.decode.options.isAttributeValue;
// → `false` by default
// Override the global default setting:
he.decode.options.isAttributeValue = true;
// Using the global default setting, which is now `true`:
he.decode('foo&ampbar');
// → 'foo&ampbar'
```
### `he.escape(text)`
This function takes a string of text and escapes it for use in text contexts in XML or HTML documents. Only the following characters are escaped: `&`, `<`, `>`, `"`, `'`, and `` ` ``.
```js
he.escape('<img src=\'x\' onerror="prompt(1)">');
// → '&lt;img src=&#x27;x&#x27; onerror=&quot;prompt(1)&quot;&gt;'
```
### `he.unescape(html, options)`
`he.unescape` is an alias for `he.decode`. It takes a string of HTML and decodes any named and numerical character references in it.
### Using the `he` binary
To use the `he` binary in your shell, simply install _he_ globally using npm:
```bash
npm install -g he
```
After that you will be able to encode/decode HTML entities from the command line:
```bash
$ he --encode 'föo ♥ bår 𝌆 baz'
f&#xF6;o &#x2665; b&#xE5;r &#x1D306; baz
$ he --encode --use-named-refs 'föo ♥ bår 𝌆 baz'
f&ouml;o &hearts; b&aring;r &#x1D306; baz
$ he --decode 'f&ouml;o &hearts; b&aring;r &#x1D306; baz'
föo ♥ bår 𝌆 baz
```
Read a local text file, encode it for use in an HTML text context, and save the result to a new file:
```bash
$ he --encode < foo.txt > foo-escaped.html
```
Or do the same with an online text file:
```bash
$ curl -sL "http://git.io/HnfEaw" | he --encode > escaped.html
```
Or, the opposite — read a local file containing a snippet of HTML in a text context, decode it back to plain text, and save the result to a new file:
```bash
$ he --decode < foo-escaped.html > foo.txt
```
Or do the same with an online HTML snippet:
```bash
$ curl -sL "http://git.io/HnfEaw" | he --decode > decoded.txt
```
See `he --help` for the full list of options.
## Support
_he_ has been tested in at least:
* Chrome 27-50
* Firefox 3-45
* Safari 4-9
* Opera 10-12, 1537
* IE 611
* Edge
* Narwhal 0.3.2
* Node.js v0.10, v0.12, v4, v5
* PhantomJS 1.9.0
* Rhino 1.7RC4
* RingoJS 0.8-0.11
## Unit tests & code coverage
After cloning this repository, run `npm install` to install the dependencies needed for he development and testing. You may want to install Istanbul _globally_ using `npm install istanbul -g`.
Once thats done, you can run the unit tests in Node using `npm test` or `node tests/tests.js`. To run the tests in Rhino, Ringo, Narwhal, and web browsers as well, use `grunt test`.
To generate the code coverage report, use `grunt cover`.
## Acknowledgements
Thanks to [Simon Pieters](https://simon.html5.org/) ([@zcorpan](https://twitter.com/zcorpan)) for the many suggestions.
## Author
| [![twitter/mathias](https://gravatar.com/avatar/24e08a9ea84deb17ae121074d0f17125?s=70)](https://twitter.com/mathias "Follow @mathias on Twitter") |
|---|
| [Mathias Bynens](https://mathiasbynens.be/) |
## License
_he_ is available under the [MIT](https://mths.be/mit) license.
+148
View File
@@ -0,0 +1,148 @@
#!/usr/bin/env node
(function() {
var fs = require('fs');
var he = require('../he.js');
var strings = process.argv.splice(2);
var stdin = process.stdin;
var data;
var timeout;
var action;
var options = {};
var log = console.log;
var main = function() {
var option = strings[0];
var count = 0;
if (/^(?:-h|--help|undefined)$/.test(option)) {
log(
'he v%s - https://mths.be/he',
he.version
);
log([
'\nUsage:\n',
'\the [--escape] string',
'\the [--encode] [--use-named-refs] [--everything] [--allow-unsafe] [--decimal] string',
'\the [--decode] [--attribute] [--strict] string',
'\the [-v | --version]',
'\the [-h | --help]',
'\nExamples:\n',
'\the --escape \\<img\\ src\\=\\\'x\\\'\\ onerror\\=\\"prompt\\(1\\)\\"\\>',
'\techo \'&copy; &#x1D306;\' | he --decode'
].join('\n'));
return process.exit(option ? 0 : 1);
}
if (/^(?:-v|--version)$/.test(option)) {
log('v%s', he.version);
return process.exit(0);
}
strings.forEach(function(string) {
// Process options
if (string == '--escape') {
action = 'escape';
return;
}
if (string == '--encode') {
action = 'encode';
return;
}
if (string == '--use-named-refs') {
action = 'encode';
options.useNamedReferences = true;
return;
}
if (string == '--everything') {
action = 'encode';
options.encodeEverything = true;
return;
}
if (string == '--allow-unsafe') {
action = 'encode';
options.allowUnsafeSymbols = true;
return;
}
if (string == '--decimal') {
action = 'encode';
options.decimal = true;
return;
}
if (string == '--decode') {
action = 'decode';
return;
}
if (string == '--attribute') {
action = 'decode';
options.isAttributeValue = true;
return;
}
if (string == '--strict') {
action = 'decode';
options.strict = true;
return;
}
// Process string(s)
var result;
if (!action) {
log('Error: he requires at least one option and a string argument.');
log('Try `he --help` for more information.');
return process.exit(1);
}
try {
result = he[action](string, options);
log(result);
count++;
} catch(error) {
log(error.message + '\n');
log('Error: failed to %s.', action);
log('If you think this is a bug in he, please report it:');
log('https://github.com/mathiasbynens/he/issues/new');
log(
'\nStack trace using he@%s:\n',
he.version
);
log(error.stack);
return process.exit(1);
}
});
if (!count) {
log('Error: he requires a string argument.');
log('Try `he --help` for more information.');
return process.exit(1);
}
// Return with exit status 0 outside of the `forEach` loop, in case
// multiple strings were passed in.
return process.exit(0);
};
if (stdin.isTTY) {
// handle shell arguments
main();
} else {
// Either the script is called from within a non-TTY context, or `stdin`
// content is being piped in.
if (!process.stdout.isTTY) {
// The script was called from a non-TTY context. This is a rather uncommon
// use case we dont actively support. However, we dont want the script
// to wait forever in such cases, so…
timeout = setTimeout(function() {
// …if no piped data arrived after a whole minute, handle shell
// arguments instead.
main();
}, 60000);
}
data = '';
stdin.on('data', function(chunk) {
clearTimeout(timeout);
data += chunk;
});
stdin.on('end', function() {
strings.push(data.trim());
main();
});
stdin.resume();
}
}());
File diff suppressed because one or more lines are too long
+78
View File
@@ -0,0 +1,78 @@
.Dd April 5, 2016
.Dt he 1
.Sh NAME
.Nm he
.Nd encode/decode HTML entities just like a browser would
.Sh SYNOPSIS
.Nm
.Op Fl -escape Ar string
.br
.Op Fl -encode Ar string
.br
.Op Fl -encode Fl -use-named-refs Fl -everything Fl -allow-unsafe Ar string
.br
.Op Fl -decode Ar string
.br
.Op Fl -decode Fl -attribute Ar string
.br
.Op Fl -decode Fl -strict Ar string
.br
.Op Fl v | -version
.br
.Op Fl h | -help
.Sh DESCRIPTION
.Nm
encodes/decodes HTML entities in strings just like a browser would.
.Sh OPTIONS
.Bl -ohang -offset
.It Sy "--escape"
Take a string of text and escape it for use in text contexts in XML or HTML documents. Only the following characters are escaped: `&`, `<`, `>`, `"`, and `'`.
.It Sy "--encode"
Take a string of text and encode any symbols that aren't printable ASCII symbols and that can be replaced with character references. For example, it would turn `©` into `&#xA9;`, but it wouldn't turn `+` into `&#x2B;` since there is no point in doing so. Additionally, it replaces any remaining non-ASCII symbols with a hexadecimal escape sequence (e.g. `&#x1D306;`). The return value of this function is always valid HTML.
.It Sy "--encode --use-named-refs"
Enable the use of named character references (like `&copy;`) in the output. If compatibility with older browsers is a concern, don't use this option.
.It Sy "--encode --everything"
Encode every symbol in the input string, even safe printable ASCII symbols.
.It Sy "--encode --allow-unsafe"
Encode non-ASCII characters only. This leaves unsafe HTML/XML symbols like `&`, `<`, `>`, `"`, and `'` intact.
.It Sy "--encode --decimal"
Use decimal digits rather than hexadecimal digits for encoded character references, e.g. output `&#169;` instead of `&#xA9;`.
.It Sy "--decode"
Takes a string of HTML and decode any named and numerical character references in it using the algorithm described in the HTML spec.
.It Sy "--decode --attribute"
Parse the input as if it was an HTML attribute value rather than a string in an HTML text content.
.It Sy "--decode --strict"
Throw an error if an invalid character reference is encountered.
.It Sy "-v, --version"
Print he's version.
.It Sy "-h, --help"
Show the help screen.
.El
.Sh EXIT STATUS
The
.Nm he
utility exits with one of the following values:
.Pp
.Bl -tag -width flag -compact
.It Li 0
.Nm
did what it was instructed to do successfully; either it encoded/decoded the input and printed the result, or it printed the version or usage message.
.It Li 1
.Nm
encountered an error.
.El
.Sh EXAMPLES
.Bl -ohang -offset
.It Sy "he --escape '<script>alert(1)</script>'"
Print an escaped version of the given string that is safe for use in HTML text contexts, escaping only `&`, `<`, `>`, `"`, and `'`.
.It Sy "he --decode '&copy;&#x1D306;'"
Print the decoded version of the given HTML string.
.It Sy "echo\ '&copy;&#x1D306;'\ |\ he --decode"
Print the decoded version of the HTML string that gets piped in.
.El
.Sh BUGS
he's bug tracker is located at <https://github.com/mathiasbynens/he/issues>.
.Sh AUTHOR
Mathias Bynens <https://mathiasbynens.be/>
.Sh WWW
<https://mths.be/he>
+91
View File
@@ -0,0 +1,91 @@
{
"_args": [
[
"he@1.1.1",
"/mnt/Foxconn/Digitalent/Deverloper/liff-push_2series"
]
],
"_from": "he@1.1.1",
"_id": "he@1.1.1",
"_inBundle": false,
"_integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=",
"_location": "/node-html-parser/he",
"_phantomChildren": {},
"_requested": {
"type": "version",
"registry": true,
"raw": "he@1.1.1",
"name": "he",
"escapedName": "he",
"rawSpec": "1.1.1",
"saveSpec": null,
"fetchSpec": "1.1.1"
},
"_requiredBy": [
"/node-html-parser"
],
"_resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz",
"_spec": "1.1.1",
"_where": "/mnt/Foxconn/Digitalent/Deverloper/liff-push_2series",
"author": {
"name": "Mathias Bynens",
"url": "https://mathiasbynens.be/"
},
"bin": {
"he": "bin/he"
},
"bugs": {
"url": "https://github.com/mathiasbynens/he/issues"
},
"description": "A robust HTML entities encoder/decoder with full Unicode support.",
"devDependencies": {
"codecov.io": "^0.1.6",
"grunt": "^0.4.5",
"grunt-shell": "^1.1.1",
"grunt-template": "^0.2.3",
"istanbul": "^0.4.2",
"jsesc": "^1.0.0",
"lodash": "^4.8.2",
"qunit-extras": "^1.4.5",
"qunitjs": "~1.11.0",
"regenerate": "^1.2.1",
"requirejs": "^2.1.22",
"sort-object": "^3.0.2"
},
"directories": {
"bin": "bin",
"man": "man",
"test": "tests"
},
"files": [
"LICENSE-MIT.txt",
"he.js",
"bin/",
"man/"
],
"homepage": "https://mths.be/he",
"keywords": [
"string",
"entities",
"entity",
"html",
"encode",
"decode",
"unicode"
],
"license": "MIT",
"main": "he.js",
"man": [
"/mnt/Foxconn/Digitalent/Deverloper/liff-push_2series/node_modules/node-html-parser/node_modules/he/man/he.1"
],
"name": "he",
"repository": {
"type": "git",
"url": "git+https://github.com/mathiasbynens/he.git"
},
"scripts": {
"build": "grunt build",
"test": "node tests/tests.js"
},
"version": "1.1.1"
}
+107
View File
@@ -0,0 +1,107 @@
{
"_args": [
[
"node-html-parser@1.2.20",
"/mnt/Foxconn/Digitalent/Deverloper/liff-push_2series"
]
],
"_from": "node-html-parser@1.2.20",
"_id": "node-html-parser@1.2.20",
"_inBundle": false,
"_integrity": "sha512-1fUpYjAducDrrBSE0etRUV1tM+wSFTudmrslMXuk35wL/L29E7e1CLQn4CNzFLnqtYpmDlWhkD6VUloyHA0dwA==",
"_location": "/node-html-parser",
"_phantomChildren": {},
"_requested": {
"type": "version",
"registry": true,
"raw": "node-html-parser@1.2.20",
"name": "node-html-parser",
"escapedName": "node-html-parser",
"rawSpec": "1.2.20",
"saveSpec": null,
"fetchSpec": "1.2.20"
},
"_requiredBy": [
"/@nuxt/generator"
],
"_resolved": "https://registry.npmjs.org/node-html-parser/-/node-html-parser-1.2.20.tgz",
"_spec": "1.2.20",
"_where": "/mnt/Foxconn/Digitalent/Deverloper/liff-push_2series",
"author": {
"name": "Xiaoyi Shi",
"email": "ashi009@gmail.com"
},
"bugs": {
"url": "https://github.com/taoqf/node-fast-html-parser/issues"
},
"config": {
"blanket": {
"pattern": "./dist/index.js",
"data-cover-never": [
"node_modules"
]
},
"travis-cov": {
"threshold": 70
}
},
"contributors": [
{
"name": "taoqf",
"email": "tao_qiufeng@126.com"
}
],
"dependencies": {
"he": "1.1.1"
},
"description": "A very fast HTML parser, generating a simplified DOM, with basic element query support.",
"devDependencies": {
"@types/entities": "latest",
"@types/he": "latest",
"@types/node": "latest",
"@typescript-eslint/eslint-plugin": "latest",
"@typescript-eslint/eslint-plugin-tslint": "latest",
"@typescript-eslint/parser": "latest",
"blanket": "latest",
"del-cli": "latest",
"eslint": "latest",
"high5": "^1.0.0",
"htmlparser": "^1.7.7",
"htmlparser-benchmark": "^1.1.3",
"htmlparser2": "^4.1.0",
"libxmljs": "^0.19.7",
"mocha": "latest",
"parse5": "^6.0.0",
"should": "latest",
"spec": "latest",
"travis-cov": "latest",
"tslint": "^5.0.0",
"typescript": "next"
},
"directories": {
"test": "test"
},
"homepage": "https://github.com/taoqf/node-fast-html-parser",
"keywords": [
"fast html parser nodejs typescript"
],
"license": "MIT",
"main": "dist/index.js",
"name": "node-html-parser",
"repository": {
"type": "git",
"url": "git+https://github.com/taoqf/node-fast-html-parser.git"
},
"scripts": {
"build": "npm run lint && npm run clean && npm run ts:cjs && npm run ts:umd",
"clean": "del-cli ./dist/",
"dev": "tsc -w",
"lint": "eslint ./src/*.ts ./src/**/*.ts",
"pretest": "tsc -m commonjs",
"test": "mocha",
"ts:cjs": "tsc -m commonjs",
"ts:umd": "tsc -t es5 -m amd -d false --outFile ./dist/main.js"
},
"types": "dist/index.d.ts",
"version": "1.2.20"
}
+2127
View File
File diff suppressed because it is too large Load Diff