From 3606a1504c7a2d7b97a82586a009e0c9e4a72d0b Mon Sep 17 00:00:00 2001 From: Daniel Cassidy Date: Fri, 31 May 2019 18:01:36 +0100 Subject: [PATCH] sax: Various improvements (#35861) * sax: Mark arguments optional. "strict" and "opt" arguments are optional when creating a parser or stream. * sax: Add event overloads for SAXStream * sax: Enable as many tslint rules as possible. * sax: Fix header to conform to dt-header lint rule * sax: Fix violations of no-consecutive-blank-lines * sax: Fix violations of only-arrow-functions * sax: Fix violations of prefer-const * sax: Fix violations of strict-export-declare-modifiers * sax: Fix violations of unified-signatures * sax: Add self to authors * sax: Add "this" types to event handlers * sax: Add tests for stream events * sax: Add tests for optional parameters * sax: Update version number * sax: Add trailing newline --- types/sax/index.d.ts | 41 +++++++--- types/sax/sax-tests.ts | 179 ++++++++++++++++++++++++++++++++--------- types/sax/tslint.json | 79 +----------------- 3 files changed, 168 insertions(+), 131 deletions(-) diff --git a/types/sax/index.d.ts b/types/sax/index.d.ts index 40d17caa4d..1e0c53c381 100644 --- a/types/sax/index.d.ts +++ b/types/sax/index.d.ts @@ -1,14 +1,14 @@ -// Type definitions for sax-js 1.x +// Type definitions for sax-js 1.2 // Project: https://github.com/isaacs/sax-js -// Definitions by: Asana -// Evert Pot +// Definitions by: Vincent Siao (Asana, Inc.) +// Evert Pot +// Daniel Cassidy // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped /// +export const EVENTS: string[]; -export declare var EVENTS: string[]; - -interface SAXOptions { +export interface SAXOptions { trim?: boolean; normalize?: boolean; lowercase?: boolean; @@ -28,7 +28,7 @@ export interface QualifiedAttribute extends QualifiedName { value: string; } -interface BaseTag { +export interface BaseTag { name: string; isSelfClosing: boolean; } @@ -43,9 +43,9 @@ export interface Tag extends BaseTag { attributes: { [key: string]: string }; } -export declare function parser(strict: boolean, opt: SAXOptions): SAXParser; -export declare class SAXParser { - constructor(strict: boolean, opt?: SAXOptions); +export function parser(strict?: boolean, opt?: SAXOptions): SAXParser; +export class SAXParser { + constructor(strict?: boolean, opt?: SAXOptions); // Methods end(): void; @@ -86,8 +86,23 @@ export declare class SAXParser { } import stream = require("stream"); -export declare function createStream(strict: boolean, opt: SAXOptions): SAXStream; -export declare class SAXStream extends stream.Duplex { - constructor(strict: boolean, opt: SAXOptions); +export function createStream(strict?: boolean, opt?: SAXOptions): SAXStream; +export class SAXStream extends stream.Duplex { + constructor(strict?: boolean, opt?: SAXOptions); private _parser: SAXParser; + on(event: "text", listener: (this: this, text: string) => void): this; + on(event: "doctype", listener: (this: this, doctype: string) => void): this; + on(event: "processinginstruction", listener: (this: this, node: { name: string; body: string }) => void): this; + on(event: "opentag", listener: (this: this, tag: Tag | QualifiedTag) => void): this; + on(event: "closetag", listener: (this: this, tagName: string) => void): this; + on(event: "attribute", listener: (this: this, attr: { name: string; value: string }) => void): this; + on(event: "comment", listener: (this: this, comment: string) => void): this; + on(event: "opencdata" | "closecdata" | "end" | "ready" | "close" | "readable" | "drain" | "finish", listener: (this: this) => void): this; + on(event: "cdata", listener: (this: this, cdata: string) => void): this; + on(event: "opennamespace" | "closenamespace", listener: (this: this, ns: { prefix: string; uri: string }) => void): this; + on(event: "script", listener: (this: this, script: string) => void): this; + on(event: "data", listener: (this: this, chunk: any) => void): this; + on(event: "error", listener: (this: this, err: Error) => void): this; + on(event: "pipe" | "unpipe", listener: (this: this, src: stream.Readable) => void): this; + on(event: string | symbol, listener: (this: this, ...args: any[]) => void): this; } diff --git a/types/sax/sax-tests.ts b/types/sax/sax-tests.ts index 5b11ab425e..27ed1a6506 100644 --- a/types/sax/sax-tests.ts +++ b/types/sax/sax-tests.ts @@ -2,88 +2,187 @@ import sax = require("sax"); import fs = require("fs"); (function xmlnsTests() { - let opts: sax.SAXOptions = { + const opts: sax.SAXOptions = { lowercase: true, normalize: true, xmlns: true, position: true }; - let parser = sax.parser(/*strict=*/true, opts); + const parser = sax.parser(/*strict=*/true, opts); parser.ENTITIES["foo"] = "bar"; - parser.onerror = function(e: Error) { - }; + parser.onerror = (e: Error) => {}; - parser.ontext = function(text: string) { - }; + parser.ontext = (text: string) => {}; - parser.onopentag = function(tag: sax.QualifiedTag) { - let prefix: string = tag.prefix; - let local: string = tag.local; - let uri: string = tag.uri; - let name: string = tag.name; - let isSelfClosing: boolean = tag.isSelfClosing; + parser.onopentag = (tag: sax.QualifiedTag) => { + const prefix: string = tag.prefix; + const local: string = tag.local; + const uri: string = tag.uri; + const name: string = tag.name; + const isSelfClosing: boolean = tag.isSelfClosing; - let attr: sax.QualifiedAttribute = tag.attributes["name"]; + const attr: sax.QualifiedAttribute = tag.attributes["name"]; if (attr) { - let attrPrefix: string = attr.prefix; - let attrLocal: string = attr.local; - let attrUri: string = attr.uri; - let attrName: string = attr.name; - let attrValue: string = attr.value; + const attrPrefix: string = attr.prefix; + const attrLocal: string = attr.local; + const attrUri: string = attr.uri; + const attrName: string = attr.name; + const attrValue: string = attr.value; } }; - parser.onattribute = function(attr: { name: string; value: string; }) { - }; + parser.onattribute = (attr: { name: string; value: string; }) => {}; - parser.onend = function() { - }; + parser.onend = () => {}; parser.write("Hello, world!").close(); + const saxStream = sax.createStream(/*strict=*/true, opts); - let saxStream = sax.createStream(/*strict=*/true, opts); + saxStream.on("text", text => { + // $ExpectType string + text; + }); + + saxStream.on("doctype", doctype => { + // $ExpectType string + doctype; + }); + + saxStream.on("processinginstruction", node => { + // $ExpectType { name: string; body: string; } + node; + }); + + saxStream.on("opentag", tag => { + // $ExpectType Tag | QualifiedTag + tag; + }); + + saxStream.on("closetag", tagName => { + // $ExpectType string + tagName; + }); + + saxStream.on("attribute", attr => { + // $ExpectType { name: string; value: string; } + attr; + }); + + saxStream.on("comment", comment => { + // $ExpectType string + comment; + }); + + saxStream.on("cdata", cdata => { + // $ExpectType string + cdata; + }); + + saxStream.on("opennamespace", ns => { + // $ExpectType { prefix: string; uri: string; } + ns; + }); + + saxStream.on("closenamespace", ns => { + // $ExpectType { prefix: string; uri: string; } + ns; + }); + + saxStream.on("script", script => { + // $ExpectType string + script; + }); + + saxStream.on("error", error => { + // $ExpectType Error + error; - saxStream.on("error", function(e: Error) { this._parser.error = null; this._parser.resume(); }); + saxStream.on("pipe", src => { + // $ExpectType Readable + src; + }); + + saxStream.on("unpipe", src => { + // $ExpectType Readable + src; + }); + fs.createReadStream("file.xml") .pipe(saxStream) .pipe(fs.createWriteStream("file-copy.xml")); })(); (function noXmlnsTests() { - let opts: sax.SAXOptions = { + const opts: sax.SAXOptions = { lowercase: true, normalize: true, xmlns: false, position: true }; - let parser = sax.parser(/*strict=*/true, opts); + const parser = sax.parser(/*strict=*/true, opts); - parser.onerror = function(e: Error) { + parser.onerror = (e: Error) => {}; + + parser.ontext = (text: string) => {}; + + parser.onopentag = (tag: sax.Tag) => { + const name: string = tag.name; + const isSelfClosing: boolean = tag.isSelfClosing; + const attrValue: string = tag.attributes["name"]; }; - parser.ontext = function(text: string) { - }; + parser.onattribute = (attr: { name: string; value: string; }) => {}; - parser.onopentag = function(tag: sax.Tag) { - let name: string = tag.name; - let isSelfClosing: boolean = tag.isSelfClosing; - let attrValue: string = tag.attributes["name"]; - }; - - parser.onattribute = function(attr: { name: string; value: string; }) { - }; - - parser.onend = function() { - }; + parser.onend = () => {}; parser.write("Hello, world!").close(); })(); + +// $ExpectType SAXParser +sax.parser(); + +// $ExpectType SAXParser +sax.parser(true); + +// $ExpectType SAXParser +sax.parser(true, {}); + +// $ExpectType SAXParser +sax.parser(true, {normalize: true, position: false}); + +new sax.SAXParser(); + +new sax.SAXParser(true); + +new sax.SAXParser(true, {}); + +new sax.SAXParser(false, {lowercase: true, xmlns: false}); + +// $ExpectType SAXStream +sax.createStream(); + +// $ExpectType SAXStream +sax.createStream(false); + +// $ExpectType SAXStream +sax.createStream(true, {}); + +// $ExpectType SAXStream +sax.createStream(true, {trim: true, position: false}); + +new sax.SAXStream(); + +new sax.SAXStream(true); + +new sax.SAXStream(false, {}); + +new sax.SAXStream(false, {noscript: true}); diff --git a/types/sax/tslint.json b/types/sax/tslint.json index 3d59f55fda..f93cf8562a 100644 --- a/types/sax/tslint.json +++ b/types/sax/tslint.json @@ -1,80 +1,3 @@ { - "extends": "dtslint/dt.json", - "rules": { - "adjacent-overload-signatures": false, - "array-type": false, - "arrow-return-shorthand": false, - "ban-types": false, - "callable-types": false, - "comment-format": false, - "dt-header": false, - "npm-naming": false, - "eofline": false, - "export-just-namespace": false, - "import-spacing": false, - "interface-name": false, - "interface-over-type-literal": false, - "jsdoc-format": false, - "max-line-length": false, - "member-access": false, - "new-parens": false, - "no-any-union": false, - "no-boolean-literal-compare": false, - "no-conditional-assignment": false, - "no-consecutive-blank-lines": false, - "no-construct": false, - "no-declare-current-package": false, - "no-duplicate-imports": false, - "no-duplicate-variable": false, - "no-empty-interface": false, - "no-for-in-array": false, - "no-inferrable-types": false, - "no-internal-module": false, - "no-irregular-whitespace": false, - "no-mergeable-namespace": false, - "no-misused-new": false, - "no-namespace": false, - "no-object-literal-type-assertion": false, - "no-padding": false, - "no-redundant-jsdoc": false, - "no-redundant-jsdoc-2": false, - "no-redundant-undefined": false, - "no-reference-import": false, - "no-relative-import-in-test": false, - "no-self-import": false, - "no-single-declare-module": false, - "no-string-throw": false, - "no-unnecessary-callback-wrapper": false, - "no-unnecessary-class": false, - "no-unnecessary-generics": false, - "no-unnecessary-qualifier": false, - "no-unnecessary-type-assertion": false, - "no-useless-files": false, - "no-var-keyword": false, - "no-var-requires": false, - "no-void-expression": false, - "no-trailing-whitespace": false, - "object-literal-key-quotes": false, - "object-literal-shorthand": false, - "one-line": false, - "one-variable-per-declaration": false, - "only-arrow-functions": false, - "prefer-conditional-expression": false, - "prefer-const": false, - "prefer-declare-function": false, - "prefer-for-of": false, - "prefer-method-signature": false, - "prefer-template": false, - "radix": false, - "semicolon": false, - "space-before-function-paren": false, - "space-within-parens": false, - "strict-export-declare-modifiers": false, - "trim-file": false, - "triple-equals": false, - "typedef-whitespace": false, - "unified-signatures": false, - "void-return": false, - "whitespace": false - } + "extends": "dtslint/dt.json" }