From f33a9352395f79e968e1c5a1b27640fa6ed73b58 Mon Sep 17 00:00:00 2001 From: inikulin Date: Wed, 2 May 2018 11:49:57 +0100 Subject: [PATCH] Add type definition for parse5 --- notNeededPackages.json | 6 - types/jsdom/index.d.ts | 4 +- .../index.d.ts | 210 ++++++ .../parse5-htmlparser2-tree-adapter-tests.ts | 70 ++ .../tsconfig.json | 23 + .../tslint.json | 1 + types/parse5-parser-stream/index.d.ts | 92 +++ .../parse5-parser-stream-tests.ts | 32 + types/parse5-parser-stream/tsconfig.json | 23 + types/parse5-parser-stream/tslint.json | 1 + .../index.d.ts | 33 + ...rse5-plain-text-conversion-stream-tests.ts | 27 + .../tsconfig.json | 23 + .../tslint.json | 1 + types/parse5-sax-parser/index.d.ts | 192 ++++++ .../parse5-sax-parser-tests.ts | 45 ++ types/parse5-sax-parser/tsconfig.json | 23 + types/parse5-sax-parser/tslint.json | 1 + types/parse5-serializer-stream/index.d.ts | 41 ++ .../parse5-serializer-stream-tests.ts | 16 + types/parse5-serializer-stream/tsconfig.json | 23 + types/parse5-serializer-stream/tslint.json | 1 + types/parse5/index.d.ts | 601 ++++++++++++++++++ types/parse5/parse5-tests.ts | 191 ++++++ types/parse5/tsconfig.json | 23 + types/parse5/tslint.json | 1 + 26 files changed, 1696 insertions(+), 8 deletions(-) create mode 100644 types/parse5-htmlparser2-tree-adapter/index.d.ts create mode 100644 types/parse5-htmlparser2-tree-adapter/parse5-htmlparser2-tree-adapter-tests.ts create mode 100644 types/parse5-htmlparser2-tree-adapter/tsconfig.json create mode 100644 types/parse5-htmlparser2-tree-adapter/tslint.json create mode 100644 types/parse5-parser-stream/index.d.ts create mode 100644 types/parse5-parser-stream/parse5-parser-stream-tests.ts create mode 100644 types/parse5-parser-stream/tsconfig.json create mode 100644 types/parse5-parser-stream/tslint.json create mode 100644 types/parse5-plain-text-conversion-stream/index.d.ts create mode 100644 types/parse5-plain-text-conversion-stream/parse5-plain-text-conversion-stream-tests.ts create mode 100644 types/parse5-plain-text-conversion-stream/tsconfig.json create mode 100644 types/parse5-plain-text-conversion-stream/tslint.json create mode 100644 types/parse5-sax-parser/index.d.ts create mode 100644 types/parse5-sax-parser/parse5-sax-parser-tests.ts create mode 100644 types/parse5-sax-parser/tsconfig.json create mode 100644 types/parse5-sax-parser/tslint.json create mode 100644 types/parse5-serializer-stream/index.d.ts create mode 100644 types/parse5-serializer-stream/parse5-serializer-stream-tests.ts create mode 100644 types/parse5-serializer-stream/tsconfig.json create mode 100644 types/parse5-serializer-stream/tslint.json create mode 100644 types/parse5/index.d.ts create mode 100644 types/parse5/parse5-tests.ts create mode 100644 types/parse5/tsconfig.json create mode 100644 types/parse5/tslint.json diff --git a/notNeededPackages.json b/notNeededPackages.json index 6f3e4fe093..897648af02 100644 --- a/notNeededPackages.json +++ b/notNeededPackages.json @@ -1002,12 +1002,6 @@ "sourceRepoURL": "https://github.com/blakeembrey/param-case", "asOfVersion": "1.1.2" }, - { - "libraryName": "parse5", - "typingsPackageName": "parse5", - "sourceRepoURL": "https://github.com/inikulin/parse5", - "asOfVersion": "3.0.0" - }, { "libraryName": "pascal-case", "typingsPackageName": "pascal-case", diff --git a/types/jsdom/index.d.ts b/types/jsdom/index.d.ts index cfb54fa25f..5ccdd33a65 100644 --- a/types/jsdom/index.d.ts +++ b/types/jsdom/index.d.ts @@ -7,7 +7,7 @@ /// import { EventEmitter } from 'events'; -import { MarkupData } from 'parse5'; +import { ElementLocation } from 'parse5'; import * as tough from 'tough-cookie'; import { Script } from 'vm'; @@ -32,7 +32,7 @@ export class JSDOM { /** * The nodeLocation() method will find where a DOM node is within the source document, returning the parse5 location info for the node. */ - nodeLocation(node: Node): MarkupData.ElementLocation | null; + nodeLocation(node: Node): ElementLocation | null; /** * The built-in vm module of Node.js allows you to create Script instances, diff --git a/types/parse5-htmlparser2-tree-adapter/index.d.ts b/types/parse5-htmlparser2-tree-adapter/index.d.ts new file mode 100644 index 0000000000..12aa70219b --- /dev/null +++ b/types/parse5-htmlparser2-tree-adapter/index.d.ts @@ -0,0 +1,210 @@ +// Type definitions for parse5-htmlparser2-tree-adapter 5.0 +// Project: https://github.com/inikulin/parse5 +// Definitions by: Ivan Nikulin +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// TypeScript Version: 2.2 + +import * as parse5 from "parse5"; + +/** + * htmlparser2 tree adapter Node interface. + */ +export interface Node { + /** + * The type of the node. E.g. {@link Document} will have `type` equal to 'root'`. + */ + type: string; + /** + * [DOM spec](https://dom.spec.whatwg.org/#dom-node-nodetype)-compatible node {@link type}. + */ + nodeType: number; + /** + * Parent node. + */ + parent: ParentNode; + /** + * Same as {@link parent}. [DOM spec](https://dom.spec.whatwg.org)-compatible alias. + */ + parentNode: ParentNode; + /** + * Previous sibling. + */ + prev: Node; + /** + * Same as {@link prev}. [DOM spec](https://dom.spec.whatwg.org)-compatible alias. + */ + previousSibling: Node; + /** + * Next sibling. + */ + next: Node; + /** + * Same as {@link next}. [DOM spec](https://dom.spec.whatwg.org)-compatible alias. + */ + nextSibling: Node; +} + +/** + * htmlparser2 tree adapter ParentNode interface. + */ +export interface ParentNode extends Node { + /** + * Child nodes. + */ + children: Node[]; + /** + * Same as {@link children}. [DOM spec](https://dom.spec.whatwg.org)-compatible alias. + */ + childNodes: Node[]; + /** + * First child of the node. + */ + firstChild: Node; + /** + * Last child of the node. + */ + lastChild: Node; +} + +/** + * htmlparser2 tree adapter DocumentType interface. + */ +export interface DocumentType extends Node { + /** + * The type of the node. + */ + type: "directive"; + /** + * Node name. + */ + name: "!doctype"; + /** + * Serialized doctype {@link name}, {@link publicId} and {@link systemId}. + */ + data: string; + /** + * Document type name. + */ + "x-name": string; + /** + * Document type public identifier. + */ + "x-publicId": string; + /** + * Document type system identifier. + */ + "x-systemId": string; +} + +/** + * htmlparser2 tree adapter Document interface. + */ +export interface Document extends ParentNode { + /** + * The type of the node. + */ + type: "root"; + /** + * The name of the node. + */ + name: "root"; + /** + * [Document mode](https://dom.spec.whatwg.org/#concept-document-limited-quirks). + */ + "x-mode": parse5.DocumentMode; +} + +/** + * htmlparser2 tree adapter DocumentFragment interface. + */ +export interface DocumentFragment extends ParentNode { + /** + * The type of the node. + */ + type: "root"; + /** + * The name of the node. + */ + name: "root"; +} + +/** + * htmlparser2 tree adapter Element interface. + */ +export interface Element extends ParentNode { + /** + * The name of the node. Equals to element {@link tagName}. + */ + name: string; + /** + * Element tag name. + */ + tagName: string; + /** + * Element namespace. + */ + namespace: string; + /** + * Element attributes. + */ + attribs: { [name: string]: string }; + /** + * Element attribute namespaces. + */ + "x-attribsNamespace": { [name: string]: string }; + /** + * Element attribute namespace-related prefixes. + */ + "x-attribsPrefix": { [name: string]: string }; + /** + * Element source code location info. Available if location info is enabled via ParserOptions. + */ + sourceCodeLocation?: parse5.ElementLocation; +} + +/** + * htmlparser2 tree adapter CommentNode interface. + */ +export interface CommentNode extends Node { + /** + * The name of the node. + */ + name: "comment"; + /** + * Comment text. + */ + data: string; + /** + * Same as {@link data}. [DOM spec](https://dom.spec.whatwg.org)-compatible alias. + */ + nodeValue: string; + /** + * Comment source code location info. Available if location info is enabled via ParserOptions. + */ + sourceCodeLocation?: parse5.Location; +} + +/** + * htmlparser2 tree adapter TextNode interface. + */ +export interface TextNode extends Node { + /** + * The name of the node. + */ + name: "text"; + /** + * Text content. + */ + data: string; + /** + * Same as {@link data}. [DOM spec](https://dom.spec.whatwg.org)-compatible alias. + */ + nodeValue: string; + /** + * Comment source code location info. Available if location info is enabled via ParserOptions. + */ + sourceCodeLocation?: parse5.Location; +} + +declare const treeAdapter: parse5.TreeAdapter; +export default treeAdapter; diff --git a/types/parse5-htmlparser2-tree-adapter/parse5-htmlparser2-tree-adapter-tests.ts b/types/parse5-htmlparser2-tree-adapter/parse5-htmlparser2-tree-adapter-tests.ts new file mode 100644 index 0000000000..e14ad9da3b --- /dev/null +++ b/types/parse5-htmlparser2-tree-adapter/parse5-htmlparser2-tree-adapter-tests.ts @@ -0,0 +1,70 @@ +import { parse } from "parse5"; +import treeAdapter, { + Node, + ParentNode, + Document, + DocumentType, + Element, + TextNode, + CommentNode +} from "parse5-htmlparser2-tree-adapter"; + +// htmlparser2 AST +const htmlparser2Document = parse("", { + treeAdapter +}) as Document; + +htmlparser2Document; // $ExpectType Document +htmlparser2Document.name; // $ExpectType "root" +htmlparser2Document.type; // $ExpectType "root" +htmlparser2Document["x-mode"]; // $ExpectType DocumentMode + +const htmlparser2Node = htmlparser2Document as Node; + +htmlparser2Node.next; // $ExpectType Node +htmlparser2Node.nextSibling; // $ExpectType Node +htmlparser2Node.nodeType; // $ExpectType number +htmlparser2Node.parent; // $ExpectType ParentNode +htmlparser2Node.parentNode; // $ExpectType ParentNode +htmlparser2Node.prev; // $ExpectType Node +htmlparser2Node.previousSibling; // $ExpectType Node +htmlparser2Node.type; // $ExpectType string + +const htmlparser2ParentNode = htmlparser2Document as ParentNode; + +htmlparser2ParentNode; // $ExpectType ParentNode +htmlparser2ParentNode.childNodes[0]; // $ExpectType Node +htmlparser2ParentNode.children[0]; // $ExpectType Node +htmlparser2ParentNode.firstChild; // $ExpectType Node +htmlparser2ParentNode.lastChild; // $ExpectType Node + +const htmlparser2Doctype = htmlparser2Document.childNodes[0] as DocumentType; + +htmlparser2Doctype; // $ExpectType DocumentType +htmlparser2Doctype.data; // $ExpectType string +htmlparser2Doctype.name; // $ExpectType "!doctype" +htmlparser2Doctype["x-name"]; // $ExpectType string +htmlparser2Doctype["x-publicId"]; // $ExpectType string +htmlparser2Doctype["x-systemId"]; // $ExpectType string + +const htmlparser2Element = htmlparser2Document.childNodes[0] as Element; + +htmlparser2Element; // $ExpectType Element +htmlparser2Element.attribs["someAttr"]; // $ExpectType string +htmlparser2Element["x-attribsNamespace"]["someAttr"]; // $ExpectType string +htmlparser2Element["x-attribsPrefix"]["someAttr"]; // $ExpectType string +htmlparser2Element.namespace; // $ExpectType string +htmlparser2Element.tagName; // $ExpectType string +htmlparser2Element.sourceCodeLocation!; // $ExpectType ElementLocation + +const htmlparser2TextNode = htmlparser2Document.childNodes[0] as TextNode; + +htmlparser2TextNode.data; // $ExpectType string +htmlparser2TextNode.nodeValue; // $ExpectType string +htmlparser2TextNode.sourceCodeLocation!; // $ExpectType Location + +const htmlparser2CommentNode = htmlparser2Document.childNodes[0] as CommentNode; + +htmlparser2CommentNode.data; // $ExpectType string +htmlparser2CommentNode.nodeValue; // $ExpectType string +htmlparser2CommentNode.sourceCodeLocation!; // $ExpectType Location diff --git a/types/parse5-htmlparser2-tree-adapter/tsconfig.json b/types/parse5-htmlparser2-tree-adapter/tsconfig.json new file mode 100644 index 0000000000..c7655de33c --- /dev/null +++ b/types/parse5-htmlparser2-tree-adapter/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": [ + "es6" + ], + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "baseUrl": "../", + "typeRoots": [ + "../" + ], + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": [ + "index.d.ts", + "parse5-htmlparser2-tree-adapter-tests.ts" + ] +} diff --git a/types/parse5-htmlparser2-tree-adapter/tslint.json b/types/parse5-htmlparser2-tree-adapter/tslint.json new file mode 100644 index 0000000000..3db14f85ea --- /dev/null +++ b/types/parse5-htmlparser2-tree-adapter/tslint.json @@ -0,0 +1 @@ +{ "extends": "dtslint/dt.json" } diff --git a/types/parse5-parser-stream/index.d.ts b/types/parse5-parser-stream/index.d.ts new file mode 100644 index 0000000000..ac10af57af --- /dev/null +++ b/types/parse5-parser-stream/index.d.ts @@ -0,0 +1,92 @@ +// Type definitions for parse5-parser-stream 5.0 +// Project: https://github.com/inikulin/parse5 +// Definitions by: Ivan Nikulin +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// TypeScript Version: 2.2 + +/// + +import * as stream from "stream"; +import * as parse5 from "parse5"; + +/** + * Streaming HTML parser with scripting support. + * A [writable stream](https://nodejs.org/api/stream.html#stream_class_stream_writable). + * + * ** NOTE:** This API is available only for Node.js. + * + * @example + * ```js + * + * const parse5 = require('parse5'); + * const http = require('http'); + * + * // Fetch the page content and obtain it's node + * http.get('http://inikulin.github.io/parse5/', res => { + * const parser = new parse5.ParserStream(); + * + * parser.once('finish', () => { + * console.log(parser.document.childNodes[1].childNodes[0].tagName); //> 'head' + * }); + * + * res.pipe(parser); + * }); + * ``` + */ +export default class ParserStream extends stream.Writable { + /** + * @param options - Parsing options. + */ + constructor(options?: parse5.ParserOptions); + + /** + * The resulting document node. + */ + document: TDocument; + + /** + * Raised when parser encounters a `'); + * ``` + */ + on( + event: "script", + listener: ( + scriptElement: parse5.Element, + documentWrite: (html: string) => void, + resume: () => void + ) => void + ): this; + /** + * WritableStream events + */ + on(event: string, listener: (...params: any[]) => any): this; +} diff --git a/types/parse5-parser-stream/parse5-parser-stream-tests.ts b/types/parse5-parser-stream/parse5-parser-stream-tests.ts new file mode 100644 index 0000000000..6793ce7fa9 --- /dev/null +++ b/types/parse5-parser-stream/parse5-parser-stream-tests.ts @@ -0,0 +1,32 @@ +import * as parse5 from "parse5"; +import ParserStream from "parse5-parser-stream"; +import { createReadStream } from "fs"; + +const defaultAdapter = new Object() as parse5.TreeAdapter; +let parser = new ParserStream(); + +parser = new ParserStream({ sourceCodeLocationInfo: true }); +parser = new ParserStream({ treeAdapter: defaultAdapter }); +parser = new ParserStream({ + sourceCodeLocationInfo: true, + treeAdapter: defaultAdapter +}); +parser = new ParserStream({ + sourceCodeLocationInfo: true, + treeAdapter: defaultAdapter +}); + +parser.document; // $ExpectType DefaultTreeDocument + +parser + .on( + "script", + ( + element: parse5.Element, + documentWrite: (html: string) => void, + resume: () => {} + ) => {} + ) + .on("finish", () => {}); + +createReadStream("file").pipe(parser); diff --git a/types/parse5-parser-stream/tsconfig.json b/types/parse5-parser-stream/tsconfig.json new file mode 100644 index 0000000000..6b52a77de9 --- /dev/null +++ b/types/parse5-parser-stream/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": [ + "es6" + ], + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "baseUrl": "../", + "typeRoots": [ + "../" + ], + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": [ + "index.d.ts", + "parse5-parser-stream-tests.ts" + ] +} diff --git a/types/parse5-parser-stream/tslint.json b/types/parse5-parser-stream/tslint.json new file mode 100644 index 0000000000..3db14f85ea --- /dev/null +++ b/types/parse5-parser-stream/tslint.json @@ -0,0 +1 @@ +{ "extends": "dtslint/dt.json" } diff --git a/types/parse5-plain-text-conversion-stream/index.d.ts b/types/parse5-plain-text-conversion-stream/index.d.ts new file mode 100644 index 0000000000..d5ac51ba18 --- /dev/null +++ b/types/parse5-plain-text-conversion-stream/index.d.ts @@ -0,0 +1,33 @@ +// Type definitions for parse5-plain-text-conversion-stream 5.0 +// Project: https://github.com/inikulin/parse5 +// Definitions by: Ivan Nikulin +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// TypeScript Version: 2.2 + +import ParserStream from "parse5-parser-stream"; + +/** + * Converts plain text files into HTML document as required by [HTML specification](https://html.spec.whatwg.org/#read-text). + * A [writable stream](https://nodejs.org/api/stream.html#stream_class_stream_writable). + * + * ** NOTE:** This API is available only for Node.js. + * + * @example + * ```js + * + * const parse5 = require('parse5'); + * const fs = require('fs'); + * + * const file = fs.createReadStream('war_and_peace.txt'); + * const converter = new parse5.PlainTextConversionStream(); + * + * converter.once('finish', () => { + * console.log(converter.document.childNodes[1].childNodes[0].tagName); //> 'head' + * }); + * + * file.pipe(converter); + * ``` + */ +export default class PlainTextConversionStream extends ParserStream< + TDocument +> {} diff --git a/types/parse5-plain-text-conversion-stream/parse5-plain-text-conversion-stream-tests.ts b/types/parse5-plain-text-conversion-stream/parse5-plain-text-conversion-stream-tests.ts new file mode 100644 index 0000000000..00f6728dc2 --- /dev/null +++ b/types/parse5-plain-text-conversion-stream/parse5-plain-text-conversion-stream-tests.ts @@ -0,0 +1,27 @@ +import * as parse5 from "parse5"; +import PlainTextConversionStream from "parse5-plain-text-conversion-stream"; +import { createReadStream } from "fs"; + +const defaultAdapter = new Object() as parse5.TreeAdapter; +let converter = new PlainTextConversionStream(); + +converter = new PlainTextConversionStream({ + sourceCodeLocationInfo: true +}); +converter = new PlainTextConversionStream({ + treeAdapter: defaultAdapter +}); +converter = new PlainTextConversionStream({ + sourceCodeLocationInfo: true, + treeAdapter: defaultAdapter +}); +converter = new PlainTextConversionStream({ + sourceCodeLocationInfo: true, + treeAdapter: defaultAdapter +}); + +converter.document; // $ExpectType DefaultTreeDocument + +converter.on("finish", () => {}); + +createReadStream("file").pipe(converter); diff --git a/types/parse5-plain-text-conversion-stream/tsconfig.json b/types/parse5-plain-text-conversion-stream/tsconfig.json new file mode 100644 index 0000000000..47698adf67 --- /dev/null +++ b/types/parse5-plain-text-conversion-stream/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": [ + "es6" + ], + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "baseUrl": "../", + "typeRoots": [ + "../" + ], + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": [ + "index.d.ts", + "parse5-plain-text-conversion-stream-tests.ts" + ] +} diff --git a/types/parse5-plain-text-conversion-stream/tslint.json b/types/parse5-plain-text-conversion-stream/tslint.json new file mode 100644 index 0000000000..3db14f85ea --- /dev/null +++ b/types/parse5-plain-text-conversion-stream/tslint.json @@ -0,0 +1 @@ +{ "extends": "dtslint/dt.json" } diff --git a/types/parse5-sax-parser/index.d.ts b/types/parse5-sax-parser/index.d.ts new file mode 100644 index 0000000000..0d98fb51e2 --- /dev/null +++ b/types/parse5-sax-parser/index.d.ts @@ -0,0 +1,192 @@ +// Type definitions for parse5-sax-parser 5.0 +// Project: https://github.com/inikulin/parse5 +// Definitions by: Ivan Nikulin +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// TypeScript Version: 2.2 + +/// + +import * as stream from "stream"; +import * as parse5 from "parse5"; + +export interface StartTagToken { + /** + * Tag name. + */ + tagName: string; + /** + * List of attributes. + */ + attrs: parse5.Attribute[]; + /** + * Indicates if the tag is self-closing. + */ + selfClosing: boolean; + /** + * Start tag source code location info. Available if location info is enabled via {@link SAXParserOptions}. + */ + sourceCodeLocation?: parse5.StartTagLocation; +} + +export interface EndTagToken { + /** + * Tag name. + */ + tagName: string; + /** + * End tag source code location info. Available if location info is enabled via {@link SAXParserOptions}. + */ + sourceCodeLocation?: parse5.Location; +} + +export interface CommentToken { + /** + * Comment text. + */ + text: string; + /** + * Comment source code location info. Available if location info is enabled via {@link SAXParserOptions}. + */ + sourceCodeLocation?: parse5.Location; +} + +export interface TextToken { + /** + * Text content. + */ + text: string; + /** + * Text content source code location info. Available if location info is enabled via {@link SAXParserOptions}. + */ + sourceCodeLocation?: parse5.Location; +} + +export interface DoctypeToken { + /** + * Document type name. + */ + name: string; + /** + * Document type public identifier. + */ + publicId: string; + /** + * Document type system identifier. + */ + systemId: string; + /** + * Document type declaration source code location info. Available if location info is enabled via {@link SAXParserOptions}. + */ + sourceCodeLocation?: parse5.Location; +} + +export interface SAXParserOptions { + /** + * Enables source code location information for the tokens. + * When enabled, each token event handler will receive {@link Location} (or {@link StartTagLocation}) + * object as its last argument. + */ + sourceCodeLocationInfo?: boolean; +} + +/** + * Streaming [SAX](https://en.wikipedia.org/wiki/Simple_API_for_XML)-style HTML parser. + * A [transform stream](https://nodejs.org/api/stream.html#stream_class_stream_transform) + * (which means you can pipe *through* it, see example). + * + * ** NOTE:** This API is available only for Node.js. + * + * @example + * ```js + * + * const parse5 = require('parse5'); + * const http = require('http'); + * const fs = require('fs'); + * + * const file = fs.createWriteStream('/home/google.com.html'); + * const parser = new parse5.SAXParser(); + * + * parser.on('text', text => { + * // Handle page text content + * ... + * }); + * + * http.get('http://google.com', res => { + * // SAXParser is the Transform stream, which means you can pipe + * // through it. So, you can analyze page content and, e.g., save it + * // to the file at the same time: + * res.pipe(parser).pipe(file); + * }); + * ``` + */ +export default class SAXParser extends stream.Transform { + /** + * @param options - Parsing options. + */ + constructor(options?: SAXParserOptions); + + /** + * Raised when the parser encounters a start tag. + * + * @param listener.startTag - Start tag token. + */ + on(event: "startTag", listener: (startTag: StartTagToken) => void): this; + + /** + * Raised when parser encounters an end tag. + * + * @param listener.endTag - End tag token. + */ + on(event: "endTag", listener: (endTag: EndTagToken) => void): this; + /** + * Raised when parser encounters text content. + * + * @param listener.text - Text token. + */ + on(event: "text", listener: (text: TextToken) => void): this; + /** + * Raised when parser encounters a comment. + * + * @param listener.comment - Comment content. + */ + on(event: "comment", listener: (comment: CommentToken) => void): this; + /** + * Raised when parser encounters a [document type declaration](https://en.wikipedia.org/wiki/Document_type_declaration). + * + * @param listener.doctype - Document type token. + */ + on(event: "doctype", listener: (doctype: DoctypeToken) => void): this; + /** + * TransformStream events + */ + on(event: string, listener: (...params: any[]) => any): this; + + /** + * Stops parsing. Useful if you want the parser to stop consuming CPU time once you've obtained the desired info + * from the input stream. Doesn't prevent piping, so that data will flow through the parser as usual. + * + * @example + * ```js + * + * const parse5 = require('parse5'); + * const http = require('http'); + * const fs = require('fs'); + * + * const file = fs.createWriteStream('google.com.html'); + * const parser = new parse5.SAXParser(); + * + * parser.on('doctype', (name, publicId, systemId) => { + * // Process doctype info ans stop parsing + * ... + * parser.stop(); + * }); + * + * http.get('http://google.com', res => { + * // Despite the fact that parser.stop() was called whole + * // content of the page will be written to the file + * res.pipe(parser).pipe(file); + * }); + * ``` + */ + stop(): void; +} diff --git a/types/parse5-sax-parser/parse5-sax-parser-tests.ts b/types/parse5-sax-parser/parse5-sax-parser-tests.ts new file mode 100644 index 0000000000..75fd4c25b2 --- /dev/null +++ b/types/parse5-sax-parser/parse5-sax-parser-tests.ts @@ -0,0 +1,45 @@ +import SAXParser, { + StartTagToken, + EndTagToken, + CommentToken, + TextToken, + DoctypeToken +} from "parse5-sax-parser"; +import { createReadStream, createWriteStream } from "fs"; + +let sax = new SAXParser(); + +sax = new SAXParser({ sourceCodeLocationInfo: true }); + +sax.stop(); + +sax + .on("startTag", (startTag: StartTagToken) => { + startTag.tagName; // $ExpectType string + startTag.attrs; // $ExpectType Attribute[] + startTag.selfClosing; // $ExpectType boolean + startTag.sourceCodeLocation!; // $ExpectType StartTagLocation + }) + .on("endTag", (endTag: EndTagToken) => { + endTag.tagName; // $ExpectType string + endTag.sourceCodeLocation!; // $ExpectType Location + }) + .on("comment", (comment: CommentToken) => { + comment.text; // $ExpectType string + comment.sourceCodeLocation!; // $ExpectType Location + }) + .on("text", (text: TextToken) => { + text.text; // $ExpectType string + text.sourceCodeLocation!; // $ExpectType Location + }) + .on("doctype", (doctype: DoctypeToken) => { + doctype.name; // $ExpectType string + doctype.publicId; // $ExpectType string + doctype.systemId; // $ExpectType string + doctype.sourceCodeLocation!; // $ExpectType Location + }) + .on("finish", () => {}); + +createReadStream("file1") + .pipe(sax) + .pipe(createWriteStream("file2")); diff --git a/types/parse5-sax-parser/tsconfig.json b/types/parse5-sax-parser/tsconfig.json new file mode 100644 index 0000000000..13ec568936 --- /dev/null +++ b/types/parse5-sax-parser/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": [ + "es6" + ], + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "baseUrl": "../", + "typeRoots": [ + "../" + ], + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": [ + "index.d.ts", + "parse5-sax-parser-tests.ts" + ] +} diff --git a/types/parse5-sax-parser/tslint.json b/types/parse5-sax-parser/tslint.json new file mode 100644 index 0000000000..3db14f85ea --- /dev/null +++ b/types/parse5-sax-parser/tslint.json @@ -0,0 +1 @@ +{ "extends": "dtslint/dt.json" } diff --git a/types/parse5-serializer-stream/index.d.ts b/types/parse5-serializer-stream/index.d.ts new file mode 100644 index 0000000000..d96db5e40c --- /dev/null +++ b/types/parse5-serializer-stream/index.d.ts @@ -0,0 +1,41 @@ +// Type definitions for parse5-serializer-stream 5.0 +// Project: https://github.com/inikulin/parse5 +// Definitions by: Ivan Nikulin +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// TypeScript Version: 2.2 + +/// + +import * as stream from "stream"; +import * as parse5 from "parse5"; + +/** + * Streaming AST node to an HTML serializer. + * A [readable stream](https://nodejs.org/api/stream.html#stream_class_stream_readable). + * + * ** NOTE:** This API is available only for Node.js. + * + * @example + * ```js + * + * const parse5 = require('parse5'); + * const fs = require('fs'); + * + * const file = fs.createWriteStream('/home/index.html'); + * + * // Serializes the parsed document to HTML and writes it to the file. + * const document = parse5.parse('Who is John Galt?'); + * const serializer = new parse5.SerializerStream(document); + * + * serializer.pipe(file); + * ``` + */ +export default class SerializerStream extends stream.Readable { + /** + * Streaming AST node to an HTML serializer. A readable stream. + * + * @param node - Node to serialize. + * @param options - Serialization options. + */ + constructor(node: parse5.Node, options?: parse5.SerializerOptions); +} diff --git a/types/parse5-serializer-stream/parse5-serializer-stream-tests.ts b/types/parse5-serializer-stream/parse5-serializer-stream-tests.ts new file mode 100644 index 0000000000..3f5a8fbb96 --- /dev/null +++ b/types/parse5-serializer-stream/parse5-serializer-stream-tests.ts @@ -0,0 +1,16 @@ +import { parse, TreeAdapter } from "parse5"; +import SerializerStream from "parse5-serializer-stream"; +import { createReadStream, createWriteStream } from "fs"; + +const document = parse(""); +const defaultAdapter = new Object() as TreeAdapter; +let serializer = new SerializerStream(document); + +serializer = new SerializerStream(document, { + treeAdapter: defaultAdapter +}); +serializer = new SerializerStream(document, { + treeAdapter: defaultAdapter +}); + +serializer.pipe(createWriteStream("file")); diff --git a/types/parse5-serializer-stream/tsconfig.json b/types/parse5-serializer-stream/tsconfig.json new file mode 100644 index 0000000000..52c5352bf7 --- /dev/null +++ b/types/parse5-serializer-stream/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": [ + "es6" + ], + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "baseUrl": "../", + "typeRoots": [ + "../" + ], + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": [ + "index.d.ts", + "parse5-serializer-stream-tests.ts" + ] +} diff --git a/types/parse5-serializer-stream/tslint.json b/types/parse5-serializer-stream/tslint.json new file mode 100644 index 0000000000..3db14f85ea --- /dev/null +++ b/types/parse5-serializer-stream/tslint.json @@ -0,0 +1 @@ +{ "extends": "dtslint/dt.json" } diff --git a/types/parse5/index.d.ts b/types/parse5/index.d.ts new file mode 100644 index 0000000000..f495207d24 --- /dev/null +++ b/types/parse5/index.d.ts @@ -0,0 +1,601 @@ +// Type definitions for parse5 5.0 +// Project: https://github.com/inikulin/parse5 +// Definitions by: Ivan Nikulin +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// TypeScript Version: 2.2 + +export interface Location { + /** + * One-based line index of the first character + */ + startLine: number; + /** + * One-based column index of the first character + */ + startCol: number; + /** + * One-based line index of the last character + */ + endLine: number; + /** + * One-based column index of the last character + */ + endCol: number; + /** + * Zero-based first character index + */ + startOffset: number; + /** + * Zero-based last character index + */ + endOffset: number; +} + +export interface AttributesLocation { + [attributeName: string]: Location; +} + +export interface StartTagLocation extends Location { + /** + * Start tag attributes' location info + */ + attrs: AttributesLocation; +} + +export interface ElementLocation extends StartTagLocation { + /** + * Element's start tag location info. + */ + startTag: StartTagLocation; + /** + * Element's end tag location info. + */ + endTag: Location; +} + +export interface ParserOptions { + /** + * The [scripting flag](https://html.spec.whatwg.org/multipage/parsing.html#scripting-flag). If set + * to `true`, `noscript` element content will be parsed as text. + * + * **Default:** `true` + */ + scriptingEnabled?: boolean; + /** + * Enables source code location information. When enabled, each node (except the root node) + * will have a `sourceCodeLocation` property. If the node is not an empty element, `sourceCodeLocation` will + * be a {@link ElementLocation} object, otherwise it will be {@link Location}. + * If the element was implicitly created by the parser (as part of + * [tree correction](https://html.spec.whatwg.org/multipage/syntax.html#an-introduction-to-error-handling-and-strange-cases-in-the-parser)), + * its `sourceCodeLocation` property will be `undefined`. + * + * **Default:** `false` + */ + sourceCodeLocationInfo?: boolean; + /** + * Specifies the resulting tree format. + * + * **Default:** `treeAdapters.default` + */ + treeAdapter?: TreeAdapter; +} + +export interface SerializerOptions { + /*** + * Specifies input tree format. + * + * **Default:** `treeAdapters.default` + */ + treeAdapter?: TreeAdapter; +} + +/** + * [Document mode](https://dom.spec.whatwg.org/#concept-document-limited-quirks). + */ +export type DocumentMode = "no-quirks" | "quirks" | "limited-quirks"; + +// Default tree adapter + +/** + * Element attribute. + */ +export interface Attribute { + /** + * The name of the attribute. + */ + name: string; + /** + * The value of the attribute. + */ + value: string; + /** + * The namespace of the attribute. + */ + namespace?: string; + /** + * The namespace-related prefix of the attribute. + */ + prefix?: string; +} + +/** + * Default tree adapter Node interface. + */ +export interface DefaultTreeNode { + /** + * The name of the node. E.g. {@link Document} will have `nodeName` equal to '#document'`. + */ + nodeName: string; +} + +/** + * Default tree adapter ParentNode interface. + */ +export interface DefaultTreeParentNode { + /** + * Child nodes. + */ + childNodes: DefaultTreeNode[]; +} + +/** + * Default tree adapter DocumentType interface. + */ +export interface DefaultTreeDocumentType extends DefaultTreeNode { + /** + * The name of the node. + */ + nodeName: "#documentType"; + /** + * Document type name. + */ + name: string; + /** + * Document type public identifier. + */ + publicId: string; + /** + * Document type system identifier. + */ + systemId: string; +} + +/** + * Default tree adapter Document interface. + */ +export interface DefaultTreeDocument extends DefaultTreeParentNode { + /** + * The name of the node. + */ + nodeName: "#document"; + /** + * [Document mode](https://dom.spec.whatwg.org/#concept-document-limited-quirks). + */ + mode: DocumentMode; +} + +/** + * Default tree adapter DocumentFragment interface. + */ +export interface DefaultTreeDocumentFragment extends DefaultTreeParentNode { + /** + * The name of the node. + */ + nodeName: "#document-fragment"; +} + +/** + * Default tree adapter Element interface. + */ +export interface DefaultTreeElement extends DefaultTreeParentNode { + /** + * The name of the node. Equals to element {@link tagName}. + */ + nodeName: string; + /** + * Element tag name. + */ + tagName: string; + /** + * Element namespace. + */ + namespaceURI: string; + /** + * List of element attributes. + */ + attrs: Attribute[]; + /** + * Parent node. + */ + parentNode: DefaultTreeParentNode; + /** + * Element source code location info. Available if location info is enabled via {@link ParserOptions}. + */ + sourceCodeLocation?: ElementLocation; +} + +/** + * Default tree adapter CommentNode interface. + */ +export interface DefaultTreeCommentNode extends DefaultTreeNode { + /** + * The name of the node. + */ + nodeName: "#comment"; + /** + * Comment text. + */ + data: string; + /** + * Parent node. + */ + parentNode: DefaultTreeParentNode; + /** + * Comment source code location info. Available if location info is enabled via {@link ParserOptions}. + */ + sourceCodeLocation?: Location; +} + +/** + * Default tree adapter TextNode interface. + */ +export interface DefaultTreeTextNode extends DefaultTreeNode { + /** + * The name of the node. + */ + nodeName: "#text"; + /** + * Text content. + */ + value: string; + /** + * Parent node. + */ + parentNode: DefaultTreeParentNode; + /** + * Text node source code location info. Available if location info is enabled via {@link ParserOptions}. + */ + sourceCodeLocation?: Location; +} + +// Generic node intefaces +/** + * Generic Node interface. + * Cast to the actual AST interface (e.g. {@link parse5.DefaultTreeNode}) to get access to the properties. + */ +export type Node = DefaultTreeNode | object; +/** + * Generic ParentNode interface. + * Cast to the actual AST interface (e.g. {@link parse5.DefaultTreeParentNode}) to get access to the properties. + */ +export type ParentNode = DefaultTreeParentNode | object; +/** + * Generic DocumentType interface. + * Cast to the actual AST interface (e.g. {@link parse5.DefaultTreeDocumentType}) to get access to the properties. + */ +export type DocumentType = DefaultTreeDocumentType | object; +/** + * Generic Document interface. + * Cast to the actual AST interface (e.g. {@link parse5.DefaultTreeDocument}) to get access to the properties. + */ +export type Document = DefaultTreeDocument | object; +/** + * Generic DocumentFragment interface. + * Cast to the actual AST interface (e.g. {@link parse5.DefaultTreeDocumentFragment}) to get access to the properties. + */ +export type DocumentFragment = DefaultTreeDocumentFragment | object; +/** + * Generic Element interface. + * Cast to the actual AST interface (e.g. {@link parse5.DefaultTreeElement}) to get access to the properties. + */ +export type Element = DefaultTreeElement | object; +/** + * Generic TextNode interface. + * Cast to the actual AST interface (e.g. {@link parse5.DefaultTreeTextNode}) to get access to the properties. + */ +export type TextNode = DefaultTreeTextNode | object; +/** + * Generic CommentNode interface. + * Cast to the actual AST interface (e.g. {@link parse5.Default.CommentNode}) to get access to the properties. + */ +export type CommentNode = DefaultTreeCommentNode | object; + +/** + * Tree adapter is a set of utility functions that provides minimal required abstraction layer beetween parser and a specific AST format. + * Note that `TreeAdapter` is not designed to be a general purpose AST manipulation library. You can build such library + * on top of existing `TreeAdapter` or use one of the existing libraries from npm. + * + * @see [default implementation](https://github.com/inikulin/parse5/blob/master/lib/tree_adapters/default.js) + */ +export interface TreeAdapter { + /** + * Creates a document node. + */ + createDocument(): Document; + /** + * Creates a document fragment node. + */ + createDocumentFragment(): DocumentFragment; + /** + * Creates an element node. + * + * @param tagName - Tag name of the element. + * @param namespaceURI - Namespace of the element. + * @param attrs - Attribute name-value pair array. Foreign attributes may contain `namespace` and `prefix` fields as well. + */ + createElement( + tagName: string, + namespaceURI: string, + attrs: Attribute[] + ): Element; + /** + * Creates a comment node. + * + * @param data - Comment text. + */ + createCommentNode(data: string): CommentNode; + /** + * Appends a child node to the given parent node. + * + * @param parentNode - Parent node. + * @param newNode - Child node. + */ + appendChild(parentNode: ParentNode, newNode: Node): void; + /** + * Inserts a child node to the given parent node before the given reference node. + * + * @param parentNode - Parent node. + * @param newNode - Child node. + * @param referenceNode - Reference node. + */ + insertBefore( + parentNode: ParentNode, + newNode: Node, + referenceNode: Node + ): void; + /** + * Sets the `