From 0cd793e6ef23ea1b85ae6b6ac64886ecc64fe9bb Mon Sep 17 00:00:00 2001 From: Christian Bewernitz Date: Tue, 18 Oct 2022 08:23:42 +0200 Subject: [PATCH 1/9] style: Apply prettier to all code and merge eslint configs as far as possible. --- .editorconfig | 1 + .eslintrc.yml | 18 +- .prettierrc.yaml | 3 +- examples/nodejs/package.json | 34 +- examples/nodejs/src/index.js | 10 +- examples/typescript-node-es6/package.json | 40 +- examples/typescript-node-es6/src/index.ts | 12 +- examples/typescript-node-es6/tsconfig.json | 182 +-- lib/conventions.js | 56 +- lib/dom-parser.js | 278 ++-- lib/dom.js | 1385 ++++++++--------- lib/entities.js | 494 +++--- lib/index.js | 10 +- lib/sax.js | 878 +++++------ package.json | 3 +- test/.eslintrc.yml | 8 - test/conventions/assign.test.js | 69 +- test/conventions/freeze.test.js | 52 +- test/conventions/html.test.js | 170 +- test/conventions/mime-type.test.js | 46 +- test/conventions/namespace.test.js | 37 +- test/dom-parser.test.js | 300 ++-- test/dom/attr.test.js | 88 +- test/dom/clone.test.js | 38 +- test/dom/document.test.js | 211 ++- test/dom/dom-implementation.test.js | 493 +++--- test/dom/element.test.js | 369 +++-- test/dom/fragment.test.js | 20 +- test/dom/ns-test.test.js | 59 +- test/dom/serializer.test.js | 258 ++- test/error/error-handler.test.js | 54 +- test/error/reported-levels.test.js | 155 +- test/error/reported.js | 69 +- test/error/xml-error.test.js | 44 +- .../xml-reader-dom-handler-errors.test.js | 93 +- test/get-test-parser.js | 14 +- test/html/normalize.test.js | 68 +- test/parse/big-file-performance.test.js | 194 ++- test/parse/doctype.test.js | 70 +- test/parse/entities.test.js | 18 +- test/parse/file.test.js | 18 +- test/parse/locator.test.js | 54 +- test/parse/namespace.test.js | 53 +- test/parse/node.test.js | 173 +- test/parse/normalize-line-endings.test.js | 60 +- test/parse/parse-element.test.js | 159 +- test/parse/parse-error.test.js | 48 +- test/parse/simple.test.js | 91 +- test/parse/test-doc-whitespace.test.js | 34 +- test/parse/unclosedcomment.test.js | 14 +- test/test.js | 41 +- test/xmltest/generate-snapshot.js | 18 +- test/xmltest/not-wf.test.js | 29 +- test/xmltest/valid.test.js | 33 +- test/xss.test.js | 47 +- 55 files changed, 3489 insertions(+), 3784 deletions(-) delete mode 100644 test/.eslintrc.yml diff --git a/.editorconfig b/.editorconfig index 2c08e15e3..ed845a9b3 100644 --- a/.editorconfig +++ b/.editorconfig @@ -7,3 +7,4 @@ indent_style = tab indent_size = 2 end_of_line = lf insert_final_newline = true +max_line_length = 130 diff --git a/.eslintrc.yml b/.eslintrc.yml index 316c90f9f..bcd8bdab2 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -3,27 +3,19 @@ env: commonjs: true es2020: true node: true +extends: 'plugin:prettier/recommended' + plugins: - es5 - anti-trojan-source -# FUTURE TBD: -# extends: 'eslint:recommended' parserOptions: ecmaVersion: 11 rules: "anti-trojan-source/no-bidi": - error - # FUTURE TBD: - # indent: - # - error - # - tab linebreak-style: - error - unix - # FUTURE TBD: - # quotes: - # - error - # - single - # semi: - # - error - # - always + strict: + - error + - global diff --git a/.prettierrc.yaml b/.prettierrc.yaml index 07d3f7ff0..4e5ce0a6b 100644 --- a/.prettierrc.yaml +++ b/.prettierrc.yaml @@ -1,3 +1,4 @@ useTabs: true -semi: false +semi: true +trailingComma: es5 singleQuote: true diff --git a/examples/nodejs/package.json b/examples/nodejs/package.json index 357e33282..c3acebd91 100644 --- a/examples/nodejs/package.json +++ b/examples/nodejs/package.json @@ -1,19 +1,19 @@ { - "name": "@xmldom/xmldom-example-nodejs", - "private": true, - "description": "Show how to use xmldom in a nodejs project", - "main": "src/index.js", - "scripts": { - "test": "node src/index.js" - }, - "keywords": [ - "test", - "commonjs", - "nodejs" - ], - "author": "", - "license": "MIT", - "dependencies": { - "@xmldom/xmldom": "file:../.." - } + "name": "@xmldom/xmldom-example-nodejs", + "private": true, + "description": "Show how to use xmldom in a nodejs project", + "main": "src/index.js", + "scripts": { + "test": "node src/index.js" + }, + "keywords": [ + "test", + "commonjs", + "nodejs" + ], + "author": "", + "license": "MIT", + "dependencies": { + "@xmldom/xmldom": "file:../.." + } } diff --git a/examples/nodejs/src/index.js b/examples/nodejs/src/index.js index ff8c7353f..40f73ca9f 100644 --- a/examples/nodejs/src/index.js +++ b/examples/nodejs/src/index.js @@ -1,15 +1,15 @@ -const { DOMParser, XMLSerializer } = require('@xmldom/xmldom') +const { DOMParser, XMLSerializer } = require('@xmldom/xmldom'); const source = ` test -` +`; -const doc = new DOMParser().parseFromString(source, 'text/xml') +const doc = new DOMParser().parseFromString(source, 'text/xml'); -const serialized = new XMLSerializer().serializeToString(doc) +const serialized = new XMLSerializer().serializeToString(doc); if (source !== serialized) { - console.error(`expected\n${source}\nbut was\n${serialized}`) + console.error(`expected\n${source}\nbut was\n${serialized}`); process.exit(1); } diff --git a/examples/typescript-node-es6/package.json b/examples/typescript-node-es6/package.json index aa31cf060..9b403fe6a 100644 --- a/examples/typescript-node-es6/package.json +++ b/examples/typescript-node-es6/package.json @@ -1,22 +1,22 @@ { - "name": "@xmldom/xmldom-example-typescript-node-es6", - "private": true, - "description": "", - "main": "index.js", - "type": "module", - "scripts": { - "tsc": "tsc", - "test": "node dist/index.js" - }, - "keywords": [ - "test", - "typescript" - ], - "license": "MIT", - "devDependencies": { - "typescript": "*" - }, - "dependencies": { - "@xmldom/xmldom": "file:../.." - } + "name": "@xmldom/xmldom-example-typescript-node-es6", + "private": true, + "description": "", + "main": "index.js", + "type": "module", + "scripts": { + "tsc": "tsc", + "test": "node dist/index.js" + }, + "keywords": [ + "test", + "typescript" + ], + "license": "MIT", + "devDependencies": { + "typescript": "*" + }, + "dependencies": { + "@xmldom/xmldom": "file:../.." + } } diff --git a/examples/typescript-node-es6/src/index.ts b/examples/typescript-node-es6/src/index.ts index 21e1e65bd..f60f7b2d4 100644 --- a/examples/typescript-node-es6/src/index.ts +++ b/examples/typescript-node-es6/src/index.ts @@ -1,16 +1,16 @@ -import {DOMParser, XMLSerializer} from '@xmldom/xmldom'; +import { DOMParser, XMLSerializer } from '@xmldom/xmldom'; const source = ` test -` +`; -const doc = new DOMParser().parseFromString(source, 'text/xml') +const doc = new DOMParser().parseFromString(source, 'text/xml'); -if (!doc) throw 'expected Document but was undefined' +if (!doc) throw 'expected Document but was undefined'; -const serialized = new XMLSerializer().serializeToString(doc) +const serialized = new XMLSerializer().serializeToString(doc); if (source !== serialized) { - throw `expected\n${source}\nbut was\n${serialized}` + throw `expected\n${source}\nbut was\n${serialized}`; } diff --git a/examples/typescript-node-es6/tsconfig.json b/examples/typescript-node-es6/tsconfig.json index 0a80aa7cd..1c747f619 100644 --- a/examples/typescript-node-es6/tsconfig.json +++ b/examples/typescript-node-es6/tsconfig.json @@ -1,100 +1,102 @@ { - "compilerOptions": { - /* Visit https://aka.ms/tsconfig.json to read more about this file */ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig.json to read more about this file */ - /* Projects */ - // "incremental": true, /* Enable incremental compilation */ - // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ - // "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */ - // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */ - // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ - // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Projects */ + // "incremental": true, /* Enable incremental compilation */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ - /* Language and Environment */ - "target": "es5", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ - "lib": ["ES5"], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ - // "jsx": "preserve", /* Specify what JSX code is generated. */ - // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ - // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ - // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */ - // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ - // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */ - // "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */ - // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ - // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + /* Language and Environment */ + "target": "es5" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, + "lib": [ + "ES5" + ] /* Specify a set of bundled library declaration files that describe the target runtime environment. */, + // "jsx": "preserve", /* Specify what JSX code is generated. */ + // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */ + // "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ - /* Modules */ - "module": "ES2020", /* Specify what module code is generated. */ - // "rootDir": "./", /* Specify the root folder within your source files. */ - "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ - // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ - // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ - // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ - // "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */ - // "types": [], /* Specify type package names to be included without being referenced in a source file. */ - // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ - // "resolveJsonModule": true, /* Enable importing .json files */ - // "noResolve": true, /* Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project. */ + /* Modules */ + "module": "ES2020" /* Specify what module code is generated. */, + // "rootDir": "./", /* Specify the root folder within your source files. */ + "moduleResolution": "node" /* Specify how TypeScript looks up a file from a given module specifier. */, + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "resolveJsonModule": true, /* Enable importing .json files */ + // "noResolve": true, /* Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project. */ - /* JavaScript Support */ - // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */ - // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ - // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */ - /* Emit */ - "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ - // "declarationMap": true, /* Create sourcemaps for d.ts files. */ - // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ - // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ - // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */ - "outDir": "./dist", /* Specify an output folder for all emitted files. */ - // "removeComments": true, /* Disable emitting comments. */ - // "noEmit": true, /* Disable emitting files from a compilation. */ - // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ - // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */ - // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ - // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ - // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ - // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ - // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ - // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ - // "newLine": "crlf", /* Set the newline character for emitting files. */ - // "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */ - // "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */ - // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ - // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ - // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + /* Emit */ + "declaration": true /* Generate .d.ts files from TypeScript and JavaScript files in your project. */, + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */ + "outDir": "./dist" /* Specify an output folder for all emitted files. */, + // "removeComments": true, /* Disable emitting comments. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ - /* Interop Constraints */ - // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ - // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ - "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */ - // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ - "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */, + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, - /* Type Checking */ - "strict": true, /* Enable all strict type-checking options. */ - // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */ - // "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */ - // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ - // "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */ - // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ - // "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */ - // "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */ - // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ - // "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */ - // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */ - // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ - // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ - // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ - // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ - // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ - // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */ - // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ - // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Type Checking */ + "strict": true /* Enable all strict type-checking options. */, + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */ + // "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */ + // "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ - /* Completeness */ - // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ - "skipLibCheck": true /* Skip type checking all .d.ts files. */ - } + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + } } diff --git a/lib/conventions.js b/lib/conventions.js index 5bdf031da..fda7b2fdb 100644 --- a/lib/conventions.js +++ b/lib/conventions.js @@ -1,4 +1,4 @@ -'use strict' +'use strict'; /** * "Shallow freezes" an object to render it immutable. @@ -17,9 +17,9 @@ */ function freeze(object, oc) { if (oc === undefined) { - oc = Object + oc = Object; } - return oc && typeof oc.freeze === 'function' ? oc.freeze(object) : object + return oc && typeof oc.freeze === 'function' ? oc.freeze(object) : object; } /** @@ -37,14 +37,14 @@ function freeze(object, oc) { */ function assign(target, source) { if (target === null || typeof target !== 'object') { - throw new TypeError('target is not an object') + throw new TypeError('target is not an object'); } for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { - target[key] = source[key] + target[key] = source[key]; } } - return target + return target; } /** @@ -87,7 +87,7 @@ var HTML_BOOLEAN_ATTRIBUTES = freeze({ required: true, reversed: true, selected: true, -}) +}); /** * Check if `name` is matching one of the HTML boolean attribute names. @@ -100,7 +100,7 @@ var HTML_BOOLEAN_ATTRIBUTES = freeze({ * @see https://html.spec.whatwg.org/#attributes-3 */ function isHTMLBooleanAttribute(name) { - return HTML_BOOLEAN_ATTRIBUTES.hasOwnProperty(name.toLowerCase()) + return HTML_BOOLEAN_ATTRIBUTES.hasOwnProperty(name.toLowerCase()); } /** @@ -131,7 +131,7 @@ var HTML_VOID_ELEMENTS = freeze({ source: true, track: true, wbr: true, -}) +}); /** * Check if `tagName` is matching one of the HTML void element names. @@ -144,7 +144,7 @@ var HTML_VOID_ELEMENTS = freeze({ * @see https://html.spec.whatwg.org/#void-elements */ function isHTMLVoidElement(tagName) { - return HTML_VOID_ELEMENTS.hasOwnProperty(tagName.toLowerCase()) + return HTML_VOID_ELEMENTS.hasOwnProperty(tagName.toLowerCase()); } /** @@ -161,7 +161,7 @@ var HTML_RAW_TEXT_ELEMENTS = freeze({ style: false, textarea: true, title: true, -}) +}); /** * Check if `tagName` is matching one of the HTML raw text element names. @@ -227,7 +227,7 @@ var MIME_TYPE = freeze({ * @see [`DOMParser.parseFromString` @ HTML Specification](https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#dom-domparser-parsefromstring) */ isHTML: function (value) { - return value === MIME_TYPE.HTML + return value === MIME_TYPE.HTML; }, /** @@ -242,9 +242,7 @@ var MIME_TYPE = freeze({ * @see https://dom.spec.whatwg.org/#dom-domimplementation-createhtmldocument */ hasDefaultHTMLNamespace: function (mimeType) { - return ( - MIME_TYPE.isHTML(mimeType) || mimeType === MIME_TYPE.XML_XHTML_APPLICATION - ) + return MIME_TYPE.isHTML(mimeType) || mimeType === MIME_TYPE.XML_XHTML_APPLICATION; }, /** @@ -283,7 +281,7 @@ var MIME_TYPE = freeze({ * @see https://en.wikipedia.org/wiki/Scalable_Vector_Graphics Wikipedia */ XML_SVG_IMAGE: 'image/svg+xml', -}) +}); /** * Namespaces that are used in this code base. @@ -306,7 +304,7 @@ var NAMESPACE = freeze({ * @see NAMESPACE.HTML */ isHTML: function (uri) { - return uri === NAMESPACE.HTML + return uri === NAMESPACE.HTML; }, /** @@ -329,16 +327,16 @@ var NAMESPACE = freeze({ * @see https://www.w3.org/2000/xmlns/ */ XMLNS: 'http://www.w3.org/2000/xmlns/', -}) +}); -exports.assign = assign -exports.freeze = freeze -exports.HTML_BOOLEAN_ATTRIBUTES = HTML_BOOLEAN_ATTRIBUTES -exports.HTML_RAW_TEXT_ELEMENTS = HTML_RAW_TEXT_ELEMENTS -exports.HTML_VOID_ELEMENTS = HTML_VOID_ELEMENTS -exports.isHTMLBooleanAttribute = isHTMLBooleanAttribute -exports.isHTMLRawTextElement = isHTMLRawTextElement -exports.isHTMLEscapableRawTextElement = isHTMLEscapableRawTextElement -exports.isHTMLVoidElement = isHTMLVoidElement -exports.MIME_TYPE = MIME_TYPE -exports.NAMESPACE = NAMESPACE +exports.assign = assign; +exports.freeze = freeze; +exports.HTML_BOOLEAN_ATTRIBUTES = HTML_BOOLEAN_ATTRIBUTES; +exports.HTML_RAW_TEXT_ELEMENTS = HTML_RAW_TEXT_ELEMENTS; +exports.HTML_VOID_ELEMENTS = HTML_VOID_ELEMENTS; +exports.isHTMLBooleanAttribute = isHTMLBooleanAttribute; +exports.isHTMLRawTextElement = isHTMLRawTextElement; +exports.isHTMLEscapableRawTextElement = isHTMLEscapableRawTextElement; +exports.isHTMLVoidElement = isHTMLVoidElement; +exports.MIME_TYPE = MIME_TYPE; +exports.NAMESPACE = NAMESPACE; diff --git a/lib/dom-parser.js b/lib/dom-parser.js index b54f81d04..079221a6a 100644 --- a/lib/dom-parser.js +++ b/lib/dom-parser.js @@ -1,7 +1,7 @@ -'use strict' +'use strict'; -var conventions = require("./conventions"); -var dom = require('./dom') +var conventions = require('./conventions'); +var dom = require('./dom'); var entities = require('./entities'); var sax = require('./sax'); @@ -35,9 +35,7 @@ var XMLReader = sax.XMLReader; * @returns {string} */ function normalizeLineEndings(input) { - return input - .replace(/\r[\n\u0085]/g, '\n') - .replace(/[\r\u0085\u2028]/g, '\n') + return input.replace(/\r[\n\u0085]/g, '\n').replace(/[\r\u0085\u2028]/g, '\n'); } /** @@ -85,9 +83,8 @@ function normalizeLineEndings(input) { * @see https://developer.mozilla.org/en-US/docs/Web/API/DOMParser * @see https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#dom-parsing-and-serialization */ -function DOMParser(options){ - - options = options || {locator:true}; +function DOMParser(options) { + options = options || { locator: true }; /** * The method to use instead of `Object.assign` (or if not available `conventions.assign`), @@ -98,7 +95,7 @@ function DOMParser(options){ * @private * @see conventions.assign */ - this.assign = options.assign || Object.assign || conventions.assign + this.assign = options.assign || Object.assign || conventions.assign; /** * For internal testing: The class for creating an instance for handling events from the SAX parser. @@ -108,7 +105,7 @@ function DOMParser(options){ * @readonly * @private */ - this.domHandler = options.domHandler || DOMHandler + this.domHandler = options.domHandler || DOMHandler; /** * A function that can be invoked as the errorHandler instead of the default ones. @@ -123,7 +120,7 @@ function DOMParser(options){ * @type {(string) => string} * @readonly */ - this.normalizeLineEndings = options.normalizeLineEndings || normalizeLineEndings + this.normalizeLineEndings = options.normalizeLineEndings || normalizeLineEndings; /** * Configures if the nodes created during parsing @@ -133,7 +130,7 @@ function DOMParser(options){ * @type {boolean} * @readonly */ - this.locator = !!options.locator + this.locator = !!options.locator; /** * The default namespace can be provided by the key that is the empty string. @@ -143,7 +140,7 @@ function DOMParser(options){ * @type {Readonly} * @readonly */ - this.xmlns = options.xmlns || {} + this.xmlns = options.xmlns || {}; } /** @@ -175,55 +172,63 @@ function DOMParser(options){ * @see https://html.spec.whatwg.org/#dom-domparser-parsefromstring-dev */ DOMParser.prototype.parseFromString = function (source, mimeType) { - var defaultNSMap = this.assign({}, this.xmlns) - var entityMap = entities.XML_ENTITIES - var defaultNamespace = defaultNSMap[''] || null + var defaultNSMap = this.assign({}, this.xmlns); + var entityMap = entities.XML_ENTITIES; + var defaultNamespace = defaultNSMap[''] || null; if (MIME_TYPE.hasDefaultHTMLNamespace(mimeType)) { - entityMap = entities.HTML_ENTITIES - defaultNamespace = NAMESPACE.HTML + entityMap = entities.HTML_ENTITIES; + defaultNamespace = NAMESPACE.HTML; } else if (mimeType === MIME_TYPE.XML_SVG_IMAGE) { - defaultNamespace = NAMESPACE.SVG + defaultNamespace = NAMESPACE.SVG; } - defaultNSMap[''] = defaultNamespace - defaultNSMap.xml = defaultNSMap.xml || NAMESPACE.XML + defaultNSMap[''] = defaultNamespace; + defaultNSMap.xml = defaultNSMap.xml || NAMESPACE.XML; var domBuilder = new this.domHandler({ mimeType: mimeType, defaultNamespace: defaultNamespace, - }) + }); var locator = this.locator ? {} : undefined; if (this.locator) { - domBuilder.setDocumentLocator(locator) + domBuilder.setDocumentLocator(locator); } - var sax = new XMLReader() - sax.errorHandler = buildErrorHandler(this.errorHandler, domBuilder, locator) - sax.domBuilder = domBuilder + var sax = new XMLReader(); + sax.errorHandler = buildErrorHandler(this.errorHandler, domBuilder, locator); + sax.domBuilder = domBuilder; if (source && typeof source === 'string') { - sax.parse(this.normalizeLineEndings(source), defaultNSMap, entityMap) + sax.parse(this.normalizeLineEndings(source), defaultNSMap, entityMap); } else { - sax.errorHandler.error('invalid doc source') + sax.errorHandler.error('invalid doc source'); } - return domBuilder.doc -} -function buildErrorHandler(errorImpl,domBuilder,locator){ - if(!errorImpl){ - if(domBuilder instanceof DOMHandler){ + return domBuilder.doc; +}; +function buildErrorHandler(errorImpl, domBuilder, locator) { + if (!errorImpl) { + if (domBuilder instanceof DOMHandler) { return domBuilder; } - errorImpl = domBuilder ; + errorImpl = domBuilder; } - var errorHandler = {} + var errorHandler = {}; var isCallback = errorImpl instanceof Function; - locator = locator||{} - function build(key){ + locator = locator || {}; + function build(key) { var fn = errorImpl[key]; - if(!fn && isCallback){ - fn = errorImpl.length == 2?function(msg){errorImpl(key,msg)}:errorImpl; + if (!fn && isCallback) { + fn = + errorImpl.length == 2 + ? function (msg) { + errorImpl(key, msg); + } + : errorImpl; } - errorHandler[key] = fn && function(msg){ - fn('[xmldom '+key+']\t'+msg+_locator(locator)); - }||function(){}; + errorHandler[key] = + (fn && + function (msg) { + fn('[xmldom ' + key + ']\t' + msg + _locator(locator)); + }) || + function () {}; } build('warning'); build('error'); @@ -247,7 +252,7 @@ function buildErrorHandler(errorImpl,domBuilder,locator){ * @see http://www.saxproject.org/apidoc/org/xml/sax/ext/DefaultHandler2.html */ function DOMHandler(options) { - var opt = options || {} + var opt = options || {}; /** * The mime type is used to determine if the DOM handler will create an XML or HTML document. * Only if it is set to `text/html` it will create an HTML document. @@ -257,7 +262,7 @@ function DOMHandler(options) { * @readonly * @see MIME_TYPE */ - this.mimeType = opt.mimeType || MIME_TYPE.XML_APPLICATION + this.mimeType = opt.mimeType || MIME_TYPE.XML_APPLICATION; /** * The namespace to use to create an XML document. @@ -273,14 +278,13 @@ function DOMHandler(options) { * @readonly * @private */ - this.defaultNamespace = opt.defaultNamespace || null + this.defaultNamespace = opt.defaultNamespace || null; /** * @private * @type {boolean} */ - this.cdata = false - + this.cdata = false; /** * The last `Element` that was created by `startElement`. @@ -291,7 +295,7 @@ function DOMHandler(options) { * @type {Element | Node | undefined} * @private */ - this.currentElement = undefined + this.currentElement = undefined; /** * The Document that is created as part of `startDocument`, @@ -300,7 +304,7 @@ function DOMHandler(options) { * @type {Document | undefined} * @readonly */ - this.doc = undefined + this.doc = undefined; /** * The locator is stored as part of setDocumentLocator. @@ -313,9 +317,9 @@ function DOMHandler(options) { * @readonly (the sax parser currently sometimes set's it) * @private */ - this.locator = undefined + this.locator = undefined; } -function position(locator,node){ +function position(locator, node) { node.lineNumber = locator.lineNumber; node.columnNumber = locator.columnNumber; } @@ -328,67 +332,61 @@ DOMHandler.prototype = { * * @see http://www.saxproject.org/apidoc/org/xml/sax/ContentHandler.html */ - startDocument : function() { - var impl = new DOMImplementation() - this.doc = MIME_TYPE.isHTML(this.mimeType) - ? impl.createHTMLDocument(false) - : impl.createDocument(this.defaultNamespace, '') + startDocument: function () { + var impl = new DOMImplementation(); + this.doc = MIME_TYPE.isHTML(this.mimeType) ? impl.createHTMLDocument(false) : impl.createDocument(this.defaultNamespace, ''); }, - startElement:function(namespaceURI, localName, qName, attrs) { + startElement: function (namespaceURI, localName, qName, attrs) { var doc = this.doc; - var el = doc.createElementNS(namespaceURI, qName||localName); - var len = attrs.length; - appendElement(this, el); - this.currentElement = el; + var el = doc.createElementNS(namespaceURI, qName || localName); + var len = attrs.length; + appendElement(this, el); + this.currentElement = el; - this.locator && position(this.locator,el) - for (var i = 0 ; i < len; i++) { - var namespaceURI = attrs.getURI(i); - var value = attrs.getValue(i); - var qName = attrs.getQName(i); + this.locator && position(this.locator, el); + for (var i = 0; i < len; i++) { + var namespaceURI = attrs.getURI(i); + var value = attrs.getValue(i); + var qName = attrs.getQName(i); var attr = doc.createAttributeNS(namespaceURI, qName); - this.locator &&position(attrs.getLocator(i),attr); + this.locator && position(attrs.getLocator(i), attr); attr.value = attr.nodeValue = value; - el.setAttributeNode(attr) - } + el.setAttributeNode(attr); + } }, - endElement:function(namespaceURI, localName, qName) { - var current = this.currentElement + endElement: function (namespaceURI, localName, qName) { + var current = this.currentElement; var tagName = current.tagName; this.currentElement = current.parentNode; }, - startPrefixMapping:function(prefix, uri) { + startPrefixMapping: function (prefix, uri) {}, + endPrefixMapping: function (prefix) {}, + processingInstruction: function (target, data) { + var ins = this.doc.createProcessingInstruction(target, data); + this.locator && position(this.locator, ins); + appendElement(this, ins); }, - endPrefixMapping:function(prefix) { - }, - processingInstruction:function(target, data) { - var ins = this.doc.createProcessingInstruction(target, data); - this.locator && position(this.locator,ins) - appendElement(this, ins); - }, - ignorableWhitespace:function(ch, start, length) { - }, - characters:function(chars, start, length) { - chars = _toString.apply(this,arguments) + ignorableWhitespace: function (ch, start, length) {}, + characters: function (chars, start, length) { + chars = _toString.apply(this, arguments); //console.log(chars) - if(chars){ + if (chars) { if (this.cdata) { var charNode = this.doc.createCDATASection(chars); } else { var charNode = this.doc.createTextNode(chars); } - if(this.currentElement){ + if (this.currentElement) { this.currentElement.appendChild(charNode); - }else if(/^\s*$/.test(chars)){ + } else if (/^\s*$/.test(chars)) { this.doc.appendChild(charNode); //process xml } - this.locator && position(this.locator,charNode) + this.locator && position(this.locator, charNode); } }, - skippedEntity:function(name) { - }, - endDocument:function() { + skippedEntity: function (name) {}, + endDocument: function () { this.doc.normalize(); }, /** @@ -397,62 +395,63 @@ DOMHandler.prototype = { * * @param {Locator} locator */ - setDocumentLocator:function (locator) { + setDocumentLocator: function (locator) { if (locator) { - locator.lineNumber = 0 + locator.lineNumber = 0; } - this.locator = locator + this.locator = locator; }, //LexicalHandler - comment:function(chars, start, length) { - chars = _toString.apply(this,arguments) - var comm = this.doc.createComment(chars); - this.locator && position(this.locator,comm) - appendElement(this, comm); + comment: function (chars, start, length) { + chars = _toString.apply(this, arguments); + var comm = this.doc.createComment(chars); + this.locator && position(this.locator, comm); + appendElement(this, comm); }, - startCDATA:function() { - //used in characters() methods - this.cdata = true; + startCDATA: function () { + //used in characters() methods + this.cdata = true; }, - endCDATA:function() { - this.cdata = false; + endCDATA: function () { + this.cdata = false; }, - startDTD:function(name, publicId, systemId) { + startDTD: function (name, publicId, systemId) { var impl = this.doc.implementation; - if (impl && impl.createDocumentType) { - var dt = impl.createDocumentType(name, publicId, systemId); - this.locator && position(this.locator,dt) - appendElement(this, dt); - this.doc.doctype = dt; - } + if (impl && impl.createDocumentType) { + var dt = impl.createDocumentType(name, publicId, systemId); + this.locator && position(this.locator, dt); + appendElement(this, dt); + this.doc.doctype = dt; + } }, /** * @see org.xml.sax.ErrorHandler * @link http://www.saxproject.org/apidoc/org/xml/sax/ErrorHandler.html */ - warning:function(error) { - console.warn('[xmldom warning]\t'+error,_locator(this.locator)); + warning: function (error) { + console.warn('[xmldom warning]\t' + error, _locator(this.locator)); }, - error:function(error) { - console.error('[xmldom error]\t'+error,_locator(this.locator)); + error: function (error) { + console.error('[xmldom error]\t' + error, _locator(this.locator)); }, - fatalError:function(error) { + fatalError: function (error) { throw new ParseError(error, this.locator); + }, +}; +function _locator(l) { + if (l) { + return '\n@#[line:' + l.lineNumber + ',col:' + l.columnNumber + ']'; } } -function _locator(l){ - if(l){ - return '\n@#[line:'+l.lineNumber+',col:'+l.columnNumber+']' - } -} -function _toString(chars,start,length){ - if(typeof chars == 'string'){ - return chars.substr(start,length) - }else{//java sax connect width xmldom on rhino(what about: "? && !(chars instanceof String)") - if(chars.length >= start+length || start){ - return new java.lang.String(chars,start,length)+''; +function _toString(chars, start, length) { + if (typeof chars == 'string') { + return chars.substr(start, length); + } else { + //java sax connect width xmldom on rhino(what about: "? && !(chars instanceof String)") + if (chars.length >= start + length || start) { + return new java.lang.String(chars, start, length) + ''; } return chars; } @@ -489,18 +488,23 @@ function _toString(chars,start,length){ * #notationDecl(name, publicId, systemId) {}; * #unparsedEntityDecl(name, publicId, systemId, notationName) {}; */ -"endDTD,startEntity,endEntity,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,resolveEntity,getExternalSubset,notationDecl,unparsedEntityDecl".replace(/\w+/g,function(key){ - DOMHandler.prototype[key] = function(){return null} -}) +'endDTD,startEntity,endEntity,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,resolveEntity,getExternalSubset,notationDecl,unparsedEntityDecl'.replace( + /\w+/g, + function (key) { + DOMHandler.prototype[key] = function () { + return null; + }; + } +); /* Private static helpers treated below as private instance methods, so don't need to add these to the public API; we might use a Relator to also get rid of non-standard public properties */ -function appendElement (hander,node) { - if (!hander.currentElement) { - hander.doc.appendChild(node); - } else { - hander.currentElement.appendChild(node); - } -}//appendChild and setAttributeNS are preformance key +function appendElement(hander, node) { + if (!hander.currentElement) { + hander.doc.appendChild(node); + } else { + hander.currentElement.appendChild(node); + } +} //appendChild and setAttributeNS are preformance key exports.__DOMHandler = DOMHandler; exports.normalizeLineEndings = normalizeLineEndings; diff --git a/lib/dom.js b/lib/dom.js index 088cc621c..34c7998a0 100644 --- a/lib/dom.js +++ b/lib/dom.js @@ -1,4 +1,6 @@ -var conventions = require("./conventions"); +'use strict'; + +var conventions = require('./conventions'); var isHTMLRawTextElement = conventions.isHTMLRawTextElement; var isHTMLVoidElement = conventions.isHTMLVoidElement; var MIME_TYPE = conventions.MIME_TYPE; @@ -9,8 +11,8 @@ var NAMESPACE = conventions.NAMESPACE; * @param {string} input * @returns {boolean} */ -function notEmptyString (input) { - return input !== '' +function notEmptyString(input) { + return input !== ''; } /** * @see https://infra.spec.whatwg.org/#split-on-ascii-whitespace @@ -21,7 +23,7 @@ function notEmptyString (input) { */ function splitOnASCIIWhitespace(input) { // U+0009 TAB, U+000A LF, U+000C FF, U+000D CR, U+0020 SPACE - return input ? input.split(/[\t\n\f\r ]+/).filter(notEmptyString) : [] + return input ? input.split(/[\t\n\f\r ]+/).filter(notEmptyString) : []; } /** @@ -31,7 +33,7 @@ function splitOnASCIIWhitespace(input) { * @param {string} element * @returns {Record} */ -function orderedSetReducer (current, element) { +function orderedSetReducer(current, element) { if (!current.hasOwnProperty(element)) { current[element] = true; } @@ -46,7 +48,7 @@ function orderedSetReducer (current, element) { function toOrderedSet(input) { if (!input) return []; var list = splitOnASCIIWhitespace(input); - return Object.keys(list.reduce(orderedSetReducer, {})) + return Object.keys(list.reduce(orderedSetReducer, {})); } /** @@ -56,14 +58,14 @@ function toOrderedSet(input) { * @param {any[]} list * @returns {function(any): boolean} */ -function arrayIncludes (list) { - return function(element) { +function arrayIncludes(list) { + return function (element) { return list && list.indexOf(element) !== -1; - } + }; } -function copy(src,dest){ - for(var p in src){ +function copy(src, dest) { + for (var p in src) { if (Object.prototype.hasOwnProperty.call(src, p)) { dest[p] = src[p]; } @@ -74,57 +76,58 @@ function copy(src,dest){ ^\w+\.prototype\.([_\w]+)\s*=\s*((?:.*\{\s*?[\r\n][\s\S]*?^})|\S.*?(?=[;\r\n]));? ^\w+\.prototype\.([_\w]+)\s*=\s*(\S.*?(?=[;\r\n]));? */ -function _extends(Class,Super){ +function _extends(Class, Super) { var pt = Class.prototype; - if(!(pt instanceof Super)){ - function t(){}; + if (!(pt instanceof Super)) { + function t() {} t.prototype = Super.prototype; t = new t(); - copy(pt,t); + copy(pt, t); Class.prototype = pt = t; } - if(pt.constructor != Class){ - if(typeof Class != 'function'){ - console.error("unknown Class:"+Class) + if (pt.constructor != Class) { + if (typeof Class != 'function') { + console.error('unknown Class:' + Class); } - pt.constructor = Class + pt.constructor = Class; } } // Node Types -var NodeType = {} -var ELEMENT_NODE = NodeType.ELEMENT_NODE = 1; -var ATTRIBUTE_NODE = NodeType.ATTRIBUTE_NODE = 2; -var TEXT_NODE = NodeType.TEXT_NODE = 3; -var CDATA_SECTION_NODE = NodeType.CDATA_SECTION_NODE = 4; -var ENTITY_REFERENCE_NODE = NodeType.ENTITY_REFERENCE_NODE = 5; -var ENTITY_NODE = NodeType.ENTITY_NODE = 6; -var PROCESSING_INSTRUCTION_NODE = NodeType.PROCESSING_INSTRUCTION_NODE = 7; -var COMMENT_NODE = NodeType.COMMENT_NODE = 8; -var DOCUMENT_NODE = NodeType.DOCUMENT_NODE = 9; -var DOCUMENT_TYPE_NODE = NodeType.DOCUMENT_TYPE_NODE = 10; -var DOCUMENT_FRAGMENT_NODE = NodeType.DOCUMENT_FRAGMENT_NODE = 11; -var NOTATION_NODE = NodeType.NOTATION_NODE = 12; +var NodeType = {}; +var ELEMENT_NODE = (NodeType.ELEMENT_NODE = 1); +var ATTRIBUTE_NODE = (NodeType.ATTRIBUTE_NODE = 2); +var TEXT_NODE = (NodeType.TEXT_NODE = 3); +var CDATA_SECTION_NODE = (NodeType.CDATA_SECTION_NODE = 4); +var ENTITY_REFERENCE_NODE = (NodeType.ENTITY_REFERENCE_NODE = 5); +var ENTITY_NODE = (NodeType.ENTITY_NODE = 6); +var PROCESSING_INSTRUCTION_NODE = (NodeType.PROCESSING_INSTRUCTION_NODE = 7); +var COMMENT_NODE = (NodeType.COMMENT_NODE = 8); +var DOCUMENT_NODE = (NodeType.DOCUMENT_NODE = 9); +var DOCUMENT_TYPE_NODE = (NodeType.DOCUMENT_TYPE_NODE = 10); +var DOCUMENT_FRAGMENT_NODE = (NodeType.DOCUMENT_FRAGMENT_NODE = 11); +var NOTATION_NODE = (NodeType.NOTATION_NODE = 12); // ExceptionCode -var ExceptionCode = {} +var ExceptionCode = {}; var ExceptionMessage = {}; -var INDEX_SIZE_ERR = ExceptionCode.INDEX_SIZE_ERR = ((ExceptionMessage[1]="Index size error"),1); -var DOMSTRING_SIZE_ERR = ExceptionCode.DOMSTRING_SIZE_ERR = ((ExceptionMessage[2]="DOMString size error"),2); -var HIERARCHY_REQUEST_ERR = ExceptionCode.HIERARCHY_REQUEST_ERR = ((ExceptionMessage[3]="Hierarchy request error"),3); -var WRONG_DOCUMENT_ERR = ExceptionCode.WRONG_DOCUMENT_ERR = ((ExceptionMessage[4]="Wrong document"),4); -var INVALID_CHARACTER_ERR = ExceptionCode.INVALID_CHARACTER_ERR = ((ExceptionMessage[5]="Invalid character"),5); -var NO_DATA_ALLOWED_ERR = ExceptionCode.NO_DATA_ALLOWED_ERR = ((ExceptionMessage[6]="No data allowed"),6); -var NO_MODIFICATION_ALLOWED_ERR = ExceptionCode.NO_MODIFICATION_ALLOWED_ERR = ((ExceptionMessage[7]="No modification allowed"),7); -var NOT_FOUND_ERR = ExceptionCode.NOT_FOUND_ERR = ((ExceptionMessage[8]="Not found"),8); -var NOT_SUPPORTED_ERR = ExceptionCode.NOT_SUPPORTED_ERR = ((ExceptionMessage[9]="Not supported"),9); -var INUSE_ATTRIBUTE_ERR = ExceptionCode.INUSE_ATTRIBUTE_ERR = ((ExceptionMessage[10]="Attribute in use"),10); +var INDEX_SIZE_ERR = (ExceptionCode.INDEX_SIZE_ERR = ((ExceptionMessage[1] = 'Index size error'), 1)); +var DOMSTRING_SIZE_ERR = (ExceptionCode.DOMSTRING_SIZE_ERR = ((ExceptionMessage[2] = 'DOMString size error'), 2)); +var HIERARCHY_REQUEST_ERR = (ExceptionCode.HIERARCHY_REQUEST_ERR = ((ExceptionMessage[3] = 'Hierarchy request error'), 3)); +var WRONG_DOCUMENT_ERR = (ExceptionCode.WRONG_DOCUMENT_ERR = ((ExceptionMessage[4] = 'Wrong document'), 4)); +var INVALID_CHARACTER_ERR = (ExceptionCode.INVALID_CHARACTER_ERR = ((ExceptionMessage[5] = 'Invalid character'), 5)); +var NO_DATA_ALLOWED_ERR = (ExceptionCode.NO_DATA_ALLOWED_ERR = ((ExceptionMessage[6] = 'No data allowed'), 6)); +var NO_MODIFICATION_ALLOWED_ERR = (ExceptionCode.NO_MODIFICATION_ALLOWED_ERR = + ((ExceptionMessage[7] = 'No modification allowed'), 7)); +var NOT_FOUND_ERR = (ExceptionCode.NOT_FOUND_ERR = ((ExceptionMessage[8] = 'Not found'), 8)); +var NOT_SUPPORTED_ERR = (ExceptionCode.NOT_SUPPORTED_ERR = ((ExceptionMessage[9] = 'Not supported'), 9)); +var INUSE_ATTRIBUTE_ERR = (ExceptionCode.INUSE_ATTRIBUTE_ERR = ((ExceptionMessage[10] = 'Attribute in use'), 10)); //level2 -var INVALID_STATE_ERR = ExceptionCode.INVALID_STATE_ERR = ((ExceptionMessage[11]="Invalid state"),11); -var SYNTAX_ERR = ExceptionCode.SYNTAX_ERR = ((ExceptionMessage[12]="Syntax error"),12); -var INVALID_MODIFICATION_ERR = ExceptionCode.INVALID_MODIFICATION_ERR = ((ExceptionMessage[13]="Invalid modification"),13); -var NAMESPACE_ERR = ExceptionCode.NAMESPACE_ERR = ((ExceptionMessage[14]="Invalid namespace"),14); -var INVALID_ACCESS_ERR = ExceptionCode.INVALID_ACCESS_ERR = ((ExceptionMessage[15]="Invalid access"),15); +var INVALID_STATE_ERR = (ExceptionCode.INVALID_STATE_ERR = ((ExceptionMessage[11] = 'Invalid state'), 11)); +var SYNTAX_ERR = (ExceptionCode.SYNTAX_ERR = ((ExceptionMessage[12] = 'Syntax error'), 12)); +var INVALID_MODIFICATION_ERR = (ExceptionCode.INVALID_MODIFICATION_ERR = ((ExceptionMessage[13] = 'Invalid modification'), 13)); +var NAMESPACE_ERR = (ExceptionCode.NAMESPACE_ERR = ((ExceptionMessage[14] = 'Invalid namespace'), 14)); +var INVALID_ACCESS_ERR = (ExceptionCode.INVALID_ACCESS_ERR = ((ExceptionMessage[15] = 'Invalid access'), 15)); /** * DOM Level 2 @@ -133,34 +136,33 @@ var INVALID_ACCESS_ERR = ExceptionCode.INVALID_ACCESS_ERR = ((Excep * @see http://www.w3.org/TR/REC-DOM-Level-1/ecma-script-language-binding.html */ function DOMException(code, message) { - if(message instanceof Error){ + if (message instanceof Error) { var error = message; - }else{ + } else { error = this; Error.call(this, ExceptionMessage[code]); this.message = ExceptionMessage[code]; - if(Error.captureStackTrace) Error.captureStackTrace(this, DOMException); + if (Error.captureStackTrace) Error.captureStackTrace(this, DOMException); } error.code = code; - if(message) this.message = this.message + ": " + message; + if (message) this.message = this.message + ': ' + message; return error; -}; +} DOMException.prototype = Error.prototype; -copy(ExceptionCode,DOMException) +copy(ExceptionCode, DOMException); /** * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-536297177 * The NodeList interface provides the abstraction of an ordered collection of nodes, without defining or constraining how this collection is implemented. NodeList objects in the DOM are live. * The items in the NodeList are accessible via an integral index, starting from 0. */ -function NodeList() { -}; +function NodeList() {} NodeList.prototype = { /** * The number of nodes in the list. The range of valid child node indices is 0 to length-1 inclusive. * @standard level1 */ - length:0, + length: 0, /** * Returns the indexth item in the collection. If index is greater than or equal to the number of nodes in the list, this returns null. * @standard level1 @@ -169,38 +171,38 @@ NodeList.prototype = { * @return Node * The node at the indexth position in the NodeList, or null if that is not a valid index. */ - item: function(index) { + item: function (index) { return this[index] || null; }, toString: function (nodeFilter) { - for(var buf = [], i = 0;i=0){ - var lastIndex = list.length-1 - while(i= 0) { + var lastIndex = list.length - 1; + while (i < lastIndex) { + list[i] = list[++i]; } list.length = lastIndex; - if(el){ + if (el) { var doc = el.ownerDocument; - if(doc){ - _onRemoveAttribute(doc,el,attr); + if (doc) { + _onRemoveAttribute(doc, el, attr); attr.ownerElement = null; } } - }else{ - throw DOMException(NOT_FOUND_ERR,new Error(el.tagName+'@'+attr)) + } else { + throw DOMException(NOT_FOUND_ERR, new Error(el.tagName + '@' + attr)); } } NamedNodeMap.prototype = { - length:0, - item:NodeList.prototype.item, - getNamedItem: function(key) { -// if(key.indexOf(':')>0 || key == 'xmlns'){ -// return null; -// } + length: 0, + item: NodeList.prototype.item, + getNamedItem: function (key) { + // if(key.indexOf(':')>0 || key == 'xmlns'){ + // return null; + // } //console.log() var i = this.length; - while(i--){ + while (i--) { var attr = this[i]; //console.log(attr.nodeName,key) - if(attr.nodeName == key){ + if (attr.nodeName == key) { return attr; } } }, - setNamedItem: function(attr) { + setNamedItem: function (attr) { var el = attr.ownerElement; - if(el && el!=this._ownerElement){ + if (el && el != this._ownerElement) { throw new DOMException(INUSE_ATTRIBUTE_ERR); } var oldAttr = this.getNamedItem(attr.nodeName); - _addNamedNode(this._ownerElement,this,attr,oldAttr); + _addNamedNode(this._ownerElement, this, attr, oldAttr); return oldAttr; }, /* returns Node */ - setNamedItemNS: function(attr) {// raises: WRONG_DOCUMENT_ERR,NO_MODIFICATION_ALLOWED_ERR,INUSE_ATTRIBUTE_ERR - var el = attr.ownerElement, oldAttr; - if(el && el!=this._ownerElement){ + setNamedItemNS: function (attr) { + // raises: WRONG_DOCUMENT_ERR,NO_MODIFICATION_ALLOWED_ERR,INUSE_ATTRIBUTE_ERR + var el = attr.ownerElement, + oldAttr; + if (el && el != this._ownerElement) { throw new DOMException(INUSE_ATTRIBUTE_ERR); } - oldAttr = this.getNamedItemNS(attr.namespaceURI,attr.localName); - _addNamedNode(this._ownerElement,this,attr,oldAttr); + oldAttr = this.getNamedItemNS(attr.namespaceURI, attr.localName); + _addNamedNode(this._ownerElement, this, attr, oldAttr); return oldAttr; }, /* returns Node */ - removeNamedItem: function(key) { + removeNamedItem: function (key) { var attr = this.getNamedItem(key); - _removeNamedNode(this._ownerElement,this,attr); + _removeNamedNode(this._ownerElement, this, attr); return attr; - - - },// raises: NOT_FOUND_ERR,NO_MODIFICATION_ALLOWED_ERR + }, // raises: NOT_FOUND_ERR,NO_MODIFICATION_ALLOWED_ERR //for level2 - removeNamedItemNS:function(namespaceURI,localName){ - var attr = this.getNamedItemNS(namespaceURI,localName); - _removeNamedNode(this._ownerElement,this,attr); + removeNamedItemNS: function (namespaceURI, localName) { + var attr = this.getNamedItemNS(namespaceURI, localName); + _removeNamedNode(this._ownerElement, this, attr); return attr; }, - getNamedItemNS: function(namespaceURI, localName) { + getNamedItemNS: function (namespaceURI, localName) { var i = this.length; - while(i--){ + while (i--) { var node = this[i]; - if(node.localName == localName && node.namespaceURI == namespaceURI){ + if (node.localName == localName && node.namespaceURI == namespaceURI) { return node; } } return null; - } + }, }; /** @@ -337,8 +340,7 @@ NamedNodeMap.prototype = { * @see https://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-102161490 DOM Level 3 Core * @see https://dom.spec.whatwg.org/#domimplementation DOM Living Standard */ -function DOMImplementation() { -} +function DOMImplementation() {} DOMImplementation.prototype = { /** @@ -356,8 +358,8 @@ DOMImplementation.prototype = { * @see https://www.w3.org/TR/REC-DOM-Level-1/level-one-core.html#ID-5CED94D7 DOM Level 1 Core * @see https://dom.spec.whatwg.org/#dom-domimplementation-hasfeature DOM Living Standard */ - hasFeature: function(feature, version) { - return true; + hasFeature: function (feature, version) { + return true; }, /** * Creates an XML Document object of the specified type with its document element. @@ -383,21 +385,21 @@ DOMImplementation.prototype = { * @see https://www.w3.org/TR/xml/#NT-NameStartChar XML Spec: Names * @see https://www.w3.org/TR/xml-names/#ns-qualnames XML Namespaces: Qualified names */ - createDocument: function(namespaceURI, qualifiedName, doctype){ + createDocument: function (namespaceURI, qualifiedName, doctype) { var contentType = MIME_TYPE.XML_APPLICATION; if (namespaceURI === NAMESPACE.HTML) { contentType = MIME_TYPE.XML_XHTML_APPLICATION; } else if (namespaceURI === NAMESPACE.SVG) { - contentType = MIME_TYPE.XML_SVG_IMAGE + contentType = MIME_TYPE.XML_SVG_IMAGE; } - var doc = new Document({contentType: contentType}); + var doc = new Document({ contentType: contentType }); doc.implementation = this; doc.childNodes = new NodeList(); doc.doctype = doctype || null; - if (doctype){ + if (doctype) { doc.appendChild(doctype); } - if (qualifiedName){ + if (qualifiedName) { var root = doc.createElementNS(namespaceURI, qualifiedName); doc.appendChild(root); } @@ -425,7 +427,7 @@ DOMImplementation.prototype = { * @see https://www.w3.org/TR/xml/#NT-NameStartChar XML Spec: Names * @see https://www.w3.org/TR/xml-names/#ns-qualnames XML Namespaces: Qualified names */ - createDocumentType: function(qualifiedName, publicId, systemId){ + createDocumentType: function (qualifiedName, publicId, systemId) { var node = new DocumentType(); node.name = qualifiedName; node.nodeName = qualifiedName; @@ -447,93 +449,93 @@ DOMImplementation.prototype = { * @see https://dom.spec.whatwg.org/#dom-domimplementation-createhtmldocument * @see https://dom.spec.whatwg.org/#html-document */ - createHTMLDocument: function(title) { - var doc = new Document({contentType: MIME_TYPE.HTML}) - doc.implementation = this - doc.childNodes = new NodeList() + createHTMLDocument: function (title) { + var doc = new Document({ contentType: MIME_TYPE.HTML }); + doc.implementation = this; + doc.childNodes = new NodeList(); if (title !== false) { - doc.doctype = this.createDocumentType('html') + doc.doctype = this.createDocumentType('html'); doc.doctype.ownerDocument = this; doc.appendChild(doc.doctype); - var htmlNode = doc.createElement('html') - doc.appendChild(htmlNode) - var headNode = doc.createElement('head') - htmlNode.appendChild(headNode) + var htmlNode = doc.createElement('html'); + doc.appendChild(htmlNode); + var headNode = doc.createElement('head'); + htmlNode.appendChild(headNode); if (typeof title === 'string') { var titleNode = doc.createElement('title'); - titleNode.appendChild(doc.createTextNode(title)) - headNode.appendChild(titleNode) + titleNode.appendChild(doc.createTextNode(title)); + headNode.appendChild(titleNode); } - htmlNode.appendChild(doc.createElement('body')) + htmlNode.appendChild(doc.createElement('body')); } - return doc - } + return doc; + }, }; - /** * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1950641247 */ -function Node() { -}; +function Node() {} Node.prototype = { - firstChild : null, - lastChild : null, - previousSibling : null, - nextSibling : null, - attributes : null, - parentNode : null, - childNodes : null, - ownerDocument : null, - nodeValue : null, - namespaceURI : null, - prefix : null, - localName : null, + firstChild: null, + lastChild: null, + previousSibling: null, + nextSibling: null, + attributes: null, + parentNode: null, + childNodes: null, + ownerDocument: null, + nodeValue: null, + namespaceURI: null, + prefix: null, + localName: null, // Modified in DOM Level 2: - insertBefore:function(newChild, refChild){//raises - return _insertBefore(this,newChild,refChild); + insertBefore: function (newChild, refChild) { + //raises + return _insertBefore(this, newChild, refChild); }, - replaceChild:function(newChild, oldChild){//raises - this.insertBefore(newChild,oldChild); - if(oldChild){ + replaceChild: function (newChild, oldChild) { + //raises + this.insertBefore(newChild, oldChild); + if (oldChild) { this.removeChild(oldChild); } }, - removeChild:function(oldChild){ - return _removeChild(this,oldChild); + removeChild: function (oldChild) { + return _removeChild(this, oldChild); }, - appendChild:function(newChild){ - return this.insertBefore(newChild,null); + appendChild: function (newChild) { + return this.insertBefore(newChild, null); }, - hasChildNodes:function(){ + hasChildNodes: function () { return this.firstChild != null; }, - cloneNode:function(deep){ - return cloneNode(this.ownerDocument||this,this,deep); + cloneNode: function (deep) { + return cloneNode(this.ownerDocument || this, this, deep); }, // Modified in DOM Level 2: - normalize:function(){ + normalize: function () { var child = this.firstChild; - while(child){ + while (child) { var next = child.nextSibling; - if(next && next.nodeType == TEXT_NODE && child.nodeType == TEXT_NODE){ + if (next && next.nodeType == TEXT_NODE && child.nodeType == TEXT_NODE) { this.removeChild(next); child.appendData(next.data); - }else{ + } else { child.normalize(); child = next; } } }, - // Introduced in DOM Level 2: - isSupported:function(feature, version){ - return this.ownerDocument.implementation.hasFeature(feature,version); + // Introduced in DOM Level 2: + isSupported: function (feature, version) { + return this.ownerDocument.implementation.hasFeature(feature, version); + }, + // Introduced in DOM Level 2: + hasAttributes: function () { + return this.attributes.length > 0; }, - // Introduced in DOM Level 2: - hasAttributes:function(){ - return this.attributes.length>0; - }, /** * Look up the prefix associated to the given namespace URI, starting from this node. * **The default namespace declarations are ignored by this method.** @@ -548,70 +550,68 @@ Node.prototype = { * @see https://dom.spec.whatwg.org/#dom-node-lookupprefix * @see https://github.com/xmldom/xmldom/issues/322 */ - lookupPrefix:function(namespaceURI){ - var el = this; - while(el){ - var map = el._nsMap; - //console.dir(map) - if(map){ - for(var n in map){ - if (Object.prototype.hasOwnProperty.call(map, n) && map[n] === namespaceURI) { - return n; - } - } - } - el = el.nodeType == ATTRIBUTE_NODE?el.ownerDocument : el.parentNode; - } - return null; - }, - // Introduced in DOM Level 3: - lookupNamespaceURI:function(prefix){ - var el = this; - while(el){ - var map = el._nsMap; - //console.dir(map) - if(map){ - if(Object.prototype.hasOwnProperty.call(map, prefix)){ - return map[prefix] ; - } - } - el = el.nodeType == ATTRIBUTE_NODE?el.ownerDocument : el.parentNode; - } - return null; - }, - // Introduced in DOM Level 3: - isDefaultNamespace:function(namespaceURI){ - var prefix = this.lookupPrefix(namespaceURI); - return prefix == null; - } + lookupPrefix: function (namespaceURI) { + var el = this; + while (el) { + var map = el._nsMap; + //console.dir(map) + if (map) { + for (var n in map) { + if (Object.prototype.hasOwnProperty.call(map, n) && map[n] === namespaceURI) { + return n; + } + } + } + el = el.nodeType == ATTRIBUTE_NODE ? el.ownerDocument : el.parentNode; + } + return null; + }, + // Introduced in DOM Level 3: + lookupNamespaceURI: function (prefix) { + var el = this; + while (el) { + var map = el._nsMap; + //console.dir(map) + if (map) { + if (Object.prototype.hasOwnProperty.call(map, prefix)) { + return map[prefix]; + } + } + el = el.nodeType == ATTRIBUTE_NODE ? el.ownerDocument : el.parentNode; + } + return null; + }, + // Introduced in DOM Level 3: + isDefaultNamespace: function (namespaceURI) { + var prefix = this.lookupPrefix(namespaceURI); + return prefix == null; + }, }; - -function _xmlEncoder(c){ - return c == '<' && '<' || - c == '>' && '>' || - c == '&' && '&' || - c == '"' && '"' || - '&#'+c.charCodeAt()+';' +function _xmlEncoder(c) { + return ( + (c == '<' && '<') || (c == '>' && '>') || (c == '&' && '&') || (c == '"' && '"') || '&#' + c.charCodeAt() + ';' + ); } - -copy(NodeType,Node); -copy(NodeType,Node.prototype); +copy(NodeType, Node); +copy(NodeType, Node.prototype); /** * @param callback return true for continue,false for break * @return boolean true: break visit; */ -function _visitNode(node,callback){ - if(callback(node)){ +function _visitNode(node, callback) { + if (callback(node)) { return true; } - if(node = node.firstChild){ - do{ - if(_visitNode(node,callback)){return true} - }while(node=node.nextSibling) - } + if ((node = node.firstChild)) { + do { + if (_visitNode(node, callback)) { + return true; + } + } while ((node = node.nextSibling)); + } } /** @@ -634,7 +634,7 @@ function _visitNode(node,callback){ * @see https://developer.mozilla.org/en-US/docs/Web/API/Document * @see https://dom.spec.whatwg.org/#interface-document */ -function Document(options){ +function Document(options) { var opt = options || {}; /** * The mime type of the document is determined at creation time and can not be modified. @@ -646,7 +646,7 @@ function Document(options){ * @see DOMImplementation * @see MIME_TYPE */ - this.contentType = opt.contentType || MIME_TYPE.XML_APPLICATION + this.contentType = opt.contentType || MIME_TYPE.XML_APPLICATION; /** * * @type {'html' | 'xml'} @@ -655,24 +655,24 @@ function Document(options){ * @see https://dom.spec.whatwg.org/#concept-document-type * @see DOMImplementation */ - this.type = MIME_TYPE.isHTML(this.contentType) ? 'html' : 'xml' + this.type = MIME_TYPE.isHTML(this.contentType) ? 'html' : 'xml'; } -function _onAddAttribute(doc,el,newAttr){ +function _onAddAttribute(doc, el, newAttr) { doc && doc._inc++; - var ns = newAttr.namespaceURI ; - if(ns === NAMESPACE.XMLNS){ + var ns = newAttr.namespaceURI; + if (ns === NAMESPACE.XMLNS) { //update namespace - el._nsMap[newAttr.prefix?newAttr.localName:''] = newAttr.value + el._nsMap[newAttr.prefix ? newAttr.localName : ''] = newAttr.value; } } -function _onRemoveAttribute(doc,el,newAttr,remove){ +function _onRemoveAttribute(doc, el, newAttr, remove) { doc && doc._inc++; - var ns = newAttr.namespaceURI ; - if(ns === NAMESPACE.XMLNS){ + var ns = newAttr.namespaceURI; + if (ns === NAMESPACE.XMLNS) { //update namespace - delete el._nsMap[newAttr.prefix?newAttr.localName:''] + delete el._nsMap[newAttr.prefix ? newAttr.localName : '']; } } @@ -688,8 +688,8 @@ function _onRemoveAttribute(doc,el,newAttr,remove){ * @param {Node} [newChild] * @private */ -function _onUpdateChild (doc, el, newChild) { - if(doc && doc._inc){ +function _onUpdateChild(doc, el, newChild) { + if (doc && doc._inc) { doc._inc++; //update childNodes var cs = el.childNodes; @@ -720,7 +720,7 @@ function _onUpdateChild (doc, el, newChild) { * @returns {Node} the child that was removed. * @private */ -function _removeChild (parentNode, child) { +function _removeChild(parentNode, child) { var previous = child.previousSibling; var next = child.nextSibling; if (previous) { @@ -742,18 +742,18 @@ function _removeChild (parentNode, child) { /** * preformance key(refChild == null) */ -function _insertBefore(parentNode,newChild,nextChild){ +function _insertBefore(parentNode, newChild, nextChild) { var cp = newChild.parentNode; - if(cp){ - cp.removeChild(newChild);//remove and update + if (cp) { + cp.removeChild(newChild); //remove and update } - if(newChild.nodeType === DOCUMENT_FRAGMENT_NODE){ + if (newChild.nodeType === DOCUMENT_FRAGMENT_NODE) { var newFirst = newChild.firstChild; if (newFirst == null) { return newChild; } var newLast = newChild.lastChild; - }else{ + } else { newFirst = newLast = newChild; } var pre = nextChild ? nextChild.previousSibling : parentNode.lastChild; @@ -761,21 +761,20 @@ function _insertBefore(parentNode,newChild,nextChild){ newFirst.previousSibling = pre; newLast.nextSibling = nextChild; - - if(pre){ + if (pre) { pre.nextSibling = newFirst; - }else{ + } else { parentNode.firstChild = newFirst; } - if(nextChild == null){ + if (nextChild == null) { parentNode.lastChild = newLast; - }else{ + } else { nextChild.previousSibling = newLast; } - do{ + do { newFirst.parentNode = parentNode; - }while(newFirst !== newLast && (newFirst= newFirst.nextSibling)) - _onUpdateChild(parentNode.ownerDocument||parentNode,parentNode); + } while (newFirst !== newLast && (newFirst = newFirst.nextSibling)); + _onUpdateChild(parentNode.ownerDocument || parentNode, parentNode); //console.log(parentNode.lastChild.nextSibling == null) if (newChild.nodeType == DOCUMENT_FRAGMENT_NODE) { newChild.firstChild = newChild.lastChild = null; @@ -794,7 +793,7 @@ function _insertBefore(parentNode,newChild,nextChild){ * @returns {Node} * @private */ -function _appendSingleChild (parentNode, newChild) { +function _appendSingleChild(parentNode, newChild) { if (newChild.parentNode) { newChild.parentNode.removeChild(newChild); } @@ -817,56 +816,57 @@ Document.prototype = { * @readonly * @type DOMImplementation */ - implementation : null, - nodeName : '#document', - nodeType : DOCUMENT_NODE, + implementation: null, + nodeName: '#document', + nodeType: DOCUMENT_NODE, /** * The DocumentType node of the document. * * @readonly * @type DocumentType */ - doctype : null, - documentElement : null, - _inc : 1, + doctype: null, + documentElement: null, + _inc: 1, - insertBefore : function(newChild, refChild){//raises - if(newChild.nodeType == DOCUMENT_FRAGMENT_NODE){ + insertBefore: function (newChild, refChild) { + //raises + if (newChild.nodeType == DOCUMENT_FRAGMENT_NODE) { var child = newChild.firstChild; - while(child){ + while (child) { var next = child.nextSibling; - this.insertBefore(child,refChild); + this.insertBefore(child, refChild); child = next; } return newChild; } - if(this.documentElement == null && newChild.nodeType == ELEMENT_NODE){ + if (this.documentElement == null && newChild.nodeType == ELEMENT_NODE) { this.documentElement = newChild; } - return _insertBefore(this,newChild,refChild),(newChild.ownerDocument = this),newChild; + return _insertBefore(this, newChild, refChild), (newChild.ownerDocument = this), newChild; }, - removeChild : function(oldChild){ - if(this.documentElement == oldChild){ + removeChild: function (oldChild) { + if (this.documentElement == oldChild) { this.documentElement = null; } - return _removeChild(this,oldChild); + return _removeChild(this, oldChild); }, // Introduced in DOM Level 2: - importNode : function(importedNode,deep){ - return importNode(this,importedNode,deep); + importNode: function (importedNode, deep) { + return importNode(this, importedNode, deep); }, // Introduced in DOM Level 2: - getElementById : function(id){ + getElementById: function (id) { var rtv = null; - _visitNode(this.documentElement,function(node){ - if(node.nodeType == ELEMENT_NODE){ - if(node.getAttribute('id') == id){ + _visitNode(this.documentElement, function (node) { + if (node.nodeType == ELEMENT_NODE) { + if (node.getAttribute('id') == id) { rtv = node; return true; } } - }) + }); return rtv; }, @@ -887,23 +887,23 @@ Document.prototype = { * @see https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementsByClassName * @see https://dom.spec.whatwg.org/#concept-getelementsbyclassname */ - getElementsByClassName: function(classNames) { - var classNamesSet = toOrderedSet(classNames) - return new LiveNodeList(this, function(base) { + getElementsByClassName: function (classNames) { + var classNamesSet = toOrderedSet(classNames); + return new LiveNodeList(this, function (base) { var ls = []; if (classNamesSet.length > 0) { - _visitNode(base.documentElement, function(node) { - if(node !== base && node.nodeType === ELEMENT_NODE) { - var nodeClassNames = node.getAttribute('class') + _visitNode(base.documentElement, function (node) { + if (node !== base && node.nodeType === ELEMENT_NODE) { + var nodeClassNames = node.getAttribute('class'); // can be null if the attribute does not exist if (nodeClassNames) { // before splitting and iterating just compare them for the most common case var matches = classNames === nodeClassNames; if (!matches) { - var nodeClassNamesSet = toOrderedSet(nodeClassNames) - matches = classNamesSet.every(arrayIncludes(nodeClassNamesSet)) + var nodeClassNamesSet = toOrderedSet(nodeClassNames); + matches = classNamesSet.every(arrayIncludes(nodeClassNamesSet)); } - if(matches) { + if (matches) { ls.push(node); } } @@ -933,52 +933,52 @@ Document.prototype = { * @see https://dom.spec.whatwg.org/#dom-document-createelement * @see https://dom.spec.whatwg.org/#concept-create-element */ - createElement : function(tagName){ + createElement: function (tagName) { var node = new Element(); node.ownerDocument = this; if (this.type === 'html') { - tagName = tagName.toLowerCase() + tagName = tagName.toLowerCase(); } if (MIME_TYPE.hasDefaultHTMLNamespace(this.contentType)) { - node.namespaceURI = NAMESPACE.HTML + node.namespaceURI = NAMESPACE.HTML; } node.nodeName = tagName; node.tagName = tagName; node.localName = tagName; node.childNodes = new NodeList(); - var attrs = node.attributes = new NamedNodeMap(); + var attrs = (node.attributes = new NamedNodeMap()); attrs._ownerElement = node; return node; }, - createDocumentFragment : function(){ + createDocumentFragment: function () { var node = new DocumentFragment(); node.ownerDocument = this; node.childNodes = new NodeList(); return node; }, - createTextNode : function(data){ + createTextNode: function (data) { var node = new Text(); node.ownerDocument = this; - node.appendData(data) + node.appendData(data); return node; }, - createComment : function(data){ + createComment: function (data) { var node = new Comment(); node.ownerDocument = this; - node.appendData(data) + node.appendData(data); return node; }, - createCDATASection : function(data){ + createCDATASection: function (data) { var node = new CDATASection(); node.ownerDocument = this; - node.appendData(data) + node.appendData(data); return node; }, - createProcessingInstruction : function(target,data){ + createProcessingInstruction: function (target, data) { var node = new ProcessingInstruction(); node.ownerDocument = this; node.tagName = node.target = target; - node.nodeValue= node.data = data; + node.nodeValue = node.data = data; return node; }, /** @@ -996,41 +996,41 @@ Document.prototype = { * @see https://developer.mozilla.org/en-US/docs/Web/API/Document/createAttribute * @see https://dom.spec.whatwg.org/#dom-document-createattribute */ - createAttribute: function(name){ + createAttribute: function (name) { if (this.type === 'html') { - name = name.toLowerCase() + name = name.toLowerCase(); } return this._createAttribute(name); }, - _createAttribute: function(name){ + _createAttribute: function (name) { var node = new Attr(); node.ownerDocument = this; node.name = name; - node.nodeName = name; + node.nodeName = name; node.localName = name; node.specified = true; return node; }, - createEntityReference : function(name){ + createEntityReference: function (name) { var node = new EntityReference(); - node.ownerDocument = this; - node.nodeName = name; + node.ownerDocument = this; + node.nodeName = name; return node; }, // Introduced in DOM Level 2: - createElementNS : function(namespaceURI,qualifiedName){ + createElementNS: function (namespaceURI, qualifiedName) { var node = new Element(); var pl = qualifiedName.split(':'); - var attrs = node.attributes = new NamedNodeMap(); + var attrs = (node.attributes = new NamedNodeMap()); node.childNodes = new NodeList(); node.ownerDocument = this; node.nodeName = qualifiedName; node.tagName = qualifiedName; node.namespaceURI = namespaceURI; - if(pl.length == 2){ + if (pl.length == 2) { node.prefix = pl[0]; node.localName = pl[1]; - }else{ + } else { //el.prefix = null; node.localName = qualifiedName; } @@ -1038,7 +1038,7 @@ Document.prototype = { return node; }, // Introduced in DOM Level 2: - createAttributeNS : function(namespaceURI,qualifiedName){ + createAttributeNS: function (namespaceURI, qualifiedName) { var node = new Attr(); var pl = qualifiedName.split(':'); node.ownerDocument = this; @@ -1046,93 +1046,92 @@ Document.prototype = { node.name = qualifiedName; node.namespaceURI = namespaceURI; node.specified = true; - if(pl.length == 2){ + if (pl.length == 2) { node.prefix = pl[0]; node.localName = pl[1]; - }else{ + } else { //el.prefix = null; node.localName = qualifiedName; } return node; - } + }, }; -_extends(Document,Node); - +_extends(Document, Node); function Element() { this._nsMap = {}; -}; +} Element.prototype = { - nodeType : ELEMENT_NODE, + nodeType: ELEMENT_NODE, getQualifiedName: function () { - return this.prefix ? this.prefix+':'+this.localName : this.localName + return this.prefix ? this.prefix + ':' + this.localName : this.localName; }, _isInHTMLDocumentAndNamespace: function () { return this.ownerDocument.type === 'html' && this.namespaceURI === NAMESPACE.HTML; }, - hasAttribute : function(name){ - return this.getAttributeNode(name)!=null; + hasAttribute: function (name) { + return this.getAttributeNode(name) != null; }, - getAttribute : function(name){ + getAttribute: function (name) { var attr = this.getAttributeNode(name); - return attr && attr.value || ''; + return (attr && attr.value) || ''; }, - getAttributeNode : function(name){ + getAttributeNode: function (name) { if (this._isInHTMLDocumentAndNamespace()) { - name = name.toLowerCase() + name = name.toLowerCase(); } return this.attributes.getNamedItem(name); }, - setAttribute : function(name, value){ + setAttribute: function (name, value) { if (this._isInHTMLDocumentAndNamespace()) { - name = name.toLowerCase() + name = name.toLowerCase(); } - var attr = this.ownerDocument._createAttribute(name) - attr.value = attr.nodeValue = "" + value; - this.setAttributeNode(attr) + var attr = this.ownerDocument._createAttribute(name); + attr.value = attr.nodeValue = '' + value; + this.setAttributeNode(attr); }, - removeAttribute : function(name){ - var attr = this.getAttributeNode(name) + removeAttribute: function (name) { + var attr = this.getAttributeNode(name); attr && this.removeAttributeNode(attr); }, // four real operation method - appendChild:function(newChild){ - if(newChild.nodeType === DOCUMENT_FRAGMENT_NODE){ - return this.insertBefore(newChild,null); - }else{ - return _appendSingleChild(this,newChild); + appendChild: function (newChild) { + if (newChild.nodeType === DOCUMENT_FRAGMENT_NODE) { + return this.insertBefore(newChild, null); + } else { + return _appendSingleChild(this, newChild); } }, - setAttributeNode : function(newAttr){ + setAttributeNode: function (newAttr) { return this.attributes.setNamedItem(newAttr); }, - setAttributeNodeNS : function(newAttr){ + setAttributeNodeNS: function (newAttr) { return this.attributes.setNamedItemNS(newAttr); }, - removeAttributeNode : function(oldAttr){ + removeAttributeNode: function (oldAttr) { //console.log(this == oldAttr.ownerElement) return this.attributes.removeNamedItem(oldAttr.nodeName); }, //get real attribute name,and remove it by removeAttributeNode - removeAttributeNS : function(namespaceURI, localName){ + removeAttributeNS: function (namespaceURI, localName) { var old = this.getAttributeNodeNS(namespaceURI, localName); old && this.removeAttributeNode(old); }, - hasAttributeNS : function(namespaceURI, localName){ - return this.getAttributeNodeNS(namespaceURI, localName)!=null; + hasAttributeNS: function (namespaceURI, localName) { + return this.getAttributeNodeNS(namespaceURI, localName) != null; }, - getAttributeNS : function(namespaceURI, localName){ + getAttributeNS: function (namespaceURI, localName) { var attr = this.getAttributeNodeNS(namespaceURI, localName); - return attr && attr.value || ''; + return (attr && attr.value) || ''; }, - setAttributeNS : function(namespaceURI, qualifiedName, value){ + setAttributeNS: function (namespaceURI, qualifiedName, value) { var attr = this.ownerDocument.createAttributeNS(namespaceURI, qualifiedName); - attr.value = attr.nodeValue = "" + value; - this.setAttributeNode(attr) + attr.value = attr.nodeValue = '' + value; + this.setAttributeNode(attr); }, - getAttributeNodeNS : function(namespaceURI, localName){ + getAttributeNodeNS: function (namespaceURI, localName) { return this.attributes.getNamedItemNS(namespaceURI, localName); }, @@ -1161,23 +1160,21 @@ Element.prototype = { * @see https://developer.mozilla.org/en-US/docs/Web/API/Element/getElementsByTagName * @see https://dom.spec.whatwg.org/#concept-getelementsbytagname */ - getElementsByTagName : function(qualifiedName){ - var isHTMLDocument = (this.nodeType === DOCUMENT_NODE ? this : this.ownerDocument).type === 'html' - var lowerQualifiedName = qualifiedName.toLowerCase() - return new LiveNodeList(this,function(base){ + getElementsByTagName: function (qualifiedName) { + var isHTMLDocument = (this.nodeType === DOCUMENT_NODE ? this : this.ownerDocument).type === 'html'; + var lowerQualifiedName = qualifiedName.toLowerCase(); + return new LiveNodeList(this, function (base) { var ls = []; - _visitNode(base, function(node) { - if (node === base || node.nodeType !== ELEMENT_NODE) { - return + _visitNode(base, function (node) { + if (node === base || node.nodeType !== ELEMENT_NODE) { + return; } if (qualifiedName === '*') { ls.push(node); } else { var nodeQualifiedName = node.getQualifiedName(); - var matchingQName = isHTMLDocument && node.namespaceURI === NAMESPACE.HTML - ? lowerQualifiedName - : qualifiedName - if(nodeQualifiedName === matchingQName){ + var matchingQName = isHTMLDocument && node.namespaceURI === NAMESPACE.HTML ? lowerQualifiedName : qualifiedName; + if (nodeQualifiedName === matchingQName) { ls.push(node); } } @@ -1185,149 +1182,137 @@ Element.prototype = { return ls; }); }, - getElementsByTagNameNS : function(namespaceURI, localName){ - return new LiveNodeList(this,function(base){ + getElementsByTagNameNS: function (namespaceURI, localName) { + return new LiveNodeList(this, function (base) { var ls = []; - _visitNode(base,function(node){ - if(node !== base && node.nodeType === ELEMENT_NODE && (namespaceURI === '*' || node.namespaceURI === namespaceURI) && (localName === '*' || node.localName == localName)){ + _visitNode(base, function (node) { + if ( + node !== base && + node.nodeType === ELEMENT_NODE && + (namespaceURI === '*' || node.namespaceURI === namespaceURI) && + (localName === '*' || node.localName == localName) + ) { ls.push(node); } }); return ls; - }); - } + }, }; Document.prototype.getElementsByTagName = Element.prototype.getElementsByTagName; Document.prototype.getElementsByTagNameNS = Element.prototype.getElementsByTagNameNS; - -_extends(Element,Node); -function Attr() { -}; +_extends(Element, Node); +function Attr() {} Attr.prototype.nodeType = ATTRIBUTE_NODE; -_extends(Attr,Node); +_extends(Attr, Node); - -function CharacterData() { -}; +function CharacterData() {} CharacterData.prototype = { - data : '', - substringData : function(offset, count) { - return this.data.substring(offset, offset+count); + data: '', + substringData: function (offset, count) { + return this.data.substring(offset, offset + count); }, - appendData: function(text) { - text = this.data+text; + appendData: function (text) { + text = this.data + text; this.nodeValue = this.data = text; this.length = text.length; }, - insertData: function(offset,text) { - this.replaceData(offset,0,text); - + insertData: function (offset, text) { + this.replaceData(offset, 0, text); }, - appendChild:function(newChild){ - throw new Error(ExceptionMessage[HIERARCHY_REQUEST_ERR]) + appendChild: function (newChild) { + throw new Error(ExceptionMessage[HIERARCHY_REQUEST_ERR]); }, - deleteData: function(offset, count) { - this.replaceData(offset,count,""); + deleteData: function (offset, count) { + this.replaceData(offset, count, ''); }, - replaceData: function(offset, count, text) { - var start = this.data.substring(0,offset); - var end = this.data.substring(offset+count); + replaceData: function (offset, count, text) { + var start = this.data.substring(0, offset); + var end = this.data.substring(offset + count); text = start + text + end; this.nodeValue = this.data = text; this.length = text.length; - } -} -_extends(CharacterData,Node); -function Text() { + }, }; +_extends(CharacterData, Node); +function Text() {} Text.prototype = { - nodeName : "#text", - nodeType : TEXT_NODE, - splitText : function(offset) { + nodeName: '#text', + nodeType: TEXT_NODE, + splitText: function (offset) { var text = this.data; var newText = text.substring(offset); text = text.substring(0, offset); this.data = this.nodeValue = text; this.length = text.length; var newNode = this.ownerDocument.createTextNode(newText); - if(this.parentNode){ + if (this.parentNode) { this.parentNode.insertBefore(newNode, this.nextSibling); } return newNode; - } -} -_extends(Text,CharacterData); -function Comment() { + }, }; +_extends(Text, CharacterData); +function Comment() {} Comment.prototype = { - nodeName : "#comment", - nodeType : COMMENT_NODE -} -_extends(Comment,CharacterData); - -function CDATASection() { + nodeName: '#comment', + nodeType: COMMENT_NODE, }; -CDATASection.prototype = { - nodeName : "#cdata-section", - nodeType : CDATA_SECTION_NODE -} -_extends(CDATASection,CharacterData); - +_extends(Comment, CharacterData); -function DocumentType() { +function CDATASection() {} +CDATASection.prototype = { + nodeName: '#cdata-section', + nodeType: CDATA_SECTION_NODE, }; +_extends(CDATASection, CharacterData); + +function DocumentType() {} DocumentType.prototype.nodeType = DOCUMENT_TYPE_NODE; -_extends(DocumentType,Node); +_extends(DocumentType, Node); -function Notation() { -}; +function Notation() {} Notation.prototype.nodeType = NOTATION_NODE; -_extends(Notation,Node); +_extends(Notation, Node); -function Entity() { -}; +function Entity() {} Entity.prototype.nodeType = ENTITY_NODE; -_extends(Entity,Node); +_extends(Entity, Node); -function EntityReference() { -}; +function EntityReference() {} EntityReference.prototype.nodeType = ENTITY_REFERENCE_NODE; -_extends(EntityReference,Node); - -function DocumentFragment() { -}; -DocumentFragment.prototype.nodeName = "#document-fragment"; -DocumentFragment.prototype.nodeType = DOCUMENT_FRAGMENT_NODE; -_extends(DocumentFragment,Node); +_extends(EntityReference, Node); +function DocumentFragment() {} +DocumentFragment.prototype.nodeName = '#document-fragment'; +DocumentFragment.prototype.nodeType = DOCUMENT_FRAGMENT_NODE; +_extends(DocumentFragment, Node); -function ProcessingInstruction() { -} +function ProcessingInstruction() {} ProcessingInstruction.prototype.nodeType = PROCESSING_INSTRUCTION_NODE; -_extends(ProcessingInstruction,Node); -function XMLSerializer(){} +_extends(ProcessingInstruction, Node); +function XMLSerializer() {} XMLSerializer.prototype.serializeToString = function (node, nodeFilter) { return nodeSerializeToString.call(node, nodeFilter); -} +}; Node.prototype.toString = nodeSerializeToString; function nodeSerializeToString(nodeFilter) { var buf = []; - var refNode = this.nodeType === DOCUMENT_NODE && this.documentElement || this; + var refNode = (this.nodeType === DOCUMENT_NODE && this.documentElement) || this; var prefix = refNode.prefix; var uri = refNode.namespaceURI; - if(uri && prefix == null){ + if (uri && prefix == null) { var prefix = refNode.lookupPrefix(uri); - if(prefix == null){ - var visibleNamespaces=[ - {namespace:uri,prefix:null} - //{namespace:uri,prefix:''} - ] + if (prefix == null) { + var visibleNamespaces = [ + { namespace: uri, prefix: null }, + //{namespace:uri,prefix:''} + ]; } } - serializeToString(this,buf,nodeFilter,visibleNamespaces); + serializeToString(this, buf, nodeFilter, visibleNamespaces); return buf.join(''); } @@ -1344,11 +1329,11 @@ function needNamespaceDefine(node, isHTML, visibleNamespaces) { if (!uri) { return false; } - if (prefix === "xml" && uri === NAMESPACE.XML || uri === NAMESPACE.XMLNS) { + if ((prefix === 'xml' && uri === NAMESPACE.XML) || uri === NAMESPACE.XMLNS) { return false; } - var i = visibleNamespaces.length + var i = visibleNamespaces.length; while (i--) { var ns = visibleNamespaces[i]; // get namespace prefix @@ -1372,234 +1357,235 @@ function needNamespaceDefine(node, isHTML, visibleNamespaces) { * @see https://w3c.github.io/DOM-Parsing/#serializing-an-element-s-attributes */ function addSerializedAttribute(buf, qualifiedName, value) { - buf.push(' ', qualifiedName, '="', value.replace(/[<>&"\t\n\r]/g, _xmlEncoder), '"') + buf.push(' ', qualifiedName, '="', value.replace(/[<>&"\t\n\r]/g, _xmlEncoder), '"'); } -function serializeToString (node, buf, nodeFilter, visibleNamespaces) { +function serializeToString(node, buf, nodeFilter, visibleNamespaces) { if (!visibleNamespaces) { visibleNamespaces = []; } - var doc = node.nodeType === DOCUMENT_NODE ? node : node.ownerDocument - var isHTML = doc.type === 'html' + var doc = node.nodeType === DOCUMENT_NODE ? node : node.ownerDocument; + var isHTML = doc.type === 'html'; - if(nodeFilter){ + if (nodeFilter) { node = nodeFilter(node); - if(node){ - if(typeof node == 'string'){ + if (node) { + if (typeof node == 'string') { buf.push(node); return; } - }else{ + } else { return; } //buf.sort.apply(attrs, attributeSorter); } - switch(node.nodeType){ - case ELEMENT_NODE: - var attrs = node.attributes; - var len = attrs.length; - var child = node.firstChild; - var nodeName = node.tagName; - - var prefixedNodeName = nodeName - if (!isHTML && !node.prefix && node.namespaceURI) { - var defaultNS - // lookup current default ns from `xmlns` attribute - for (var ai = 0; ai < attrs.length; ai++) { - if (attrs.item(ai).name === 'xmlns') { - defaultNS = attrs.item(ai).value - break + switch (node.nodeType) { + case ELEMENT_NODE: + var attrs = node.attributes; + var len = attrs.length; + var child = node.firstChild; + var nodeName = node.tagName; + + var prefixedNodeName = nodeName; + if (!isHTML && !node.prefix && node.namespaceURI) { + var defaultNS; + // lookup current default ns from `xmlns` attribute + for (var ai = 0; ai < attrs.length; ai++) { + if (attrs.item(ai).name === 'xmlns') { + defaultNS = attrs.item(ai).value; + break; + } } - } - if (!defaultNS) { - // lookup current default ns in visibleNamespaces - for (var nsi = visibleNamespaces.length - 1; nsi >= 0; nsi--) { - var namespace = visibleNamespaces[nsi] - if (namespace.prefix === '' && namespace.namespace === node.namespaceURI) { - defaultNS = namespace.namespace - break + if (!defaultNS) { + // lookup current default ns in visibleNamespaces + for (var nsi = visibleNamespaces.length - 1; nsi >= 0; nsi--) { + var namespace = visibleNamespaces[nsi]; + if (namespace.prefix === '' && namespace.namespace === node.namespaceURI) { + defaultNS = namespace.namespace; + break; + } } } - } - if (defaultNS !== node.namespaceURI) { - for (var nsi = visibleNamespaces.length - 1; nsi >= 0; nsi--) { - var namespace = visibleNamespaces[nsi] - if (namespace.namespace === node.namespaceURI) { - if (namespace.prefix) { - prefixedNodeName = namespace.prefix + ':' + nodeName + if (defaultNS !== node.namespaceURI) { + for (var nsi = visibleNamespaces.length - 1; nsi >= 0; nsi--) { + var namespace = visibleNamespaces[nsi]; + if (namespace.namespace === node.namespaceURI) { + if (namespace.prefix) { + prefixedNodeName = namespace.prefix + ':' + nodeName; + } + break; } - break } } } - } - buf.push('<', prefixedNodeName); - - for(var i=0;i"); - } else { - buf.push(">"); - //if is cdata child node - if (isHTML && isHTMLRawTextElement(nodeName)) { - while(child){ - if(child.data){ - buf.push(child.data); - }else{ + // add namespace for current node + if (nodeName === prefixedNodeName && needNamespaceDefine(node, isHTML, visibleNamespaces)) { + var prefix = node.prefix || ''; + var uri = node.namespaceURI; + addSerializedAttribute(buf, prefix ? 'xmlns:' + prefix : 'xmlns', uri); + visibleNamespaces.push({ prefix: prefix, namespace: uri }); + } + // in XML elements can be closed when they have no children + var canCloseTag = !child; + if (canCloseTag && (isHTML || NAMESPACE.isHTML(node.namespaceURI))) { + // in HTML (doc or ns) only void elements can be closed right away + canCloseTag = isHTMLVoidElement(nodeName); + } + if (canCloseTag) { + buf.push('/>'); + } else { + buf.push('>'); + //if is cdata child node + if (isHTML && isHTMLRawTextElement(nodeName)) { + while (child) { + if (child.data) { + buf.push(child.data); + } else { + serializeToString(child, buf, nodeFilter, visibleNamespaces.slice()); + } + child = child.nextSibling; + } + } else { + while (child) { serializeToString(child, buf, nodeFilter, visibleNamespaces.slice()); + child = child.nextSibling; } - child = child.nextSibling; - } - } else { - while(child){ - serializeToString(child, buf, nodeFilter, visibleNamespaces.slice()); - child = child.nextSibling; } + buf.push(''); } - buf.push(""); - } - // remove added visible namespaces - //visibleNamespaces.length = startVisibleNamespaces; - return; - case DOCUMENT_NODE: - case DOCUMENT_FRAGMENT_NODE: - var child = node.firstChild; - while(child){ - serializeToString(child, buf, nodeFilter, visibleNamespaces.slice()); - child = child.nextSibling; - } - return; - case ATTRIBUTE_NODE: - return addSerializedAttribute(buf, node.name, node.value); - case TEXT_NODE: - /** - * The ampersand character (&) and the left angle bracket (<) must not appear in their literal form, - * except when used as markup delimiters, or within a comment, a processing instruction, or a CDATA section. - * If they are needed elsewhere, they must be escaped using either numeric character references or the strings - * `&` and `<` respectively. - * The right angle bracket (>) may be represented using the string " > ", and must, for compatibility, - * be escaped using either `>` or a character reference when it appears in the string `]]>` in content, - * when that string is not marking the end of a CDATA section. - * - * In the content of elements, character data is any string of characters - * which does not contain the start-delimiter of any markup - * and does not include the CDATA-section-close delimiter, `]]>`. - * - * @see https://www.w3.org/TR/xml/#NT-CharData - * @see https://w3c.github.io/DOM-Parsing/#xml-serializing-a-text-node - */ - return buf.push(node.data - .replace(/[<&>]/g,_xmlEncoder) - ); - case CDATA_SECTION_NODE: - return buf.push( ''); - case COMMENT_NODE: - return buf.push( ""); - case DOCUMENT_TYPE_NODE: - var pubid = node.publicId; - var sysid = node.systemId; - buf.push(''); - }else if(sysid && sysid!='.'){ - buf.push(' SYSTEM ', sysid, '>'); - }else{ - var sub = node.internalSubset; - if(sub){ - buf.push(" [",sub,"]"); + return; + case ATTRIBUTE_NODE: + return addSerializedAttribute(buf, node.name, node.value); + case TEXT_NODE: + /** + * The ampersand character (&) and the left angle bracket (<) must not appear in their literal form, + * except when used as markup delimiters, or within a comment, a processing instruction, or a CDATA section. + * If they are needed elsewhere, they must be escaped using either numeric character references or the strings + * `&` and `<` respectively. + * The right angle bracket (>) may be represented using the string " > ", and must, for compatibility, + * be escaped using either `>` or a character reference when it appears in the string `]]>` in content, + * when that string is not marking the end of a CDATA section. + * + * In the content of elements, character data is any string of characters + * which does not contain the start-delimiter of any markup + * and does not include the CDATA-section-close delimiter, `]]>`. + * + * @see https://www.w3.org/TR/xml/#NT-CharData + * @see https://w3c.github.io/DOM-Parsing/#xml-serializing-a-text-node + */ + return buf.push(node.data.replace(/[<&>]/g, _xmlEncoder)); + case CDATA_SECTION_NODE: + return buf.push(''); + case COMMENT_NODE: + return buf.push(''); + case DOCUMENT_TYPE_NODE: + var pubid = node.publicId; + var sysid = node.systemId; + buf.push(''); + } else if (sysid && sysid != '.') { + buf.push(' SYSTEM ', sysid, '>'); + } else { + var sub = node.internalSubset; + if (sub) { + buf.push(' [', sub, ']'); + } + buf.push('>'); } - buf.push(">"); - } - return; - case PROCESSING_INSTRUCTION_NODE: - return buf.push( ""); - case ENTITY_REFERENCE_NODE: - return buf.push( '&',node.nodeName,';'); - //case ENTITY_NODE: - //case NOTATION_NODE: - default: - buf.push('??',node.nodeName); + return; + case PROCESSING_INSTRUCTION_NODE: + return buf.push(''); + case ENTITY_REFERENCE_NODE: + return buf.push('&', node.nodeName, ';'); + //case ENTITY_NODE: + //case NOTATION_NODE: + default: + buf.push('??', node.nodeName); } } -function importNode(doc,node,deep){ +function importNode(doc, node, deep) { var node2; switch (node.nodeType) { - case ELEMENT_NODE: - node2 = node.cloneNode(false); - node2.ownerDocument = doc; + case ELEMENT_NODE: + node2 = node.cloneNode(false); + node2.ownerDocument = doc; //var attrs = node2.attributes; //var len = attrs.length; //for(var i=0;i', lt:'<', quot:'"'}) +exports.XML_ENTITIES = freeze({ + amp: '&', + apos: "'", + gt: '>', + lt: '<', + quot: '"', +}); /** * A map of currently 241 entities that are detected in an HTML document. @@ -25,251 +31,251 @@ exports.XML_ENTITIES = freeze({amp:'&', apos:"'", gt:'>', lt:'<', quot:'"'}) * @see https://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references#Entities_representing_special_characters_in_XHTML Wikpedia (XHTML) */ exports.HTML_ENTITIES = freeze({ - lt: '<', - gt: '>', - amp: '&', - quot: '"', - apos: "'", - Agrave: "\u00C0", - Aacute: "\u00C1", - Acirc: "\u00C2", - Atilde: "\u00C3", - Auml: "\u00C4", - Aring: "\u00C5", - AElig: "\u00C6", - Ccedil: "\u00C7", - Egrave: "\u00C8", - Eacute: "\u00C9", - Ecirc: "\u00CA", - Euml: "\u00CB", - Igrave: "\u00CC", - Iacute: "\u00CD", - Icirc: "\u00CE", - Iuml: "\u00CF", - ETH: "\u00D0", - Ntilde: "\u00D1", - Ograve: "\u00D2", - Oacute: "\u00D3", - Ocirc: "\u00D4", - Otilde: "\u00D5", - Ouml: "\u00D6", - Oslash: "\u00D8", - Ugrave: "\u00D9", - Uacute: "\u00DA", - Ucirc: "\u00DB", - Uuml: "\u00DC", - Yacute: "\u00DD", - THORN: "\u00DE", - szlig: "\u00DF", - agrave: "\u00E0", - aacute: "\u00E1", - acirc: "\u00E2", - atilde: "\u00E3", - auml: "\u00E4", - aring: "\u00E5", - aelig: "\u00E6", - ccedil: "\u00E7", - egrave: "\u00E8", - eacute: "\u00E9", - ecirc: "\u00EA", - euml: "\u00EB", - igrave: "\u00EC", - iacute: "\u00ED", - icirc: "\u00EE", - iuml: "\u00EF", - eth: "\u00F0", - ntilde: "\u00F1", - ograve: "\u00F2", - oacute: "\u00F3", - ocirc: "\u00F4", - otilde: "\u00F5", - ouml: "\u00F6", - oslash: "\u00F8", - ugrave: "\u00F9", - uacute: "\u00FA", - ucirc: "\u00FB", - uuml: "\u00FC", - yacute: "\u00FD", - thorn: "\u00FE", - yuml: "\u00FF", - nbsp: "\u00a0", - iexcl: "\u00A1", - cent: "\u00A2", - pound: "\u00A3", - curren: "\u00A4", - yen: "\u00A5", - brvbar: "\u00A6", - sect: "\u00A7", - uml: "\u00A8", - copy: "\u00A9", - ordf: "\u00AA", - laquo: "\u00AB", - not: "\u00AC", - shy: "\u00AD", - reg: "\u00AE", - macr: "\u00AF", - deg: "\u00B0", - plusmn: "\u00B1", - sup2: "\u00B2", - sup3: "\u00B3", - acute: "\u00B4", - micro: "\u00B5", - para: "\u00B6", - middot: "\u00B7", - cedil: "\u00B8", - sup1: "\u00B9", - ordm: "\u00BA", - raquo: "\u00BB", - frac14: "\u00BC", - frac12: "\u00BD", - frac34: "\u00BE", - iquest: "\u00BF", - times: "\u00D7", - divide: "\u00F7", - forall: "\u2200", - part: "\u2202", - exist: "\u2203", - empty: "\u2205", - nabla: "\u2207", - isin: "\u2208", - notin: "\u2209", - ni: "\u220B", - prod: "\u220F", - sum: "\u2211", - minus: "\u2212", - lowast: "\u2217", - radic: "\u221A", - prop: "\u221D", - infin: "\u221E", - ang: "\u2220", - and: "\u2227", - or: "\u2228", - cap: "\u2229", - cup: "\u222A", - 'int': "\u222B", - there4: "\u2234", - sim: "\u223C", - cong: "\u2245", - asymp: "\u2248", - ne: "\u2260", - equiv: "\u2261", - le: "\u2264", - ge: "\u2265", - sub: "\u2282", - sup: "\u2283", - nsub: "\u2284", - sube: "\u2286", - supe: "\u2287", - oplus: "\u2295", - otimes: "\u2297", - perp: "\u22A5", - sdot: "\u22C5", - Alpha: "\u0391", - Beta: "\u0392", - Gamma: "\u0393", - Delta: "\u0394", - Epsilon: "\u0395", - Zeta: "\u0396", - Eta: "\u0397", - Theta: "\u0398", - Iota: "\u0399", - Kappa: "\u039A", - Lambda: "\u039B", - Mu: "\u039C", - Nu: "\u039D", - Xi: "\u039E", - Omicron: "\u039F", - Pi: "\u03A0", - Rho: "\u03A1", - Sigma: "\u03A3", - Tau: "\u03A4", - Upsilon: "\u03A5", - Phi: "\u03A6", - Chi: "\u03A7", - Psi: "\u03A8", - Omega: "\u03A9", - alpha: "\u03B1", - beta: "\u03B2", - gamma: "\u03B3", - delta: "\u03B4", - epsilon: "\u03B5", - zeta: "\u03B6", - eta: "\u03B7", - theta: "\u03B8", - iota: "\u03B9", - kappa: "\u03BA", - lambda: "\u03BB", - mu: "\u03BC", - nu: "\u03BD", - xi: "\u03BE", - omicron: "\u03BF", - pi: "\u03C0", - rho: "\u03C1", - sigmaf: "\u03C2", - sigma: "\u03C3", - tau: "\u03C4", - upsilon: "\u03C5", - phi: "\u03C6", - chi: "\u03C7", - psi: "\u03C8", - omega: "\u03C9", - thetasym: "\u03D1", - upsih: "\u03D2", - piv: "\u03D6", - OElig: "\u0152", - oelig: "\u0153", - Scaron: "\u0160", - scaron: "\u0161", - Yuml: "\u0178", - fnof: "\u0192", - circ: "\u02C6", - tilde: "\u02DC", - ensp: "\u2002", - emsp: "\u2003", - thinsp: "\u2009", - zwnj: "\u200C", - zwj: "\u200D", - lrm: "\u200E", - rlm: "\u200F", - ndash: "\u2013", - mdash: "\u2014", - lsquo: "\u2018", - rsquo: "\u2019", - sbquo: "\u201A", - ldquo: "\u201C", - rdquo: "\u201D", - bdquo: "\u201E", - dagger: "\u2020", - Dagger: "\u2021", - bull: "\u2022", - hellip: "\u2026", - permil: "\u2030", - prime: "\u2032", - Prime: "\u2033", - lsaquo: "\u2039", - rsaquo: "\u203A", - oline: "\u203E", - euro: "\u20AC", - trade: "\u2122", - larr: "\u2190", - uarr: "\u2191", - rarr: "\u2192", - darr: "\u2193", - harr: "\u2194", - crarr: "\u21B5", - lceil: "\u2308", - rceil: "\u2309", - lfloor: "\u230A", - rfloor: "\u230B", - loz: "\u25CA", - spades: "\u2660", - clubs: "\u2663", - hearts: "\u2665", - diams: "\u2666" + lt: '<', + gt: '>', + amp: '&', + quot: '"', + apos: "'", + Agrave: '\u00C0', + Aacute: '\u00C1', + Acirc: '\u00C2', + Atilde: '\u00C3', + Auml: '\u00C4', + Aring: '\u00C5', + AElig: '\u00C6', + Ccedil: '\u00C7', + Egrave: '\u00C8', + Eacute: '\u00C9', + Ecirc: '\u00CA', + Euml: '\u00CB', + Igrave: '\u00CC', + Iacute: '\u00CD', + Icirc: '\u00CE', + Iuml: '\u00CF', + ETH: '\u00D0', + Ntilde: '\u00D1', + Ograve: '\u00D2', + Oacute: '\u00D3', + Ocirc: '\u00D4', + Otilde: '\u00D5', + Ouml: '\u00D6', + Oslash: '\u00D8', + Ugrave: '\u00D9', + Uacute: '\u00DA', + Ucirc: '\u00DB', + Uuml: '\u00DC', + Yacute: '\u00DD', + THORN: '\u00DE', + szlig: '\u00DF', + agrave: '\u00E0', + aacute: '\u00E1', + acirc: '\u00E2', + atilde: '\u00E3', + auml: '\u00E4', + aring: '\u00E5', + aelig: '\u00E6', + ccedil: '\u00E7', + egrave: '\u00E8', + eacute: '\u00E9', + ecirc: '\u00EA', + euml: '\u00EB', + igrave: '\u00EC', + iacute: '\u00ED', + icirc: '\u00EE', + iuml: '\u00EF', + eth: '\u00F0', + ntilde: '\u00F1', + ograve: '\u00F2', + oacute: '\u00F3', + ocirc: '\u00F4', + otilde: '\u00F5', + ouml: '\u00F6', + oslash: '\u00F8', + ugrave: '\u00F9', + uacute: '\u00FA', + ucirc: '\u00FB', + uuml: '\u00FC', + yacute: '\u00FD', + thorn: '\u00FE', + yuml: '\u00FF', + nbsp: '\u00a0', + iexcl: '\u00A1', + cent: '\u00A2', + pound: '\u00A3', + curren: '\u00A4', + yen: '\u00A5', + brvbar: '\u00A6', + sect: '\u00A7', + uml: '\u00A8', + copy: '\u00A9', + ordf: '\u00AA', + laquo: '\u00AB', + not: '\u00AC', + shy: '\u00AD', + reg: '\u00AE', + macr: '\u00AF', + deg: '\u00B0', + plusmn: '\u00B1', + sup2: '\u00B2', + sup3: '\u00B3', + acute: '\u00B4', + micro: '\u00B5', + para: '\u00B6', + middot: '\u00B7', + cedil: '\u00B8', + sup1: '\u00B9', + ordm: '\u00BA', + raquo: '\u00BB', + frac14: '\u00BC', + frac12: '\u00BD', + frac34: '\u00BE', + iquest: '\u00BF', + times: '\u00D7', + divide: '\u00F7', + forall: '\u2200', + part: '\u2202', + exist: '\u2203', + empty: '\u2205', + nabla: '\u2207', + isin: '\u2208', + notin: '\u2209', + ni: '\u220B', + prod: '\u220F', + sum: '\u2211', + minus: '\u2212', + lowast: '\u2217', + radic: '\u221A', + prop: '\u221D', + infin: '\u221E', + ang: '\u2220', + and: '\u2227', + or: '\u2228', + cap: '\u2229', + cup: '\u222A', + int: '\u222B', + there4: '\u2234', + sim: '\u223C', + cong: '\u2245', + asymp: '\u2248', + ne: '\u2260', + equiv: '\u2261', + le: '\u2264', + ge: '\u2265', + sub: '\u2282', + sup: '\u2283', + nsub: '\u2284', + sube: '\u2286', + supe: '\u2287', + oplus: '\u2295', + otimes: '\u2297', + perp: '\u22A5', + sdot: '\u22C5', + Alpha: '\u0391', + Beta: '\u0392', + Gamma: '\u0393', + Delta: '\u0394', + Epsilon: '\u0395', + Zeta: '\u0396', + Eta: '\u0397', + Theta: '\u0398', + Iota: '\u0399', + Kappa: '\u039A', + Lambda: '\u039B', + Mu: '\u039C', + Nu: '\u039D', + Xi: '\u039E', + Omicron: '\u039F', + Pi: '\u03A0', + Rho: '\u03A1', + Sigma: '\u03A3', + Tau: '\u03A4', + Upsilon: '\u03A5', + Phi: '\u03A6', + Chi: '\u03A7', + Psi: '\u03A8', + Omega: '\u03A9', + alpha: '\u03B1', + beta: '\u03B2', + gamma: '\u03B3', + delta: '\u03B4', + epsilon: '\u03B5', + zeta: '\u03B6', + eta: '\u03B7', + theta: '\u03B8', + iota: '\u03B9', + kappa: '\u03BA', + lambda: '\u03BB', + mu: '\u03BC', + nu: '\u03BD', + xi: '\u03BE', + omicron: '\u03BF', + pi: '\u03C0', + rho: '\u03C1', + sigmaf: '\u03C2', + sigma: '\u03C3', + tau: '\u03C4', + upsilon: '\u03C5', + phi: '\u03C6', + chi: '\u03C7', + psi: '\u03C8', + omega: '\u03C9', + thetasym: '\u03D1', + upsih: '\u03D2', + piv: '\u03D6', + OElig: '\u0152', + oelig: '\u0153', + Scaron: '\u0160', + scaron: '\u0161', + Yuml: '\u0178', + fnof: '\u0192', + circ: '\u02C6', + tilde: '\u02DC', + ensp: '\u2002', + emsp: '\u2003', + thinsp: '\u2009', + zwnj: '\u200C', + zwj: '\u200D', + lrm: '\u200E', + rlm: '\u200F', + ndash: '\u2013', + mdash: '\u2014', + lsquo: '\u2018', + rsquo: '\u2019', + sbquo: '\u201A', + ldquo: '\u201C', + rdquo: '\u201D', + bdquo: '\u201E', + dagger: '\u2020', + Dagger: '\u2021', + bull: '\u2022', + hellip: '\u2026', + permil: '\u2030', + prime: '\u2032', + Prime: '\u2033', + lsaquo: '\u2039', + rsaquo: '\u203A', + oline: '\u203E', + euro: '\u20AC', + trade: '\u2122', + larr: '\u2190', + uarr: '\u2191', + rarr: '\u2192', + darr: '\u2193', + harr: '\u2194', + crarr: '\u21B5', + lceil: '\u2308', + rceil: '\u2309', + lfloor: '\u230A', + rfloor: '\u230B', + loz: '\u25CA', + spades: '\u2660', + clubs: '\u2663', + hearts: '\u2665', + diams: '\u2666', }); /** * @deprecated use `HTML_ENTITIES` instead * @see HTML_ENTITIES */ -exports.entityMap = exports.HTML_ENTITIES +exports.entityMap = exports.HTML_ENTITIES; diff --git a/lib/index.js b/lib/index.js index 85be0abc9..a4a18e4d1 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,6 +1,6 @@ -'use strict' +'use strict'; -var dom = require('./dom') -exports.DOMImplementation = dom.DOMImplementation -exports.XMLSerializer = dom.XMLSerializer -exports.DOMParser = require('./dom-parser').DOMParser +var dom = require('./dom'); +exports.DOMImplementation = dom.DOMImplementation; +exports.XMLSerializer = dom.XMLSerializer; +exports.DOMParser = require('./dom-parser').DOMParser; diff --git a/lib/sax.js b/lib/sax.js index cc400a300..86a89c536 100644 --- a/lib/sax.js +++ b/lib/sax.js @@ -1,6 +1,6 @@ -'use strict' +'use strict'; -var conventions = require("./conventions"); +var conventions = require('./conventions'); var isHTMLRawTextElement = conventions.isHTMLRawTextElement; var isHTMLEscapableRawTextElement = conventions.isHTMLEscapableRawTextElement; var NAMESPACE = conventions.NAMESPACE; @@ -9,22 +9,25 @@ var MIME_TYPE = conventions.MIME_TYPE; //[4] NameStartChar ::= ":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF] //[4a] NameChar ::= NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040] //[5] Name ::= NameStartChar (NameChar)* -var nameStartChar = /[A-Z_a-z\xC0-\xD6\xD8-\xF6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]///\u10000-\uEFFFF -var nameChar = new RegExp("[\\-\\.0-9"+nameStartChar.source.slice(1,-1)+"\\u00B7\\u0300-\\u036F\\u203F-\\u2040]"); -var tagNamePattern = new RegExp('^'+nameStartChar.source+nameChar.source+'*(?:\:'+nameStartChar.source+nameChar.source+'*)?$'); +var nameStartChar = + /[A-Z_a-z\xC0-\xD6\xD8-\xF6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]/; //\u10000-\uEFFFF +var nameChar = new RegExp('[\\-\\.0-9' + nameStartChar.source.slice(1, -1) + '\\u00B7\\u0300-\\u036F\\u203F-\\u2040]'); +var tagNamePattern = new RegExp( + '^' + nameStartChar.source + nameChar.source + '*(?::' + nameStartChar.source + nameChar.source + '*)?$' +); //var tagNamePattern = /^[a-zA-Z_][\w\-\.]*(?:\:[a-zA-Z_][\w\-\.]*)?$/ //var handlers = 'resolveEntity,getExternalSubset,characters,endDocument,endElement,endPrefixMapping,ignorableWhitespace,processingInstruction,setDocumentLocator,skippedEntity,startDocument,startElement,startPrefixMapping,notationDecl,unparsedEntityDecl,error,fatalError,warning,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,comment,endCDATA,endDTD,endEntity,startCDATA,startDTD,startEntity'.split(',') //S_TAG, S_ATTR, S_EQ, S_ATTR_NOQUOT_VALUE //S_ATTR_SPACE, S_ATTR_END, S_TAG_SPACE, S_TAG_CLOSE -var S_TAG = 0;//tag name offerring -var S_ATTR = 1;//attr name offerring -var S_ATTR_SPACE=2;//attr name end and space offer -var S_EQ = 3;//=space? -var S_ATTR_NOQUOT_VALUE = 4;//attr value(no quot value only) -var S_ATTR_END = 5;//attr value end and no space(quot end) -var S_TAG_SPACE = 6;//(attr value end || tag end ) && (space offer) -var S_TAG_CLOSE = 7;//closed el +var S_TAG = 0; //tag name offerring +var S_ATTR = 1; //attr name offerring +var S_ATTR_SPACE = 2; //attr name end and space offer +var S_EQ = 3; //=space? +var S_ATTR_NOQUOT_VALUE = 4; //attr value(no quot value only) +var S_ATTR_END = 5; //attr value end and no space(quot end) +var S_TAG_SPACE = 6; //(attr value end || tag end ) && (space offer) +var S_TAG_CLOSE = 7; //closed el /** * Creates an error that will not be caught by XMLReader aka the SAX parser. @@ -34,201 +37,191 @@ var S_TAG_CLOSE = 7;//closed el * @constructor */ function ParseError(message, locator) { - this.message = message - this.locator = locator - if(Error.captureStackTrace) Error.captureStackTrace(this, ParseError); + this.message = message; + this.locator = locator; + if (Error.captureStackTrace) Error.captureStackTrace(this, ParseError); } ParseError.prototype = new Error(); -ParseError.prototype.name = ParseError.name +ParseError.prototype.name = ParseError.name; -function XMLReader(){ - -} +function XMLReader() {} XMLReader.prototype = { - parse:function(source,defaultNSMap,entityMap){ + parse: function (source, defaultNSMap, entityMap) { var domBuilder = this.domBuilder; domBuilder.startDocument(); - _copy(defaultNSMap ,defaultNSMap = {}) - parse(source,defaultNSMap,entityMap, - domBuilder,this.errorHandler); + _copy(defaultNSMap, (defaultNSMap = {})); + parse(source, defaultNSMap, entityMap, domBuilder, this.errorHandler); domBuilder.endDocument(); - } -} -function parse(source,defaultNSMapCopy,entityMap,domBuilder,errorHandler){ + }, +}; +function parse(source, defaultNSMapCopy, entityMap, domBuilder, errorHandler) { var isHTML = MIME_TYPE.isHTML(domBuilder.mimeType); function fixedFromCharCode(code) { // String.prototype.fromCharCode does not supports // > 2 bytes unicode chars directly if (code > 0xffff) { code -= 0x10000; - var surrogate1 = 0xd800 + (code >> 10) - , surrogate2 = 0xdc00 + (code & 0x3ff); + var surrogate1 = 0xd800 + (code >> 10), + surrogate2 = 0xdc00 + (code & 0x3ff); return String.fromCharCode(surrogate1, surrogate2); } else { return String.fromCharCode(code); } } - function entityReplacer(a){ - var k = a.slice(1,-1); + function entityReplacer(a) { + var k = a.slice(1, -1); if (Object.hasOwnProperty.call(entityMap, k)) { return entityMap[k]; - }else if(k.charAt(0) === '#'){ - return fixedFromCharCode(parseInt(k.substr(1).replace('x','0x'))) - }else{ - errorHandler.error('entity not found:'+a); + } else if (k.charAt(0) === '#') { + return fixedFromCharCode(parseInt(k.substr(1).replace('x', '0x'))); + } else { + errorHandler.error('entity not found:' + a); return a; } } - function appendText(end){//has some bugs - if(end>start){ - var xt = source.substring(start,end).replace(/&#?\w+;/g,entityReplacer); - locator&&position(start); - domBuilder.characters(xt,0,end-start); - start = end + function appendText(end) { + //has some bugs + if (end > start) { + var xt = source.substring(start, end).replace(/&#?\w+;/g, entityReplacer); + locator && position(start); + domBuilder.characters(xt, 0, end - start); + start = end; } } - function position(p,m){ - while(p>=lineEnd && (m = linePattern.exec(source))){ + function position(p, m) { + while (p >= lineEnd && (m = linePattern.exec(source))) { lineStart = m.index; lineEnd = lineStart + m[0].length; locator.lineNumber++; - //console.log('line++:',locator,startPos,endPos) } - locator.columnNumber = p-lineStart+1; + locator.columnNumber = p - lineStart + 1; } var lineStart = 0; var lineEnd = 0; - var linePattern = /.*(?:\r\n?|\n)|.*$/g + var linePattern = /.*(?:\r\n?|\n)|.*$/g; var locator = domBuilder.locator; - var parseStack = [{currentNSMap:defaultNSMapCopy}] + var parseStack = [{ currentNSMap: defaultNSMapCopy }]; var closeMap = {}; var start = 0; - while(true){ - try{ - var tagStart = source.indexOf('<',start); - if(tagStart<0){ - if(!source.substr(start).match(/^\s*$/)){ + while (true) { + try { + var tagStart = source.indexOf('<', start); + if (tagStart < 0) { + if (!source.substr(start).match(/^\s*$/)) { var doc = domBuilder.doc; - var text = doc.createTextNode(source.substr(start)); - doc.appendChild(text); - domBuilder.currentElement = text; + var text = doc.createTextNode(source.substr(start)); + doc.appendChild(text); + domBuilder.currentElement = text; } return; } - if(tagStart>start){ + if (tagStart > start) { appendText(tagStart); } - switch(source.charAt(tagStart+1)){ + switch (source.charAt(tagStart + 1)) { case '/': - var config = parseStack.pop(); - var end = source.indexOf(">", tagStart + 3); - var tagNameRaw = source.substring(tagStart + 2, end > 0 ? end : undefined); - var tagNameMatch = new RegExp("(" + tagNamePattern.source.slice(0, -1) + ")").exec(tagNameRaw); - // for the root level the config does not contain the tagName - var tagName = tagNameMatch && tagNameMatch[1] ? tagNameMatch[1] : (config.tagName || domBuilder.doc.documentElement.tagName); - if (end < 0) { - errorHandler.error("end tag name: " + tagName + " is not complete"); - end = tagStart + 1 + tagName.length; - } else if (tagNameRaw.match(/', tagStart + 3); + var tagNameRaw = source.substring(tagStart + 2, end > 0 ? end : undefined); + var tagNameMatch = new RegExp('(' + tagNamePattern.source.slice(0, -1) + ')').exec(tagNameRaw); + // for the root level the config does not contain the tagName + var tagName = + tagNameMatch && tagNameMatch[1] ? tagNameMatch[1] : config.tagName || domBuilder.doc.documentElement.tagName; + if (end < 0) { + errorHandler.error('end tag name: ' + tagName + ' is not complete'); + end = tagStart + 1 + tagName.length; + } else if (tagNameRaw.match(/ - locator&&position(tagStart); - end = parseInstruction(source,tagStart,domBuilder); - break; - case '!':// + locator && position(tagStart); + end = parseInstruction(source, tagStart, domBuilder); + break; + case '!': // start){ + if (end > start) { start = end; - }else{ + } else { //TODO: 这里有可能sax回退,有位置错误风险 - appendText(Math.max(tagStart,start)+1); + appendText(Math.max(tagStart, start) + 1); } } } -function copyLocator(f,t){ +function copyLocator(f, t) { t.lineNumber = f.lineNumber; t.columnNumber = f.columnNumber; return t; @@ -238,10 +231,7 @@ function copyLocator(f,t){ * @see #appendElement(source,elStartEnd,el,selfClosed,entityReplacer,domBuilder,parseStack); * @return end of the elementStartPart(end of elementEndPart for selfClosed el) */ -function parseElementStartPart( - source,start,el,currentNSMap,entityReplacer,errorHandler, isHTML -){ - +function parseElementStartPart(source, start, el, currentNSMap, entityReplacer, errorHandler, isHTML) { /** * @param {string} qname * @param {string} value @@ -249,7 +239,7 @@ function parseElementStartPart( */ function addAttribute(qname, value, startIndex) { if (el.attributeNames.hasOwnProperty(qname)) { - errorHandler.fatalError('Attribute ' + qname + ' redefined') + errorHandler.fatalError('Attribute ' + qname + ' redefined'); } el.addValue( qname, @@ -259,172 +249,178 @@ function parseElementStartPart( // - trimming and collapsing multiple spaces into a single one for attributes that are not of type CDATA value.replace(/[\t\n\r]/g, ' ').replace(/&#?\w+;/g, entityReplacer), startIndex - ) + ); } var attrName; var value; var p = ++start; - var s = S_TAG;//status - while(true){ + var s = S_TAG; //status + while (true) { var c = source.charAt(p); - switch(c){ - case '=': - if(s === S_ATTR){//attrName - attrName = source.slice(start,p); - s = S_EQ; - }else if(s === S_ATTR_SPACE){ - s = S_EQ; - }else{ - //fatalError: equal must after attrName or space after attrName - throw new Error('attribute equal must after attrName'); // No known test case - } - break; - case '\'': - case '"': - if(s === S_EQ || s === S_ATTR //|| s == S_ATTR_SPACE - ){//equal - if(s === S_ATTR){ - errorHandler.warning('attribute value must after "="') - attrName = source.slice(start,p) + switch (c) { + case '=': + if (s === S_ATTR) { + //attrName + attrName = source.slice(start, p); + s = S_EQ; + } else if (s === S_ATTR_SPACE) { + s = S_EQ; + } else { + //fatalError: equal must after attrName or space after attrName + throw new Error('attribute equal must after attrName'); // No known test case } - start = p+1; - p = source.indexOf(c,start) - if(p>0){ + break; + case "'": + case '"': + if ( + s === S_EQ || + s === S_ATTR //|| s == S_ATTR_SPACE + ) { + //equal + if (s === S_ATTR) { + errorHandler.warning('attribute value must after "="'); + attrName = source.slice(start, p); + } + start = p + 1; + p = source.indexOf(c, start); + if (p > 0) { + value = source.slice(start, p); + addAttribute(attrName, value, start - 1); + s = S_ATTR_END; + } else { + //fatalError: no end quot match + throw new Error("attribute value no end '" + c + "' match"); + } + } else if (s == S_ATTR_NOQUOT_VALUE) { value = source.slice(start, p); - addAttribute(attrName, value, start-1); + addAttribute(attrName, value, start); + errorHandler.warning('attribute "' + attrName + '" missed start quot(' + c + ')!!'); + start = p + 1; s = S_ATTR_END; - }else{ - //fatalError: no end quot match - throw new Error('attribute value no end \''+c+'\' match'); + } else { + //fatalError: no equal before + throw new Error('attribute value must after "="'); // No known test case } - }else if(s == S_ATTR_NOQUOT_VALUE){ - value = source.slice(start, p); - addAttribute(attrName, value, start); - errorHandler.warning('attribute "'+attrName+'" missed start quot('+c+')!!'); - start = p+1; - s = S_ATTR_END - }else{ - //fatalError: no equal before - throw new Error('attribute value must after "="'); // No known test case - } - break; - case '/': - switch(s){ - case S_TAG: - el.setTagName(source.slice(start,p)); - case S_ATTR_END: - case S_TAG_SPACE: - case S_TAG_CLOSE: - s =S_TAG_CLOSE; - el.closed = true; - case S_ATTR_NOQUOT_VALUE: - case S_ATTR: - case S_ATTR_SPACE: break; - //case S_EQ: - default: - throw new Error("attribute invalid close char('/')") // No known test case - } - break; - case ''://end document - errorHandler.error('unexpected end of input'); - if(s == S_TAG){ - el.setTagName(source.slice(start,p)); - } - return p; - case '>': - switch(s){ - case S_TAG: - el.setTagName(source.slice(start,p)); - case S_ATTR_END: - case S_TAG_SPACE: - case S_TAG_CLOSE: - break;//normal - case S_ATTR_NOQUOT_VALUE://Compatible state - case S_ATTR: - value = source.slice(start,p); - if(value.slice(-1) === '/'){ - el.closed = true; - value = value.slice(0,-1) - } - case S_ATTR_SPACE: - if(s === S_ATTR_SPACE){ - value = attrName; - } - if(s == S_ATTR_NOQUOT_VALUE){ - errorHandler.warning('attribute "'+value+'" missed quot(")!'); - addAttribute(attrName, value, start) - }else{ - if(!isHTML){ - errorHandler.warning('attribute "'+value+'" missed value!! "'+value+'" instead!!') - } - addAttribute(value, value, start) + case '/': + switch (s) { + case S_TAG: + el.setTagName(source.slice(start, p)); + case S_ATTR_END: + case S_TAG_SPACE: + case S_TAG_CLOSE: + s = S_TAG_CLOSE; + el.closed = true; + case S_ATTR_NOQUOT_VALUE: + case S_ATTR: + case S_ATTR_SPACE: + break; + //case S_EQ: + default: + throw new Error("attribute invalid close char('/')"); // No known test case } break; - case S_EQ: - throw new Error('attribute value missed!!'); - } -// console.log(tagName,tagNamePattern,tagNamePattern.test(tagName)) - return p; - /*xml space '\x20' | #x9 | #xD | #xA; */ - case '\u0080': - c = ' '; - default: - if(c<= ' '){//space - switch(s){ - case S_TAG: - el.setTagName(source.slice(start,p));//tagName - s = S_TAG_SPACE; - break; - case S_ATTR: - attrName = source.slice(start,p) - s = S_ATTR_SPACE; - break; - case S_ATTR_NOQUOT_VALUE: - var value = source.slice(start, p); - errorHandler.warning('attribute "'+value+'" missed quot(")!!'); - addAttribute(attrName, value, start) - case S_ATTR_END: - s = S_TAG_SPACE; - break; - //case S_TAG_SPACE: - //case S_EQ: - //case S_ATTR_SPACE: - // void();break; - //case S_TAG_CLOSE: - //ignore warning + case '': //end document + errorHandler.error('unexpected end of input'); + if (s == S_TAG) { + el.setTagName(source.slice(start, p)); } - }else{//not space -//S_TAG, S_ATTR, S_EQ, S_ATTR_NOQUOT_VALUE -//S_ATTR_SPACE, S_ATTR_END, S_TAG_SPACE, S_TAG_CLOSE - switch(s){ - //case S_TAG:void();break; - //case S_ATTR:void();break; - //case S_ATTR_NOQUOT_VALUE:void();break; - case S_ATTR_SPACE: - var tagName = el.tagName; - if (!isHTML) { - errorHandler.warning('attribute "'+attrName+'" missed value!! "'+attrName+'" instead2!!') + return p; + case '>': + switch (s) { + case S_TAG: + el.setTagName(source.slice(start, p)); + case S_ATTR_END: + case S_TAG_SPACE: + case S_TAG_CLOSE: + break; //normal + case S_ATTR_NOQUOT_VALUE: //Compatible state + case S_ATTR: + value = source.slice(start, p); + if (value.slice(-1) === '/') { + el.closed = true; + value = value.slice(0, -1); + } + case S_ATTR_SPACE: + if (s === S_ATTR_SPACE) { + value = attrName; + } + if (s == S_ATTR_NOQUOT_VALUE) { + errorHandler.warning('attribute "' + value + '" missed quot(")!'); + addAttribute(attrName, value, start); + } else { + if (!isHTML) { + errorHandler.warning('attribute "' + value + '" missed value!! "' + value + '" instead!!'); + } + addAttribute(value, value, start); + } + break; + case S_EQ: + throw new Error('attribute value missed!!'); + } + // console.log(tagName,tagNamePattern,tagNamePattern.test(tagName)) + return p; + /*xml space '\x20' | #x9 | #xD | #xA; */ + case '\u0080': + c = ' '; + default: + if (c <= ' ') { + //space + switch (s) { + case S_TAG: + el.setTagName(source.slice(start, p)); //tagName + s = S_TAG_SPACE; + break; + case S_ATTR: + attrName = source.slice(start, p); + s = S_ATTR_SPACE; + break; + case S_ATTR_NOQUOT_VALUE: + var value = source.slice(start, p); + errorHandler.warning('attribute "' + value + '" missed quot(")!!'); + addAttribute(attrName, value, start); + case S_ATTR_END: + s = S_TAG_SPACE; + break; + //case S_TAG_SPACE: + //case S_EQ: + //case S_ATTR_SPACE: + // void();break; + //case S_TAG_CLOSE: + //ignore warning + } + } else { + //not space + //S_TAG, S_ATTR, S_EQ, S_ATTR_NOQUOT_VALUE + //S_ATTR_SPACE, S_ATTR_END, S_TAG_SPACE, S_TAG_CLOSE + switch (s) { + //case S_TAG:void();break; + //case S_ATTR:void();break; + //case S_ATTR_NOQUOT_VALUE:void();break; + case S_ATTR_SPACE: + var tagName = el.tagName; + if (!isHTML) { + errorHandler.warning('attribute "' + attrName + '" missed value!! "' + attrName + '" instead2!!'); + } + addAttribute(attrName, attrName, start); + start = p; + s = S_ATTR; + break; + case S_ATTR_END: + errorHandler.warning('attribute space is required"' + attrName + '"!!'); + case S_TAG_SPACE: + s = S_ATTR; + start = p; + break; + case S_EQ: + s = S_ATTR_NOQUOT_VALUE; + start = p; + break; + case S_TAG_CLOSE: + throw new Error("elements closed character '/' and '>' must be connected to"); } - addAttribute(attrName, attrName, start); - start = p; - s = S_ATTR; - break; - case S_ATTR_END: - errorHandler.warning('attribute space is required"'+attrName+'"!!') - case S_TAG_SPACE: - s = S_ATTR; - start = p; - break; - case S_EQ: - s = S_ATTR_NOQUOT_VALUE; - start = p; - break; - case S_TAG_CLOSE: - throw new Error("elements closed character '/' and '>' must be connected to"); } - } - }//end outer switch + } //end outer switch //console.log('p++',p) p++; } @@ -432,115 +428,119 @@ function parseElementStartPart( /** * @return true if has new namespace define */ -function appendElement(el,domBuilder,currentNSMap){ +function appendElement(el, domBuilder, currentNSMap) { var tagName = el.tagName; var localNSMap = null; //var currentNSMap = parseStack[parseStack.length-1].currentNSMap; var i = el.length; - while(i--){ + while (i--) { var a = el[i]; var qName = a.qName; var value = a.value; var nsp = qName.indexOf(':'); - if(nsp>0){ - var prefix = a.prefix = qName.slice(0,nsp); - var localName = qName.slice(nsp+1); - var nsPrefix = prefix === 'xmlns' && localName - }else{ + if (nsp > 0) { + var prefix = (a.prefix = qName.slice(0, nsp)); + var localName = qName.slice(nsp + 1); + var nsPrefix = prefix === 'xmlns' && localName; + } else { localName = qName; - prefix = null - nsPrefix = qName === 'xmlns' && '' + prefix = null; + nsPrefix = qName === 'xmlns' && ''; } //can not set prefix,because prefix !== '' - a.localName = localName ; + a.localName = localName; //prefix == null for no ns prefix attribute - if(nsPrefix !== false){//hack!! - if(localNSMap == null){ - localNSMap = {} + if (nsPrefix !== false) { + //hack!! + if (localNSMap == null) { + localNSMap = {}; //console.log(currentNSMap,0) - _copy(currentNSMap,currentNSMap={}) + _copy(currentNSMap, (currentNSMap = {})); //console.log(currentNSMap,1) } currentNSMap[nsPrefix] = localNSMap[nsPrefix] = value; - a.uri = NAMESPACE.XMLNS - domBuilder.startPrefixMapping(nsPrefix, value) + a.uri = NAMESPACE.XMLNS; + domBuilder.startPrefixMapping(nsPrefix, value); } } var i = el.length; - while(i--){ + while (i--) { a = el[i]; var prefix = a.prefix; - if(prefix){//no prefix attribute has no namespace - if(prefix === 'xml'){ + if (prefix) { + //no prefix attribute has no namespace + if (prefix === 'xml') { a.uri = NAMESPACE.XML; - }if(prefix !== 'xmlns'){ - a.uri = currentNSMap[prefix || ''] + } + if (prefix !== 'xmlns') { + a.uri = currentNSMap[prefix || '']; } } } var nsp = tagName.indexOf(':'); - if(nsp>0){ - prefix = el.prefix = tagName.slice(0,nsp); - localName = el.localName = tagName.slice(nsp+1); - }else{ - prefix = null;//important!! + if (nsp > 0) { + prefix = el.prefix = tagName.slice(0, nsp); + localName = el.localName = tagName.slice(nsp + 1); + } else { + prefix = null; //important!! localName = el.localName = tagName; } //no prefix element has default namespace - var ns = el.uri = currentNSMap[prefix || '']; - domBuilder.startElement(ns,localName,tagName,el); + var ns = (el.uri = currentNSMap[prefix || '']); + domBuilder.startElement(ns, localName, tagName, el); //endPrefixMapping and startPrefixMapping have not any help for dom builder //localNSMap = null - if(el.closed){ - domBuilder.endElement(ns,localName,tagName); - if(localNSMap){ + if (el.closed) { + domBuilder.endElement(ns, localName, tagName); + if (localNSMap) { for (prefix in localNSMap) { if (Object.prototype.hasOwnProperty.call(localNSMap, prefix)) { domBuilder.endPrefixMapping(prefix); } } } - }else{ + } else { el.currentNSMap = currentNSMap; el.localNSMap = localNSMap; //parseStack.push(el); return true; } } -function parseHtmlSpecialContent(source,elStartEnd,tagName,entityReplacer,domBuilder){ +function parseHtmlSpecialContent(source, elStartEnd, tagName, entityReplacer, domBuilder) { // https://html.spec.whatwg.org/#raw-text-elements // https://html.spec.whatwg.org/#escapable-raw-text-elements // https://html.spec.whatwg.org/#cdata-rcdata-restrictions:raw-text-elements // TODO: https://html.spec.whatwg.org/#cdata-rcdata-restrictions var isEscapableRaw = isHTMLEscapableRawTextElement(tagName); - if(isEscapableRaw || isHTMLRawTextElement(tagName)){ - var elEndStart = source.indexOf('',elStartEnd); - var text = source.substring(elStartEnd+1,elEndStart); + if (isEscapableRaw || isHTMLRawTextElement(tagName)) { + var elEndStart = source.indexOf('', elStartEnd); + var text = source.substring(elStartEnd + 1, elEndStart); - if(isEscapableRaw){ - text = text.replace(/&#?\w+;/g,entityReplacer); + if (isEscapableRaw) { + text = text.replace(/&#?\w+;/g, entityReplacer); } - domBuilder.characters(text,0,text.length); - return elEndStart; + domBuilder.characters(text, 0, text.length); + return elEndStart; } - return elStartEnd+1; + return elStartEnd + 1; } -function fixSelfClosed(source,elStartEnd,tagName,closeMap){ +function fixSelfClosed(source, elStartEnd, tagName, closeMap) { //if(tagName in closeMap){ var pos = closeMap[tagName]; - if(pos == null){ + if (pos == null) { //console.log(tagName) - pos = source.lastIndexOf('') - if(pos'); + if (pos < elStartEnd) { + //忘记闭合 + pos = source.lastIndexOf('',start+4); - //append comment source.substring(4,end)//', start + 4); + //append comment source.substring(4,end)//\n` + - '\n' + - ' something\n' + - 'x', + `${instruction} + + something +x`, 'text/xml' - ) + ); expect(dom).toMatchObject({ firstChild: { @@ -83,33 +83,33 @@ describe('DOMLocator', () => { columnNumber: 5, }, }, - }) - }) + }); + }); it('attribute position', () => { // TODO: xml not well formed but no warning or error, extract into different test? - const xml = '<;test' + const xml = '
<;test'; const { errors, parser } = getTestParser({ locator: { systemId: 'c:/test/1.xml' }, - }) + }); - const doc = parser.parseFromString(xml, 'text/html') + const doc = parser.parseFromString(xml, 'text/html'); - expect({ actual: doc.toString(), ...errors }).toMatchSnapshot() + expect({ actual: doc.toString(), ...errors }).toMatchSnapshot(); - const attr = doc.documentElement.firstChild.attributes.item(0) + const attr = doc.documentElement.firstChild.attributes.item(0); expect(attr).toMatchObject({ lineNumber: 1, columnNumber: 19, // position of the starting quote - }) - }) + }); + }); it('logs error positions', () => { - const { errors, parser } = getTestParser() + const { errors, parser } = getTestParser(); - parser.parseFromString('\n\t', 'text/html') + parser.parseFromString('\n\t', 'text/html'); - expect(errors).toMatchSnapshot() - }) -}) + expect(errors).toMatchSnapshot(); + }); +}); diff --git a/test/parse/namespace.test.js b/test/parse/namespace.test.js index 20f2b5f2a..6568cfbdd 100644 --- a/test/parse/namespace.test.js +++ b/test/parse/namespace.test.js @@ -1,20 +1,20 @@ -'use strict' +'use strict'; -const { DOMParser } = require('../../lib') +const { DOMParser } = require('../../lib'); /** * Returns an array containing only one occurrence of every sting in `values` (like in a Set). * * @param values {string} */ -const uniqArray = (...values) => [...new Set(values)] +const uniqArray = (...values) => [...new Set(values)]; describe('XML Namespace Parse', () => { it('default namespace', () => { const { documentElement } = new DOMParser().parseFromString( '', 'text/xml' - ) + ); expect( uniqArray( @@ -23,18 +23,16 @@ describe('XML Namespace Parse', () => { documentElement.firstChild.namespaceURI, documentElement.firstChild.lookupNamespaceURI('') ) - ).toMatchObject(['http://test.com']) - expect( - documentElement.firstChild.getAttributeNode('attr').namespaceURI - ).toBeUndefined() - }) + ).toMatchObject(['http://test.com']); + expect(documentElement.firstChild.getAttributeNode('attr').namespaceURI).toBeUndefined(); + }); it('prefix namespace', () => { const { documentElement } = new DOMParser().parseFromString( '', 'text/xml' - ) - const firstChild = documentElement.firstChild + ); + const firstChild = documentElement.firstChild; expect( uniqArray( @@ -42,30 +40,21 @@ describe('XML Namespace Parse', () => { firstChild.namespaceURI, firstChild.getAttributeNode('p1:attr').namespaceURI ) - ).toMatchObject(['http://p1.com']) - expect( - uniqArray( - firstChild.nextSibling.namespaceURI, - firstChild.nextSibling.lookupNamespaceURI('p2') - ) - ).toMatchObject(['http://p2.com']) - expect(firstChild.getAttributeNode('attr')).toBeUndefined() - }) + ).toMatchObject(['http://p1.com']); + expect(uniqArray(firstChild.nextSibling.namespaceURI, firstChild.nextSibling.lookupNamespaceURI('p2'))).toMatchObject([ + 'http://p2.com', + ]); + expect(firstChild.getAttributeNode('attr')).toBeUndefined(); + }); it('after prefix namespace', () => { const { documentElement } = new DOMParser().parseFromString( '', 'text/xml' - ) + ); - expect(documentElement.firstChild.namespaceURI).toStrictEqual( - 'http://p.com' - ) - expect(documentElement.lastChild.namespaceURI).toStrictEqual( - 'http://test.com' - ) - expect( - documentElement.firstChild.nextSibling.lookupNamespaceURI('p') - ).toStrictEqual('http://test.com') - }) -}) + expect(documentElement.firstChild.namespaceURI).toStrictEqual('http://p.com'); + expect(documentElement.lastChild.namespaceURI).toStrictEqual('http://test.com'); + expect(documentElement.firstChild.nextSibling.lookupNamespaceURI('p')).toStrictEqual('http://test.com'); + }); +}); diff --git a/test/parse/node.test.js b/test/parse/node.test.js index 1e70997cf..d2e41f8b9 100644 --- a/test/parse/node.test.js +++ b/test/parse/node.test.js @@ -1,26 +1,24 @@ -'use strict' +'use strict'; -const { Node } = require('../../lib/dom') -const { DOMParser } = require('../../lib') +const { Node } = require('../../lib/dom'); +const { DOMParser } = require('../../lib'); const expectNeighbours = (first, second, ...nodes) => { - expect(first.nextSibling).toStrictEqual(second) - expect(second.previousSibling).toStrictEqual(first) - expect(first.parentNode).toStrictEqual(second.parentNode) + expect(first.nextSibling).toStrictEqual(second); + expect(second.previousSibling).toStrictEqual(first); + expect(first.parentNode).toStrictEqual(second.parentNode); if (nodes.length > 0) { - expectNeighbours(second, ...nodes) + expectNeighbours(second, ...nodes); } -} +}; describe('XML Node Parse', () => { it('element', () => { - const dom = new DOMParser().parseFromString('') + const dom = new DOMParser().parseFromString(''); - expect(dom.documentElement.nodeType).toStrictEqual(Node.ELEMENT_NODE) - expect(dom.documentElement.firstChild.nodeType).toStrictEqual( - Node.ELEMENT_NODE - ) + expect(dom.documentElement.nodeType).toStrictEqual(Node.ELEMENT_NODE); + expect(dom.documentElement.firstChild.nodeType).toStrictEqual(Node.ELEMENT_NODE); expect(dom).toMatchObject({ childNodes: { length: 1, @@ -36,25 +34,23 @@ describe('XML Node Parse', () => { nodeName: 'xml', tagName: 'xml', }, - }) - }) + }); + }); it('text', () => { - const { firstChild } = new DOMParser().parseFromString( - 'start center end' - ).documentElement + const { firstChild } = new DOMParser().parseFromString('start center end').documentElement; - expect(firstChild.nodeType).toStrictEqual(Node.TEXT_NODE) + expect(firstChild.nodeType).toStrictEqual(Node.TEXT_NODE); expect(firstChild).toMatchObject({ data: 'start center end', nextSibling: null, - }) - }) + }); + }); it('cdata', () => { const { documentElement } = new DOMParser().parseFromString( 'start ]]> end' - ) + ); expect(documentElement.firstChild).toMatchObject({ data: 'start ', nextSibling: { @@ -65,32 +61,26 @@ describe('XML Node Parse', () => { }, }, }, - }) - }) + }); + }); it('cdata empty', () => { - const { documentElement } = new DOMParser().parseFromString( - 'start end' - ) + const { documentElement } = new DOMParser().parseFromString('start end'); expect(documentElement).toMatchObject({ textContent: 'start end', - }) - }) + }); + }); it('comment', () => { - const { documentElement } = new DOMParser().parseFromString( - '' - ) + const { documentElement } = new DOMParser().parseFromString(''); expect(documentElement.firstChild).toMatchObject({ nodeValue: ' comment&>< ', - }) - }) + }); + }); it('cdata comment', () => { - const { documentElement } = new DOMParser().parseFromString( - 'start ]]> end' - ) + const { documentElement } = new DOMParser().parseFromString('start ]]> end'); expect(documentElement.firstChild).toMatchObject({ nodeName: '#text', // 0 @@ -111,98 +101,89 @@ describe('XML Node Parse', () => { }, }, }, - }) - }) + }); + }); describe('appendChild', () => { it('returns the argument', () => { - const dom = new DOMParser().parseFromString('') + const dom = new DOMParser().parseFromString(''); - const child = dom.createElement('child') + const child = dom.createElement('child'); - expect(dom.documentElement.appendChild(child)).toStrictEqual(child) - }) + expect(dom.documentElement.appendChild(child)).toStrictEqual(child); + }); it('appends as firstChild', () => { - const dom = new DOMParser().parseFromString('') - const child = dom.createElement('child') + const dom = new DOMParser().parseFromString(''); + const child = dom.createElement('child'); - dom.documentElement.appendChild(child) + dom.documentElement.appendChild(child); - expect(dom.documentElement.firstChild).toStrictEqual(child) - }) + expect(dom.documentElement.firstChild).toStrictEqual(child); + }); it('subsequent calls append in order', () => { - const dom = new DOMParser().parseFromString('') - const fragment = dom.createDocumentFragment() + const dom = new DOMParser().parseFromString(''); + const fragment = dom.createDocumentFragment(); - expect(fragment.nodeType).toStrictEqual(Node.DOCUMENT_FRAGMENT_NODE) + expect(fragment.nodeType).toStrictEqual(Node.DOCUMENT_FRAGMENT_NODE); - const first = fragment.appendChild(dom.createElement('first')) - const last = fragment.appendChild(dom.createElement('last')) + const first = fragment.appendChild(dom.createElement('first')); + const last = fragment.appendChild(dom.createElement('last')); - expectNeighbours(first, last) - expect(fragment.firstChild).toStrictEqual(first) - expect(fragment.lastChild).toStrictEqual(last) - }) - }) + expectNeighbours(first, last); + expect(fragment.firstChild).toStrictEqual(first); + expect(fragment.lastChild).toStrictEqual(last); + }); + }); describe('insertBefore', () => { it('places created element before existing element', () => { - const dom = new DOMParser().parseFromString('') - const inserted = dom.createElement('sibling') - const child = dom.documentElement.firstChild + const dom = new DOMParser().parseFromString(''); + const inserted = dom.createElement('sibling'); + const child = dom.documentElement.firstChild; - child.parentNode.insertBefore(inserted, child) + child.parentNode.insertBefore(inserted, child); - expectNeighbours(inserted, child) - }) + expectNeighbours(inserted, child); + }); it('inserts all elements in DocumentFragment', () => { - const dom = new DOMParser().parseFromString('') - const child = dom.documentElement.firstChild + const dom = new DOMParser().parseFromString(''); + const child = dom.documentElement.firstChild; - const fragment = dom.createDocumentFragment() - const first = fragment.appendChild(dom.createElement('first')) - const second = fragment.appendChild(dom.createElement('second')) + const fragment = dom.createDocumentFragment(); + const first = fragment.appendChild(dom.createElement('first')); + const second = fragment.appendChild(dom.createElement('second')); - child.parentNode.insertBefore(fragment, child) + child.parentNode.insertBefore(fragment, child); - expectNeighbours(first, second, child) - expect(child.parentNode.firstChild).toStrictEqual(first) - }) - }) + expectNeighbours(first, second, child); + expect(child.parentNode.firstChild).toStrictEqual(first); + }); + }); it('preserves instruction', () => { - const source = - '&' + const source = '&'; - const actual = new DOMParser() - .parseFromString(source, 'text/xml') - .toString() + const actual = new DOMParser().parseFromString(source, 'text/xml').toString(); - expect(actual).toStrictEqual(source) - }) + expect(actual).toStrictEqual(source); + }); it('preserves doctype with public id and sysid', () => { const DOCTYPE = '' + ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'; - const actual = new DOMParser() - .parseFromString(`${DOCTYPE}`, 'text/html') - .toString() + const actual = new DOMParser().parseFromString(`${DOCTYPE}`, 'text/html').toString(); - expect(actual).toStrictEqual( - `${DOCTYPE}` - ) - }) + expect(actual).toStrictEqual(`${DOCTYPE}`); + }); it('preserves doctype with sysid', () => { - const DOCTYPE = '' + const DOCTYPE = ''; - const actual = new DOMParser() - .parseFromString(`${DOCTYPE}`, 'text/xml') - .toString() + const actual = new DOMParser().parseFromString(`${DOCTYPE}`, 'text/xml').toString(); - expect(actual).toStrictEqual(`${DOCTYPE}`) - }) -}) + expect(actual).toStrictEqual(`${DOCTYPE}`); + }); +}); diff --git a/test/parse/normalize-line-endings.test.js b/test/parse/normalize-line-endings.test.js index b4668b6fb..fbe77df1f 100644 --- a/test/parse/normalize-line-endings.test.js +++ b/test/parse/normalize-line-endings.test.js @@ -1,54 +1,48 @@ -'use strict' +'use strict'; -const { DOMParser, normalizeLineEndings } = require('../../lib/dom-parser') -const { MIME_TYPE } = require('../../lib/conventions') -const whitespaceToHex = (str) => - str.replace(/\s/g, (c) => `#x${c.charCodeAt(0).toString(16)}`) +const { DOMParser, normalizeLineEndings } = require('../../lib/dom-parser'); +const { MIME_TYPE } = require('../../lib/conventions'); +const whitespaceToHex = (str) => str.replace(/\s/g, (c) => `#x${c.charCodeAt(0).toString(16)}`); describe('DOMParser constructor option normalizeLineEndings', () => { it('should apply the exported function by default', () => { - const parser = new DOMParser() - const actual = parser.parseFromString( - '\r\n \r \u0085', - MIME_TYPE.XML_TEXT - ) + const parser = new DOMParser(); + const actual = parser.parseFromString('\r\n \r \u0085', MIME_TYPE.XML_TEXT); - expect(whitespaceToHex(actual.firstChild.nodeValue)).toBe( - '#xa#x20#xa#x20#xa' - ) - }) + expect(whitespaceToHex(actual.firstChild.nodeValue)).toBe('#xa#x20#xa#x20#xa'); + }); it('should use the provided normalizeLineEndings option', () => { - const mockNormalize = jest.fn(() => '') + const mockNormalize = jest.fn(() => ''); const actual = new DOMParser({ normalizeLineEndings: mockNormalize, - }).parseFromString('', MIME_TYPE.XML_TEXT) + }).parseFromString('', MIME_TYPE.XML_TEXT); - expect(mockNormalize).toHaveBeenCalled() - expect(actual.documentElement.tagName).toBe('replacement') - }) -}) + expect(mockNormalize).toHaveBeenCalled(); + expect(actual.documentElement.tagName).toBe('replacement'); + }); +}); describe('normalizeLineEndings', () => { it('should normalize the two-character sequence #xD #xA (aka "\\r\\n")', () => { - expect(whitespaceToHex(normalizeLineEndings('\r\n'))).toBe('#xa') - expect(whitespaceToHex(normalizeLineEndings('\x0D\x0A'))).toBe('#xa') - }) + expect(whitespaceToHex(normalizeLineEndings('\r\n'))).toBe('#xa'); + expect(whitespaceToHex(normalizeLineEndings('\x0D\x0A'))).toBe('#xa'); + }); it('should normalize the two-character sequence #xD #x85', () => { - expect(whitespaceToHex(normalizeLineEndings('\r\u0085'))).toBe('#xa') - }) + expect(whitespaceToHex(normalizeLineEndings('\r\u0085'))).toBe('#xa'); + }); it('should normalize the single character #x85', () => { - expect(whitespaceToHex(normalizeLineEndings('\u0085'))).toBe('#xa') - }) + expect(whitespaceToHex(normalizeLineEndings('\u0085'))).toBe('#xa'); + }); it('should normalize the single character #x2028', () => { - expect(whitespaceToHex(normalizeLineEndings('\u2028'))).toBe('#xa') - }) + expect(whitespaceToHex(normalizeLineEndings('\u2028'))).toBe('#xa'); + }); it('should normalize any #xD character that is not immediately followed by #xA or #x85', () => { - expect(whitespaceToHex(normalizeLineEndings('\r \n'))).toBe('#xa#x20#xa') - expect(whitespaceToHex(normalizeLineEndings(' \r\r'))).toBe('#x20#xa#xa') - }) -}) + expect(whitespaceToHex(normalizeLineEndings('\r \n'))).toBe('#xa#x20#xa'); + expect(whitespaceToHex(normalizeLineEndings(' \r\r'))).toBe('#x20#xa#xa'); + }); +}); diff --git a/test/parse/parse-element.test.js b/test/parse/parse-element.test.js index bc99f273e..b416ebf29 100644 --- a/test/parse/parse-element.test.js +++ b/test/parse/parse-element.test.js @@ -1,21 +1,16 @@ -'use strict' +'use strict'; -const { getTestParser } = require('../get-test-parser') -const { DOMParser } = require('../../lib') -const { MIME_TYPE } = require('../../lib/conventions') +const { getTestParser } = require('../get-test-parser'); +const { DOMParser } = require('../../lib'); +const { MIME_TYPE } = require('../../lib/conventions'); describe('XML Node Parse', () => { describe('no attribute', () => { - it.each(['', '', '', ''])( - '%s', - (input) => { - const actual = new DOMParser() - .parseFromString(input, 'text/xml') - .toString() - expect(actual).toBe('') - } - ) - }) + it.each(['', '', '', ''])('%s', (input) => { + const actual = new DOMParser().parseFromString(input, 'text/xml').toString(); + expect(actual).toBe(''); + }); + }); it('nested closing tag with whitespace', () => { const actual = new DOMParser() .parseFromString( @@ -29,64 +24,52 @@ describe('XML Node Parse', () => { `, 'text/xml' ) - .toString() + .toString(); expect(actual).toBe(` Giada De Laurentiis Everyday Italian -`) - }) +`); + }); it('sibling closing tag with whitespace', () => { - const actual = new DOMParser() - .parseFromString(`Harry Potter`, 'text/xml') - .toString() - expect(actual).toBe(`Harry Potter`) - }) + const actual = new DOMParser().parseFromString(`Harry Potter`, 'text/xml').toString(); + expect(actual).toBe(`Harry Potter`); + }); describe('simple attributes', () => { describe('nothing special', () => { - it.each([ - '', - '', - '', - ])('%s', (input) => { - const actual = new DOMParser() - .parseFromString(input, 'text/xml') - .toString() - - expect(actual).toBe('') - }) - }) + it.each(['', '', ''])('%s', (input) => { + const actual = new DOMParser().parseFromString(input, 'text/xml').toString(); + + expect(actual).toBe(''); + }); + }); describe('empty b', () => { - it.each([ - '', - '', - '', - '', - ])('%s', (input) => { - expect( - new DOMParser().parseFromString(input, 'text/xml').toString() - ).toBe('') - }) - }) + it.each(['', '', '', ''])( + '%s', + (input) => { + expect(new DOMParser().parseFromString(input, 'text/xml').toString()).toBe(''); + } + ); + }); // https://www.w3.org/TR/xml/#AVNormalize describe('containing whitespace', () => { it('should transform whitespace literals into spaces', () => { - const { parser } = getTestParser() + const { parser } = getTestParser(); const dom = parser.parseFromString( // `\r\n` would be replaced by `\n` due to https://www.w3.org/TR/xml/#sec-line-ends '', MIME_TYPE.XML_TEXT - ) + ); - const attr = dom.documentElement.attributes.getNamedItem('attr') + const attr = dom.documentElement.attributes.getNamedItem('attr'); - expect(attr.value).toBe(' ') - }) + expect(attr.value).toBe(' '); + }); it.each([ [' ', '\t'], @@ -99,51 +82,39 @@ describe('XML Node Parse', () => { [' ', '\r'], [' ', ' '], [' ', ' '], - ])( - 'should transform whitespace character reference %s to literal', - (reference, literal) => { - const { parser } = getTestParser() - const dom = parser.parseFromString( - ``, - MIME_TYPE.XML_TEXT - ) - - const attr = dom.documentElement.attributes.getNamedItem('attr') - expect(attr.value).toBe(literal) - } - ) - }) + ])('should transform whitespace character reference %s to literal', (reference, literal) => { + const { parser } = getTestParser(); + const dom = parser.parseFromString(``, MIME_TYPE.XML_TEXT); + + const attr = dom.documentElement.attributes.getNamedItem('attr'); + expect(attr.value).toBe(literal); + }); + }); it('unclosed root tag will be closed', () => { - const { errors, parser } = getTestParser() + const { errors, parser } = getTestParser(); - const actual = parser - .parseFromString('', 'text/xml') - .toString() + const actual = parser.parseFromString('', 'text/xml').toString(); - expect({ actual, ...errors }).toMatchSnapshot() - }) + expect({ actual, ...errors }).toMatchSnapshot(); + }); it('should be able to have `constructor` attribute', () => { - const { errors, parser } = getTestParser() + const { errors, parser } = getTestParser(); - const actual = parser - .parseFromString('', 'text/xml') - .toString() + const actual = parser.parseFromString('', 'text/xml').toString(); - expect({ actual, ...errors }).toMatchSnapshot() - }) + expect({ actual, ...errors }).toMatchSnapshot(); + }); it('should be able to have `__prototype__` attribute', () => { - const { errors, parser } = getTestParser() + const { errors, parser } = getTestParser(); - const actual = parser - .parseFromString('', 'text/xml') - .toString() + const actual = parser.parseFromString('', 'text/xml').toString(); - expect({ actual, ...errors }).toMatchSnapshot() - }) - }) + expect({ actual, ...errors }).toMatchSnapshot(); + }); + }); describe('namespaced attributes', () => { it.each([ @@ -151,21 +122,17 @@ describe('XML Node Parse', () => { '', '', ])('%s', (input) => { - const actual = new DOMParser() - .parseFromString(input, 'text/xml') - .toString() + const actual = new DOMParser().parseFromString(input, 'text/xml').toString(); - expect(actual).toBe('') - }) + expect(actual).toBe(''); + }); it('unclosed root tag will be closed', () => { - const { errors, parser } = getTestParser() + const { errors, parser } = getTestParser(); - const actual = parser - .parseFromString('', 'text/xml') - .toString() + const actual = parser.parseFromString('', 'text/xml').toString(); - expect({ actual, ...errors }).toMatchSnapshot() - }) - }) -}) + expect({ actual, ...errors }).toMatchSnapshot(); + }); + }); +}); diff --git a/test/parse/parse-error.test.js b/test/parse/parse-error.test.js index 4b10cd7cc..f779169b4 100644 --- a/test/parse/parse-error.test.js +++ b/test/parse/parse-error.test.js @@ -1,38 +1,38 @@ -'use strict' -const { ParseError } = require('../../lib/sax') +'use strict'; +const { ParseError } = require('../../lib/sax'); describe('ParseError', () => { it('should have name ParseError', () => { - expect(new ParseError('').name).toBe('ParseError') - }) + expect(new ParseError('').name).toBe('ParseError'); + }); it('should be an instance of Error', () => { - expect(new ParseError('') instanceof Error).toBe(true) - }) + expect(new ParseError('') instanceof Error).toBe(true); + }); it('should be an instance of ParseError', () => { - expect(new ParseError('') instanceof ParseError).toBe(true) - }) + expect(new ParseError('') instanceof ParseError).toBe(true); + }); it('should store first argument as message', () => { - const error = new ParseError('FROM TEST') - expect(error.message).toBe('FROM TEST') - }) + const error = new ParseError('FROM TEST'); + expect(error.message).toBe('FROM TEST'); + }); it('should store second argument as locator', () => { - const locator = {} - const error = new ParseError('', locator) - expect(error.locator).toBe(locator) - }) + const locator = {}; + const error = new ParseError('', locator); + expect(error.locator).toBe(locator); + }); it('should have correct StackTrace', () => { - const error = new ParseError('MESSAGE') - const stack = error.stack && error.stack.split(/[\n\r]+/) - expect(stack && stack.length).toBeGreaterThan(1) - expect(stack[0]).toBe('ParseError: MESSAGE') - expect(stack[1]).toContain(__filename) - }) + const error = new ParseError('MESSAGE'); + const stack = error.stack && error.stack.split(/[\n\r]+/); + expect(stack && stack.length).toBeGreaterThan(1); + expect(stack[0]).toBe('ParseError: MESSAGE'); + expect(stack[1]).toContain(__filename); + }); it('Error should not be instanceof ParseError', () => { - expect(new Error() instanceof ParseError).toBe(false) - }) -}) + expect(new Error() instanceof ParseError).toBe(false); + }); +}); diff --git a/test/parse/simple.test.js b/test/parse/simple.test.js index 68cd06e5f..1b5b3bc7d 100644 --- a/test/parse/simple.test.js +++ b/test/parse/simple.test.js @@ -1,50 +1,39 @@ -'use strict' +'use strict'; -const { getTestParser } = require('../get-test-parser') +const { getTestParser } = require('../get-test-parser'); describe('parse', () => { it('simple', () => { - const { errors, parser } = getTestParser() + const { errors, parser } = getTestParser(); - const actual = parser - .parseFromString('', 'text/html') - .toString() + const actual = parser.parseFromString('', 'text/html').toString(); - expect({ actual, ...errors }).toMatchSnapshot() - }) + expect({ actual, ...errors }).toMatchSnapshot(); + }); it('unclosed inner', () => { - const { errors, parser } = getTestParser() + const { errors, parser } = getTestParser(); - const actual = parser - .parseFromString( - '', - 'text/xml' - ) - .toString() + const actual = parser.parseFromString('', 'text/xml').toString(); - expect({ actual, ...errors }).toMatchSnapshot() - }) + expect({ actual, ...errors }).toMatchSnapshot(); + }); it('unclosed root', () => { - const { errors, parser } = getTestParser() + const { errors, parser } = getTestParser(); - const actual = parser - .parseFromString('
<;test', 'text/html' ) - .toString() + .toString(); - expect({ actual, ...errors }).toMatchSnapshot() - }) + expect({ actual, ...errors }).toMatchSnapshot(); + }); describe('invalid input', () => { it.each([ @@ -104,21 +93,19 @@ describe('parse', () => { ['number', 12345], ['null', null], ])('%s', (msg, testValue) => { - const { parser } = getTestParser(rethrowErrorHandler()) + const { parser } = getTestParser(rethrowErrorHandler()); - expect(() => parser.parseFromString(testValue)).toThrow( - /^\[xmldom error\][\s]*invalid doc source[\s\S]*$/ - ) - }) - }) -}) + expect(() => parser.parseFromString(testValue)).toThrow(/^\[xmldom error\][\s]*invalid doc source[\s\S]*$/); + }); + }); +}); function rethrowErrorHandler() { return { errorHandler: { error: function (errorMessage) { - throw errorMessage + throw errorMessage; }, }, - } + }; } diff --git a/test/parse/test-doc-whitespace.test.js b/test/parse/test-doc-whitespace.test.js index 13c1d434e..82b9f006f 100644 --- a/test/parse/test-doc-whitespace.test.js +++ b/test/parse/test-doc-whitespace.test.js @@ -1,31 +1,31 @@ -'use strict' +'use strict'; -const { getTestParser } = require('../get-test-parser') +const { getTestParser } = require('../get-test-parser'); describe('errorHandle', () => { it('unclosed tag', () => { - const { errors, parser } = getTestParser() + const { errors, parser } = getTestParser(); - const actual = parser.parseFromString(' { - const testSource = '\n\n' - const { errors, parser } = getTestParser() + const testSource = '\n\n'; + const { errors, parser } = getTestParser(); - const actual = parser.parseFromString(testSource, 'text/xml').toString() + const actual = parser.parseFromString(testSource, 'text/xml').toString(); - expect({ actual, ...errors }).toMatchSnapshot() - }) + expect({ actual, ...errors }).toMatchSnapshot(); + }); it('should encode < literal when not part of a tag', () => { - const description = '

populaciji (< 0.1%), te se

' - const { errors, parser } = getTestParser() + const description = '

populaciji (< 0.1%), te se

'; + const { errors, parser } = getTestParser(); - const actual = parser.parseFromString(description, 'text/html').toString() + const actual = parser.parseFromString(description, 'text/html').toString(); - expect({ actual, ...errors }).toMatchSnapshot() - }) -}) + expect({ actual, ...errors }).toMatchSnapshot(); + }); +}); diff --git a/test/parse/unclosedcomment.test.js b/test/parse/unclosedcomment.test.js index 89be99101..35c044fd2 100644 --- a/test/parse/unclosedcomment.test.js +++ b/test/parse/unclosedcomment.test.js @@ -1,13 +1,13 @@ -'use strict' +'use strict'; -const { getTestParser } = require('../get-test-parser') +const { getTestParser } = require('../get-test-parser'); describe('errorHandle', () => { it('unclosedcomment', () => { - const { errors, parser } = getTestParser() + const { errors, parser } = getTestParser(); - const actual = parser.parseFromString('