pax_global_header00006660000000000000000000000064143314321120014504gustar00rootroot0000000000000052 comment=238b1ea8431fae8817812c68d55b4933248af07e xmldom-0.8.6/000077500000000000000000000000001433143211200130175ustar00rootroot00000000000000xmldom-0.8.6/.editorconfig000066400000000000000000000002161433143211200154730ustar00rootroot00000000000000# http://EditorConfig.org root = true [*.js] charset = utf-8 indent_style = tab indent_size = 2 end_of_line = lf insert_final_newline = true xmldom-0.8.6/.eslintrc.yml000066400000000000000000000005511433143211200154440ustar00rootroot00000000000000env: browser: true commonjs: true es2020: true node: true plugins: - es5 # FUTURE TBD: # extends: 'eslint:recommended' parserOptions: ecmaVersion: 11 rules: # FUTURE TBD: # indent: # - error # - tab linebreak-style: - error - unix # FUTURE TBD: # quotes: # - error # - single # semi: # - error # - always xmldom-0.8.6/.github/000077500000000000000000000000001433143211200143575ustar00rootroot00000000000000xmldom-0.8.6/.github/workflows/000077500000000000000000000000001433143211200164145ustar00rootroot00000000000000xmldom-0.8.6/.github/workflows/examples.yml000066400000000000000000000026001433143211200207530ustar00rootroot00000000000000# This workflow will run the examples provided in the examples folder name: examples on: push: branches: [ master ] pull_request: branches: [ master ] jobs: nodejs: runs-on: ubuntu-latest strategy: matrix: node-version: - 10.x - 12.x - 14.x - 16.x steps: - uses: actions/checkout@v3 - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} - run: npm install working-directory: examples/nodejs - run: npm run test working-directory: examples/nodejs typescript-node-es6: runs-on: ubuntu-latest strategy: matrix: ts-version: - 3.8 - 4 node-version: - 10 - 12 - 14 - 16 steps: - uses: actions/checkout@v3 - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} - run: ./pretest.sh ${{ matrix.ts-version }} working-directory: examples/typescript-node-es6 - run: node --experimental-modules dist/index.js if: ${{ matrix.node-version == 12 }} working-directory: examples/typescript-node-es6 - run: node dist/index.js if: ${{ matrix.node-version > 12 }} working-directory: examples/typescript-node-es6 xmldom-0.8.6/.github/workflows/stryker.yml000066400000000000000000000021301433143211200206360ustar00rootroot00000000000000# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions name: run Stryker - Node.js CI on: push: branches: [ master ] pull_request: branches: [ master ] jobs: build: runs-on: ubuntu-latest strategy: matrix: node-version: [14.x] steps: - uses: actions/checkout@v3 - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} - run: npm ci - if: ${{ github.event_name == 'pull_request' }} # on pr branches we only do a dry-run that doesn't mutate anything but checks the configuration works run: npm run stryker:dry-run - if: ${{ github.event_name == 'push' }} # on the default branch we run the full suite wich takes > 1 hour to run run: npm run stryker env: STRYKER_DASHBOARD_API_KEY: ${{ secrets.STRYKER_DASHBOARD_API_KEY }} xmldom-0.8.6/.github/workflows/test-node.js.yml000066400000000000000000000021071433143211200214540ustar00rootroot00000000000000# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions name: Node.js CI on: push: branches: [ master ] pull_request: branches: [ master ] jobs: test: runs-on: ubuntu-latest strategy: matrix: node-version: - 10.x - 12.x - 14.x - 16.x steps: - uses: actions/checkout@v3 - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} - run: npm ci --no-audit - run: npm run test lint: runs-on: ubuntu-latest strategy: matrix: node-version: - 14.x steps: - uses: actions/checkout@v3 - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} - run: npm ci --no-audit - run: npm run lint xmldom-0.8.6/.gitignore000066400000000000000000000001411433143211200150030ustar00rootroot00000000000000# stryker temp files /.stryker-tmp /node_modules /reports /test/error/reported.json docs/*.jar xmldom-0.8.6/.npmrc000066400000000000000000000006251433143211200141420ustar00rootroot00000000000000# make sure to publish the scoped package as a public one # https://docs.npmjs.com/cli/v6/using-npm/config#access access=public # we do not apply a prefix to our version tags # https://docs.npmjs.com/cli/v6/using-npm/config#tag-version-prefix tag-version-prefix="" # pin versions when installing, to avoid extra PR by renovate # https://docs.npmjs.com/cli/v6/using-npm/config#save-exact save-exact=true xmldom-0.8.6/.prettierrc.yaml000066400000000000000000000000541433143211200161430ustar00rootroot00000000000000useTabs: true semi: false singleQuote: true xmldom-0.8.6/CHANGELOG.md000066400000000000000000000505251433143211200146370ustar00rootroot00000000000000# Changelog All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [0.8.6](https://github.com/xmldom/xmldom/compare/0.8.5...0.8.6) ### Fixed - Properly check nodes before replacement [`#457`](https://github.com/xmldom/xmldom/pull/457) / [`#455`](https://github.com/xmldom/xmldom/issues/455) / [`#456`](https://github.com/xmldom/xmldom/issues/456) Thank you, [@edemaine](https://github.com/edemaine), [@pedro-l9](https://github.com/pedro-l9), for your contributions ## [0.8.5](https://github.com/xmldom/xmldom/compare/0.8.4...0.8.5) ### Fixed - fix: Restore ES5 compatibility [`#452`](https://github.com/xmldom/xmldom/pull/452) / [`#453`](https://github.com/xmldom/xmldom/issues/453) Thank you, [@fengxinming](https://github.com/fengxinming), for your contributions ## [0.8.4](https://github.com/xmldom/xmldom/compare/0.8.3...0.8.4) ### Fixed - Security: Prevent inserting DOM nodes when they are not well-formed [`CVE-2022-39353`](https://github.com/xmldom/xmldom/security/advisories/GHSA-crh6-fp67-6883) In case such a DOM would be created, the part that is not well-formed will be transformed into text nodes, in which xml specific characters like `<` and `>` are encoded accordingly. In the upcoming version 0.9.0 those text nodes will no longer be added and an error will be thrown instead. This change can break your code, if you relied on this behavior, e.g. multiple root elements in the past. We consider it more important to align with the specs that we want to be aligned with, considering the potential security issues that might derive from people not being aware of the difference in behavior. Related Spec: Thank you, [@frumioj](https://github.com/frumioj), [@cjbarth](https://github.com/cjbarth), [@markgollnick](https://github.com/markgollnick) for your contributions ## [0.8.3](https://github.com/xmldom/xmldom/compare/0.8.3...0.8.2) ### Fixed - Avoid iterating over prototype properties [`#437`](https://github.com/xmldom/xmldom/pull/437) / [`#436`](https://github.com/xmldom/xmldom/issues/436) Thank you, [@Supraja9726](https://github.com/Supraja9726) for your contributions ## [0.8.2](https://github.com/xmldom/xmldom/compare/0.8.1...0.8.2) ### Fixed - fix(dom): Serialize `>` as specified (#395) [`#58`](https://github.com/xmldom/xmldom/issues/58) ### Other - docs: Add `nodeType` values to public interface description [`#396`](https://github.com/xmldom/xmldom/pull/396) - test: Add executable examples for node and typescript [`#317`](https://github.com/xmldom/xmldom/pull/317) - fix(dom): Serialize `>` as specified [`#395`](https://github.com/xmldom/xmldom/pull/395) - chore: Add minimal `Object.assign` ponyfill [`#379`](https://github.com/xmldom/xmldom/pull/379) - docs: Refine release documentation [`#378`](https://github.com/xmldom/xmldom/pull/378) - chore: update various dev dependencies Thank you [@niklasl](https://github.com/niklasl), [@cburatto](https://github.com/cburatto), [@SheetJSDev](https://github.com/SheetJSDev), [@pyrsmk](https://github.com/pyrsmk) for your contributions ## [0.8.1](https://github.com/xmldom/xmldom/compare/0.8.0...0.8.1) ### Fixes - Only use own properties in entityMap [`#374`](https://github.com/xmldom/xmldom/pull/374) ### Docs - Add security policy [`#365`](https://github.com/xmldom/xmldom/pull/365) - changelog: Correct contributor name and link [`#366`](https://github.com/xmldom/xmldom/pull/366) - Describe release/publish steps [`#358`](https://github.com/xmldom/xmldom/pull/358), [`#376`](https://github.com/xmldom/xmldom/pull/376) - Add snyk package health badge [`#360`](https://github.com/xmldom/xmldom/pull/360) ## [0.8.0](https://github.com/xmldom/xmldom/compare/0.7.5...0.8.0) ### Fixed - Normalize all line endings according to XML specs [1.0](https://w3.org/TR/xml/#sec-line-ends) and [1.1](https://www.w3.org/TR/xml11/#sec-line-ends) \ BREAKING CHANGE: Certain combination of line break characters are normalized to a single `\n` before parsing takes place and will no longer be preserved. - [`#303`](https://github.com/xmldom/xmldom/issues/303) / [`#307`](https://github.com/xmldom/xmldom/pull/307) - [`#49`](https://github.com/xmldom/xmldom/issues/49), [`#97`](https://github.com/xmldom/xmldom/issues/97), [`#324`](https://github.com/xmldom/xmldom/issues/324) / [`#314`](https://github.com/xmldom/xmldom/pull/314) - XMLSerializer: Preserve whitespace character references [`#284`](https://github.com/xmldom/xmldom/issues/284) / [`#310`](https://github.com/xmldom/xmldom/pull/310) \ BREAKING CHANGE: If you relied on the not spec compliant preservation of literal `\t`, `\n` or `\r` in **attribute values**. To preserve those you will have to create XML that instead contains the correct numerical (or hexadecimal) equivalent (e.g. ` `, ` `, ` `). - Drop deprecated exports `DOMImplementation` and `XMLSerializer` from `lib/dom-parser.js` [#53](https://github.com/xmldom/xmldom/issues/53) / [`#309`](https://github.com/xmldom/xmldom/pull/309) BREAKING CHANGE: Use the one provided by the main package export. - dom: Remove all links as part of `removeChild` [`#343`](https://github.com/xmldom/xmldom/issues/343) / [`#355`](https://github.com/xmldom/xmldom/pull/355) ### Chore - ci: Restore latest tested node version to 16.x [`#325`](https://github.com/xmldom/xmldom/pull/325) - ci: Split test and lint steps into jobs [`#111`](https://github.com/xmldom/xmldom/issues/111) / [`#304`](https://github.com/xmldom/xmldom/pull/304) - Pinned and updated devDependencies Thank you [@marrus-sh](https://github.com/marrus-sh), [@victorandree](https://github.com/victorandree), [@mdierolf](https://github.com/mdierolf), [@tsabbay](https://github.com/tsabbay), [@fatihpense](https://github.com/fatihpense) for your contributions ## 0.7.5 [Commits](https://github.com/xmldom/xmldom/compare/0.7.4...0.7.5) ### Fixes: - Preserve default namespace when serializing [`#319`](https://github.com/xmldom/xmldom/issues/319) / [`#321`](https://github.com/xmldom/xmldom/pull/321) Thank you, [@lupestro](https://github.com/lupestro) ## 0.7.4 [Commits](https://github.com/xmldom/xmldom/compare/0.7.3...0.7.4) ### Fixes: - Restore ability to parse `__prototype__` attributes [`#315`](https://github.com/xmldom/xmldom/pull/315) Thank you, [@dsimpsonOMF](https://github.com/dsimpsonOMF) ## 0.7.3 [Commits](https://github.com/xmldom/xmldom/compare/0.7.2...0.7.3) ### Fixes: - Add doctype when parsing from string [`#277`](https://github.com/xmldom/xmldom/issues/277) / [`#301`](https://github.com/xmldom/xmldom/pull/301) - Correct typo in error message [`#294`](https://github.com/xmldom/xmldom/pull/294) Thank you, [@rrthomas](https://github.com/rrthomas) ### Refactor: - Improve exports & require statements, new main package entry [`#233`](https://github.com/xmldom/xmldom/pull/233) ### Docs: - Fix Stryker badge [`#298`](https://github.com/xmldom/xmldom/pull/298) - Fix link to help-wanted issues [`#299`](https://github.com/xmldom/xmldom/pull/299) ### Chore: - Execute stryker:dry-run on branches [`#302`](https://github.com/xmldom/xmldom/pull/302) - Fix stryker config [`#300`](https://github.com/xmldom/xmldom/pull/300) - Split test and lint scripts [`#297`](https://github.com/xmldom/xmldom/pull/297) - Switch to stryker dashboard owned by org [`#292`](https://github.com/xmldom/xmldom/pull/292) ## 0.7.2 [Commits](https://github.com/xmldom/xmldom/compare/0.7.1...0.7.2) ### Fixes: - Types: Add index.d.ts to packaged files [`#288`](https://github.com/xmldom/xmldom/pull/288) Thank you, [@forty](https://github.com/forty) ## 0.7.1 [Commits](https://github.com/xmldom/xmldom/compare/0.7.0...0.7.1) ### Fixes: - Types: Copy types from DefinitelyTyped [`#283`](https://github.com/xmldom/xmldom/pull/283) Thank you, [@kachkaev](https://github.com/kachkaev) ### Chore: - package.json: remove author, maintainers, etc. [`#279`](https://github.com/xmldom/xmldom/pull/279) ## 0.7.0 [Commits](https://github.com/xmldom/xmldom/compare/0.6.0...0.7.0) Due to [`#271`](https://github.com/xmldom/xmldom/issue/271) this version was published as - unscoped `xmldom` package to github (git tags [`0.7.0`](https://github.com/xmldom/xmldom/tree/0.7.0) and [`0.7.0+unscoped`](https://github.com/xmldom/xmldom/tree/0.7.0%2Bunscoped)) - scoped `@xmldom/xmldom` package to npm (git tag `0.7.0+scoped`) For more details look at [`#278`](https://github.com/xmldom/xmldom/pull/278#issuecomment-902172483) ### Fixes: - Security: Misinterpretation of malicious XML input [`CVE-2021-32796`](https://github.com/xmldom/xmldom/security/advisories/GHSA-5fg8-2547-mr8q) - Implement `Document.getElementsByClassName` as specified [`#213`](https://github.com/xmldom/xmldom/pull/213), thank you, [@ChALkeR](https://github.com/ChALkeR) - Inherit namespace prefix from parent when required [`#268`](https://github.com/xmldom/xmldom/pull/268) - Handle whitespace in closing tags [`#267`](https://github.com/xmldom/xmldom/pull/267) - Update `DOMImplementation` according to recent specs [`#210`](https://github.com/xmldom/xmldom/pull/210) BREAKING CHANGE: Only if you "passed features to be marked as available as a constructor arguments" and expected it to "magically work". - No longer serializes any namespaces with an empty URI [`#244`](https://github.com/xmldom/xmldom/pull/244) (related to [`#168`](https://github.com/xmldom/xmldom/pull/168) released in 0.6.0) BREAKING CHANGE: Only if you rely on ["unsetting" a namespace prefix](https://github.com/xmldom/xmldom/pull/168#issuecomment-886984994) by setting it to an empty string - Set `localName` as part of `Document.createElement` [`#229`](https://github.com/xmldom/xmldom/pull/229), thank you, [@rrthomas](https://github.com/rrthomas) ### CI - We are now additionally running tests against node v16 - Stryker tests on the master branch now run against node v14 ### Docs - Describe relations with and between specs: [`#211`](https://github.com/xmldom/xmldom/pull/211), [`#247`](https://github.com/xmldom/xmldom/pull/247) ## 0.6.0 [Commits](https://github.com/xmldom/xmldom/compare/0.5.0...0.6.0) ### Fixes - Stop serializing empty namespace values like `xmlns:ds=""` [`#168`](https://github.com/xmldom/xmldom/pull/168) BREAKING CHANGE: If your code expected empty namespaces attributes to be serialized. Thank you, [@pdecat](https://github.com/pdecat) and [@FranckDepoortere](https://github.com/FranckDepoortere) - Escape `<` to `<` when serializing attribute values [`#198`](https://github.com/xmldom/xmldom/issues/198) / [`#199`](https://github.com/xmldom/xmldom/pull/199) ## 0.5.0 [Commits](https://github.com/xmldom/xmldom/compare/0.4.0...0.5.0) ### Fixes - Avoid misinterpretation of malicious XML input - [`GHSA-h6q6-9hqw-rwfv`](https://github.com/xmldom/xmldom/security/advisories/GHSA-h6q6-9hqw-rwfv) (CVE-2021-21366) - Improve error reporting; throw on duplicate attribute\ BREAKING CHANGE: It is currently not clear how to consistently deal with duplicate attributes, so it's also safer for our users to fail when detecting them. It's possible to configure the `DOMParser.errorHandler` before parsing, to handle those errors differently. To accomplish this and also be able to verify it in tests I needed to - create a new `Error` type `ParseError` and export it - Throw `ParseError` from `errorHandler.fatalError` and prevent those from being caught in `XMLReader`. - export `DOMHandler` constructor as `__DOMHandler` - Preserve quotes in DOCTYPE declaration Since the only purpose of parsing the DOCTYPE is to be able to restore it when serializing, we decided that it would be best to leave the parsed `publicId` and `systemId` as is, including any quotes. BREAKING CHANGE: If somebody relies on the actual unquoted values of those ids, they will need to take care of either single or double quotes and the right escaping. (Without this change this would not have been possible because the SAX parser already dropped the information about the quotes that have been used in the source.) https://www.w3.org/TR/2006/REC-xml11-20060816/#dtd https://www.w3.org/TR/2006/REC-xml11-20060816/#IDAX1KS (External Entity Declaration) - Fix breaking preprocessors' directives when parsing attributes [`#171`](https://github.com/xmldom/xmldom/pull/171) - fix(dom): Escape `]]>` when serializing CharData [`#181`](https://github.com/xmldom/xmldom/pull/181) - Switch to (only) MIT license (drop problematic LGPL license option) [`#178`](https://github.com/xmldom/xmldom/pull/178) - Export DOMException; remove custom assertions; etc. [`#174`](https://github.com/xmldom/xmldom/pull/174) ### Docs - Update MDN links in `readme.md` [`#188`](https://github.com/xmldom/xmldom/pull/188) ## 0.4.0 [Commits](https://github.com/xmldom/xmldom/compare/0.3.0...0.4.0) ### Fixes - **BREAKING** Restore ` ` behavior from v0.1.27 [`#67`](https://github.com/xmldom/xmldom/pull/67) - **BREAKING** Typecheck source param before parsing [`#113`](https://github.com/xmldom/xmldom/pull/113) - Include documents in package files list [`#156`](https://github.com/xmldom/xmldom/pull/156) - Preserve doctype with sysid [`#144`](https://github.com/xmldom/xmldom/pull/144) - Remove ES6 syntax from getElementsByClassName [`#91`](https://github.com/xmldom/xmldom/pull/91) - Revert "Add lowercase of åäö in entityMap" due to duplicate entries [`#84`](https://github.com/xmldom/xmldom/pull/84) - fix: Convert all line separators to LF [`#66`](https://github.com/xmldom/xmldom/pull/66) ### Docs - Update CHANGELOG.md through version 0.3.0 [`#63`](https://github.com/xmldom/xmldom/pull/63) - Update badges [`#78`](https://github.com/xmldom/xmldom/pull/78) - Add .editorconfig file [`#104`](https://github.com/xmldom/xmldom/pull/104) - Add note about import [`#79`](https://github.com/xmldom/xmldom/pull/79) - Modernize & improve the example in readme.md [`#81`](https://github.com/xmldom/xmldom/pull/81) ### CI - Add Stryker Mutator [`#70`](https://github.com/xmldom/xmldom/pull/70) - Add Stryker action to update dashboard [`#77`](https://github.com/xmldom/xmldom/pull/77) - Add Node GitHub action workflow [`#64`](https://github.com/xmldom/xmldom/pull/64) - add & enable eslint [`#106`](https://github.com/xmldom/xmldom/pull/106) - Use eslint-plugin-es5 to enforce ES5 syntax [`#107`](https://github.com/xmldom/xmldom/pull/107) - Recover `vows` tests, drop `proof` tests [`#59`](https://github.com/xmldom/xmldom/pull/59) - Add jest tessuite and first tests [`#114`](https://github.com/xmldom/xmldom/pull/114) - Add jest testsuite with `xmltest` cases [`#112`](https://github.com/xmldom/xmldom/pull/112) - Configure Renovate [`#108`](https://github.com/xmldom/xmldom/pull/108) - Test European HTML entities [`#86`](https://github.com/xmldom/xmldom/pull/86) - Updated devDependencies ### Other - Remove files that are not of any use [`#131`](https://github.com/xmldom/xmldom/pull/131), [`#65`](https://github.com/xmldom/xmldom/pull/65), [`#33`](https://github.com/xmldom/xmldom/pull/33) ## 0.3.0 [Commits](https://github.com/xmldom/xmldom/compare/0.2.1...0.3.0) - **BREAKING** Node >=10.x is now required. - **BREAKING** Remove `component.json` (deprecated package manager https://github.com/componentjs/guide) - **BREAKING** Move existing sources into `lib` subdirectory. - **POSSIBLY BREAKING** Introduce `files` entry in `package.json` and remove use of `.npmignore`. - [Add `Document.getElementsByClassName`](https://github.com/xmldom/xmldom/issues/24). - [Add `Node` to the list of exports](https://github.com/xmldom/xmldom/pull/27) - [Add lowercase of åäö in `entityMap`](https://github.com/xmldom/xmldom/pull/23). - Move CHANGELOG to markdown file. - Move LICENSE to markdown file. ## 0.2.1 [Commits](https://github.com/xmldom/xmldom/compare/0.2.0...0.2.1) - Correct `homepage`, `repository` and `bugs` URLs in `package.json`. ## 0.2.0 [Commits](https://github.com/xmldom/xmldom/compare/v0.1.27...0.2.0) - Includes all **BREAKING** changes introduced in [`xmldom-alpha@v0.1.28`](#0128) by the original authors. - **POSSIBLY BREAKING** [remove the `Object.create` check from the `_extends` method of `dom.js` that added a `__proto__` property](https://github.com/xmldom/xmldom/commit/0be2ae910a8a22c9ec2cac042e04de4c04317d2a#diff-7d1c5d97786fdf9af5446a241d0b6d56L19-L22) (). - **POSSIBLY BREAKING** [remove code that added a `__proto__` property](https://github.com/xmldom/xmldom/commit/366159a76a181ce9a0d83f5dc48205686cfaf9cc) - formatting/corrections in `package.json` ## 0.1.31 [Commits](https://github.com/xmldom/xmldom/compare/v0.1.27...v0.1.31) The patch versions (`v0.1.29` - `v0.1.31`) that have been released on the [v0.1.x branch](https://github.com/xmldom/xmldom/tree/0.1.x), to reflect the changed maintainers, **are branched off from [`v0.1.27`](#0127) so they don't include the breaking changes introduced in [`xmldom-alpha@v0.1.28`](#0128)**: ## Maintainer changes After the last commit to the original repository on the 9th of May 2017, the first commit to is from the 19th of December 2019. [The fork has been announced in the original repository on the 2nd of March 2020.](https://github.com/jindw/xmldom/issues/259) The versions listed below have been published to one or both of the following packages: - - It is currently not planned to continue publishing the `xmldom-alpha` package. The new maintainers did not invest time to understand changes that led to the last `xmldom` version [`0.1.27`](#0127) published by the original maintainer, but consider it the basis for their work. A timeline of all the changes that happened from that version until `0.3.0` is available in . Any related questions should be asked there. ## 0.1.28 [Commits](https://github.com/xmldom/xmldom/compare/v0.1.27...xmldom-alpha@v0.1.28) Published by @jindw on the 9th of May 2017 as - `xmldom-alpha@0.1.28` - **BREAKING** includes [regression regarding ` ` (issue #57)](https://github.com/xmldom/xmldom/issues/57) - [Fix `license` field in `package.json`](https://github.com/jindw/xmldom/pull/178) - [Conditional converting of HTML entities](https://github.com/jindw/xmldom/pull/80) - Fix `dom.js` serialization issue for missing document element ([example that failed on `toString()` before this change](https://github.com/xmldom/xmldom/blob/a58dcf7a265522e80ce520fe3be0cddb1b976f6f/test/parse/unclosedcomment.js#L10-L11)) - Add new module `entities.js` ## 0.1.27 Published by @jindw on the 28th of Nov 2016 as - `xmldom@0.1.27` - `xmldom-alpha@0.1.27` - Various bug fixes. ## 0.1.26 Published on the 18th of Nov 2016 as `xmldom@0.1.26` - Details unknown ## 0.1.25 Published on the 18th of Nov 2016 as - `xmldom@0.1.25` - Details unknown ## 0.1.24 Published on the 27th of November 2016 as - `xmldom@0.1.24` - `xmldom-alpha@0.1.24` - Added node filter. ## 0.1.23 Published on the 5th of May 2016 as - `xmldom-alpha@0.1.23` - Add namespace support for nest node serialize. - Various other bug fixes. ## 0.1.22 - Merge XMLNS serialization. - Remove \r from source string. - Print namespaces for child elements. - Switch references to nodeType to use named constants. - Add nodelist toString support. ## 0.1.21 - Fix serialize bug. ## 0.1.20 - Optimize invalid XML support. - Add toString sorter for attributes output. - Add html self closed node button. - Add `*` NS support for getElementsByTagNameNS. - Convert attribute's value to string in setAttributeNS. - Add support for HTML entities for HTML docs only. - Fix TypeError when Document is created with DocumentType. ## 0.1.19 - Fix [infinite loop on unclosed comment (jindw/xmldom#68)](https://github.com/jindw/xmldom/issues/68) - Add error report for unclosed tag. - Various other fixes. ## 0.1.18 - Add default `ns` support. - parseFromString now renders entirely plain text documents as textNode. - Enable option to ignore white space on parsing. ## 0.1.17 **Details missing for this and potential earlier version** ## 0.1.16 - Correctly handle multibyte Unicode greater than two byts. #57. #56. - Initial unit testing and test coverage. #53. #46. #19. - Create Bower `component.json` #52. ## 0.1.8 - Add: some test case from node-o3-xml(excludes xpath support) - Fix: remove existed attribute before setting (bug introduced in v0.1.5) - Fix: index direct access for childNodes and any NodeList collection(not w3c standard) - Fix: remove last child bug xmldom-0.8.6/LICENSE000066400000000000000000000024221433143211200140240ustar00rootroot00000000000000Copyright 2019 - present Christopher J. Brody and other contributors, as listed in: https://github.com/xmldom/xmldom/graphs/contributors Copyright 2012 - 2017 @jindw and other contributors, as listed in: https://github.com/jindw/xmldom/graphs/contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. xmldom-0.8.6/SECURITY.md000066400000000000000000000076251433143211200146220ustar00rootroot00000000000000# Security Policy The most up-to-date version of this document can be found at . ## Supported Versions This repository contains the code for the libraries `xmldom` and `@xmldom/xmldom` on npm. As long as we didn't publish v1, we aim to maintain the last two minor versions with security fixes. If it is possible we provide security fixes as path versions. If you think there is a good reason to also patch an earlier version let us know in a github issue or the release discussion once the fix has been provided. The maintainers will consider it and if we agree and have/find the required resources, a patch for that version will be provided. Please notice that [we are no longer able to publish the (unscoped) `xmldom` package](https://github.com/xmldom/xmldom/issues/271), and that all existing versions of `xmldom` are affected by at least one security vulnerability and should be considered deprecated. You can still report issues regarding `xmldom` as described below. If you need help with migrating from `xmldom` to `@xmldom/xmldom`, file a github issue or PR in the affected repository and mention @karfau. ## Reporting vulnerabilities Please email reports about any security related issues you find to `security@xmldom.org`, which will forward it to the list of maintainers. The maintainers will try to respond within 7 calendar days. (If nobody peplies after 7 days, please us send a reminder!) As part of you communication please make sure to always hit "Reply all", so all maintainers are kept in the loop. In addition, please include the following information along with your report: - Your name and affiliation (if any). - A description of the technical details of the vulnerabilities. It is very important to let us know how we can reproduce your findings. - An explanation who can exploit this vulnerability, and what they gain when doing so -- write an attack scenario. This will help us evaluate your report quickly, especially if the issue is complex. - Whether this vulnerability public or known to third parties. If it is, please provide details. If you believe that an existing (public) issue is security-related, please send an email to `security@xmldom.org`. The email should include the issue URL and a short description of why it should be handled according to this security policy. Once an issue is reported, the maintainers use the following disclosure process: - When a report is received, we confirm the issue, determine its severity and the affected versions. - If we know of specific third-party services or software based on xmldom that require mitigation before publication, those projects will be notified. - A [github security advisory](https://docs.github.com/en/code-security/security-advisories/about-github-security-advisories) is [created](https://docs.github.com/en/code-security/security-advisories/creating-a-security-advisory) (but not published) which details the problem and steps for mitigation. - If the reporter provides a github account and agrees to it, we (add that github account as a collaborator on the advisuory)[https://docs.github.com/en/code-security/security-advisories/adding-a-collaborator-to-a-security-advisory]. - The vulnerability is fixed in a [private fork](https://docs.github.com/en/code-security/security-advisories/collaborating-in-a-temporary-private-fork-to-resolve-a-security-vulnerability) and potential workarounds are identified. - The maintainers audit the existing code to find any potential similar problems. - The release for the current minor version and the [security advisory are published](https://docs.github.com/en/code-security/security-advisories/publishing-a-security-advisory). - The release(s) for previous minor version(s) are published. We credit reporters for identifying security issues, if they confirm that they want to. ## Known vulnerabilities See https://github.com/xmldom/xmldom/security/advisories?state=published xmldom-0.8.6/auto-changelog.hbs000066400000000000000000000014371433143211200164170ustar00rootroot00000000000000# Changelog All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). {{#each releases}} {{#if href}} ## [{{title}}]({{href}}){{#if tag}} - {{isoDate}}{{/if}} {{else}} ## {{title}}{{#if tag}} - {{isoDate}}{{/if}} {{/if}} {{#if summary}} {{summary}} {{/if}} {{#if merges}} ### Merged {{#each merges}} - {{#if commit.breaking}}**Breaking change:** {{/if}}{{message}} {{#if href}}[`#{{id}}`]({{href}}){{/if}} {{/each}} {{/if}} {{#if fixes}} ### Fixed {{#each fixes}} - {{#if commit.breaking}}**Breaking change:** {{/if}}{{commit.subject}}{{#each fixes}} {{#if href}}[`#{{id}}`]({{href}}){{/if}}{{/each}} {{/each}} {{/if}} {{/each}} xmldom-0.8.6/changelog-has-version.sh000077500000000000000000000007301433143211200175410ustar00rootroot00000000000000#!/bin/bash set -xeu # the script assumes that it's run as part of an npm script # so $npm_package_ variable are set # https://docs.npmjs.com/cli/v6/using-npm/scripts#packagejson-vars # before trying to release a version we want to make sure the changelog has been updated # well at least the headline needs to be there grep "## \[$npm_package_version\](" CHANGELOG.md || (echo "CHANGELOG.md is missing content for $npm_package_version! Read docs/RELEASE.md" && exit 1) xmldom-0.8.6/docs/000077500000000000000000000000001433143211200137475ustar00rootroot00000000000000xmldom-0.8.6/docs/RELEASE.md000066400000000000000000000115751433143211200153620ustar00rootroot00000000000000# Roadmap and Releases ## Milestones We always have the following [open milestones](https://github.com/xmldom/xmldom/milestones) for transparency regarding priority - **0.M.0**\ the upcoming/planned minor bump release for new features or breaking changes - **0.M.x**\ This milestone might not exist if no patch release is planned yet.\ If `0.M.0` was released: the upcoming/planned patch bump(s) release(s) for bug fixes.\ If `0.M.0` was not released: the things to work on right after the next planned minor bump - **[next breaking/minor release](https://github.com/xmldom/xmldom/milestone/12)** \ The topics that will be picked up once the milestones with specified versions have been released - **[before 1.0.0](https://github.com/xmldom/xmldom/milestone/5)** \ The issues in this milestone are going to be worked on.\ After each minor or patch release we pick topics from this milestone and put them into the "next patch release" or "next minor release" milestones.\ All of these will be worked on before we consider planning for a 1.0.0 release. - **[planning 1.0.0](https://github.com/xmldom/xmldom/milestone/4)** \ There is no timeline for when this is going to happen.\ For issues in this milestone to become relevant for maintainers we will have to finish all issues in the `before 1.0.0` milestone.\ In most cases maintainers didn't even invest time to think through, how to handle them.\ It might even happen that we decide to not include them into `1.0.0`. For external contributors: Before creating a PR for these, communicate in the issue, how to go about it. Ideally with a proposal and arguments. ## How to release Currently, the release process is not fully automated, so here is how we do it. > We are very open for PRs that show how we can automate parts of this process or go for a fully automated process that is able to cover most of this process. We are open to discuss things that are redundant in PRs. > I can imagine that we could automatically create pre-releases when anything relevant lands on master. Those pre-release versions won't appear in the changelog, but the github release can (automatically) have all the information. ### 0. Prerequisites for a release - [All changes to be included in the current milestone are landed on the default branch and the related tickets are closed](https://github.com/orgs/xmldom/projects/1/views/5). - All related PRs are connected to the current milestone - The default branch is checked out and up to date. `git fetch --all && git checkout -B master upstream/master` - Make sure all dependencies up-to-date locally: `nvm i 12 && npm ci` - determine the upcoming `$NEXT_VERSION` number according to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) - it should already be reflected in the current milestone - if there are any breaking changes or new features: `$bump` is `minor` - otherwise `$bump` is `patch` - keep in mind we are not doing any `major` bumps so far! - keep in mind we are not using a `v` prefix anywhere! ### 1. Generate update for CHANGELOG - `npm run changelog` - Tweak the result until it matches the previous entries - Remove the now repeated first lines - change the headline by replacing `Unreleased` and `HEAD` with `$NEXT_VERSION` (no `v` prefix!) - Split features/fixes/chore/docs/... according to the commit message - Mention people that contributed to PRs in the list Changes - Mention people that contributed to fixed issues by creating them or commenting - Create a PR, review it (read the updated markdown on github once!) and land it `npm run release` ( => `np` => `npm run version` => `changelog-has-version.sh`) asserts that the new version is part of the changelog before publishing. ### 2. Create and publish the release - `git fetch --all && git checkout -B master upstream/master` - `npm run release -- $bump` and follow the instructions - Copy the content of the changelog to the release draft - Change the first headline to be just a link with the text `Commits` - Run `npm pack @xmldom/xmldom` to **download** the published binary and **upload** the file to the release - If it's a minor bump: Check the box for creating a release discussion - If it's a patch bump: update the related release discussion of the minor bump by adding the changelog to the bottom and changing the discussion title to have an `x` in the patch part of the version. ### 3. Update Milestones Edit the current milestone: - set the due date to the release date and - Set the description to the release discussion - close it Create a new milestone named `0.M.0` or `0.M.x` if it doesn't exist yet.\ Pick and add the issue(s) / pr(s) from (in that order) 1. [`next breaking/minor release`](https://github.com/xmldom/xmldom/milestone/12) 2. [`before 1.0.0`](https://github.com/xmldom/xmldom/milestone/5) Update the [project board](https://github.com/orgs/xmldom/projects/1/views/5) to point to the new milestone. xmldom-0.8.6/docs/architecture.puml000066400000000000000000000017301433143211200173310ustar00rootroot00000000000000@startuml 'Syntax: https://plantuml.com/component-diagram 'to update the SVG after changing this file run 'docs/puml2svg.sh skinparam componentStyle rectangle frame "lib/dom.js" { cloud "Spec:DOM" { [DOMException] [DOMImplementation] interface Document interface Element interface Node } component XMLSerializer [ XMLSerializer Spec:DOM-Parsing ] } frame "lib/dom-parser.js" { component DOMParser [ DOMParser Spec:HTML ] component DOMHandler [ DOMHandler Spec:SAX ] } frame "lib/sax.js" { component XMLReader [ XMLReader Spec:SAX ] [ParseError] } DOMParser -d-> DOMHandler: new DOMParser -r-> XMLReader: new XMLReader --> DOMHandler: using XMLReader --> ParseError: throw DOMHandler --> DOMImplementation: new DOMHandler --> Document: using DOMImplementation -d-> Document: new Document -r-> Node: new Document -l-> Element: new Document -d-> DOMException: throw XMLSerializer -u-> Node: visit @enduml xmldom-0.8.6/docs/architecture.svg000066400000000000000000000342461433143211200171630ustar00rootroot00000000000000lib/dom.jsSpec:DOMlib/dom-parser.jslib/sax.jsXMLSerializerSpec:DOM-ParsingDOMExceptionDOMImplementationDocumentElementNodeDOMParserSpec:HTMLDOMHandlerSpec:SAXXMLReaderSpec:SAXParseErrornewnewusingthrownewusingnewnewnewthrowvisitxmldom-0.8.6/docs/puml2svg.sh000077500000000000000000000012321433143211200160630ustar00rootroot00000000000000#!/bin/bash set -eu if [[ ! -d docs ]] ; then echo "execute from the root directory!" && exit 1 fi export PLANTUML_VERSION=1.2021.7 function svg { if [[ -f "docs/$1.puml" ]] ; then echo "updating docs/$1.svg" if [[ -f docs/plantuml.jar ]] ; then # for using java, download plantuml.jar into the docs folder from https://plantuml.com/download < "docs/$1.puml" java -jar docs/plantuml.jar -pipe -tsvg -nometadata > "docs/$1.svg" else < "docs/$1.puml" docker run --rm -i karfau/plantuml:$PLANTUML_VERSION -pipe -tsvg -nometadata > "docs/$1.svg" fi else echo "missing file 'docs/$1.puml'" fi } svg architecture svg specs xmldom-0.8.6/docs/specs.puml000066400000000000000000000061761433143211200157750ustar00rootroot00000000000000@startuml 'Syntax: https://plantuml.com/object-diagram 'to update the SVG after changing this file run 'docs/puml2svg.sh title "References between relevant specs" note "About spec status: [[https://www.w3.org/2020/Process-20200915/#rec-track The W3C Recommendation Track]]" as status map "W3C DOM Parsing and Serialization [[https://www.w3.org/standards/history/DOM-Parsing history]]" as DOMParsing { [[https://w3c.github.io/DOM-Parsing/ latest]] => Editors Draft **[[https://www.w3.org/TR/2016/WD-DOM-Parsing-20160517/ 2016]]** => Working Draft [[https://www.w3.org/TR/2014/CR-DOM-Parsing-20140617/ 2014]] => Outdated Candidate Recommendation } map "Document Object Model (DOM) [[https://www.w3.org/standards/history/dom history]]" as DOM { [[https://dom.spec.whatwg.org/ latest]] => Living Standard **[[https://dom.spec.whatwg.org/review-drafts/2019-06/ Level 4 (2020)]]** => DOM Recommendation [[https://www.w3.org/TR/DOM-Level-3-Core/ Level 3 Core (2004)]] => Recommendation (**[[https://dom.spec.whatwg.org/#historical has outdated parts!]]**, [[https://www.w3.org/standards/history/DOM-Level-3-Core history]]) **[[https://www.w3.org/TR/DOM-Level-2-HTML/ Level 2 HTML (2003)]]** => Superseded Recommendation **[[https://www.w3.org/TR/DOM-Level-2-Core/ Level 2 Core (2000)]]** => Superseded Recommendation } map "Hyper Text Markup Language (HTML)" as HTML { [[https://html.spec.whatwg.org/ latest]] => Living Standard [[https://html.spec.whatwg.org/review-drafts/2020-01/ HTML5 (2020)]] => Recommendation [[https://www.w3.org/standards/history/html history]] [[https://www.w3.org/TR/html401/ HTML4.01 (1999)]] => Recommendation [[https://www.w3.org/standards/history/html401 history]] [[https://www.w3.org/TR/html401/ HTML4.01 (1999)]] => Superseded Recommendation [[https://www.w3.org/standards/history/html401 history]] [[https://www.w3.org/TR/xhtml1/ XHTML 1.0 (2002)]] => Superseded Recommendation [[https://www.w3.org/standards/history/xhtml1 history]] [[https://www.w3.org/TR/xhtml1/ XHTML 1.0 (2002)]] => Superseded Recommendation [[https://www.w3.org/standards/history/xhtml1 history]] } map "Extensible Markup Language (XML)" as XML { [[https://www.w3.org/TR/xml11/ 1.1 (2006)]] => Recommendation [[https://www.w3.org/standards/history/xml11 history]] [[https://www.w3.org/TR/xml/ 1.0 (2008)]] => Recommendation [[https://www.w3.org/standards/history/xml history]] } map "Namespaces in XML" as XMLNS { [[https://www.w3.org/TR/xml-names11/ 1.1 (2006)]] => Recommendation [[https://www.w3.org/TR/REC-xml-names/ 1.0 (2009)]] => Recommendation } map "WebIDL [[https://www.w3.org/standards/history/WebIDL-1 history]]" as WebIDL { [[https://heycam.github.io/webidl/ latest]] => Editors Draft [[https://www.w3.org/TR/WebIDL-1/ Level 1 (2016)]] => Recommendation } map "[[http://www.saxproject.org/ Simple API for XML (SAX)]]" as SAX { } map "[[https://infra.spec.whatwg.org/ Infra Standard]]" as Infra { } DOM <--> HTML DOM --> Infra DOM --> WebIDL DOM --> XML DOMParsing --> DOM DOMParsing <--> HTML DOMParsing --> XML DOMParsing --> WebIDL HTML --> Infra HTML --> XML HTML --> XMLNS SAX --> XML SAX --> XMLNS XMLNS --> XML @enduml xmldom-0.8.6/docs/specs.svg000066400000000000000000000724461433143211200156220ustar00rootroot00000000000000References between relevant specsAbout spec status:The W3C Recommendation TrackW3C DOM Parsing and SerializationhistorylatestEditors Draft2016Working Draft2014Outdated Candidate RecommendationDocument Object Model (DOM)historylatestLiving StandardLevel 4 (2020)DOM RecommendationLevel 3 Core (2004)Recommendation (has outdated parts!,history)Level 2 HTML (2003)Superseded RecommendationLevel 2 Core (2000)Superseded RecommendationHyper Text Markup Language (HTML)latestLiving StandardHTML5 (2020)RecommendationhistoryHTML4.01 (1999)Superseded RecommendationhistoryXHTML 1.0 (2002)Superseded RecommendationhistoryExtensible Markup Language (XML)1.1 (2006)Recommendationhistory1.0 (2008)RecommendationhistoryNamespaces in XML1.1 (2006)Recommendation1.0 (2009)RecommendationWebIDLhistorylatestEditors DraftLevel 1 (2016)RecommendationSimple API for XML (SAX)Infra Standardxmldom-0.8.6/examples/000077500000000000000000000000001433143211200146355ustar00rootroot00000000000000xmldom-0.8.6/examples/nodejs/000077500000000000000000000000001433143211200161175ustar00rootroot00000000000000xmldom-0.8.6/examples/nodejs/.gitignore000066400000000000000000000000371433143211200201070ustar00rootroot00000000000000node_modules package-lock.json xmldom-0.8.6/examples/nodejs/.npmrc000066400000000000000000000000231433143211200172320ustar00rootroot00000000000000package-lock=false xmldom-0.8.6/examples/nodejs/package.json000066400000000000000000000005541433143211200204110ustar00rootroot00000000000000{ "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:../.." } } xmldom-0.8.6/examples/nodejs/src/000077500000000000000000000000001433143211200167065ustar00rootroot00000000000000xmldom-0.8.6/examples/nodejs/src/index.js000066400000000000000000000005671433143211200203630ustar00rootroot00000000000000const { DOMParser, XMLSerializer } = require('@xmldom/xmldom') const source = ` test ` const doc = new DOMParser().parseFromString(source, 'text/xml') const serialized = new XMLSerializer().serializeToString(doc) if (source !== serialized) { console.error(`expected\n${source}\nbut was\n${serialized}`) process.exit(1); } xmldom-0.8.6/examples/typescript-node-es6/000077500000000000000000000000001433143211200204615ustar00rootroot00000000000000xmldom-0.8.6/examples/typescript-node-es6/.gitignore000066400000000000000000000000441433143211200224470ustar00rootroot00000000000000dist node_modules package-lock.json xmldom-0.8.6/examples/typescript-node-es6/.npmrc000066400000000000000000000000231433143211200215740ustar00rootroot00000000000000package-lock=false xmldom-0.8.6/examples/typescript-node-es6/package.json000066400000000000000000000006101433143211200227440ustar00rootroot00000000000000{ "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:../.." } } xmldom-0.8.6/examples/typescript-node-es6/pretest.sh000077500000000000000000000003301433143211200225020ustar00rootroot00000000000000#!/usr/bin/env bash set -xeu rm -rf node_modules dist npm i [[ -n ${1:-''} ]] && npm i --no-save typescript@${1} echo "Using TypeScript $(node_modules/.bin/tsc --version) (change with first argument)" npm run tsc xmldom-0.8.6/examples/typescript-node-es6/src/000077500000000000000000000000001433143211200212505ustar00rootroot00000000000000xmldom-0.8.6/examples/typescript-node-es6/src/index.ts000066400000000000000000000005271433143211200227330ustar00rootroot00000000000000import {DOMParser, XMLSerializer} from '@xmldom/xmldom'; const source = ` test ` const doc = new DOMParser().parseFromString(source, 'text/xml') const serialized = new XMLSerializer().serializeToString(doc) if (source !== serialized) { throw `expected\n${source}\nbut was\n${serialized}` } xmldom-0.8.6/examples/typescript-node-es6/tsconfig.json000066400000000000000000000251341433143211200231750ustar00rootroot00000000000000{ "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. */ /* 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. */ /* 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. */ /* 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. */ /* Completeness */ // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ "skipLibCheck": true /* Skip type checking all .d.ts files. */ } } xmldom-0.8.6/index.d.ts000066400000000000000000000017511433143211200147240ustar00rootroot00000000000000/// declare module "@xmldom/xmldom" { var DOMParser: DOMParserStatic; var XMLSerializer: XMLSerializerStatic; var DOMImplementation: DOMImplementationStatic; interface DOMImplementationStatic { new(): DOMImplementation; } interface DOMParserStatic { new (): DOMParser; new (options: Options): DOMParser; } interface XMLSerializerStatic { new (): XMLSerializer; } interface DOMParser { parseFromString(xmlsource: string, mimeType?: string): Document; } interface XMLSerializer { serializeToString(node: Node): string; } interface Options { locator?: any; errorHandler?: ErrorHandlerFunction | ErrorHandlerObject | undefined; } interface ErrorHandlerFunction { (level: string, msg: any): any; } interface ErrorHandlerObject { warning?: ((msg: any) => any) | undefined; error?: ((msg: any) => any) | undefined; fatalError?: ((msg: any) => any) | undefined; } } xmldom-0.8.6/jest.config.js000066400000000000000000000146171433143211200155770ustar00rootroot00000000000000// For a detailed explanation regarding each configuration property, visit: // https://jestjs.io/docs/en/configuration.html module.exports = { // All imported modules in your tests should be mocked automatically // automock: false, // Stop running tests after `n` failures // bail: 0, // The directory where Jest should store its cached dependency information // cacheDirectory: "/tmp/jest_rs", // Automatically clear mock calls and instances between every test clearMocks: true, // Indicates whether the coverage information should be collected while executing the test // collectCoverage: false, // An array of glob patterns indicating a set of files for which coverage information should be collected // collectCoverageFrom: undefined, // The directory where Jest should output its coverage files // coverageDirectory: "coverage", // An array of regexp pattern strings used to skip coverage collection // coveragePathIgnorePatterns: [ // "/node_modules/" // ], // Indicates which provider should be used to instrument code for coverage // coverageProvider: "v8", // A list of reporter names that Jest uses when writing coverage reports // coverageReporters: [ // "json", // "text", // "lcov", // "clover" // ], // An object that configures minimum threshold enforcement for coverage results // coverageThreshold: undefined, // A path to a custom dependency extractor // dependencyExtractor: undefined, // Make calling deprecated APIs throw helpful error messages // errorOnDeprecated: false, // Force coverage collection from ignored files using an array of glob patterns // forceCoverageMatch: [], // A path to a module which exports an async function that is triggered once before all test suites // globalSetup: undefined, // A path to a module which exports an async function that is triggered once after all test suites // globalTeardown: undefined, // A set of global variables that need to be available in all test environments // globals: {}, // The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers. // maxWorkers: "50%", // An array of directory names to be searched recursively up from the requiring module's location // moduleDirectories: [ // "node_modules" // ], // An array of file extensions your modules use // moduleFileExtensions: [ // "js", // "json", // "jsx", // "ts", // "tsx", // "node" // ], // A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module // moduleNameMapper: {}, // An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader // modulePathIgnorePatterns: [], // Activates notifications for test results // notify: false, // An enum that specifies notification mode. Requires { notify: true } // notifyMode: "failure-change", // A preset that is used as a base for Jest's configuration // preset: undefined, // Run tests from one or more projects // projects: undefined, // Use this configuration option to add custom reporters to Jest // reporters: undefined, // Automatically reset mock state between every test // resetMocks: false, // Reset the module registry before running each individual test // resetModules: false, // A path to a custom resolver // resolver: undefined, // Automatically restore mock state between every test // restoreMocks: false, // The root directory that Jest should scan for tests and modules within // rootDir: undefined, // A list of paths to directories that Jest should use to search for files in // roots: [ // "" // ], // Allows you to use a custom runner instead of Jest's default test runner // runner: "jest-runner", // The paths to modules that run some code to configure or set up the testing environment before each test // setupFiles: [], // A list of paths to modules that run some code to configure or set up the testing framework before each test // setupFilesAfterEnv: [], // The number of seconds after which a test is considered as slow and reported as such in the results. // slowTestThreshold: 5, // A list of paths to snapshot serializer modules Jest should use for snapshot testing // snapshotSerializers: [], // The test environment that will be used for testing testEnvironment: "node", // Options that will be passed to the testEnvironment // testEnvironmentOptions: {}, // Adds a location field to test results // testLocationInResults: false, // The glob patterns Jest uses to detect test files // testMatch: [ // "**/__tests__/**/*.[jt]s?(x)", // "**/?(*.)+(spec|test).[tj]s?(x)" // ], // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped // testPathIgnorePatterns: [ // "/node_modules/" // ], // The regexp pattern or array of patterns that Jest uses to detect test files testRegex: [ /\.test\.js?$/ ], // This option allows the use of a custom results processor // testResultsProcessor: undefined, // This option allows use of a custom test runner // testRunner: "jasmine2", // This option sets the URL for the jsdom environment. It is reflected in properties such as location.href // testURL: "http://localhost", // Setting this value to "fake" allows the use of fake timers for functions such as "setTimeout" // timers: "real", // A map from regular expressions to paths to transformers // transform: undefined, // An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation // transformIgnorePatterns: [ // "/node_modules/", // "\\.pnp\\.[^\\/]+$" // ], // An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them // unmockedModulePathPatterns: undefined, // Indicates whether each individual test should be reported during the run // verbose: undefined, // An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode // watchPathIgnorePatterns: [], // Whether to use watchman for file crawling // watchman: true, }; xmldom-0.8.6/lib/000077500000000000000000000000001433143211200135655ustar00rootroot00000000000000xmldom-0.8.6/lib/.eslintrc.yml000066400000000000000000000000441433143211200162070ustar00rootroot00000000000000extends: - 'plugin:es5/no-es2015' xmldom-0.8.6/lib/conventions.js000066400000000000000000000142651433143211200165000ustar00rootroot00000000000000'use strict' /** * Ponyfill for `Array.prototype.find` which is only available in ES6 runtimes. * * Works with anything that has a `length` property and index access properties, including NodeList. * * @template {unknown} T * @param {Array | ({length:number, [number]: T})} list * @param {function (item: T, index: number, list:Array | ({length:number, [number]: T})):boolean} predicate * @param {Partial>?} ac `Array.prototype` by default, * allows injecting a custom implementation in tests * @returns {T | undefined} * * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find * @see https://tc39.es/ecma262/multipage/indexed-collections.html#sec-array.prototype.find */ function find(list, predicate, ac) { if (ac === undefined) { ac = Array.prototype; } if (list && typeof ac.find === 'function') { return ac.find.call(list, predicate); } for (var i = 0; i < list.length; i++) { if (Object.prototype.hasOwnProperty.call(list, i)) { var item = list[i]; if (predicate.call(undefined, item, i, list)) { return item; } } } } /** * "Shallow freezes" an object to render it immutable. * Uses `Object.freeze` if available, * otherwise the immutability is only in the type. * * Is used to create "enum like" objects. * * @template T * @param {T} object the object to freeze * @param {Pick = Object} oc `Object` by default, * allows to inject custom object constructor for tests * @returns {Readonly} * * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze */ function freeze(object, oc) { if (oc === undefined) { oc = Object } return oc && typeof oc.freeze === 'function' ? oc.freeze(object) : object } /** * Since we can not rely on `Object.assign` we provide a simplified version * that is sufficient for our needs. * * @param {Object} target * @param {Object | null | undefined} source * * @returns {Object} target * @throws TypeError if target is not an object * * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign * @see https://tc39.es/ecma262/multipage/fundamental-objects.html#sec-object.assign */ function assign(target, source) { if (target === null || typeof target !== '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] } } return target } /** * All mime types that are allowed as input to `DOMParser.parseFromString` * * @see https://developer.mozilla.org/en-US/docs/Web/API/DOMParser/parseFromString#Argument02 MDN * @see https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#domparsersupportedtype WHATWG HTML Spec * @see DOMParser.prototype.parseFromString */ var MIME_TYPE = freeze({ /** * `text/html`, the only mime type that triggers treating an XML document as HTML. * * @see DOMParser.SupportedType.isHTML * @see https://www.iana.org/assignments/media-types/text/html IANA MimeType registration * @see https://en.wikipedia.org/wiki/HTML Wikipedia * @see https://developer.mozilla.org/en-US/docs/Web/API/DOMParser/parseFromString MDN * @see https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#dom-domparser-parsefromstring WHATWG HTML Spec */ HTML: 'text/html', /** * Helper method to check a mime type if it indicates an HTML document * * @param {string} [value] * @returns {boolean} * * @see https://www.iana.org/assignments/media-types/text/html IANA MimeType registration * @see https://en.wikipedia.org/wiki/HTML Wikipedia * @see https://developer.mozilla.org/en-US/docs/Web/API/DOMParser/parseFromString MDN * @see https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#dom-domparser-parsefromstring */ isHTML: function (value) { return value === MIME_TYPE.HTML }, /** * `application/xml`, the standard mime type for XML documents. * * @see https://www.iana.org/assignments/media-types/application/xml IANA MimeType registration * @see https://tools.ietf.org/html/rfc7303#section-9.1 RFC 7303 * @see https://en.wikipedia.org/wiki/XML_and_MIME Wikipedia */ XML_APPLICATION: 'application/xml', /** * `text/html`, an alias for `application/xml`. * * @see https://tools.ietf.org/html/rfc7303#section-9.2 RFC 7303 * @see https://www.iana.org/assignments/media-types/text/xml IANA MimeType registration * @see https://en.wikipedia.org/wiki/XML_and_MIME Wikipedia */ XML_TEXT: 'text/xml', /** * `application/xhtml+xml`, indicates an XML document that has the default HTML namespace, * but is parsed as an XML document. * * @see https://www.iana.org/assignments/media-types/application/xhtml+xml IANA MimeType registration * @see https://dom.spec.whatwg.org/#dom-domimplementation-createdocument WHATWG DOM Spec * @see https://en.wikipedia.org/wiki/XHTML Wikipedia */ XML_XHTML_APPLICATION: 'application/xhtml+xml', /** * `image/svg+xml`, * * @see https://www.iana.org/assignments/media-types/image/svg+xml IANA MimeType registration * @see https://www.w3.org/TR/SVG11/ W3C SVG 1.1 * @see https://en.wikipedia.org/wiki/Scalable_Vector_Graphics Wikipedia */ XML_SVG_IMAGE: 'image/svg+xml', }) /** * Namespaces that are used in this code base. * * @see http://www.w3.org/TR/REC-xml-names */ var NAMESPACE = freeze({ /** * The XHTML namespace. * * @see http://www.w3.org/1999/xhtml */ HTML: 'http://www.w3.org/1999/xhtml', /** * Checks if `uri` equals `NAMESPACE.HTML`. * * @param {string} [uri] * * @see NAMESPACE.HTML */ isHTML: function (uri) { return uri === NAMESPACE.HTML }, /** * The SVG namespace. * * @see http://www.w3.org/2000/svg */ SVG: 'http://www.w3.org/2000/svg', /** * The `xml:` namespace. * * @see http://www.w3.org/XML/1998/namespace */ XML: 'http://www.w3.org/XML/1998/namespace', /** * The `xmlns:` namespace * * @see https://www.w3.org/2000/xmlns/ */ XMLNS: 'http://www.w3.org/2000/xmlns/', }) exports.assign = assign; exports.find = find; exports.freeze = freeze; exports.MIME_TYPE = MIME_TYPE; exports.NAMESPACE = NAMESPACE; xmldom-0.8.6/lib/dom-parser.js000066400000000000000000000241101433143211200161720ustar00rootroot00000000000000var conventions = require("./conventions"); var dom = require('./dom') var entities = require('./entities'); var sax = require('./sax'); var DOMImplementation = dom.DOMImplementation; var NAMESPACE = conventions.NAMESPACE; var ParseError = sax.ParseError; var XMLReader = sax.XMLReader; /** * Normalizes line ending according to https://www.w3.org/TR/xml11/#sec-line-ends: * * > XML parsed entities are often stored in computer files which, * > for editing convenience, are organized into lines. * > These lines are typically separated by some combination * > of the characters CARRIAGE RETURN (#xD) and LINE FEED (#xA). * > * > To simplify the tasks of applications, the XML processor must behave * > as if it normalized all line breaks in external parsed entities (including the document entity) * > on input, before parsing, by translating all of the following to a single #xA character: * > * > 1. the two-character sequence #xD #xA * > 2. the two-character sequence #xD #x85 * > 3. the single character #x85 * > 4. the single character #x2028 * > 5. any #xD character that is not immediately followed by #xA or #x85. * * @param {string} input * @returns {string} */ function normalizeLineEndings(input) { return input .replace(/\r[\n\u0085]/g, '\n') .replace(/[\r\u0085\u2028]/g, '\n') } /** * @typedef Locator * @property {number} [columnNumber] * @property {number} [lineNumber] */ /** * @typedef DOMParserOptions * @property {DOMHandler} [domBuilder] * @property {Function} [errorHandler] * @property {(string) => string} [normalizeLineEndings] used to replace line endings before parsing * defaults to `normalizeLineEndings` * @property {Locator} [locator] * @property {Record} [xmlns] * * @see normalizeLineEndings */ /** * The DOMParser interface provides the ability to parse XML or HTML source code * from a string into a DOM `Document`. * * _xmldom is different from the spec in that it allows an `options` parameter, * to override the default behavior._ * * @param {DOMParserOptions} [options] * @constructor * * @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){ this.options = options ||{locator:{}}; } DOMParser.prototype.parseFromString = function(source,mimeType){ var options = this.options; var sax = new XMLReader(); var domBuilder = options.domBuilder || new DOMHandler();//contentHandler and LexicalHandler var errorHandler = options.errorHandler; var locator = options.locator; var defaultNSMap = options.xmlns||{}; var isHTML = /\/x?html?$/.test(mimeType);//mimeType.toLowerCase().indexOf('html') > -1; var entityMap = isHTML ? entities.HTML_ENTITIES : entities.XML_ENTITIES; if(locator){ domBuilder.setDocumentLocator(locator) } sax.errorHandler = buildErrorHandler(errorHandler,domBuilder,locator); sax.domBuilder = options.domBuilder || domBuilder; if(isHTML){ defaultNSMap[''] = NAMESPACE.HTML; } defaultNSMap.xml = defaultNSMap.xml || NAMESPACE.XML; var normalize = options.normalizeLineEndings || normalizeLineEndings; if (source && typeof source === 'string') { sax.parse( normalize(source), defaultNSMap, entityMap ) } else { sax.errorHandler.error('invalid doc source') } return domBuilder.doc; } function buildErrorHandler(errorImpl,domBuilder,locator){ if(!errorImpl){ if(domBuilder instanceof DOMHandler){ return domBuilder; } errorImpl = domBuilder ; } var errorHandler = {} var isCallback = errorImpl instanceof Function; locator = locator||{} function build(key){ var fn = errorImpl[key]; 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(){}; } build('warning'); build('error'); build('fatalError'); return errorHandler; } //console.log('#\n\n\n\n\n\n\n####') /** * +ContentHandler+ErrorHandler * +LexicalHandler+EntityResolver2 * -DeclHandler-DTDHandler * * DefaultHandler:EntityResolver, DTDHandler, ContentHandler, ErrorHandler * DefaultHandler2:DefaultHandler,LexicalHandler, DeclHandler, EntityResolver2 * @link http://www.saxproject.org/apidoc/org/xml/sax/helpers/DefaultHandler.html */ function DOMHandler() { this.cdata = false; } function position(locator,node){ node.lineNumber = locator.lineNumber; node.columnNumber = locator.columnNumber; } /** * @see org.xml.sax.ContentHandler#startDocument * @link http://www.saxproject.org/apidoc/org/xml/sax/ContentHandler.html */ DOMHandler.prototype = { startDocument : function() { this.doc = new DOMImplementation().createDocument(null, null, null); if (this.locator) { this.doc.documentURI = this.locator.systemId; } }, 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; 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); attr.value = attr.nodeValue = value; el.setAttributeNode(attr) } }, endElement:function(namespaceURI, localName, qName) { var current = this.currentElement var tagName = current.tagName; this.currentElement = current.parentNode; }, 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); }, ignorableWhitespace:function(ch, start, length) { }, characters:function(chars, start, length) { chars = _toString.apply(this,arguments) //console.log(chars) if(chars){ if (this.cdata) { var charNode = this.doc.createCDATASection(chars); } else { var charNode = this.doc.createTextNode(chars); } if(this.currentElement){ this.currentElement.appendChild(charNode); }else if(/^\s*$/.test(chars)){ this.doc.appendChild(charNode); //process xml } this.locator && position(this.locator,charNode) } }, skippedEntity:function(name) { }, endDocument:function() { this.doc.normalize(); }, setDocumentLocator:function (locator) { if(this.locator = locator){// && !('lineNumber' in locator)){ locator.lineNumber = 0; } }, //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); }, startCDATA:function() { //used in characters() methods this.cdata = true; }, endCDATA:function() { this.cdata = false; }, 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; } }, /** * @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)); }, error:function(error) { console.error('[xmldom error]\t'+error,_locator(this.locator)); }, fatalError:function(error) { throw new ParseError(error, this.locator); } } function _locator(l){ if(l){ return '\n@'+(l.systemId ||'')+'#[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)+''; } return chars; } } /* * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/LexicalHandler.html * used method of org.xml.sax.ext.LexicalHandler: * #comment(chars, start, length) * #startCDATA() * #endCDATA() * #startDTD(name, publicId, systemId) * * * IGNORED method of org.xml.sax.ext.LexicalHandler: * #endDTD() * #startEntity(name) * #endEntity(name) * * * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/DeclHandler.html * IGNORED method of org.xml.sax.ext.DeclHandler * #attributeDecl(eName, aName, type, mode, value) * #elementDecl(name, model) * #externalEntityDecl(name, publicId, systemId) * #internalEntityDecl(name, value) * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/EntityResolver2.html * IGNORED method of org.xml.sax.EntityResolver2 * #resolveEntity(String name,String publicId,String baseURI,String systemId) * #resolveEntity(publicId, systemId) * #getExternalSubset(name, baseURI) * @link http://www.saxproject.org/apidoc/org/xml/sax/DTDHandler.html * IGNORED method of org.xml.sax.DTDHandler * #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} }) /* 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 exports.__DOMHandler = DOMHandler; exports.normalizeLineEndings = normalizeLineEndings; exports.DOMParser = DOMParser; xmldom-0.8.6/lib/dom.js000066400000000000000000001602401433143211200147050ustar00rootroot00000000000000var conventions = require("./conventions"); var find = conventions.find; var NAMESPACE = conventions.NAMESPACE; /** * A prerequisite for `[].filter`, to drop elements that are empty * @param {string} input * @returns {boolean} */ function notEmptyString (input) { return input !== '' } /** * @see https://infra.spec.whatwg.org/#split-on-ascii-whitespace * @see https://infra.spec.whatwg.org/#ascii-whitespace * * @param {string} input * @returns {string[]} (can be empty) */ 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) : [] } /** * Adds element as a key to current if it is not already present. * * @param {Record} current * @param {string} element * @returns {Record} */ function orderedSetReducer (current, element) { if (!current.hasOwnProperty(element)) { current[element] = true; } return current; } /** * @see https://infra.spec.whatwg.org/#ordered-set * @param {string} input * @returns {string[]} */ function toOrderedSet(input) { if (!input) return []; var list = splitOnASCIIWhitespace(input); return Object.keys(list.reduce(orderedSetReducer, {})) } /** * Uses `list.indexOf` to implement something like `Array.prototype.includes`, * which we can not rely on being available. * * @param {any[]} list * @returns {function(any): boolean} */ function arrayIncludes (list) { return function(element) { return list && list.indexOf(element) !== -1; } } function copy(src,dest){ for(var p in src){ if (Object.prototype.hasOwnProperty.call(src, p)) { dest[p] = src[p]; } } } /** ^\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){ var pt = Class.prototype; if(!(pt instanceof Super)){ function t(){}; t.prototype = Super.prototype; t = new t(); copy(pt,t); Class.prototype = pt = t; } if(pt.constructor != Class){ if(typeof Class != 'function'){ console.error("unknown Class:"+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; // 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); //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); /** * DOM Level 2 * Object DOMException * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/ecma-script-binding.html * @see http://www.w3.org/TR/REC-DOM-Level-1/ecma-script-language-binding.html */ function DOMException(code, message) { if(message instanceof Error){ var error = message; }else{ error = this; Error.call(this, ExceptionMessage[code]); this.message = ExceptionMessage[code]; if(Error.captureStackTrace) Error.captureStackTrace(this, DOMException); } error.code = code; if(message) this.message = this.message + ": " + message; return error; }; DOMException.prototype = Error.prototype; 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() { }; 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, /** * 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 * @param index unsigned long * Index into the collection. * @return Node * The node at the indexth position in the NodeList, or null if that is not a valid index. */ item: function(index) { return this[index] || null; }, toString:function(isHTML,nodeFilter){ for(var buf = [], i = 0;i=0){ var lastIndex = list.length-1 while(i0 || key == 'xmlns'){ // return null; // } //console.log() var i = this.length; while(i--){ var attr = this[i]; //console.log(attr.nodeName,key) if(attr.nodeName == key){ return attr; } } }, setNamedItem: function(attr) { var el = attr.ownerElement; if(el && el!=this._ownerElement){ throw new DOMException(INUSE_ATTRIBUTE_ERR); } var oldAttr = this.getNamedItem(attr.nodeName); _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){ throw new DOMException(INUSE_ATTRIBUTE_ERR); } oldAttr = this.getNamedItemNS(attr.namespaceURI,attr.localName); _addNamedNode(this._ownerElement,this,attr,oldAttr); return oldAttr; }, /* returns Node */ removeNamedItem: function(key) { var attr = this.getNamedItem(key); _removeNamedNode(this._ownerElement,this,attr); return attr; },// 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); return attr; }, getNamedItemNS: function(namespaceURI, localName) { var i = this.length; while(i--){ var node = this[i]; if(node.localName == localName && node.namespaceURI == namespaceURI){ return node; } } return null; } }; /** * The DOMImplementation interface represents an object providing methods * which are not dependent on any particular document. * Such an object is returned by the `Document.implementation` property. * * __The individual methods describe the differences compared to the specs.__ * * @constructor * * @see https://developer.mozilla.org/en-US/docs/Web/API/DOMImplementation MDN * @see https://www.w3.org/TR/REC-DOM-Level-1/level-one-core.html#ID-102161490 DOM Level 1 Core (Initial) * @see https://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-102161490 DOM Level 2 Core * @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() { } DOMImplementation.prototype = { /** * The DOMImplementation.hasFeature() method returns a Boolean flag indicating if a given feature is supported. * The different implementations fairly diverged in what kind of features were reported. * The latest version of the spec settled to force this method to always return true, where the functionality was accurate and in use. * * @deprecated It is deprecated and modern browsers return true in all cases. * * @param {string} feature * @param {string} [version] * @returns {boolean} always true * * @see https://developer.mozilla.org/en-US/docs/Web/API/DOMImplementation/hasFeature MDN * @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; }, /** * Creates an XML Document object of the specified type with its document element. * * __It behaves slightly different from the description in the living standard__: * - There is no interface/class `XMLDocument`, it returns a `Document` instance. * - `contentType`, `encoding`, `mode`, `origin`, `url` fields are currently not declared. * - this implementation is not validating names or qualified names * (when parsing XML strings, the SAX parser takes care of that) * * @param {string|null} namespaceURI * @param {string} qualifiedName * @param {DocumentType=null} doctype * @returns {Document} * * @see https://developer.mozilla.org/en-US/docs/Web/API/DOMImplementation/createDocument MDN * @see https://www.w3.org/TR/DOM-Level-2-Core/core.html#Level-2-Core-DOM-createDocument DOM Level 2 Core (initial) * @see https://dom.spec.whatwg.org/#dom-domimplementation-createdocument DOM Level 2 Core * * @see https://dom.spec.whatwg.org/#validate-and-extract DOM: Validate and extract * @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){ var doc = new Document(); doc.implementation = this; doc.childNodes = new NodeList(); doc.doctype = doctype || null; if (doctype){ doc.appendChild(doctype); } if (qualifiedName){ var root = doc.createElementNS(namespaceURI, qualifiedName); doc.appendChild(root); } return doc; }, /** * Returns a doctype, with the given `qualifiedName`, `publicId`, and `systemId`. * * __This behavior is slightly different from the in the specs__: * - this implementation is not validating names or qualified names * (when parsing XML strings, the SAX parser takes care of that) * * @param {string} qualifiedName * @param {string} [publicId] * @param {string} [systemId] * @returns {DocumentType} which can either be used with `DOMImplementation.createDocument` upon document creation * or can be put into the document via methods like `Node.insertBefore()` or `Node.replaceChild()` * * @see https://developer.mozilla.org/en-US/docs/Web/API/DOMImplementation/createDocumentType MDN * @see https://www.w3.org/TR/DOM-Level-2-Core/core.html#Level-2-Core-DOM-createDocType DOM Level 2 Core * @see https://dom.spec.whatwg.org/#dom-domimplementation-createdocumenttype DOM Living Standard * * @see https://dom.spec.whatwg.org/#validate-and-extract DOM: Validate and extract * @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){ var node = new DocumentType(); node.name = qualifiedName; node.nodeName = qualifiedName; node.publicId = publicId || ''; node.systemId = systemId || ''; return node; } }; /** * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1950641247 */ 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, // Modified in DOM Level 2: insertBefore:function(newChild, refChild){//raises return _insertBefore(this,newChild,refChild); }, replaceChild:function(newChild, oldChild){//raises _insertBefore(this, newChild,oldChild, assertPreReplacementValidityInDocument); if(oldChild){ this.removeChild(oldChild); } }, removeChild:function(oldChild){ return _removeChild(this,oldChild); }, appendChild:function(newChild){ return this.insertBefore(newChild,null); }, hasChildNodes:function(){ return this.firstChild != null; }, cloneNode:function(deep){ return cloneNode(this.ownerDocument||this,this,deep); }, // Modified in DOM Level 2: normalize:function(){ var child = this.firstChild; while(child){ var next = child.nextSibling; if(next && next.nodeType == TEXT_NODE && child.nodeType == TEXT_NODE){ this.removeChild(next); child.appendData(next.data); }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: 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.** * See Namespace Prefix Lookup for details on the algorithm used by this method. * * _Note: The implementation seems to be incomplete when compared to the algorithm described in the specs._ * * @param {string | null} namespaceURI * @returns {string | null} * @see https://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-lookupNamespacePrefix * @see https://www.w3.org/TR/DOM-Level-3-Core/namespaces-algorithms.html#lookupNamespacePrefixAlgo * @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; } }; function _xmlEncoder(c){ return c == '<' && '<' || c == '>' && '>' || c == '&' && '&' || c == '"' && '"' || '&#'+c.charCodeAt()+';' } 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)){ return true; } if(node = node.firstChild){ do{ if(_visitNode(node,callback)){return true} }while(node=node.nextSibling) } } function Document(){ this.ownerDocument = this; } function _onAddAttribute(doc,el,newAttr){ doc && doc._inc++; var ns = newAttr.namespaceURI ; if(ns === NAMESPACE.XMLNS){ //update namespace el._nsMap[newAttr.prefix?newAttr.localName:''] = newAttr.value } } function _onRemoveAttribute(doc,el,newAttr,remove){ doc && doc._inc++; var ns = newAttr.namespaceURI ; if(ns === NAMESPACE.XMLNS){ //update namespace delete el._nsMap[newAttr.prefix?newAttr.localName:''] } } /** * Updates `el.childNodes`, updating the indexed items and it's `length`. * Passing `newChild` means it will be appended. * Otherwise it's assumed that an item has been removed, * and `el.firstNode` and it's `.nextSibling` are used * to walk the current list of child nodes. * * @param {Document} doc * @param {Node} el * @param {Node} [newChild] * @private */ function _onUpdateChild (doc, el, newChild) { if(doc && doc._inc){ doc._inc++; //update childNodes var cs = el.childNodes; if (newChild) { cs[cs.length++] = newChild; } else { var child = el.firstChild; var i = 0; while (child) { cs[i++] = child; child = child.nextSibling; } cs.length = i; delete cs[cs.length]; } } } /** * Removes the connections between `parentNode` and `child` * and any existing `child.previousSibling` or `child.nextSibling`. * * @see https://github.com/xmldom/xmldom/issues/135 * @see https://github.com/xmldom/xmldom/issues/145 * * @param {Node} parentNode * @param {Node} child * @returns {Node} the child that was removed. * @private */ function _removeChild (parentNode, child) { var previous = child.previousSibling; var next = child.nextSibling; if (previous) { previous.nextSibling = next; } else { parentNode.firstChild = next; } if (next) { next.previousSibling = previous; } else { parentNode.lastChild = previous; } child.parentNode = null; child.previousSibling = null; child.nextSibling = null; _onUpdateChild(parentNode.ownerDocument, parentNode); return child; } /** * Returns `true` if `node` can be a parent for insertion. * @param {Node} node * @returns {boolean} */ function hasValidParentNodeType(node) { return ( node && (node.nodeType === Node.DOCUMENT_NODE || node.nodeType === Node.DOCUMENT_FRAGMENT_NODE || node.nodeType === Node.ELEMENT_NODE) ); } /** * Returns `true` if `node` can be inserted according to it's `nodeType`. * @param {Node} node * @returns {boolean} */ function hasInsertableNodeType(node) { return ( node && (isElementNode(node) || isTextNode(node) || isDocTypeNode(node) || node.nodeType === Node.DOCUMENT_FRAGMENT_NODE || node.nodeType === Node.COMMENT_NODE || node.nodeType === Node.PROCESSING_INSTRUCTION_NODE) ); } /** * Returns true if `node` is a DOCTYPE node * @param {Node} node * @returns {boolean} */ function isDocTypeNode(node) { return node && node.nodeType === Node.DOCUMENT_TYPE_NODE; } /** * Returns true if the node is an element * @param {Node} node * @returns {boolean} */ function isElementNode(node) { return node && node.nodeType === Node.ELEMENT_NODE; } /** * Returns true if `node` is a text node * @param {Node} node * @returns {boolean} */ function isTextNode(node) { return node && node.nodeType === Node.TEXT_NODE; } /** * Check if en element node can be inserted before `child`, or at the end if child is falsy, * according to the presence and position of a doctype node on the same level. * * @param {Document} doc The document node * @param {Node} child the node that would become the nextSibling if the element would be inserted * @returns {boolean} `true` if an element can be inserted before child * @private * https://dom.spec.whatwg.org/#concept-node-ensure-pre-insertion-validity */ function isElementInsertionPossible(doc, child) { var parentChildNodes = doc.childNodes || []; if (find(parentChildNodes, isElementNode) || isDocTypeNode(child)) { return false; } var docTypeNode = find(parentChildNodes, isDocTypeNode); return !(child && docTypeNode && parentChildNodes.indexOf(docTypeNode) > parentChildNodes.indexOf(child)); } /** * Check if en element node can be inserted before `child`, or at the end if child is falsy, * according to the presence and position of a doctype node on the same level. * * @param {Node} doc The document node * @param {Node} child the node that would become the nextSibling if the element would be inserted * @returns {boolean} `true` if an element can be inserted before child * @private * https://dom.spec.whatwg.org/#concept-node-ensure-pre-insertion-validity */ function isElementReplacementPossible(doc, child) { var parentChildNodes = doc.childNodes || []; function hasElementChildThatIsNotChild(node) { return isElementNode(node) && node !== child; } if (find(parentChildNodes, hasElementChildThatIsNotChild)) { return false; } var docTypeNode = find(parentChildNodes, isDocTypeNode); return !(child && docTypeNode && parentChildNodes.indexOf(docTypeNode) > parentChildNodes.indexOf(child)); } /** * @private * Steps 1-5 of the checks before inserting and before replacing a child are the same. * * @param {Node} parent the parent node to insert `node` into * @param {Node} node the node to insert * @param {Node=} child the node that should become the `nextSibling` of `node` * @returns {Node} * @throws DOMException for several node combinations that would create a DOM that is not well-formed. * @throws DOMException if `child` is provided but is not a child of `parent`. * @see https://dom.spec.whatwg.org/#concept-node-ensure-pre-insertion-validity * @see https://dom.spec.whatwg.org/#concept-node-replace */ function assertPreInsertionValidity1to5(parent, node, child) { // 1. If `parent` is not a Document, DocumentFragment, or Element node, then throw a "HierarchyRequestError" DOMException. if (!hasValidParentNodeType(parent)) { throw new DOMException(HIERARCHY_REQUEST_ERR, 'Unexpected parent node type ' + parent.nodeType); } // 2. If `node` is a host-including inclusive ancestor of `parent`, then throw a "HierarchyRequestError" DOMException. // not implemented! // 3. If `child` is non-null and its parent is not `parent`, then throw a "NotFoundError" DOMException. if (child && child.parentNode !== parent) { throw new DOMException(NOT_FOUND_ERR, 'child not in parent'); } if ( // 4. If `node` is not a DocumentFragment, DocumentType, Element, or CharacterData node, then throw a "HierarchyRequestError" DOMException. !hasInsertableNodeType(node) || // 5. If either `node` is a Text node and `parent` is a document, // the sax parser currently adds top level text nodes, this will be fixed in 0.9.0 // || (node.nodeType === Node.TEXT_NODE && parent.nodeType === Node.DOCUMENT_NODE) // or `node` is a doctype and `parent` is not a document, then throw a "HierarchyRequestError" DOMException. (isDocTypeNode(node) && parent.nodeType !== Node.DOCUMENT_NODE) ) { throw new DOMException( HIERARCHY_REQUEST_ERR, 'Unexpected node type ' + node.nodeType + ' for parent node type ' + parent.nodeType ); } } /** * @private * Step 6 of the checks before inserting and before replacing a child are different. * * @param {Document} parent the parent node to insert `node` into * @param {Node} node the node to insert * @param {Node | undefined} child the node that should become the `nextSibling` of `node` * @returns {Node} * @throws DOMException for several node combinations that would create a DOM that is not well-formed. * @throws DOMException if `child` is provided but is not a child of `parent`. * @see https://dom.spec.whatwg.org/#concept-node-ensure-pre-insertion-validity * @see https://dom.spec.whatwg.org/#concept-node-replace */ function assertPreInsertionValidityInDocument(parent, node, child) { var parentChildNodes = parent.childNodes || []; var nodeChildNodes = node.childNodes || []; // DocumentFragment if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) { var nodeChildElements = nodeChildNodes.filter(isElementNode); // If node has more than one element child or has a Text node child. if (nodeChildElements.length > 1 || find(nodeChildNodes, isTextNode)) { throw new DOMException(HIERARCHY_REQUEST_ERR, 'More than one element or text in fragment'); } // Otherwise, if `node` has one element child and either `parent` has an element child, // `child` is a doctype, or `child` is non-null and a doctype is following `child`. if (nodeChildElements.length === 1 && !isElementInsertionPossible(parent, child)) { throw new DOMException(HIERARCHY_REQUEST_ERR, 'Element in fragment can not be inserted before doctype'); } } // Element if (isElementNode(node)) { // `parent` has an element child, `child` is a doctype, // or `child` is non-null and a doctype is following `child`. if (!isElementInsertionPossible(parent, child)) { throw new DOMException(HIERARCHY_REQUEST_ERR, 'Only one element can be added and only after doctype'); } } // DocumentType if (isDocTypeNode(node)) { // `parent` has a doctype child, if (find(parentChildNodes, isDocTypeNode)) { throw new DOMException(HIERARCHY_REQUEST_ERR, 'Only one doctype is allowed'); } var parentElementChild = find(parentChildNodes, isElementNode); // `child` is non-null and an element is preceding `child`, if (child && parentChildNodes.indexOf(parentElementChild) < parentChildNodes.indexOf(child)) { throw new DOMException(HIERARCHY_REQUEST_ERR, 'Doctype can only be inserted before an element'); } // or `child` is null and `parent` has an element child. if (!child && parentElementChild) { throw new DOMException(HIERARCHY_REQUEST_ERR, 'Doctype can not be appended since element is present'); } } } /** * @private * Step 6 of the checks before inserting and before replacing a child are different. * * @param {Document} parent the parent node to insert `node` into * @param {Node} node the node to insert * @param {Node | undefined} child the node that should become the `nextSibling` of `node` * @returns {Node} * @throws DOMException for several node combinations that would create a DOM that is not well-formed. * @throws DOMException if `child` is provided but is not a child of `parent`. * @see https://dom.spec.whatwg.org/#concept-node-ensure-pre-insertion-validity * @see https://dom.spec.whatwg.org/#concept-node-replace */ function assertPreReplacementValidityInDocument(parent, node, child) { var parentChildNodes = parent.childNodes || []; var nodeChildNodes = node.childNodes || []; // DocumentFragment if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) { var nodeChildElements = nodeChildNodes.filter(isElementNode); // If `node` has more than one element child or has a Text node child. if (nodeChildElements.length > 1 || find(nodeChildNodes, isTextNode)) { throw new DOMException(HIERARCHY_REQUEST_ERR, 'More than one element or text in fragment'); } // Otherwise, if `node` has one element child and either `parent` has an element child that is not `child` or a doctype is following `child`. if (nodeChildElements.length === 1 && !isElementReplacementPossible(parent, child)) { throw new DOMException(HIERARCHY_REQUEST_ERR, 'Element in fragment can not be inserted before doctype'); } } // Element if (isElementNode(node)) { // `parent` has an element child that is not `child` or a doctype is following `child`. if (!isElementReplacementPossible(parent, child)) { throw new DOMException(HIERARCHY_REQUEST_ERR, 'Only one element can be added and only after doctype'); } } // DocumentType if (isDocTypeNode(node)) { function hasDoctypeChildThatIsNotChild(node) { return isDocTypeNode(node) && node !== child; } // `parent` has a doctype child that is not `child`, if (find(parentChildNodes, hasDoctypeChildThatIsNotChild)) { throw new DOMException(HIERARCHY_REQUEST_ERR, 'Only one doctype is allowed'); } var parentElementChild = find(parentChildNodes, isElementNode); // or an element is preceding `child`. if (child && parentChildNodes.indexOf(parentElementChild) < parentChildNodes.indexOf(child)) { throw new DOMException(HIERARCHY_REQUEST_ERR, 'Doctype can only be inserted before an element'); } } } /** * @private * @param {Node} parent the parent node to insert `node` into * @param {Node} node the node to insert * @param {Node=} child the node that should become the `nextSibling` of `node` * @returns {Node} * @throws DOMException for several node combinations that would create a DOM that is not well-formed. * @throws DOMException if `child` is provided but is not a child of `parent`. * @see https://dom.spec.whatwg.org/#concept-node-ensure-pre-insertion-validity */ function _insertBefore(parent, node, child, _inDocumentAssertion) { // To ensure pre-insertion validity of a node into a parent before a child, run these steps: assertPreInsertionValidity1to5(parent, node, child); // If parent is a document, and any of the statements below, switched on the interface node implements, // are true, then throw a "HierarchyRequestError" DOMException. if (parent.nodeType === Node.DOCUMENT_NODE) { (_inDocumentAssertion || assertPreInsertionValidityInDocument)(parent, node, child); } var cp = node.parentNode; if(cp){ cp.removeChild(node);//remove and update } if(node.nodeType === DOCUMENT_FRAGMENT_NODE){ var newFirst = node.firstChild; if (newFirst == null) { return node; } var newLast = node.lastChild; }else{ newFirst = newLast = node; } var pre = child ? child.previousSibling : parent.lastChild; newFirst.previousSibling = pre; newLast.nextSibling = child; if(pre){ pre.nextSibling = newFirst; }else{ parent.firstChild = newFirst; } if(child == null){ parent.lastChild = newLast; }else{ child.previousSibling = newLast; } do{ newFirst.parentNode = parent; }while(newFirst !== newLast && (newFirst= newFirst.nextSibling)) _onUpdateChild(parent.ownerDocument||parent, parent); //console.log(parent.lastChild.nextSibling == null) if (node.nodeType == DOCUMENT_FRAGMENT_NODE) { node.firstChild = node.lastChild = null; } return node; } /** * Appends `newChild` to `parentNode`. * If `newChild` is already connected to a `parentNode` it is first removed from it. * * @see https://github.com/xmldom/xmldom/issues/135 * @see https://github.com/xmldom/xmldom/issues/145 * @param {Node} parentNode * @param {Node} newChild * @returns {Node} * @private */ function _appendSingleChild (parentNode, newChild) { if (newChild.parentNode) { newChild.parentNode.removeChild(newChild); } newChild.parentNode = parentNode; newChild.previousSibling = parentNode.lastChild; newChild.nextSibling = null; if (newChild.previousSibling) { newChild.previousSibling.nextSibling = newChild; } else { parentNode.firstChild = newChild; } parentNode.lastChild = newChild; _onUpdateChild(parentNode.ownerDocument, parentNode, newChild); return newChild; } Document.prototype = { //implementation : null, nodeName : '#document', nodeType : DOCUMENT_NODE, /** * The DocumentType node of the document. * * @readonly * @type DocumentType */ doctype : null, documentElement : null, _inc : 1, insertBefore : function(newChild, refChild){//raises if(newChild.nodeType == DOCUMENT_FRAGMENT_NODE){ var child = newChild.firstChild; while(child){ var next = child.nextSibling; this.insertBefore(child,refChild); child = next; } return newChild; } _insertBefore(this, newChild, refChild); newChild.ownerDocument = this; if (this.documentElement === null && newChild.nodeType === ELEMENT_NODE) { this.documentElement = newChild; } return newChild; }, removeChild : function(oldChild){ if(this.documentElement == oldChild){ this.documentElement = null; } return _removeChild(this,oldChild); }, replaceChild: function (newChild, oldChild) { //raises _insertBefore(this, newChild, oldChild, assertPreReplacementValidityInDocument); newChild.ownerDocument = this; if (oldChild) { this.removeChild(oldChild); } if (isElementNode(newChild)) { this.documentElement = newChild; } }, // Introduced in DOM Level 2: importNode : function(importedNode,deep){ return importNode(this,importedNode,deep); }, // Introduced in DOM Level 2: getElementById : function(id){ var rtv = null; _visitNode(this.documentElement,function(node){ if(node.nodeType == ELEMENT_NODE){ if(node.getAttribute('id') == id){ rtv = node; return true; } } }) return rtv; }, /** * The `getElementsByClassName` method of `Document` interface returns an array-like object * of all child elements which have **all** of the given class name(s). * * Returns an empty list if `classeNames` is an empty string or only contains HTML white space characters. * * * Warning: This is a live LiveNodeList. * Changes in the DOM will reflect in the array as the changes occur. * If an element selected by this array no longer qualifies for the selector, * it will automatically be removed. Be aware of this for iteration purposes. * * @param {string} classNames is a string representing the class name(s) to match; multiple class names are separated by (ASCII-)whitespace * * @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) { var ls = []; if (classNamesSet.length > 0) { _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)) } if(matches) { ls.push(node); } } } }); } return ls; }); }, //document factory method: createElement : function(tagName){ var node = new Element(); node.ownerDocument = this; node.nodeName = tagName; node.tagName = tagName; node.localName = tagName; node.childNodes = new NodeList(); var attrs = node.attributes = new NamedNodeMap(); attrs._ownerElement = node; return node; }, createDocumentFragment : function(){ var node = new DocumentFragment(); node.ownerDocument = this; node.childNodes = new NodeList(); return node; }, createTextNode : function(data){ var node = new Text(); node.ownerDocument = this; node.appendData(data) return node; }, createComment : function(data){ var node = new Comment(); node.ownerDocument = this; node.appendData(data) return node; }, createCDATASection : function(data){ var node = new CDATASection(); node.ownerDocument = this; node.appendData(data) return node; }, createProcessingInstruction : function(target,data){ var node = new ProcessingInstruction(); node.ownerDocument = this; node.tagName = node.target = target; node.nodeValue= node.data = data; return node; }, createAttribute : function(name){ var node = new Attr(); node.ownerDocument = this; node.name = name; node.nodeName = name; node.localName = name; node.specified = true; return node; }, createEntityReference : function(name){ var node = new EntityReference(); node.ownerDocument = this; node.nodeName = name; return node; }, // Introduced in DOM Level 2: createElementNS : function(namespaceURI,qualifiedName){ var node = new Element(); var pl = qualifiedName.split(':'); 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){ node.prefix = pl[0]; node.localName = pl[1]; }else{ //el.prefix = null; node.localName = qualifiedName; } attrs._ownerElement = node; return node; }, // Introduced in DOM Level 2: createAttributeNS : function(namespaceURI,qualifiedName){ var node = new Attr(); var pl = qualifiedName.split(':'); node.ownerDocument = this; node.nodeName = qualifiedName; node.name = qualifiedName; node.namespaceURI = namespaceURI; node.specified = true; if(pl.length == 2){ node.prefix = pl[0]; node.localName = pl[1]; }else{ //el.prefix = null; node.localName = qualifiedName; } return node; } }; _extends(Document,Node); function Element() { this._nsMap = {}; }; Element.prototype = { nodeType : ELEMENT_NODE, hasAttribute : function(name){ return this.getAttributeNode(name)!=null; }, getAttribute : function(name){ var attr = this.getAttributeNode(name); return attr && attr.value || ''; }, getAttributeNode : function(name){ return this.attributes.getNamedItem(name); }, setAttribute : function(name, value){ var attr = this.ownerDocument.createAttribute(name); attr.value = attr.nodeValue = "" + value; this.setAttributeNode(attr) }, removeAttribute : function(name){ var attr = this.getAttributeNode(name) attr && this.removeAttributeNode(attr); }, //four real opeartion method appendChild:function(newChild){ if(newChild.nodeType === DOCUMENT_FRAGMENT_NODE){ return this.insertBefore(newChild,null); }else{ return _appendSingleChild(this,newChild); } }, setAttributeNode : function(newAttr){ return this.attributes.setNamedItem(newAttr); }, setAttributeNodeNS : function(newAttr){ return this.attributes.setNamedItemNS(newAttr); }, 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){ var old = this.getAttributeNodeNS(namespaceURI, localName); old && this.removeAttributeNode(old); }, hasAttributeNS : function(namespaceURI, localName){ return this.getAttributeNodeNS(namespaceURI, localName)!=null; }, getAttributeNS : function(namespaceURI, localName){ var attr = this.getAttributeNodeNS(namespaceURI, localName); return attr && attr.value || ''; }, setAttributeNS : function(namespaceURI, qualifiedName, value){ var attr = this.ownerDocument.createAttributeNS(namespaceURI, qualifiedName); attr.value = attr.nodeValue = "" + value; this.setAttributeNode(attr) }, getAttributeNodeNS : function(namespaceURI, localName){ return this.attributes.getNamedItemNS(namespaceURI, localName); }, getElementsByTagName : function(tagName){ return new LiveNodeList(this,function(base){ var ls = []; _visitNode(base,function(node){ if(node !== base && node.nodeType == ELEMENT_NODE && (tagName === '*' || node.tagName == tagName)){ ls.push(node); } }); return ls; }); }, 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)){ ls.push(node); } }); return ls; }); } }; Document.prototype.getElementsByTagName = Element.prototype.getElementsByTagName; Document.prototype.getElementsByTagNameNS = Element.prototype.getElementsByTagNameNS; _extends(Element,Node); function Attr() { }; Attr.prototype.nodeType = ATTRIBUTE_NODE; _extends(Attr,Node); function CharacterData() { }; CharacterData.prototype = { data : '', substringData : function(offset, count) { return this.data.substring(offset, offset+count); }, 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); }, appendChild:function(newChild){ throw new Error(ExceptionMessage[HIERARCHY_REQUEST_ERR]) }, 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); text = start + text + end; this.nodeValue = this.data = text; this.length = text.length; } } _extends(CharacterData,Node); function Text() { }; Text.prototype = { 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){ this.parentNode.insertBefore(newNode, this.nextSibling); } return newNode; } } _extends(Text,CharacterData); function Comment() { }; Comment.prototype = { nodeName : "#comment", nodeType : COMMENT_NODE } _extends(Comment,CharacterData); 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); function Notation() { }; Notation.prototype.nodeType = NOTATION_NODE; _extends(Notation,Node); function Entity() { }; Entity.prototype.nodeType = ENTITY_NODE; _extends(Entity,Node); 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); function ProcessingInstruction() { } ProcessingInstruction.prototype.nodeType = PROCESSING_INSTRUCTION_NODE; _extends(ProcessingInstruction,Node); function XMLSerializer(){} XMLSerializer.prototype.serializeToString = function(node,isHtml,nodeFilter){ return nodeSerializeToString.call(node,isHtml,nodeFilter); } Node.prototype.toString = nodeSerializeToString; function nodeSerializeToString(isHtml,nodeFilter){ var buf = []; var refNode = this.nodeType == 9 && this.documentElement || this; var prefix = refNode.prefix; var uri = refNode.namespaceURI; if(uri && prefix == null){ //console.log(prefix) var prefix = refNode.lookupPrefix(uri); if(prefix == null){ //isHTML = true; var visibleNamespaces=[ {namespace:uri,prefix:null} //{namespace:uri,prefix:''} ] } } serializeToString(this,buf,isHtml,nodeFilter,visibleNamespaces); //console.log('###',this.nodeType,uri,prefix,buf.join('')) return buf.join(''); } function needNamespaceDefine(node, isHTML, visibleNamespaces) { var prefix = node.prefix || ''; var uri = node.namespaceURI; // According to [Namespaces in XML 1.0](https://www.w3.org/TR/REC-xml-names/#ns-using) , // and more specifically https://www.w3.org/TR/REC-xml-names/#nsc-NoPrefixUndecl : // > In a namespace declaration for a prefix [...], the attribute value MUST NOT be empty. // in a similar manner [Namespaces in XML 1.1](https://www.w3.org/TR/xml-names11/#ns-using) // and more specifically https://www.w3.org/TR/xml-names11/#nsc-NSDeclared : // > [...] Furthermore, the attribute value [...] must not be an empty string. // so serializing empty namespace value like xmlns:ds="" would produce an invalid XML document. if (!uri) { return false; } if (prefix === "xml" && uri === NAMESPACE.XML || uri === NAMESPACE.XMLNS) { return false; } var i = visibleNamespaces.length while (i--) { var ns = visibleNamespaces[i]; // get namespace prefix if (ns.prefix === prefix) { return ns.namespace !== uri; } } return true; } /** * Well-formed constraint: No < in Attribute Values * > The replacement text of any entity referred to directly or indirectly * > in an attribute value must not contain a <. * @see https://www.w3.org/TR/xml11/#CleanAttrVals * @see https://www.w3.org/TR/xml11/#NT-AttValue * * Literal whitespace other than space that appear in attribute values * are serialized as their entity references, so they will be preserved. * (In contrast to whitespace literals in the input which are normalized to spaces) * @see https://www.w3.org/TR/xml11/#AVNormalize * @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), '"') } function serializeToString(node,buf,isHTML,nodeFilter,visibleNamespaces){ if (!visibleNamespaces) { visibleNamespaces = []; } if(nodeFilter){ node = nodeFilter(node); if(node){ if(typeof node == 'string'){ buf.push(node); return; } }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; isHTML = NAMESPACE.isHTML(node.namespaceURI) || isHTML 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 !== 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 } } } } buf.push('<', prefixedNodeName); for(var i=0;i'); //if is cdata child node if(isHTML && /^script$/i.test(nodeName)){ while(child){ if(child.data){ buf.push(child.data); }else{ serializeToString(child, buf, isHTML, nodeFilter, visibleNamespaces.slice()); } child = child.nextSibling; } }else { while(child){ serializeToString(child, buf, isHTML, nodeFilter, visibleNamespaces.slice()); child = child.nextSibling; } } buf.push(''); }else{ 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, isHTML, 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,"]"); } 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); } } function importNode(doc,node,deep){ var node2; switch (node.nodeType) { 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:'"'}) /** * A map of currently 241 entities that are detected in an HTML document. * They contain all entries from `XML_ENTITIES`. * * @see XML_ENTITIES * @see DOMParser.parseFromString * @see DOMImplementation.prototype.createHTMLDocument * @see https://html.spec.whatwg.org/#named-character-references WHATWG HTML(5) Spec * @see https://www.w3.org/TR/xml-entity-names/ W3C XML Entity Names * @see https://www.w3.org/TR/html4/sgml/entities.html W3C HTML4/SGML * @see https://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references#Character_entity_references_in_HTML Wikipedia (HTML) * @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: "À", Aacute: "Á", Acirc: "Â", Atilde: "Ã", Auml: "Ä", Aring: "Å", AElig: "Æ", Ccedil: "Ç", Egrave: "È", Eacute: "É", Ecirc: "Ê", Euml: "Ë", Igrave: "Ì", Iacute: "Í", Icirc: "Î", Iuml: "Ï", ETH: "Ð", Ntilde: "Ñ", Ograve: "Ò", Oacute: "Ó", Ocirc: "Ô", Otilde: "Õ", Ouml: "Ö", Oslash: "Ø", Ugrave: "Ù", Uacute: "Ú", Ucirc: "Û", Uuml: "Ü", Yacute: "Ý", THORN: "Þ", szlig: "ß", agrave: "à", aacute: "á", acirc: "â", atilde: "ã", auml: "ä", aring: "å", aelig: "æ", ccedil: "ç", egrave: "è", eacute: "é", ecirc: "ê", euml: "ë", igrave: "ì", iacute: "í", icirc: "î", iuml: "ï", eth: "ð", ntilde: "ñ", ograve: "ò", oacute: "ó", ocirc: "ô", otilde: "õ", ouml: "ö", oslash: "ø", ugrave: "ù", uacute: "ú", ucirc: "û", uuml: "ü", yacute: "ý", thorn: "þ", yuml: "ÿ", nbsp: "\u00a0", iexcl: "¡", cent: "¢", pound: "£", curren: "¤", yen: "¥", brvbar: "¦", sect: "§", uml: "¨", copy: "©", ordf: "ª", laquo: "«", not: "¬", shy: "­­", reg: "®", macr: "¯", deg: "°", plusmn: "±", sup2: "²", sup3: "³", acute: "´", micro: "µ", para: "¶", middot: "·", cedil: "¸", sup1: "¹", ordm: "º", raquo: "»", frac14: "¼", frac12: "½", frac34: "¾", iquest: "¿", times: "×", divide: "÷", forall: "∀", part: "∂", exist: "∃", empty: "∅", nabla: "∇", isin: "∈", notin: "∉", ni: "∋", prod: "∏", sum: "∑", minus: "−", lowast: "∗", radic: "√", prop: "∝", infin: "∞", ang: "∠", and: "∧", or: "∨", cap: "∩", cup: "∪", 'int': "∫", there4: "∴", sim: "∼", cong: "≅", asymp: "≈", ne: "≠", equiv: "≡", le: "≤", ge: "≥", sub: "⊂", sup: "⊃", nsub: "⊄", sube: "⊆", supe: "⊇", oplus: "⊕", otimes: "⊗", perp: "⊥", sdot: "⋅", Alpha: "Α", Beta: "Β", Gamma: "Γ", Delta: "Δ", Epsilon: "Ε", Zeta: "Ζ", Eta: "Η", Theta: "Θ", Iota: "Ι", Kappa: "Κ", Lambda: "Λ", Mu: "Μ", Nu: "Ν", Xi: "Ξ", Omicron: "Ο", Pi: "Π", Rho: "Ρ", Sigma: "Σ", Tau: "Τ", Upsilon: "Υ", Phi: "Φ", Chi: "Χ", Psi: "Ψ", Omega: "Ω", alpha: "α", beta: "β", gamma: "γ", delta: "δ", epsilon: "ε", zeta: "ζ", eta: "η", theta: "θ", iota: "ι", kappa: "κ", lambda: "λ", mu: "μ", nu: "ν", xi: "ξ", omicron: "ο", pi: "π", rho: "ρ", sigmaf: "ς", sigma: "σ", tau: "τ", upsilon: "υ", phi: "φ", chi: "χ", psi: "ψ", omega: "ω", thetasym: "ϑ", upsih: "ϒ", piv: "ϖ", OElig: "Œ", oelig: "œ", Scaron: "Š", scaron: "š", Yuml: "Ÿ", fnof: "ƒ", circ: "ˆ", tilde: "˜", ensp: " ", emsp: " ", thinsp: " ", zwnj: "‌", zwj: "‍", lrm: "‎", rlm: "‏", ndash: "–", mdash: "—", lsquo: "‘", rsquo: "’", sbquo: "‚", ldquo: "“", rdquo: "”", bdquo: "„", dagger: "†", Dagger: "‡", bull: "•", hellip: "…", permil: "‰", prime: "′", Prime: "″", lsaquo: "‹", rsaquo: "›", oline: "‾", euro: "€", trade: "™", larr: "←", uarr: "↑", rarr: "→", darr: "↓", harr: "↔", crarr: "↵", lceil: "⌈", rceil: "⌉", lfloor: "⌊", rfloor: "⌋", loz: "◊", spades: "♠", clubs: "♣", hearts: "♥", diams: "♦" }); /** * @deprecated use `HTML_ENTITIES` instead * @see HTML_ENTITIES */ exports.entityMap = exports.HTML_ENTITIES xmldom-0.8.6/lib/index.js000066400000000000000000000002551433143211200152340ustar00rootroot00000000000000var dom = require('./dom') exports.DOMImplementation = dom.DOMImplementation exports.XMLSerializer = dom.XMLSerializer exports.DOMParser = require('./dom-parser').DOMParser xmldom-0.8.6/lib/sax.js000066400000000000000000000461521433143211200147260ustar00rootroot00000000000000var NAMESPACE = require("./conventions").NAMESPACE; //[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 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 /** * Creates an error that will not be caught by XMLReader aka the SAX parser. * * @param {string} message * @param {any?} locator Optional, can provide details about the location in the source * @constructor */ function ParseError(message, locator) { this.message = message this.locator = locator if(Error.captureStackTrace) Error.captureStackTrace(this, ParseError); } ParseError.prototype = new Error(); ParseError.prototype.name = ParseError.name function XMLReader(){ } XMLReader.prototype = { parse:function(source,defaultNSMap,entityMap){ var domBuilder = this.domBuilder; domBuilder.startDocument(); _copy(defaultNSMap ,defaultNSMap = {}) parse(source,defaultNSMap,entityMap, domBuilder,this.errorHandler); domBuilder.endDocument(); } } function parse(source,defaultNSMapCopy,entityMap,domBuilder,errorHandler){ 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); return String.fromCharCode(surrogate1, surrogate2); } else { return String.fromCharCode(code); } } 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); 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 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; } var lineStart = 0; var lineEnd = 0; var linePattern = /.*(?:\r\n?|\n)|.*$/g var locator = domBuilder.locator; 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*$/)){ var doc = domBuilder.doc; var text = doc.createTextNode(source.substr(start)); doc.appendChild(text); domBuilder.currentElement = text; } return; } if(tagStart>start){ appendText(tagStart); } switch(source.charAt(tagStart+1)){ case '/': var end = source.indexOf('>',tagStart+3); var tagName = source.substring(tagStart + 2, end).replace(/[ \t\n\r]+$/g, ''); var config = parseStack.pop(); if(end<0){ tagName = source.substring(tagStart+2).replace(/[\s<].*/,''); errorHandler.error("end tag name: "+tagName+' is not complete:'+config.tagName); end = tagStart+1+tagName.length; }else if(tagName.match(/\s locator&&position(tagStart); end = parseInstruction(source,tagStart,domBuilder); break; case '!':// start){ start = end; }else{ //TODO: 这里有可能sax回退,有位置错误风险 appendText(Math.max(tagStart,start)+1); } } } function copyLocator(f,t){ t.lineNumber = f.lineNumber; t.columnNumber = f.columnNumber; return 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){ /** * @param {string} qname * @param {string} value * @param {number} startIndex */ function addAttribute(qname, value, startIndex) { if (el.attributeNames.hasOwnProperty(qname)) { errorHandler.fatalError('Attribute ' + qname + ' redefined') } el.addValue( qname, // @see https://www.w3.org/TR/xml/#AVNormalize // since the xmldom sax parser does not "interpret" DTD the following is not implemented: // - recursive replacement of (DTD) entity references // - 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 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) } 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); 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(!NAMESPACE.isHTML(currentNSMap['']) || !value.match(/^(?:disabled|checked|selected)$/i)){ 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 (!NAMESPACE.isHTML(currentNSMap['']) || !attrName.match(/^(?:disabled|checked|selected)$/i)) { 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"); } } }//end outer switch //console.log('p++',p) p++; } } /** * @return true if has new namespace define */ 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--){ 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{ localName = qName; prefix = null nsPrefix = qName === 'xmlns' && '' } //can not set prefix,because prefix !== '' a.localName = localName ; //prefix == null for no ns prefix attribute if(nsPrefix !== false){//hack!! if(localNSMap == null){ localNSMap = {} //console.log(currentNSMap,0) _copy(currentNSMap,currentNSMap={}) //console.log(currentNSMap,1) } currentNSMap[nsPrefix] = localNSMap[nsPrefix] = value; a.uri = NAMESPACE.XMLNS domBuilder.startPrefixMapping(nsPrefix, value) } } var i = el.length; while(i--){ a = el[i]; var prefix = a.prefix; if(prefix){//no prefix attribute has no namespace if(prefix === 'xml'){ a.uri = NAMESPACE.XML; }if(prefix !== 'xmlns'){ a.uri = currentNSMap[prefix || ''] //{console.log('###'+a.qName,domBuilder.locator.systemId+'',currentNSMap,a.uri)} } } } 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!! localName = el.localName = tagName; } //no prefix element has default namespace 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){ for (prefix in localNSMap) { if (Object.prototype.hasOwnProperty.call(localNSMap, prefix)) { domBuilder.endPrefixMapping(prefix); } } } }else{ el.currentNSMap = currentNSMap; el.localNSMap = localNSMap; //parseStack.push(el); return true; } } function parseHtmlSpecialContent(source,elStartEnd,tagName,entityReplacer,domBuilder){ if(/^(?:script|textarea)$/i.test(tagName)){ var elEndStart = source.indexOf('',elStartEnd); var text = source.substring(elStartEnd+1,elEndStart); if(/[&<]/.test(text)){ if(/^script$/i.test(tagName)){ //if(!/\]\]>/.test(text)){ //lexHandler.startCDATA(); domBuilder.characters(text,0,text.length); //lexHandler.endCDATA(); return elEndStart; //} }//}else{//text area text = text.replace(/&#?\w+;/g,entityReplacer); domBuilder.characters(text,0,text.length); return elEndStart; //} } } return elStartEnd+1; } function fixSelfClosed(source,elStartEnd,tagName,closeMap){ //if(tagName in closeMap){ var pos = closeMap[tagName]; if(pos == null){ //console.log(tagName) pos = source.lastIndexOf('') if(pos',start+4); //append comment source.substring(4,end)// ![Overview of related specifications and their relations](docs/specs.svg) ### DOM Parsing and Serialization From the [W3C DOM Parsing and Serialization (WD 2016)](https://www.w3.org/TR/2016/WD-DOM-Parsing-20160517/) `xmldom` provides an implementation for the interfaces: - `DOMParser` - `XMLSerializer` Note that there are some known deviations between this implementation and the W3 specifications. Note: [The latest version of this spec](https://w3c.github.io/DOM-Parsing/) has the status "Editors Draft", since it is under active development. One major change is that [the definition of the `DOMParser` interface has been moved to the HTML spec](https://w3c.github.io/DOM-Parsing/#the-domparser-interface) ### DOM The original author claims that xmldom implements [DOM Level 2] in a "fully compatible" way and some parts of [DOM Level 3], but there are not enough tests to prove this. Both Specifications are now superseded by the [DOM Level 4 aka Living standard] wich has a much broader scope than xmldom. xmldom implements the following interfaces (most constructors are currently not exposed): - `Attr` - `CDATASection` - `CharacterData` - `Comment` - `Document` - `DocumentFragment` - `DocumentType` - `DOMException` (constructor exposed) - `DOMImplementation` (constructor exposed) - `Element` - `Entity` - `EntityReference` - `LiveNodeList` - `NamedNodeMap` - `Node` (constructor exposed) - `NodeList` - `Notation` - `ProcessingInstruction` - `Text` more details are available in the (incomplete) [API Reference](#api-reference) section. ### HTML xmldom does not have any goal of supporting the full spec, but it has some capability to parse, report and serialize things differently when "detecting HTML" (by checking the default namespace). There is an upcoming change to better align the implementation with the latest specs, related to . ### SAX, XML, XMLNS xmldom has an own SAX parser implementation to do the actual parsing, which implements some interfaces in alignment with the Java interfaces SAX defines: - `XMLReader` - `DOMHandler` There is an idea/proposal to make it possible to replace it with something else in xmldom-0.8.6/renovate.json000066400000000000000000000005651433143211200155430ustar00rootroot00000000000000{ "extends": [ "config:base", ":preserveSemverRanges", ":ignoreUnstable", ":respectLatest", ":semanticCommits", ":pinAllExceptPeerDependencies", "npm:unpublishSafe" ], "dependencyDashboard": true, "prHourlyLimit": 0, "rangeStrategy": "bump", "packageRules": [ { "packageNames": ["node"], "enabled": false } ] } xmldom-0.8.6/stryker.conf.json000066400000000000000000000011141433143211200163360ustar00rootroot00000000000000{ "$schema": "./node_modules/@stryker-mutator/core/schema/stryker-schema.json", "packageManager": "npm", "reporters": [ "html", "clear-text", "progress", "dashboard" ], "testRunner": "command", "dashboard": { "project": "github.com/xmldom/xmldom", "version": "master" }, "coverageAnalysis": "off", "commandRunner": { "command": "npm test -- --bail --no-cache --ci --maxWorkers=1" }, "timeoutMS_comment": "When all tests pass (mutant survives) our tests need some time. So this is configured to prevent 'timeout's", "timeoutMS": 15000 } xmldom-0.8.6/test/000077500000000000000000000000001433143211200137765ustar00rootroot00000000000000xmldom-0.8.6/test/.eslintrc.yml000066400000000000000000000003221433143211200164170ustar00rootroot00000000000000# FUTURE TBD: add extends with 'plugin:prettier/recommended' # to top-level `.eslintrc.yml` file instead extends: 'plugin:prettier/recommended' # FUTURE TBD top-level: rules: strict: - error - global xmldom-0.8.6/test/conventions/000077500000000000000000000000001433143211200163435ustar00rootroot00000000000000xmldom-0.8.6/test/conventions/__snapshots__/000077500000000000000000000000001433143211200211615ustar00rootroot00000000000000xmldom-0.8.6/test/conventions/__snapshots__/mime-type.test.js.snap000066400000000000000000000013211433143211200253400ustar00rootroot00000000000000// Jest Snapshot v1, https://goo.gl/fbAQLP exports[`MIME_TYPE should contain immutable HTML with correct value 1`] = ` Array [ "HTML", "text/html", ] `; exports[`MIME_TYPE should contain immutable XML_APPLICATION with correct value 1`] = ` Array [ "XML_APPLICATION", "application/xml", ] `; exports[`MIME_TYPE should contain immutable XML_SVG_IMAGE with correct value 1`] = ` Array [ "XML_SVG_IMAGE", "image/svg+xml", ] `; exports[`MIME_TYPE should contain immutable XML_TEXT with correct value 1`] = ` Array [ "XML_TEXT", "text/xml", ] `; exports[`MIME_TYPE should contain immutable XML_XHTML_APPLICATION with correct value 1`] = ` Array [ "XML_XHTML_APPLICATION", "application/xhtml+xml", ] `; xmldom-0.8.6/test/conventions/__snapshots__/namespace.test.js.snap000066400000000000000000000011101433143211200253620ustar00rootroot00000000000000// Jest Snapshot v1, https://goo.gl/fbAQLP exports[`NAMESPACE should contain immutable HTML with correct value 1`] = ` Array [ "HTML", "http://www.w3.org/1999/xhtml", ] `; exports[`NAMESPACE should contain immutable SVG with correct value 1`] = ` Array [ "SVG", "http://www.w3.org/2000/svg", ] `; exports[`NAMESPACE should contain immutable XML with correct value 1`] = ` Array [ "XML", "http://www.w3.org/XML/1998/namespace", ] `; exports[`NAMESPACE should contain immutable XMLNS with correct value 1`] = ` Array [ "XMLNS", "http://www.w3.org/2000/xmlns/", ] `; xmldom-0.8.6/test/conventions/assign.test.js000066400000000000000000000024221433143211200211430ustar00rootroot00000000000000'use strict' const { assign } = require('../../lib/conventions') describe('assign', () => { test.each([null, undefined, true, false, 0, NaN])( 'should throw when `target` is `%s`', (target) => { expect(() => assign(target, {})).toThrow(TypeError) } ) test('should return target', () => { const target = {} expect(assign(target, undefined)).toBe(target) }) test('should copy all enumerable fields from source to target', () => { const target = {} const source = { a: 'A', 0: 0 } assign(target, source) expect(target).toEqual(source) }) test('should not copy prototype properties to source', () => { const target = {} function Clazz(yes) { this.yes = yes } Clazz.prototype.dont = 5 Clazz.prototype.hasOwnProperty = () => true const source = new Clazz(1) assign(target, source) expect(target).toEqual({ yes: 1 }) }) test('should have no issue with null source', () => { const target = {} assign(target, null) }) test('should have no issue with undefined source', () => { const target = {} assign(target, undefined) }) test('should override existing keys', () => { const target = { key: 4, same: 'same' } const source = { key: undefined } assign(target, source) expect(target).toEqual({ key: undefined, same: 'same' }) }) }) xmldom-0.8.6/test/conventions/find.test.js000066400000000000000000000014501433143211200205770ustar00rootroot00000000000000'use strict' const { find } = require('../../lib/conventions') describe('find', () => { it('should work in node without pasing an ArrayConstructor', () => { const predicate = jest.fn((item) => item === 'b') const list = ['a', 'b', 'c'] expect(find(list, predicate)).toBe('b') expect(predicate).toHaveBeenCalledTimes(2) expect(predicate).toHaveBeenCalledWith('a', 0, list) expect(predicate).toHaveBeenCalledWith('b', 1, list) }) it('should work when ArrayConstructor does not provide find', () => { const predicate = jest.fn((item) => item === 'b') const list = ['a', 'b', 'c'] expect(find(list, predicate, {})).toBe('b') expect(predicate).toHaveBeenCalledTimes(2) expect(predicate).toHaveBeenCalledWith('a', 0, list) expect(predicate).toHaveBeenCalledWith('b', 1, list) }) }) xmldom-0.8.6/test/conventions/freeze.test.js000066400000000000000000000023201433143211200211340ustar00rootroot00000000000000'use strict' const { freeze } = require('../../lib/conventions') describe('freeze', () => { it('should return the frozen object (works in node)', () => { const input = { k: 'v' } const actual = freeze(input) expect(actual).toBe(input) try { actual.k = 0 actual.a = 'b' delete actual.k } catch { // Nothing can be added to or removed from the properties set of a frozen object. // Any attempt to do so will fail, either silently or by throwing a TypeError exception // (most commonly, but not exclusively, when in strict mode). } expect(actual).toEqual(input) }) it('should return `input` if `Object.freeze` is not available', () => { const input = { k: 'v' } const actual = freeze(input, {}) expect(actual).toBe(input) }) it('should return input if Object is not available', () => { const input = { k: 'v' } const actual = freeze(input, null) expect(actual).toBe(input) }) it('should use the custom ObjectConstructor correctly', () => { const input = { k: 'v' } const frozen = { ...input } const freezeStub = jest.fn(() => frozen) const actual = freeze(input, { freeze: freezeStub }) expect(freezeStub).toHaveBeenCalledWith(input) expect(actual).toBe(frozen) }) }) xmldom-0.8.6/test/conventions/mime-type.test.js000066400000000000000000000016511433143211200215700ustar00rootroot00000000000000'use strict' const { MIME_TYPE } = require('../../lib/conventions') describe('MIME_TYPE', () => { Object.keys(MIME_TYPE).forEach((key) => { if (key === 'isHTML') { describe('isHTML', () => { it("should return true for 'text/html'", () => { expect(MIME_TYPE.isHTML('text/html')).toBe(true) }) it('should return true for MIME_TYPE.HTML', () => { expect(MIME_TYPE.isHTML(MIME_TYPE.HTML)).toBe(true) }) it.each([ undefined, null, 0, 1, false, true, '', MIME_TYPE.XML_XHTML_APPLICATION, ])("should return false for '%s'", (value) => { expect(MIME_TYPE.isHTML(value)).toBe(false) }) }) } else { const value = MIME_TYPE[key] it(`should contain immutable ${key} with correct value`, () => { expect([key, value]).toMatchSnapshot() try { MIME_TYPE[key] = 'boo' } catch {} expect(MIME_TYPE[key]).toBe(value) }) } }) }) xmldom-0.8.6/test/conventions/namespace.test.js000066400000000000000000000016401433143211200216140ustar00rootroot00000000000000'use strict' const { NAMESPACE } = require('../../lib/conventions') describe('NAMESPACE', () => { Object.keys(NAMESPACE).forEach((key) => { if (key === 'isHTML') { describe('isHTML', () => { it('should return true for NAMESPACE.HTML', () => { expect(NAMESPACE.isHTML(NAMESPACE.HTML)).toBe(true) }) it("should return true for 'http://www.w3.org/1999/xhtml'", () => { expect(NAMESPACE.isHTML('http://www.w3.org/1999/xhtml')).toBe(true) }) it.each([undefined, null, 0, 1, false, true, '', NAMESPACE.XML])( "should return false for '%s'", (value) => { expect(NAMESPACE.isHTML(value)).toBe(false) } ) }) } else { const value = NAMESPACE[key] it(`should contain immutable ${key} with correct value`, () => { expect([key, value]).toMatchSnapshot() try { NAMESPACE[key] = 'boo' } catch {} expect(NAMESPACE[key]).toBe(value) }) } }) }) xmldom-0.8.6/test/dom-parser.test.js000066400000000000000000000052051433143211200173650ustar00rootroot00000000000000'use strict' const { DOMParser } = require('../lib') describe('DOMParser', () => { describe('constructor', () => { test('should store passed options.locator', () => { const options = { locator: {} } const it = new DOMParser(options) // TODO: is there a simpler way to test this that doesn't involve invoking parseFromString? it.parseFromString('') const expected = { columnNumber: 1, lineNumber: 1, } expect(options.locator).toStrictEqual(expected) }) test('should store passed options.xmlns for default mime type', () => { const options = { xmlns: { '': 'custom-default-ns' } } const it = new DOMParser(options) // TODO: is there a simpler way to test this that doesn't involve invoking parseFromString? const actual = it.parseFromString('') expect(actual.toString()).toBe('') }) test('should store and modify passed options.xmlns for html mime type', () => { const options = { xmlns: { '': 'custom-default-ns' } } const it = new DOMParser(options) // TODO: is there a simpler way to test this that doesn't involve invoking parseFromString? it.parseFromString('', 'text/html') expect(options.xmlns['']).toBe('http://www.w3.org/1999/xhtml') }) }) describe('parseFromString', () => { test('should use minimal entity map for default mime type', () => { const XML = '< &' const actual = new DOMParser().parseFromString(XML).toString() expect(actual).toBe(XML) }) test('should provide access to textContent and attribute values', () => { // provides an executable example for https://github.com/xmldom/xmldom/issues/93 const XML = ` first second last ` /* TODO: again this is the "simples and most readable way, but it also means testing it over and over */ const document = new DOMParser().parseFromString(XML) /* FIXME: from here we are actually testing the Document/Element/Node API maybe this should be split? */ const textTags = document.getElementsByTagName('text') expect(textTags).toHaveLength(3) const expectedText = ['first', 'second', 'last'] for (let i = 0; i < textTags.length; i++) { const textTag = textTags[i] expect(textTag.textContent).toBe(expectedText[i]) expect(textTag.getAttribute('top')).toBe(`${i}`) } }) }) }) xmldom-0.8.6/test/dom/000077500000000000000000000000001433143211200145555ustar00rootroot00000000000000xmldom-0.8.6/test/dom/attr.test.js000066400000000000000000000040131433143211200170410ustar00rootroot00000000000000'use strict' const { DOMParser } = require('../../lib') const { DOMException } = require('../../lib/dom') describe('XML attrs', () => { it('can properly set attribute', () => { const root = new DOMParser().parseFromString( '', 'text/xml' ).documentElement root.setAttribute('a', '1') expect(root.attributes[0].localName).toBe('a') root.setAttribute('b', 2) root.setAttribute('a', 1) root.setAttribute('a', 1) root.setAttribute('a', 1) expect(root.attributes.length).toBe(2) const c = root.ownerDocument.createElement('c') expect(() => { c.setAttributeNode(root.attributes.item(0)) }).toThrow(new DOMException(DOMException.INUSE_ATTRIBUTE_ERR)) }) it('can properly set ns attribute', () => { const root = new DOMParser().parseFromString( "", 'text/xml' ).documentElement const child = root.firstChild child.setAttributeNS('a', 'a:a', '1') child.setAttributeNS('b', 'b:b', '2') child.setAttributeNS('b', 'b:a', '1') expect(child.attributes.length).toBe(3) child.setAttribute('a', 1) child.setAttributeNS('b', 'b:b', '2') expect(child.attributes.length).toBe(4) const c = root.ownerDocument.createElement('c') expect(() => { c.setAttributeNodeNS(root.attributes.item(0)) }).toThrow(new DOMException(DOMException.INUSE_ATTRIBUTE_ERR)) }) it('can properly override attribute', () => { const root = new DOMParser().parseFromString( "", 'text/xml' ).documentElement root.setAttributeNS('a', 'a:a', '1') expect(root.attributes.length).toBe(4) }) it('properly supports attribute namespace', () => { const root = new DOMParser().parseFromString( "", 'text/xml' ).documentElement expect(root.getAttributeNS('a', 'b')).toBe('e') }) xit('can properly override ns attribute', () => {}) xit('can properly set existed attribute', () => {}) xit('can properly set document existed attribute', () => {}) }) xmldom-0.8.6/test/dom/clone.test.js000066400000000000000000000017521433143211200171760ustar00rootroot00000000000000'use strict' const { DOMParser, XMLSerializer } = require('../../lib') describe('XML Namespace Parse', () => { it('can properly set clone', () => { const doc1 = new DOMParser().parseFromString( "text1text2", 'text/xml' ) const doc1s = new XMLSerializer().serializeToString(doc1) const n = doc1.cloneNode(true) expect(n.toString()).toBe(doc1s.toString()) }) it('can properly import', () => { const doc1 = new DOMParser().parseFromString("") const doc2 = new DOMParser().parseFromString( "text1text2", 'text/xml' ) const doc3 = new DOMParser().parseFromString( "text1text2" ) const n = doc1.importNode(doc2.documentElement, true) doc1.documentElement.appendChild(n) expect(doc1.toString()).toBe(doc3.toString()) expect(doc2.toString()).not.toBe(doc3.toString()) }) }) xmldom-0.8.6/test/dom/document.test.js000066400000000000000000000164551433143211200177220ustar00rootroot00000000000000'use strict' const { getTestParser } = require('../get-test-parser') const { DOMImplementation, DOMException } = require('../../lib/dom') const INPUT = (first = '', second = '', third = '', fourth = '') => `

Lorem ipsum

Lorem ipsum

Lorem ipsum

Lorem ipsum

` /** * Whitespace that can be part of classnames. * Some characters (like `\u2028`) will be normalized when parsing, * but they can still be added to the dom after parsing. * * @see https://www.w3.org/TR/html52/infrastructure.html#set-of-space-separated-tokens * @see normalizeLineEndings * @see https://www.w3.org/TR/xml11/#sec-line-ends */ const NON_HTML_WHITESPACE = '\v\u00a0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000\ufeff' describe('Document.prototype', () => { describe('getElementsByClassName', () => { it('should be able to resolve [] as a class name', () => { const doc = getTestParser().parser.parseFromString(INPUT('[]')) expect(doc.getElementsByClassName('[]')).toHaveLength(1) }) it('should be able to resolve [ as a class name', () => { const doc = getTestParser().parser.parseFromString(INPUT('[')) expect(doc.getElementsByClassName('[')).toHaveLength(1) }) it('should be able to resolve multiple class names in a different order', () => { const doc = getTestParser().parser.parseFromString(INPUT()) expect(doc.getElementsByClassName('odd quote')).toHaveLength(2) }) it('should be able to resolve non html whitespace as classname', () => { const doc = getTestParser().parser.parseFromString(INPUT()) const firstP = doc.documentElement .getElementsByTagName('body')[0] .getElementsByTagName('p')[0] expect(firstP).toBeDefined() firstP.setAttribute( 'class', firstP.getAttribute('class') + ' ' + NON_HTML_WHITESPACE ) expect( doc.getElementsByClassName(`quote ${NON_HTML_WHITESPACE}`) ).toHaveLength(1) }) it('should not allow regular expression in argument', () => { const search = '(((a||||)+)+)+' const matching = 'aaaaa' expect(new RegExp(search).test(matching)).toBe(true) const doc = getTestParser().parser.parseFromString( INPUT(search, matching, search) ) expect(doc.getElementsByClassName(search)).toHaveLength(2) }) it('should return an empty collection when no class names or are passed', () => { const doc = getTestParser().parser.parseFromString(INPUT()) expect(doc.getElementsByClassName('')).toHaveLength(0) }) it('should return an empty collection when only spaces are passed', () => { const doc = getTestParser().parser.parseFromString( INPUT(' \f\n\r\t', ' \f\n\r\t', ' \f\n\r\t', ' \f\n\r\t') ) expect(doc.getElementsByClassName(' \f\n\r\t')).toHaveLength(0) }) it('should return only the case insensitive matching names', () => { const MIXED_CASES = ['AAA', 'AAa', 'AaA', 'aAA'] const doc = getTestParser().parser.parseFromString(INPUT(...MIXED_CASES)) MIXED_CASES.forEach((className) => { expect(doc.getElementsByClassName(className)).toHaveLength(1) }) }) }) describe('doctype', () => { it('should be added when passed to createDocument', () => { const impl = new DOMImplementation() const doctype = impl.createDocumentType('name') const doc = impl.createDocument(null, undefined, doctype) expect(doc.doctype === doctype).toBe(true) expect(doctype.ownerDocument === doc).toBe(true) expect(doc.firstChild === doctype).toBe(true) }) }) describe('insertBefore', () => { it('should insert the first element and set `documentElement`', () => { const doc = new DOMImplementation().createDocument(null, '') expect(doc.childNodes).toHaveLength(0) expect(doc.documentElement).toBeNull() const root = doc.createElement('root') doc.insertBefore(root) expect(doc.documentElement).toBe(root) expect(doc.childNodes).toHaveLength(1) expect(doc.childNodes.item(0)).toBe(root) }) it('should prevent inserting a second element', () => { const doc = new DOMImplementation().createDocument(null, '') const root = doc.createElement('root') const second = doc.createElement('second') doc.insertBefore(root) expect(() => doc.insertBefore(second)).toThrow(DOMException) expect(doc.documentElement).toBe(root) expect(doc.childNodes).toHaveLength(1) }) it('should prevent inserting an element before a doctype', () => { const impl = new DOMImplementation() const doctype = impl.createDocumentType('DT') const doc = impl.createDocument(null, '', doctype) expect(doc.childNodes).toHaveLength(1) const root = doc.createElement('root') expect(() => doc.insertBefore(root, doctype)).toThrow(DOMException) expect(doc.documentElement).toBeNull() expect(doc.childNodes).toHaveLength(1) expect(root.parentNode).toBeNull() }) it('should prevent inserting a second doctype', () => { const impl = new DOMImplementation() const doctype = impl.createDocumentType('DT') const doctype2 = impl.createDocumentType('DT2') const doc = impl.createDocument(null, '', doctype) expect(doc.childNodes).toHaveLength(1) expect(() => doc.insertBefore(doctype2)).toThrow(DOMException) expect(doc.childNodes).toHaveLength(1) }) it('should prevent inserting a doctype after an element', () => { const impl = new DOMImplementation() const doc = impl.createDocument(null, '') const root = doc.createElement('root') doc.insertBefore(root) const doctype = impl.createDocumentType('DT') expect(doc.childNodes).toHaveLength(1) expect(() => doc.insertBefore(doctype)).toThrow(DOMException) expect(doc.childNodes).toHaveLength(1) }) it('should prevent inserting before an child which is not a child of parent', () => { const doc = new DOMImplementation().createDocument(null, '') const root = doc.createElement('root') const withoutParent = doc.createElement('second') expect(() => doc.insertBefore(root, withoutParent)).toThrow(DOMException) expect(doc.documentElement).toBeNull() expect(doc.childNodes).toHaveLength(0) expect(root.parentNode).toBeNull() }) }) describe('replaceChild', () => { it('should remove the only element and add the new one', () => { const doc = new DOMImplementation().createDocument('', 'xml'); const initialFirstChild = doc.firstChild; const replacement = doc.createElement('replaced'); doc.replaceChild(replacement, doc.firstChild); expect(doc.childNodes).toHaveLength(1); expect(initialFirstChild.parentNode).toBeNull(); expect(doc.documentElement.name).toBe(replacement.name); }); }); describe('removeChild', () => { it('should remove all connections to node', () => { const doc = new DOMImplementation().createDocument('', 'xml'); doc.insertBefore(doc.createComment('just a comment'), doc.firstChild); expect(doc.childNodes).toHaveLength(2); const initialElement = doc.firstChild; doc.removeChild(initialElement); // expect(doc.documentElement).toBeNull(); expect(initialElement.parentNode).toBeNull(); expect(initialElement.nextSibling).toBeNull(); // expect(initialElement.previousSibling).toBeNull(); expect(doc.childNodes).toHaveLength(1); }); }); }) xmldom-0.8.6/test/dom/dom-implementation.test.js000066400000000000000000000120721433143211200216750ustar00rootroot00000000000000'use strict' const { DocumentType, DOMImplementation, Element, Node, NodeList, } = require('../../lib/dom') const NAME = 'NAME' const PREFIX = 'PREFIX' const NS = 'NS' describe('DOMImplementation', () => { describe('hasFeature (deprecated)', () => { it.each(['', '0', 'feature'])( "should return true when called with ('%s')", (f) => { expect(new DOMImplementation().hasFeature(f)).toBe(true) } ) it.each([ ['', ''], ['0', '1'], ['feature', ''], ['feature', '1'], ])("should return true when called with ('%s', '%s')", (f, v) => { expect(new DOMImplementation().hasFeature(f, v)).toBe(true) }) }) describe('createDocument', () => { it('should create a Document with basic mandatory arguments', () => { const impl = new DOMImplementation() const doc = impl.createDocument(null, '') expect(doc.nodeType).toBe(Node.DOCUMENT_NODE) expect(doc.implementation).toBe(impl) expect(doc.doctype).toBe(null) expect(doc.childNodes).toBeInstanceOf(NodeList) expect(doc.documentElement).toBe(null) }) it('should create a Document with only a doc type', () => { const impl = new DOMImplementation() const doctype = impl.createDocumentType('test') const doc = impl.createDocument(null, '', doctype) expect(doc.doctype).toBe(doctype) expect(doctype.ownerDocument).toBe(doc) expect(doc.childNodes.item(0)).toBe(doctype) }) it('should create a Document with root element without a namespace', () => { const impl = new DOMImplementation() const doc = impl.createDocument(null, NAME) const root = doc.childNodes.item(0) expect(root).toBeInstanceOf(Element) expect(root.ownerDocument).toBe(doc) expect(root.namespaceURI).toBe(null) expect(root.nodeName).toBe(NAME) expect(root.tagName).toBe(NAME) expect(root.prefix).toBe(null) expect(root.localName).toBe(NAME) expect(doc.documentElement).toBe(root) }) it('should create a Document with root element in a default namespace', () => { const impl = new DOMImplementation() const doc = impl.createDocument(NS, NAME) const root = doc.childNodes.item(0) expect(root).toBeInstanceOf(Element) expect(root.ownerDocument).toBe(doc) expect(root.namespaceURI).toBe(NS) expect(root.prefix).toBe(null) expect(root.localName).toBe(NAME) expect(root.nodeName).toBe(NAME) expect(root.tagName).toBe(NAME) expect(doc.documentElement).toBe(root) }) it('should create a Document with root element in a named namespace', () => { const impl = new DOMImplementation() const qualifiedName = `${PREFIX}:${NAME}` const doc = impl.createDocument(NS, qualifiedName) const root = doc.childNodes.item(0) expect(root).toBeInstanceOf(Element) expect(root.ownerDocument).toBe(doc) expect(root.namespaceURI).toBe(NS) expect(root.prefix).toBe(PREFIX) expect(root.localName).toBe(NAME) expect(root.nodeName).toBe(qualifiedName) expect(root.tagName).toBe(qualifiedName) expect(doc.documentElement).toBe(root) }) it('should create a Document with root element in a named namespace', () => { const impl = new DOMImplementation() const qualifiedName = `${PREFIX}:${NAME}` const doc = impl.createDocument(NS, qualifiedName) const root = doc.childNodes.item(0) expect(root).toBeInstanceOf(Element) expect(root.ownerDocument).toBe(doc) expect(root.namespaceURI).toBe(NS) expect(root.prefix).toBe(PREFIX) expect(root.localName).toBe(NAME) expect(root.nodeName).toBe(qualifiedName) expect(root.tagName).toBe(qualifiedName) expect(doc.documentElement).toBe(root) }) it('should create a Document with namespaced root element and doctype', () => { const impl = new DOMImplementation() const qualifiedName = `${PREFIX}:${NAME}` const doctype = impl.createDocumentType('test') const doc = impl.createDocument(NS, qualifiedName, doctype) expect(doc.doctype).toBe(doctype) expect(doctype.ownerDocument).toBe(doc) expect(doc.childNodes.item(0)).toBe(doctype) const root = doc.childNodes.item(1) expect(root).toBeInstanceOf(Element) expect(root.ownerDocument).toBe(doc) expect(root.namespaceURI).toBe(NS) expect(root.prefix).toBe(PREFIX) expect(root.localName).toBe(NAME) expect(root.nodeName).toBe(qualifiedName) expect(root.tagName).toBe(qualifiedName) expect(doc.documentElement).toBe(root) }) }) describe('createDocumentType', () => { it('should create a DocumentType with only a name', () => { const impl = new DOMImplementation() const doctype = impl.createDocumentType(NAME) expect(doctype).toBeInstanceOf(Node) expect(doctype).toBeInstanceOf(DocumentType) expect(doctype.nodeType).toBe(Node.DOCUMENT_TYPE_NODE) expect(doctype.name).toBe(NAME) expect(doctype.publicId).toBe('') expect(doctype.systemId).toBe('') }) it('should create a DocumentType with name, publicId and systemId', () => { const impl = new DOMImplementation() const doctype = impl.createDocumentType(NAME, '"PUBLIC"', '"SYSTEM"') expect(doctype.name).toBe(NAME) expect(doctype.publicId).toBe('"PUBLIC"') expect(doctype.systemId).toBe('"SYSTEM"') }) }) }) xmldom-0.8.6/test/dom/element.test.js000066400000000000000000000165771433143211200175420ustar00rootroot00000000000000'use strict' const { DOMParser, DOMImplementation, XMLSerializer } = require('../../lib') const { Element } = require('../../lib/dom') describe('Document', () => { // See: http://jsfiddle.net/bigeasy/ShcXP/1/ describe('getElementsByTagName', () => { it('should return the correct number of elements', () => { const doc = new DOMParser().parseFromString('') expect(doc.getElementsByTagName('*')).toHaveLength(2) expect(doc.documentElement.getElementsByTagName('*')).toHaveLength(1) }) it('should support API on element (this test needs to be split)', () => { const doc = new DOMParser().parseFromString( '' + '' + '' + '', 'text/xml' ) const childs1 = doc.documentElement.getElementsByTagName('child') expect(childs1.item(0).getAttribute('attr')).toBe('1') expect(childs1.item(1).getAttribute('attr')).toBe('2') expect(childs1.item(2).getAttribute('attr')).toBe('3') expect(childs1).toHaveLength(3) const childs2 = doc.getElementsByTagName('child') expect(childs2.item(0).getAttribute('attr')).toBe('1') expect(childs2.item(1).getAttribute('attr')).toBe('2') expect(childs2.item(2).getAttribute('attr')).toBe('3') expect(childs2).toHaveLength(3) const childs3 = doc.documentElement.getElementsByTagName('*') for (let i = 0, buf = []; i < childs3.length; i++) { buf.push(childs3[i].tagName) } expect(childs3).toHaveLength(7) const feed = new DOMParser().parseFromString( 'foo' ) const entries = feed.documentElement.getElementsByTagName('entry') expect(entries).toHaveLength(1) expect(entries[0].nodeName).toBe('entry') expect(feed.documentElement.childNodes.item(0).nodeName).toBe('entry') }) }) it('supports getElementsByTagNameNS', () => { const doc = new DOMParser().parseFromString( '' + '' + '' + '', 'text/xml' ) const childs1 = doc.documentElement.getElementsByTagNameNS( 'http://test.com', '*' ) expect(childs1).toHaveLength(6) const childs2 = doc.getElementsByTagNameNS('http://test.com', '*') expect(childs2).toHaveLength(7) const childs3 = doc.documentElement.getElementsByTagNameNS( 'http://test.com', 'test' ) expect(childs3).toHaveLength(3) const childs4 = doc.getElementsByTagNameNS('http://test.com', 'test') expect(childs4).toHaveLength(3) const childs5 = doc.getElementsByTagNameNS('*', 'test') expect(childs5).toHaveLength(4) const childs6 = doc.documentElement.getElementsByTagNameNS('*', 'test') expect(childs6).toHaveLength(4) }) it('supports getElementById', () => { const doc = new DOMParser().parseFromString( '' + '' + '', 'text/xml' ) expect(doc.getElementById('root')).not.toBeNull() expect(doc.getElementById('a1').getAttribute('title')).toBe('1') expect(doc.getElementById('a2').getAttribute('title')).toBe('2') expect(doc.getElementById('a2').getAttribute('title2')).toBe('') }) it('can properly append exist child', () => { const doc = new DOMParser().parseFromString( '' + '' + '', 'text/xml' ) const doc1 = doc const str1 = new XMLSerializer().serializeToString(doc) const doc2 = doc1.cloneNode(true) const doc3 = doc1.cloneNode(true) const doc4 = doc1.cloneNode(true) doc3.documentElement.appendChild(doc3.documentElement.lastChild) doc4.documentElement.appendChild(doc4.documentElement.firstChild) const str2 = new XMLSerializer().serializeToString(doc2) const str3 = new XMLSerializer().serializeToString(doc3) const str4 = new XMLSerializer().serializeToString(doc4) expect(str1).toBe(str2) expect(str2).toBe(str3) expect(str3).not.toBe(str4) expect(str3.length).toBe(str4.length) }) it('can properly append exist other child', () => { const doc = new DOMParser().parseFromString( '' + '' + '', 'text/xml' ) const doc1 = doc const str1 = new XMLSerializer().serializeToString(doc) const doc2 = doc1.cloneNode(true) expect(doc2.documentElement.lastChild.childNodes).toHaveLength(0) doc2.documentElement.appendChild(doc2.documentElement.firstChild.firstChild) const str2 = new XMLSerializer().serializeToString(doc2) expect(doc2.documentElement.lastChild.childNodes).toHaveLength(1) expect(str1).not.toBe(str2) expect(str1).not.toHaveLength(str2.length) const doc3 = new DOMParser().parseFromString(str2, 'text/xml') doc3.documentElement.firstChild.appendChild(doc3.documentElement.lastChild) const str3 = new XMLSerializer().serializeToString(doc3) expect(str1).toBe(str3) }) it('can properly set textContent', () => { const doc = new DOMParser().parseFromString('') const a = doc.documentElement.firstChild const b = a.nextSibling a.textContent = 'hello' expect(doc.documentElement.toString()).toBe( 'hello' ) b.textContent = 'there' expect(doc.documentElement.toString()).toBe( 'hellothere' ) b.textContent = '' expect(doc.documentElement.toString()).toBe('hello') doc.documentElement.textContent = 'bye' expect(doc.documentElement.toString()).toBe('bye') }) describe('createElement', () => { it('should set localName', () => { const doc = new DOMImplementation().createDocument(null, 'test', null) const elem = doc.createElement('foo') expect(elem.localName === 'foo') }) }) it('appendElement and removeElement', () => { const dom = new DOMParser().parseFromString(``) const doc = dom.documentElement const arr = [] while (doc.firstChild) { const node = doc.removeChild(doc.firstChild) arr.push(node) expect(node.parentNode).toBeNull() expect(node.previousSibling).toBeNull() expect(node.nextSibling).toBeNull() expect(node.ownerDocument).toBe(dom) expect(doc.firstChild).not.toBe(node) const expectedLength = 3 - arr.length expect(doc.childNodes).toHaveLength(expectedLength) expect(doc.childNodes.item(expectedLength)).toBeNull() } expect(arr).toHaveLength(3) while (arr.length) { const node = arr.shift() expect(doc.appendChild(node)).toBe(node) expect(node.parentNode).toBe(doc) const expectedLength = 3 - arr.length expect(doc.childNodes).toHaveLength(expectedLength) expect(doc.childNodes.item(expectedLength - 1)).toBe(node) if (expectedLength > 1) { expect(node.previousSibling).toBeInstanceOf(Element) expect(node.previousSibling.nextSibling).toBe(node) } } expect(doc.childNodes.toString()).toBe(``) }) xit('nested append failed', () => {}) xit('self append failed', () => {}) }) xmldom-0.8.6/test/dom/fragment.test.js000066400000000000000000000010171433143211200176730ustar00rootroot00000000000000'use strict' const { DOMParser } = require('../../lib') describe('DOM DocumentFragment', () => { // see: http://jsfiddle.net/9Wmh2/1/ it('append empty fragment', () => { const document = new DOMParser().parseFromString('

') const fragment = document.createDocumentFragment() document.getElementById('p').insertBefore(fragment, null) fragment.appendChild(document.createTextNode('a')) document.getElementById('p').insertBefore(fragment, null) expect(document.toString()).toBe('

a

') }) }) xmldom-0.8.6/test/dom/ns-test.test.js000066400000000000000000000035371433143211200174760ustar00rootroot00000000000000'use strict' const { DOMParser } = require('../../lib') // Create a Test Suite describe('XML Namespace Parse', () => { it('supports testlitecns', () => { const doc = new DOMParser({ xmlns: { c: 'http://www.xidea.org/lite/core', '': 'http://www.w3.org/1999/xhtml', }, }).parseFromString( '', 'text/xml' ) const el = doc.getElementsByTagName('c:var')[0] expect(el.namespaceURI).toBe('http://www.xidea.org/lite/core') expect(doc.toString()).toBe( '' ) }) it('should ignore default prefix xml attribute', () => { const w3 = 'http://www.w3.org/1999/xhtml' const n1 = 'http://www.frankston.com/public' const n2 = 'http://rmf.vc/n2' const hx = '' const doc = new DOMParser().parseFromString(hx, 'text/xml') const els = [].slice.call( doc.documentElement.getElementsByTagNameNS(n1, 'foo') ) for (let _i = 0, els_1 = els; _i < els_1.length; _i++) { const el = els_1[_i] const te = doc.createElementNS(n1, 'test') te.setAttributeNS(n1, 'bar', 'valx') expect(te.toString()).toBe('') el.appendChild(te) const tx = doc.createElementNS(n2, 'test') tx.setAttributeNS(n2, 'bar', 'valx') expect(tx.toString()).toBe('') el.appendChild(tx) } expect(doc.toString()).toBe( '' ) }) }) xmldom-0.8.6/test/dom/serializer.test.js000066400000000000000000000210611433143211200202420ustar00rootroot00000000000000'use strict' const { DOMParser, XMLSerializer } = require('../../lib') const { MIME_TYPE } = require('../../lib/conventions') describe('XML Serializer', () => { it('supports text node containing "]]>"', () => { const doc = new DOMParser().parseFromString('', 'text/xml') doc.documentElement.appendChild(doc.createTextNode('hello ]]> there')) expect(doc.documentElement.firstChild.toString()).toBe('hello ]]> there') }) it('supports ', 'text/html') expect(doc.documentElement.firstChild.toString()).toBe( '' ) }) describe('does not serialize namespaces with an empty URI', () => { // for more details see the comments in lib/dom.js:needNamespaceDefine it('that are used in a node', () => { const source = 'test1test2' const { documentElement } = new DOMParser().parseFromString(source) expect(documentElement.firstChild.firstChild).toMatchObject({ nodeValue: 'test1', }) expect(documentElement.lastChild.firstChild).toMatchObject({ nodeValue: 'test2', }) expect(documentElement.toString()).toStrictEqual(source) }) it('that are used in an attribute', () => { const source = '' const { documentElement } = new DOMParser().parseFromString(source) expect(documentElement.toString()).toStrictEqual(source) }) }) describe('does detect matching visible namespace for tags without prefix', () => { it('should add local namespace after sibling', () => { const str = '' const doc = new DOMParser().parseFromString(str, MIME_TYPE.XML_TEXT) const child = doc.createElementNS('AAA', 'child') expect(new XMLSerializer().serializeToString(child)).toBe( '' ) doc.documentElement.appendChild(child) expect(new XMLSerializer().serializeToString(doc)).toBe( '' ) }) it('should add local namespace from parent', () => { const str = '' const doc = new DOMParser().parseFromString(str, MIME_TYPE.XML_TEXT) const child = doc.createElementNS('AAA', 'child') expect(new XMLSerializer().serializeToString(child)).toBe( '' ) doc.documentElement.appendChild(child) expect(new XMLSerializer().serializeToString(doc)).toBe( '' ) const nested = doc.createElementNS('AAA', 'nested') expect(new XMLSerializer().serializeToString(nested)).toBe( '' ) child.appendChild(nested) expect(new XMLSerializer().serializeToString(doc)).toBe( '' ) }) it('should add local namespace as xmlns in HTML', () => { const str = '' const doc = new DOMParser().parseFromString(str, MIME_TYPE.HTML) const child = doc.createElementNS('AAA', 'child') expect(new XMLSerializer().serializeToString(child, true)).toBe( '' ) doc.documentElement.appendChild(child) expect(new XMLSerializer().serializeToString(doc, true)).toBe( '' ) const nested = doc.createElementNS('AAA', 'nested') expect(new XMLSerializer().serializeToString(nested, true)).toBe( '' ) child.appendChild(nested) expect(new XMLSerializer().serializeToString(doc, true)).toBe( '' ) }) it('should add keep different default namespace of child', () => { const str = '' const doc = new DOMParser().parseFromString(str, MIME_TYPE.XML_TEXT) const child = doc.createElementNS('BBB', 'child') child.setAttribute('xmlns', 'BBB') expect(new XMLSerializer().serializeToString(child)).toBe( '' ) doc.documentElement.appendChild(child) const nested = doc.createElementNS('BBB', 'nested') expect(new XMLSerializer().serializeToString(nested)).toBe( '' ) child.appendChild(nested) expect(new XMLSerializer().serializeToString(doc)).toBe( '' ) }) }) describe('is insensitive to namespace order', () => { it('should preserve prefixes for inner elements and attributes', () => { const NS = 'http://www.w3.org/test' const xml = ` `.trim() const dom = new DOMParser().parseFromString(xml, 'text/xml') const doc = dom.documentElement const one = doc.childNodes.item(1) expect(one).toMatchObject({ localName: 'one', nodeName: 'one', prefix: null, namespaceURI: NS, }) const group = doc.childNodes.item(3) expect(group).toMatchObject({ localName: 'group', nodeName: 'group', prefix: null, namespaceURI: NS, }) const two = group.childNodes.item(1) expect(two).toMatchObject({ localName: 'two', nodeName: 'two', prefix: null, namespaceURI: NS, }) const three = group.childNodes.item(3) expect(three).toMatchObject({ localName: 'three', nodeName: 'inner:three', prefix: 'inner', namespaceURI: NS, }) expect(new XMLSerializer().serializeToString(dom)).toEqual(xml) }) it('should preserve missing prefixes for inner prefixed elements and attributes', () => { const NS = 'http://www.w3.org/test' const xml = ` `.trim() const dom = new DOMParser().parseFromString(xml, 'text/xml') const doc = dom.documentElement const one = doc.childNodes.item(1) expect(one).toMatchObject({ localName: 'one', nodeName: 'inner:one', prefix: 'inner', namespaceURI: NS, }) const group = doc.childNodes.item(3) expect(group).toMatchObject({ localName: 'group', nodeName: 'inner:group', prefix: 'inner', namespaceURI: NS, }) const two = group.childNodes.item(1) expect(two).toMatchObject({ localName: 'two', nodeName: 'inner:two', prefix: 'inner', namespaceURI: NS, }) const three = group.childNodes.item(3) expect(three).toMatchObject({ localName: 'three', nodeName: 'three', prefix: null, namespaceURI: NS, }) expect(new XMLSerializer().serializeToString(dom)).toEqual(xml) }) it('should produce unprefixed svg elements when prefixed namespace comes first', () => { const svg = ` `.trim() const dom = new DOMParser().parseFromString(svg, 'text/xml') expect(new XMLSerializer().serializeToString(dom)).toEqual(svg) }) it('should produce unprefixed svg elements when default namespace comes first', () => { const svg = ` `.trim() const dom = new DOMParser().parseFromString(svg, 'text/xml') expect(new XMLSerializer().serializeToString(dom)).toEqual(svg) }) }) describe('properly escapes attribute values', () => { it('should properly convert whitespace literals back to character references', () => { const input = '' const dom = new DOMParser().parseFromString(input, MIME_TYPE.XML_TEXT) const attr = dom.documentElement.attributes[0] expect(new XMLSerializer().serializeToString(dom)).toBe(input) }) it('should escape special characters in namespace attributes', () => { const input = `` const doc = new DOMParser().parseFromString(input, MIME_TYPE.XML_TEXT) // in this case the explicit attribute nodes are serialized expect(new XMLSerializer().serializeToString(doc)).toBe( '' ) // in this case the namespace attributes are "inherited" from the parent, // which is not serialized expect( new XMLSerializer().serializeToString(doc.documentElement.firstChild) ).toBe( '' ) }) }) }) xmldom-0.8.6/test/error/000077500000000000000000000000001433143211200151275ustar00rootroot00000000000000xmldom-0.8.6/test/error/__snapshots__/000077500000000000000000000000001433143211200177455ustar00rootroot00000000000000xmldom-0.8.6/test/error/__snapshots__/reported-levels.test.js.snap000066400000000000000000000414071433143211200253430ustar00rootroot00000000000000// Jest Snapshot v1, https://goo.gl/fbAQLP exports[`SYNTAX_AttributeEqualMissingValue with mimeType text/html should be reported as error 1`] = ` Array [ "[xmldom error] element parse error: Error: attribute value missed!! @#[line:1,col:1]", ] `; exports[`SYNTAX_AttributeEqualMissingValue with mimeType text/html should not catch Error thrown in errorHandler.error 1`] = ` Array [ "[xmldom error] element parse error: Error: attribute value missed!!||@#[line:1,col:1] at parse (lib/sax.js:#5)", ] `; exports[`SYNTAX_AttributeEqualMissingValue with mimeType text/xml should be reported as error 1`] = ` Array [ "[xmldom error] element parse error: Error: attribute value missed!! @#[line:1,col:1]", ] `; exports[`SYNTAX_AttributeEqualMissingValue with mimeType text/xml should not catch Error thrown in errorHandler.error 1`] = ` Array [ "[xmldom error] element parse error: Error: attribute value missed!!||@#[line:1,col:1] at parse (lib/sax.js:#5)", ] `; exports[`SYNTAX_AttributeMissingEndingQuote with mimeType text/html should be reported as error 1`] = ` Array [ "[xmldom error] element parse error: Error: attribute value no end '\\"' match @#[line:1,col:1]", ] `; exports[`SYNTAX_AttributeMissingEndingQuote with mimeType text/html should not catch Error thrown in errorHandler.error 1`] = ` Array [ "[xmldom error] element parse error: Error: attribute value no end '\\"' match||@#[line:1,col:1] at parse (lib/sax.js:#5)", ] `; exports[`SYNTAX_AttributeMissingEndingQuote with mimeType text/xml should be reported as error 1`] = ` Array [ "[xmldom error] element parse error: Error: attribute value no end '\\"' match @#[line:1,col:1]", ] `; exports[`SYNTAX_AttributeMissingEndingQuote with mimeType text/xml should not catch Error thrown in errorHandler.error 1`] = ` Array [ "[xmldom error] element parse error: Error: attribute value no end '\\"' match||@#[line:1,col:1] at parse (lib/sax.js:#5)", ] `; exports[`SYNTAX_ElementClosingNotConnected with mimeType text/html should be reported as error 1`] = ` Array [ "[xmldom error] element parse error: Error: elements closed character '/' and '>' must be connected to @#[line:1,col:6]", ] `; exports[`SYNTAX_ElementClosingNotConnected with mimeType text/html should not catch Error thrown in errorHandler.error 1`] = ` Array [ "[xmldom error] element parse error: Error: elements closed character '/' and '>' must be connected to||@#[line:1,col:6] at parse (lib/sax.js:#5)", ] `; exports[`SYNTAX_ElementClosingNotConnected with mimeType text/xml should be reported as error 1`] = ` Array [ "[xmldom error] element parse error: Error: elements closed character '/' and '>' must be connected to @#[line:1,col:6]", ] `; exports[`SYNTAX_ElementClosingNotConnected with mimeType text/xml should not catch Error thrown in errorHandler.error 1`] = ` Array [ "[xmldom error] element parse error: Error: elements closed character '/' and '>' must be connected to||@#[line:1,col:6] at parse (lib/sax.js:#5)", ] `; exports[`SYNTAX_EndTagMaybeNotComplete with mimeType text/html should be reported as error 1`] = ` Array [ "[xmldom error] end tag name: inner maybe not complete @#[line:1,col:6]", ] `; exports[`SYNTAX_EndTagMaybeNotComplete with mimeType text/html should not catch Error thrown in errorHandler.error 1`] = ` Array [ "[xmldom error] end tag name: inner maybe not complete||@#[line:1,col:6] at parse (lib/sax.js:#2)", "[xmldom error] element parse error: Error: [xmldom error] end tag name: inner maybe not complete||@#[line:1,col:6]||@#[line:1,col:6] at parse (lib/sax.js:#5)", ] `; exports[`SYNTAX_EndTagMaybeNotComplete with mimeType text/xml should be reported as error 1`] = ` Array [ "[xmldom error] end tag name: inner maybe not complete @#[line:1,col:6]", ] `; exports[`SYNTAX_EndTagMaybeNotComplete with mimeType text/xml should not catch Error thrown in errorHandler.error 1`] = ` Array [ "[xmldom error] end tag name: inner maybe not complete||@#[line:1,col:6] at parse (lib/sax.js:#2)", "[xmldom error] element parse error: Error: [xmldom error] end tag name: inner maybe not complete||@#[line:1,col:6]||@#[line:1,col:6] at parse (lib/sax.js:#5)", ] `; exports[`SYNTAX_EndTagNotComplete with mimeType text/html should be reported as error 1`] = ` Array [ "[xmldom error] end tag name: xml is not complete:xml @#[line:1,col:1]", ] `; exports[`SYNTAX_EndTagNotComplete with mimeType text/html should not catch Error thrown in errorHandler.error 1`] = ` Array [ "[xmldom error] end tag name: xml is not complete:xml||@#[line:1,col:1] at parse (lib/sax.js:#1)", "[xmldom error] element parse error: Error: [xmldom error] end tag name: xml is not complete:xml||@#[line:1,col:1]||@#[line:1,col:1] at parse (lib/sax.js:#5)", ] `; exports[`SYNTAX_EndTagNotComplete with mimeType text/xml should be reported as error 1`] = ` Array [ "[xmldom error] end tag name: xml is not complete:xml @#[line:1,col:1]", ] `; exports[`SYNTAX_EndTagNotComplete with mimeType text/xml should not catch Error thrown in errorHandler.error 1`] = ` Array [ "[xmldom error] end tag name: xml is not complete:xml||@#[line:1,col:1] at parse (lib/sax.js:#1)", "[xmldom error] element parse error: Error: [xmldom error] end tag name: xml is not complete:xml||@#[line:1,col:1]||@#[line:1,col:1] at parse (lib/sax.js:#5)", ] `; exports[`SYNTAX_InvalidAttributeName with mimeType text/html should be reported as error 1`] = ` Array [ "[xmldom error] element parse error: Error: invalid attribute:123 @#[line:1,col:1]", ] `; exports[`SYNTAX_InvalidAttributeName with mimeType text/html should not catch Error thrown in errorHandler.error 1`] = ` Array [ "[xmldom error] element parse error: Error: invalid attribute:123||@#[line:1,col:1] at parse (lib/sax.js:#5)", ] `; exports[`SYNTAX_InvalidAttributeName with mimeType text/xml should be reported as error 1`] = ` Array [ "[xmldom error] element parse error: Error: invalid attribute:123 @#[line:1,col:1]", ] `; exports[`SYNTAX_InvalidAttributeName with mimeType text/xml should not catch Error thrown in errorHandler.error 1`] = ` Array [ "[xmldom error] element parse error: Error: invalid attribute:123||@#[line:1,col:1] at parse (lib/sax.js:#5)", ] `; exports[`SYNTAX_InvalidTagName with mimeType text/html should be reported as error 1`] = ` Array [ "[xmldom error] element parse error: Error: invalid tagName:123 @#[line:1,col:1]", ] `; exports[`SYNTAX_InvalidTagName with mimeType text/html should not catch Error thrown in errorHandler.error 1`] = ` Array [ "[xmldom error] element parse error: Error: invalid tagName:123||@#[line:1,col:1] at parse (lib/sax.js:#5)", ] `; exports[`SYNTAX_InvalidTagName with mimeType text/xml should be reported as error 1`] = ` Array [ "[xmldom error] element parse error: Error: invalid tagName:123 @#[line:1,col:1]", ] `; exports[`SYNTAX_InvalidTagName with mimeType text/xml should not catch Error thrown in errorHandler.error 1`] = ` Array [ "[xmldom error] element parse error: Error: invalid tagName:123||@#[line:1,col:1] at parse (lib/sax.js:#5)", ] `; exports[`SYNTAX_UnclosedComment with mimeType text/html should be reported as error 1`] = ` Array [ "[xmldom error] Unclosed comment @#[line:1,col:1]", ] `; exports[`SYNTAX_UnclosedComment with mimeType text/html should not catch Error thrown in errorHandler.error 1`] = ` Array [ "[xmldom error] Unclosed comment||@#[line:1,col:1] at parseDCC (lib/sax.js:#21)", "[xmldom error] element parse error: Error: [xmldom error] Unclosed comment||@#[line:1,col:1]||@#[line:1,col:1] at parse (lib/sax.js:#5)", ] `; exports[`SYNTAX_UnclosedComment with mimeType text/xml should be reported as error 1`] = ` Array [ "[xmldom error] Unclosed comment @#[line:1,col:1]", ] `; exports[`SYNTAX_UnclosedComment with mimeType text/xml should not catch Error thrown in errorHandler.error 1`] = ` Array [ "[xmldom error] Unclosed comment||@#[line:1,col:1] at parseDCC (lib/sax.js:#21)", "[xmldom error] element parse error: Error: [xmldom error] Unclosed comment||@#[line:1,col:1]||@#[line:1,col:1] at parse (lib/sax.js:#5)", ] `; exports[`SYNTAX_UnexpectedEndOfInput with mimeType text/html should be reported as error 1`] = ` Array [ "[xmldom error] unexpected end of input @#[line:1,col:1]", ] `; exports[`SYNTAX_UnexpectedEndOfInput with mimeType text/html should not catch Error thrown in errorHandler.error 1`] = ` Array [ "[xmldom error] unexpected end of input||@#[line:1,col:1] at parseElementStartPart (lib/sax.js:#13)", "[xmldom error] element parse error: Error: [xmldom error] unexpected end of input||@#[line:1,col:1]||@#[line:1,col:1] at parse (lib/sax.js:#5)", ] `; exports[`SYNTAX_UnexpectedEndOfInput with mimeType text/xml should be reported as error 1`] = ` Array [ "[xmldom error] unexpected end of input @#[line:1,col:1]", ] `; exports[`SYNTAX_UnexpectedEndOfInput with mimeType text/xml should not catch Error thrown in errorHandler.error 1`] = ` Array [ "[xmldom error] unexpected end of input||@#[line:1,col:1] at parseElementStartPart (lib/sax.js:#13)", "[xmldom error] element parse error: Error: [xmldom error] unexpected end of input||@#[line:1,col:1]||@#[line:1,col:1] at parse (lib/sax.js:#5)", ] `; exports[`WF_AttributeMissingQuote with mimeType text/html should be reported as warning 1`] = ` Array [ "[xmldom warning] attribute \\"value\\" missed quot(\\")! @#[line:1,col:1]", ] `; exports[`WF_AttributeMissingQuote with mimeType text/html should escalate Error thrown in errorHandler.warning to errorHandler.error 1`] = ` Array [ "[xmldom warning] attribute \\"value\\" missed quot(\\")!||@#[line:1,col:1] at parseElementStartPart (lib/sax.js:#14)", ] `; exports[`WF_AttributeMissingQuote with mimeType text/xml should be reported as warning 1`] = ` Array [ "[xmldom warning] attribute \\"value\\" missed quot(\\")! @#[line:1,col:1]", ] `; exports[`WF_AttributeMissingQuote with mimeType text/xml should escalate Error thrown in errorHandler.warning to errorHandler.error 1`] = ` Array [ "[xmldom warning] attribute \\"value\\" missed quot(\\")!||@#[line:1,col:1] at parseElementStartPart (lib/sax.js:#14)", ] `; exports[`WF_AttributeMissingQuote2 with mimeType text/html should be reported as warning 1`] = ` Array [ "[xmldom warning] attribute \\"&\\" missed quot(\\")!! @#[line:1,col:1]", ] `; exports[`WF_AttributeMissingQuote2 with mimeType text/html should escalate Error thrown in errorHandler.warning to errorHandler.error 1`] = ` Array [ "[xmldom warning] attribute \\"&\\" missed quot(\\")!!||@#[line:1,col:1] at parseElementStartPart (lib/sax.js:#17)", ] `; exports[`WF_AttributeMissingQuote2 with mimeType text/xml should be reported as warning 1`] = ` Array [ "[xmldom warning] attribute \\"&\\" missed quot(\\")!! @#[line:1,col:1]", ] `; exports[`WF_AttributeMissingQuote2 with mimeType text/xml should escalate Error thrown in errorHandler.warning to errorHandler.error 1`] = ` Array [ "[xmldom warning] attribute \\"&\\" missed quot(\\")!!||@#[line:1,col:1] at parseElementStartPart (lib/sax.js:#17)", ] `; exports[`WF_AttributeMissingStartingQuote with mimeType text/html should be reported as warning 1`] = ` Array [ "[xmldom warning] attribute \\"attr\\" missed start quot(\\")!! @#[line:1,col:1]", ] `; exports[`WF_AttributeMissingStartingQuote with mimeType text/html should escalate Error thrown in errorHandler.warning to errorHandler.error 1`] = ` Array [ "[xmldom warning] attribute \\"attr\\" missed start quot(\\")!!||@#[line:1,col:1] at parseElementStartPart (lib/sax.js:#10)", ] `; exports[`WF_AttributeMissingStartingQuote with mimeType text/xml should be reported as warning 1`] = ` Array [ "[xmldom warning] attribute \\"attr\\" missed start quot(\\")!! @#[line:1,col:1]", ] `; exports[`WF_AttributeMissingStartingQuote with mimeType text/xml should escalate Error thrown in errorHandler.warning to errorHandler.error 1`] = ` Array [ "[xmldom warning] attribute \\"attr\\" missed start quot(\\")!!||@#[line:1,col:1] at parseElementStartPart (lib/sax.js:#10)", ] `; exports[`WF_AttributeMissingValue with mimeType text/html should be reported as warning 1`] = ` Array [ "[xmldom warning] attribute \\"attr\\" missed value!! \\"attr\\" instead!! @#[line:1,col:1]", ] `; exports[`WF_AttributeMissingValue with mimeType text/html should escalate Error thrown in errorHandler.warning to errorHandler.error 1`] = ` Array [ "[xmldom warning] attribute \\"attr\\" missed value!! \\"attr\\" instead!!||@#[line:1,col:1] at parseElementStartPart (lib/sax.js:#15)", ] `; exports[`WF_AttributeMissingValue with mimeType text/xml should be reported as warning 1`] = ` Array [ "[xmldom warning] attribute \\"attr\\" missed value!! \\"attr\\" instead!! @#[line:1,col:1]", ] `; exports[`WF_AttributeMissingValue with mimeType text/xml should escalate Error thrown in errorHandler.warning to errorHandler.error 1`] = ` Array [ "[xmldom warning] attribute \\"attr\\" missed value!! \\"attr\\" instead!!||@#[line:1,col:1] at parseElementStartPart (lib/sax.js:#15)", ] `; exports[`WF_AttributeMissingValue2 with mimeType text/html should be reported as warning 1`] = ` Array [ "[xmldom warning] attribute \\"attr\\" missed value!! \\"attr\\" instead2!! @#[line:1,col:1]", "[xmldom warning] attribute \\"attr2\\" missed value!! \\"attr2\\" instead!! @#[line:1,col:1]", ] `; exports[`WF_AttributeMissingValue2 with mimeType text/html should escalate Error thrown in errorHandler.warning to errorHandler.error 1`] = ` Array [ "[xmldom warning] attribute \\"attr\\" missed value!! \\"attr\\" instead2!!||@#[line:1,col:1] at parseElementStartPart (lib/sax.js:#18)", ] `; exports[`WF_AttributeMissingValue2 with mimeType text/xml should be reported as warning 1`] = ` Array [ "[xmldom warning] attribute \\"attr\\" missed value!! \\"attr\\" instead2!! @#[line:1,col:1]", "[xmldom warning] attribute \\"attr2\\" missed value!! \\"attr2\\" instead!! @#[line:1,col:1]", ] `; exports[`WF_AttributeMissingValue2 with mimeType text/xml should escalate Error thrown in errorHandler.warning to errorHandler.error 1`] = ` Array [ "[xmldom warning] attribute \\"attr\\" missed value!! \\"attr\\" instead2!!||@#[line:1,col:1] at parseElementStartPart (lib/sax.js:#18)", ] `; exports[`WF_AttributeValueMustAfterEqual with mimeType text/html should be reported as warning 1`] = ` Array [ "[xmldom warning] attribute value must after \\"=\\" @#[line:1,col:1]", ] `; exports[`WF_AttributeValueMustAfterEqual with mimeType text/html should escalate Error thrown in errorHandler.warning to errorHandler.error 1`] = ` Array [ "[xmldom warning] attribute value must after \\"=\\"||@#[line:1,col:1] at parseElementStartPart (lib/sax.js:#8)", ] `; exports[`WF_AttributeValueMustAfterEqual with mimeType text/xml should be reported as warning 1`] = ` Array [ "[xmldom warning] attribute value must after \\"=\\" @#[line:1,col:1]", ] `; exports[`WF_AttributeValueMustAfterEqual with mimeType text/xml should escalate Error thrown in errorHandler.warning to errorHandler.error 1`] = ` Array [ "[xmldom warning] attribute value must after \\"=\\"||@#[line:1,col:1] at parseElementStartPart (lib/sax.js:#8)", ] `; exports[`WF_DuplicateAttribute with mimeType text/html should be reported as fatalError 1`] = ` Array [ "[xmldom fatalError] Attribute a redefined @#[line:1,col:1]", ] `; exports[`WF_DuplicateAttribute with mimeType text/xml should be reported as fatalError 1`] = ` Array [ "[xmldom fatalError] Attribute a redefined @#[line:1,col:1]", ] `; exports[`WF_EntityDeclared with mimeType text/html should be reported as error 1`] = ` Array [ "[xmldom error] entity not found:&e; @#[line:1,col:1]", ] `; exports[`WF_EntityDeclared with mimeType text/html should not catch Error thrown in errorHandler.error 1`] = ` Array [ "[xmldom error] entity not found:&e;||@#[line:1,col:1] at replace (lib/sax.js:#0)", "[xmldom error] element parse error: Error: [xmldom error] entity not found:&e;||@#[line:1,col:1]||@#[line:1,col:1] at parse (lib/sax.js:#5)", ] `; exports[`WF_EntityDeclared with mimeType text/xml should be reported as error 1`] = ` Array [ "[xmldom error] entity not found:&e; @#[line:1,col:1]", ] `; exports[`WF_EntityDeclared with mimeType text/xml should not catch Error thrown in errorHandler.error 1`] = ` Array [ "[xmldom error] entity not found:&e;||@#[line:1,col:1] at replace (lib/sax.js:#0)", "[xmldom error] element parse error: Error: [xmldom error] entity not found:&e;||@#[line:1,col:1]||@#[line:1,col:1] at parse (lib/sax.js:#5)", ] `; exports[`WF_UnclosedXmlAttribute with mimeType text/xml should be reported as warning 1`] = ` Array [ "[xmldom warning] unclosed xml attribute @#[line:1,col:1]", ] `; exports[`WF_UnclosedXmlAttribute with mimeType text/xml should escalate Error thrown in errorHandler.warning to errorHandler.error 1`] = ` Array [ "[xmldom warning] unclosed xml attribute||@#[line:1,col:1] at parse (lib/sax.js:#4)", ] `; xmldom-0.8.6/test/error/__snapshots__/xml-error.test.js.snap000066400000000000000000000042321433143211200241510ustar00rootroot00000000000000// Jest Snapshot v1, https://goo.gl/fbAQLP exports[`html vs xml: html attribute (miss quote) 1`] = ` Object { "actual": "", "warning": Array [ "[xmldom warning] attribute \\"1\\" missed quot(\\")! @#[line:1,col:1]", ], } `; exports[`html vs xml: invalid xml node "", "error": Array [ "[xmldom error] unexpected end of input @#[line:1,col:1]", ], "warning": Array [ "[xmldom warning] unclosed xml attribute @#[line:1,col:1]", ], } `; exports[`html vs xml: invalid xml node " ", "warning": Array [ "[xmldom warning] attribute value must after \\"=\\" @#[line:10,col:5]", ], } `; exports[`html vs xml: text/xml attribute (missing =) 1`] = ` Object { "actual": " ", "warning": Array [ "[xmldom warning] attribute value must after \\"=\\" @#[line:10,col:5]", ], } `; exports[`html vs xml: unclosed document in text/html 1`] = ` Object { "actual": "", } `; exports[`html vs xml: unclosed document in text/xml 1`] = ` Object { "actual": "", "warning": Array [ "[xmldom warning] unclosed xml attribute @#[line:1,col:1]", ], } `; xmldom-0.8.6/test/error/error-handler.test.js000066400000000000000000000027261433143211200212160ustar00rootroot00000000000000'use strict' const { DOMParser } = require('../../lib') const { REPORTED } = require('./reported') describe('custom errorHandler', () => { it('function with two args receives key and message', () => { const errors = {} const parser = new DOMParser({ // currently needs to be a `function` to make the test work, // `jest.fn()` or using `() => {}` doesn't work errorHandler: function (key, msg) { errors[key] = msg }, }) parser.parseFromString(REPORTED.WF_AttributeMissingQuote.source, 'text/xml') expect(errors).toHaveProperty('warning') parser.parseFromString( REPORTED.SYNTAX_AttributeEqualMissingValue.source, 'text/xml' ) expect(errors).toHaveProperty('error') parser.parseFromString(REPORTED.WF_DuplicateAttribute.source, 'text/xml') expect(errors).toHaveProperty('fatalError') }) it('function with one argument builds list', () => { const errors = [] const parser = new DOMParser({ // currently needs to be a `function` to make the test work, // `jest.fn()` or using `() => {}` doesn't work errorHandler: function (msg) { errors.push(msg) }, }) parser.parseFromString(REPORTED.WF_AttributeMissingQuote.source, 'text/xml') parser.parseFromString( REPORTED.SYNTAX_AttributeEqualMissingValue.source, 'text/xml' ) parser.parseFromString(REPORTED.WF_DuplicateAttribute.source, 'text/xml') expect(errors).toMatchObject([ /\[xmldom warning]/, /\[xmldom error]/, /\[xmldom fatalError]/, ]) }) }) xmldom-0.8.6/test/error/reported-levels.test.js000066400000000000000000000104271433143211200215630ustar00rootroot00000000000000'use strict' const { LINE_TO_ERROR_INDEX, REPORTED } = require('./reported') const { getTestParser } = require('../get-test-parser') const { ParseError } = require('../../lib/sax') const { DOMParser } = require('../../lib') describe.each(Object.entries(REPORTED))( '%s', (name, { source, level, match, skippedInHtml }) => { describe.each(['text/xml', 'text/html'])('with mimeType %s', (mimeType) => { const isHtml = mimeType === 'text/html' if (isHtml && skippedInHtml) { it(`should not be reported as ${level}`, () => { const { errors, parser } = getTestParser() parser.parseFromString(source, mimeType) // if no report was triggered, the key is not present on `errors` expect(errors[level]).toBeUndefined() }) } else { it(`should be reported as ${level}`, () => { const { errors, parser } = getTestParser() parser.parseFromString(source, mimeType) const reported = errors[level] // store the snapshot, so any change in message can be inspected in the git diff expect(reported).toMatchSnapshot() // if a match has been defined, filter messages expect( match ? (reported || []).filter(match) : reported ).toHaveLength(1) }) if (level === 'fatalError') { it(`should throw ParseError in errorHandler.fatalError`, () => { const parser = new DOMParser() expect(() => parser.parseFromString(source, mimeType)).toThrow( ParseError ) }) } else if (level === 'error') { it(`should not catch Error thrown in errorHandler.${level}`, () => { let thrown = [] const errorHandler = { [level]: jest.fn((message) => { const toThrow = new Error(message) thrown.push(toThrow) throw toThrow }), } const { parser } = getTestParser({ errorHandler }) expect(() => parser.parseFromString(source, mimeType)).toThrow( Error ) expect( thrown.map((error) => toErrorSnapshot(error, 'lib/sax.js')) ).toMatchSnapshot() match && expect(match(thrown[0].toString())).toBe(true) }) } else if (level === 'warning') { it('should escalate Error thrown in errorHandler.warning to errorHandler.error', () => { let thrown = [] const errorHandler = { warning: jest.fn((message) => { const toThrow = new Error(message) thrown.push(toThrow) throw toThrow }), error: jest.fn(), } const { parser } = getTestParser({ errorHandler }) parser.parseFromString(source, mimeType) expect(errorHandler.warning).toHaveBeenCalledTimes(1) expect(errorHandler.error).toHaveBeenCalledTimes(1) expect( thrown.map((error) => toErrorSnapshot(error, 'lib/sax.js')) ).toMatchSnapshot() match && expect(match(thrown[0].message)).toBe(true) }) } } }) } ) /** * Creates a string from an error that is easily readable in a snapshot * - put's the message on one line as first line * - picks the first line in the stack trace that is in `libFile`, * and strips absolute paths and character position from that stack entry * as second line. the line number in the stack is converted to the error index * (to make snapshot testing possible even with stryker). * @param {Error} error * @param {string} libFile the path from the root of the project that should be preserved in the stack * @returns {string} */ function toErrorSnapshot(error, libFile) { const libFileMatch = new RegExp(`\/.*\/(${libFile})`) return `${error.message.replace(/([\n\r]+\s*)/g, '||')}\n${error.stack .split(/[\n\r]+/) // find first line that is from lib/sax.js .filter((l) => libFileMatch.test(l))[0] // strip of absolute path .replace(libFileMatch, '$1') // strip of position of character in line .replace(/:\d+\)$/, ')') // We only store the error index int he snapshot instead of the line numbers. // This way they need to be updated less frequent and are compatible with stryker. // see `parseErrorLines` in `./reported.js` for how LINE_TO_ERROR_INDEX is created, // and `./reported.json` (after running the tests) to inspect it. .replace(new RegExp(`${libFile}:\\d+`), (fileAndLine) => { return `${libFile}:#${ fileAndLine in LINE_TO_ERROR_INDEX ? LINE_TO_ERROR_INDEX[fileAndLine].index : -1 }` })}` } xmldom-0.8.6/test/error/reported.js000066400000000000000000000261671433143211200173250ustar00rootroot00000000000000'use strict' const fs = require('fs') /** * @typedef ErrorReport * @property {string} source the XML snippet * @property {'error'|'warning'|'fatalError'} level the name of the method triggered * @property {?function(msg:string):boolean} match to pick the relevant report when there are multiple * @property {?boolean} skippedInHtml Is the error reported when parsing HTML? */ /** * A collection of XML samples and related information that cause the XMLReader * to call methods on `errorHandler`. * * @type {Record}} */ const REPORTED = { /** * Entities need to be in the entityMap to be converted as part of parsing. * xmldom currently doesn't parse entities declared in DTD. * * @see https://www.w3.org/TR/2008/REC-xml-20081126/#wf-entdeclared * @see https://www.w3.org/TR/2006/REC-xml11-20060816/#wf-entdeclared */ WF_EntityDeclared: { source: '&e;', level: 'error', match: (msg) => /entity not found/.test(msg), }, /** * Well-formedness constraint: Unique Att Spec * * An attribute name must not appear more than once * in the same start-tag or empty-element tag. * * In the browser: * - as XML it is reported as `error on line 1 at column 17: Attribute a redefined` * - as HTML only the first definition is considered * * In xmldom the behavior is different for namespaces (picks first) * than for other attributes (picks last), * which can be a security issue. * * @see https://www.w3.org/TR/2008/REC-xml-20081126/#uniqattspec * @see https://www.w3.org/TR/2006/REC-xml11-20060816/#uniqattspec */ WF_DuplicateAttribute: { source: '', level: 'fatalError', match: (msg) => /Attribute .* redefined/.test(msg), }, /** * This sample doesn't follow the specified grammar. * In the browser it is reported as `error on line 1 at column 14: expected '>'`, * but still adds the root level element to the dom. */ SYNTAX_EndTagNotComplete: { source: ' /end tag name/.test(msg) && /is not complete/.test(msg), }, /** * This sample doesn't follow the specified grammar. * In the browser it is reported as `error on line 1 at column 21: expected '>'`, * but still adds the root level element and inner tag to the dom. */ SYNTAX_EndTagMaybeNotComplete: { source: '', level: 'error', match: (msg) => /end tag name/.test(msg) && /maybe not complete/.test(msg), }, /** * This sample doesn't follow the specified grammar. * In the browser it is reported as `error on line 1 at column 6: Comment not terminated`. */ SYNTAX_UnclosedComment: { source: '', '', ' ', // this line contains the missing = for attribute value ' ', ' ', '', ' ', ].join('\n') const actual = parser.parseFromString(xml, mimeType).toString() expect({ actual, ...errors }).toMatchSnapshot() }) }) xmldom-0.8.6/test/error/xml-reader-dom-handler-errors.test.js000066400000000000000000000076501433143211200242150ustar00rootroot00000000000000'use strict' const { ParseError } = require('../../lib/sax') const { __DOMHandler, DOMParser } = require('../../lib/dom-parser') /** * All methods implemented on the DOMHandler prototype. * * @type {string[]} */ const DOMHandlerMethods = Object.keys(__DOMHandler.prototype).sort() /** * XMLReader is currently not calling all methods "implemented" by DOMHandler (some are just empty), * If this changes the first test will fail. * * @type {Set} */ const UNCALLED_METHODS = new Set([ 'attributeDecl', 'elementDecl', 'endEntity', 'externalEntityDecl', 'getExternalSubset', 'ignorableWhitespace', 'internalEntityDecl', 'notationDecl', 'resolveEntity', 'skippedEntity', 'startEntity', 'unparsedEntityDecl', ]) /** * Some of the methods DOMParser/XMLReader call during parsing are not guarded by try/catch, * hence an error happening in those will stop the parsing process. * There is a test to verify this error handling. * If it changes this list might need to be changed as well * * @type {Set} */ const UNCAUGHT_METHODS = new Set([ 'characters', 'endDocument', 'error', 'setDocumentLocator', 'startDocument', ]) function noop() {} /** * A subclass of DOMHandler that mocks all methods for later inspection. * As part of the constructor it can be told which method is supposed to throw an error * and which error constructor to use. * * The `methods` property provides the list of all mocks. */ class StubDOMHandler extends __DOMHandler { constructor(throwingMethod, ErrorClass) { super() this.methods = [] DOMHandlerMethods.forEach((method) => { const impl = jest.fn( method === throwingMethod ? () => { throw new (ErrorClass || ParseError)( `StubDOMHandler throwing in ${throwingMethod}` ) } : noop ) impl.mockName(method) this[method] = impl this.methods.push(impl) }) } } /** * This sample is triggering all method calls from XMLReader to DOMHandler at least once. * This is verified in a test. * * There is of course no guarantee that it triggers all the places where XMLReader calls DOMHandler. * For example not all possible warning and error cases are present in this file, * but some, so that the methods are triggered. * For testing all the cases of the different error levels, * there are samples per case in * @see REPORTED */ const ALL_METHODS = ` character ", } `; exports[`errorHandle should encode < literal when not part of a tag 1`] = ` Object { "actual": "

populaciji (< 0.1%), te se

", "error": Array [ "[xmldom error] element parse error: Error: invalid tagName: @#[line:1,col:16]", ], } `; exports[`errorHandle unclosed tag 1`] = ` Object { "actual": "", "error": Array [ "[xmldom error] unexpected end of input @#[line:1,col:1]", ], "warning": Array [ "[xmldom warning] unclosed xml attribute @#[line:1,col:1]", ], } `; xmldom-0.8.6/test/parse/__snapshots__/unclosedcomment.test.js.snap000066400000000000000000000003121433143211200253750ustar00rootroot00000000000000// Jest Snapshot v1, https://goo.gl/fbAQLP exports[`errorHandle unclosedcomment 1`] = ` Object { "actual": "!--", "error": Array [ "[xmldom error] Unclosed comment @#[line:1,col:1]", ], } `; xmldom-0.8.6/test/parse/big-file-performance.test.js000066400000000000000000000104511433143211200224020ustar00rootroot00000000000000/* eslint strict: off */ const { XMLSerializer, DOMParser } = require('../../lib') /* var DomJS = require('dom-js').DomJS try { var Libxml = require('libxmljs') console.log('libxml loaded!!') } catch (e) { console.error(e) } */ function xmldom(data) { console.time('xmldom') var doc = new DOMParser({ locator: null, checkLater: true }).parseFromString( data ) console.timeEnd('xmldom') if (doc.toString.name != 'xxxxx') { doc.toString = function xxxxx() { return new XMLSerializer().serializeToString(doc) } } return doc } function libxml(data) { if (Libxml) { console.time('libxml') var doc = Libxml.parseXmlString(data) console.timeEnd('libxml') var ToString = doc.toString if (ToString.name != 'xxxxx') { doc.toString = function xxxxx() { return ToString.apply(this, arguments).replace(/^\s+|\s+$/g, '') } } //console.error(doc.toString()) return doc } else { console.warn('libxml is not installed') } } function domjs(data) { console.time('dom-js') var doc new DomJS().parse(data, function (err, dom) { doc = dom }) console.timeEnd('dom-js') doc.toString = function () { return doc.toXml() } return doc } var maxRandomAttr = parseInt(Math.random() * 60) console.log('maxRandomAttr', maxRandomAttr) function addAttributes(el) { var c = parseInt(Math.random() * maxRandomAttr) while (c--) { el.setAttribute('dynamic-attr' + c, c + new Array(c).join('.')) } var child = el.firstChild while (child) { if (child.nodeType == 1) { addAttributes(child) } else if (child.nodeType == 4) { //cdata el.insertBefore(el.ownerDocument.createTextNode(child.data), child) el.removeChild(child) } child = child.nextSibling } } xdescribe('XML Node Parse', () => { it('big file parse', () => { var fs = require('fs') var path = require('path') var data = fs.readFileSync( path.resolve(__dirname, './file-test1.xml'), 'ascii' ) //data = " ![CDATA[v]] d &\n" console.log('test simple xml') var t1 = new Date() var doc1 = xmldom(data) var t2 = new Date() var doc2 = domjs(data) var t3 = new Date() var doc3 = libxml(data) var t4 = new Date() var xmldomTime = t2 - t1 var domjsTime = t3 - t2 console.assert( domjsTime > xmldomTime, 'xmldom performance must more height!!' ) doc1 = doc1.cloneNode(true) addAttributes(doc1.documentElement) data = doc1.toString() console.log('test more attribute xml') var t1 = new Date() var doc1 = xmldom(data) var t2 = new Date() var doc2 = domjs(data) var t3 = new Date() var doc3 = libxml(data) var t4 = new Date() var xmldomTime = t2 - t1 var domjsTime = t3 - t2 console.assert( domjsTime > xmldomTime, 'xmldom performance must more height!!' ) function xmlReplace(a, v) { switch (v) { case '&': return '&' case '<': return '<' default: if (v.length > 1) { return v.replace(/([&<])/g, xmlReplace) } } } xmldomresult = (domjs(doc1 + '') + '').replace( /^<\?.*?\?>\s*|/g, xmlReplace ) domjsresult = (doc2 + '').replace( /^<\?.*?\?>\s*|/g, xmlReplace ) data = xmldomresult //console.log(data.substring(100,200)) console.log('test more attribute xml without cdata') var t1 = new Date() var doc1 = xmldom(data) var t2 = new Date() var doc2 = domjs(data) var t3 = new Date() var doc3 = libxml(data) var t4 = new Date() var xmldomTime = t2 - t1 var domjsTime = t3 - t2 console.assert( domjsTime > xmldomTime, 'xmldom performance must more height!!' ) //console.log(xmldomresult,domjsresult) //assert.equal(xmldomresult,domjsresult); //,xmldomresult,domjsresult) if (xmldomresult !== domjsresult) { for (var i = 0; i < xmldomresult.length; i++) { if (xmldomresult.charAt(i) != domjsresult.charAt(i)) { console.log(xmldomresult.charAt(i)) var begin = i - 50 var len = 100 xmldomresult = xmldomresult.substr(begin, len) domjsresult = domjsresult.substr(begin, len) //console.log(xmldomresult.length,domjsresult.length) console.log('pos' + i, '\n', xmldomresult, '\n\n\n\n', domjsresult) console.assert(xmldomresult == domjsresult) break } } } //console.assert(xmldomresult == domjsresult,xmldomresult.length,i) }) }) xmldom-0.8.6/test/parse/doctype.test.js000066400000000000000000000027721433143211200201030ustar00rootroot00000000000000'use strict' const { getTestParser } = require('../get-test-parser') const { MIME_TYPE } = require('../../lib/conventions') describe('doctype', () => { describe.each(['SYSTEM', 'PUBLIC'])('%s', (idType) => { test.each([ ['outer single', ``, "'\"'"], ['outer double', ``, '"\'"'], ])( 'should parse single line DOCTYPE with mixed quotes (%s)', (_, source, idValue) => { const { errors, parser } = getTestParser() const actual = parser.parseFromString(source).firstChild expect({ [idType]: idType === 'SYSTEM' ? actual.systemId : actual.publicId, name: actual.name, ...errors, }).toEqual({ [idType]: idValue, name: 'x', }) } ) }) describe('sets Document.doctype', () => { it('should set it for XML documents', () => { const { parser } = getTestParser() const doc = parser.parseFromString('') expect(doc.doctype).toBeTruthy() expect(doc.doctype.ownerDocument === doc).toBe(true) expect(doc.firstChild === doc.doctype).toBe(true) expect(doc.childNodes.length).toBe(2) }) it('should set it for HTML documents', () => { const { parser } = getTestParser() const doc = parser.parseFromString( '', MIME_TYPE.HTML ) expect(doc.doctype).toBeTruthy() expect(doc.doctype.ownerDocument === doc).toBe(true) expect(doc.firstChild === doc.doctype).toBe(true) expect(doc.childNodes.length).toBe(2) }) }) }) xmldom-0.8.6/test/parse/entities.test.js000066400000000000000000000011441433143211200202500ustar00rootroot00000000000000'use strict' const { getTestParser } = require('../get-test-parser') const { MIME_TYPE } = require('../../lib/conventions') describe('entity replacement ignores js prototype chain', () => { it("should not pick up 'entities' from the prototype chain", () => { const source = ` &hasOwnProperty; &__proto__; &constructor; ` const { errors, parser } = getTestParser() const actual = parser.parseFromString(source, MIME_TYPE.XML_TEXT).toString() expect({ actual, ...errors }).toMatchSnapshot() }) }) xmldom-0.8.6/test/parse/file-test1.result.xml000066400000000000000000044133441433143211200211410ustar00rootroot00000000000000 8.0 05/21/12 12:18:42 ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]>
xmldom-0.8.6/test/parse/file-test1.xml000066400000000000000000044166001433143211200176220ustar00rootroot00000000000000 8.0 05/21/12 12:18:42 ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]>
xmldom-0.8.6/test/parse/file.test.js000066400000000000000000000010521433143211200173410ustar00rootroot00000000000000'use strict' const fs = require('fs') const { DOMParser } = require('../../lib') describe('from file', () => { it('file-test1.xml', () => { const data = fs .readFileSync(__dirname + '/file-test1.xml') .toString() .replace(/\r\n?/g, '\n') const expexted = fs .readFileSync(__dirname + '/file-test1.result.xml') .toString() .replace(/\r\n?/g, '\n') // fs.writeFileSync(__dirname+'/file-test1.result.xml',result) const actual = new DOMParser().parseFromString(data).toString() expect(actual).toStrictEqual(expexted) }) }) xmldom-0.8.6/test/parse/locator.test.js000066400000000000000000000053751433143211200201010ustar00rootroot00000000000000'use strict' const { DOMParser } = require('../../lib') const { getTestParser } = require('../get-test-parser') describe('DOMLocator', () => { it('empty line number', () => { const xml = [ '', '', ' ', '', ' ', ' ', ' ', '', ' ', ].join('\n') const doc = new DOMParser().parseFromString(xml, 'text/xml') expect(doc.getElementsByTagName('transition')[0]).toMatchObject({ // we are not testing for columnNumber here to keep this test as specific as possible // it proves that empty lines are counted as lines // it should only fail if that changes lineNumber: 10, }) }) it('node positions', () => { const instruction = '' const dom = new DOMParser().parseFromString( `${instruction}\n` + '\n' + '
something\n' + 'x', 'text/xml' ) expect(dom).toMatchObject({ firstChild: { // lineNumber: 1, columnNumber: 1, nextSibling: { nodeName: '#comment', lineNumber: 1, columnNumber: 1 + instruction.length, }, }, documentElement: { nodeName: 'test', lineNumber: 2, columnNumber: 1, firstChild: { nodeName: '#text', lineNumber: 2, columnNumber: 7, nextSibling: { nodeName: 'a', lineNumber: 3, columnNumber: 3, firstChild: { nodeName: '#cdata-section', lineNumber: 3, columnNumber: 19, }, lastChild: { textContent: 'something\n', lineNumber: 3, columnNumber: 32, }, }, }, lastChild: { textContent: 'x', lineNumber: 4, columnNumber: 5, }, }, }) }) it('attribute position', () => { // TODO: xml not well formed but no warning or error, extract into different test? const xml = '<;test' const { errors, parser } = getTestParser({ locator: { systemId: 'c:/test/1.xml' }, }) const doc = parser.parseFromString(xml, 'text/html') expect({ actual: doc.toString(), ...errors }).toMatchSnapshot() 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() parser.parseFromString('\n\t', 'text/html') expect(errors).toMatchSnapshot() }) }) xmldom-0.8.6/test/parse/namespace.test.js000066400000000000000000000037311433143211200203640ustar00rootroot00000000000000'use strict' 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)] describe('XML Namespace Parse', () => { it('default namespace', () => { const { documentElement } = new DOMParser().parseFromString( '', 'text/xml' ) expect( uniqArray( documentElement.namespaceURI, documentElement.lookupNamespaceURI(''), documentElement.firstChild.namespaceURI, documentElement.firstChild.lookupNamespaceURI('') ) ).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 expect( uniqArray( documentElement.lookupNamespaceURI('p1'), 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() }) 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') }) }) xmldom-0.8.6/test/parse/node.test.js000066400000000000000000000126051433143211200173550ustar00rootroot00000000000000'use strict' 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) if (nodes.length > 0) { expectNeighbours(second, ...nodes) } } describe('XML Node Parse', () => { it('element', () => { const dom = new DOMParser().parseFromString('') expect(dom.documentElement.nodeType).toStrictEqual(Node.ELEMENT_NODE) expect(dom.documentElement.firstChild.nodeType).toStrictEqual( Node.ELEMENT_NODE ) expect(dom).toMatchObject({ childNodes: { length: 1, }, documentElement: { childNodes: { length: 1, }, firstChild: { nodeName: 'child', tagName: 'child', }, nodeName: 'xml', tagName: 'xml', }, }) }) it('text', () => { const { firstChild } = new DOMParser().parseFromString( 'start center end' ).documentElement 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: { data: '', nextSibling: { nextSibling: { data: '[[[[[[[[]]]]]]]]', }, }, }, }) }) it('cdata empty', () => { const { documentElement } = new DOMParser().parseFromString( 'start end' ) expect(documentElement).toMatchObject({ textContent: 'start end', }) }) it('comment', () => { const { documentElement } = new DOMParser().parseFromString( '' ) expect(documentElement.firstChild).toMatchObject({ nodeValue: ' comment&>< ', }) }) it('cdata comment', () => { const { documentElement } = new DOMParser().parseFromString( 'start ]]> end' ) expect(documentElement.firstChild).toMatchObject({ nodeName: '#text', // 0 nodeValue: 'start ', nextSibling: { nodeName: '#cdata-section', // 1 nodeValue: '', nextSibling: { nodeName: '#text', // 2 nodeValue: ' ', nextSibling: { nodeName: '#comment', // 3 nodeValue: ' comment ', nextSibling: { nodeName: '#text', // 4 nodeValue: 'end', }, }, }, }, }) }) describe('appendChild', () => { it('returns the argument', () => { const dom = new DOMParser().parseFromString('') const child = dom.createElement('child') expect(dom.documentElement.appendChild(child)).toStrictEqual(child) }) it('appends as firstChild', () => { const dom = new DOMParser().parseFromString('') const child = dom.createElement('child') dom.documentElement.appendChild(child) expect(dom.documentElement.firstChild).toStrictEqual(child) }) it('subsequent calls append in order', () => { const dom = new DOMParser().parseFromString('') const fragment = dom.createDocumentFragment() expect(fragment.nodeType).toStrictEqual(Node.DOCUMENT_FRAGMENT_NODE) 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) }) }) describe('insertBefore', () => { it('places created element before existing element', () => { const dom = new DOMParser().parseFromString('') const inserted = dom.createElement('sibling') const child = dom.documentElement.firstChild child.parentNode.insertBefore(inserted, child) expectNeighbours(inserted, child) }) it('inserts all elements in DocumentFragment', () => { 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')) child.parentNode.insertBefore(fragment, child) expectNeighbours(first, second, child) expect(child.parentNode.firstChild).toStrictEqual(first) }) }) it('preserves instruction', () => { const source = '&' const actual = new DOMParser() .parseFromString(source, 'text/xml') .toString() expect(actual).toStrictEqual(source) }) it('preserves doctype with public id and sysid', () => { const DOCTYPE = '' const actual = new DOMParser() .parseFromString(`${DOCTYPE}`, 'text/html') .toString() expect(actual).toStrictEqual( `${DOCTYPE}` ) }) it('preserves doctype with sysid', () => { const DOCTYPE = '' const actual = new DOMParser() .parseFromString(`${DOCTYPE}`, 'text/xml') .toString() expect(actual).toStrictEqual(`${DOCTYPE}`) }) }) xmldom-0.8.6/test/parse/normalize-line-endings.test.js000066400000000000000000000035451433143211200230050ustar00rootroot00000000000000'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)}`) 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 ) expect(whitespaceToHex(actual.firstChild.nodeValue)).toBe( '#xa#x20#xa#x20#xa' ) }) it('should use the provided normalizeLineEndings option', () => { const mockNormalize = jest.fn(() => '') const actual = new DOMParser({ normalizeLineEndings: mockNormalize, }).parseFromString('', MIME_TYPE.XML_TEXT) 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') }) it('should normalize the two-character sequence #xD #x85', () => { expect(whitespaceToHex(normalizeLineEndings('\r\u0085'))).toBe('#xa') }) it('should normalize the single character #x85', () => { expect(whitespaceToHex(normalizeLineEndings('\u0085'))).toBe('#xa') }) it('should normalize the single character #x2028', () => { 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') }) }) xmldom-0.8.6/test/parse/parse-element.test.js000066400000000000000000000106751433143211200211760ustar00rootroot00000000000000'use strict' 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('nested closing tag with whitespace', () => { const actual = new DOMParser() .parseFromString( ` Giada De Laurentiis Everyday Italian `, 'text/xml' ) .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`) }) describe('simple attributes', () => { describe('nothing special', () => { 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('') }) }) // https://www.w3.org/TR/xml/#AVNormalize describe('containing whitespace', () => { it('should transform whitespace literals into spaces', () => { 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') expect(attr.value).toBe(' ') }) it.each([ [' ', '\t'], [' ', '\t'], [' ', '\n'], [' ', '\n'], [' ', '\n'], [' ', '\r'], [' ', '\r'], [' ', '\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) } ) }) it('unclosed root tag will be closed', () => { const { errors, parser } = getTestParser() const actual = parser .parseFromString('', 'text/xml') .toString() expect({ actual, ...errors }).toMatchSnapshot() }) it('should be able to have `constructor` attribute', () => { const { errors, parser } = getTestParser() const actual = parser .parseFromString('', 'text/xml') .toString() expect({ actual, ...errors }).toMatchSnapshot() }) it('should be able to have `__prototype__` attribute', () => { const { errors, parser } = getTestParser() const actual = parser .parseFromString('', 'text/xml') .toString() expect({ actual, ...errors }).toMatchSnapshot() }) }) describe('namespaced attributes', () => { it.each([ '', '', '', ])('%s', (input) => { const actual = new DOMParser() .parseFromString(input, 'text/xml') .toString() expect(actual).toBe('') }) it('unclosed root tag will be closed', () => { const { errors, parser } = getTestParser() const actual = parser .parseFromString('', 'text/xml') .toString() expect({ actual, ...errors }).toMatchSnapshot() }) }) }) xmldom-0.8.6/test/parse/parse-error.test.js000066400000000000000000000021631433143211200206670ustar00rootroot00000000000000'use strict' const { ParseError } = require('../../lib/sax') describe('ParseError', () => { it('should have name ParseError', () => { expect(new ParseError('').name).toBe('ParseError') }) it('should be an instance of Error', () => { expect(new ParseError('') instanceof Error).toBe(true) }) it('should be an instance of ParseError', () => { 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') }) it('should store second argument as 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) }) it('Error should not be instanceof ParseError', () => { expect(new Error() instanceof ParseError).toBe(false) }) }) xmldom-0.8.6/test/parse/simple.test.js000066400000000000000000000054711433143211200177240ustar00rootroot00000000000000'use strict' const { getTestParser } = require('../get-test-parser') describe('parse', () => { it('simple', () => { const { errors, parser } = getTestParser() const actual = parser .parseFromString('', 'text/html') .toString() expect({ actual, ...errors }).toMatchSnapshot() }) it('unclosed inner', () => { const { errors, parser } = getTestParser() const actual = parser .parseFromString( '', 'text/xml' ) .toString() expect({ actual, ...errors }).toMatchSnapshot() }) it('unclosed root', () => { const { errors, parser } = getTestParser() const actual = parser .parseFromString(' { const svgCase = [ '', ' ...', ' ', ' ', ' ', '', ].join('\n') const { errors, parser } = getTestParser({ locator: {} }) const actual = parser.parseFromString(svgCase, 'text/xml').toString() expect({ actual, ...errors }).toMatchSnapshot() }) it('line error', () => { const xmlLineError = [ '', ' ', '', ].join('\r\n') const { errors, parser } = getTestParser({ locator: {} }) const dom = parser.parseFromString(xmlLineError, 'text/xml') expect({ lineNumber: dom.documentElement.firstChild.nextSibling.lineNumber, ...errors, }).toMatchSnapshot() }) it('wrong closing tag', () => { const { errors, parser } = getTestParser({ locator: {} }) const actual = parser .parseFromString( // TODO: xml not well formed but no warning or error, extract into different test? '
<;test', 'text/html' ) .toString() expect({ actual, ...errors }).toMatchSnapshot() }) describe('invalid input', () => { it.each([ ['falsy string', ''], ['object', {}], ['number', 12345], ['null', null], ])('%s', (msg, testValue) => { const { parser } = getTestParser(rethrowErrorHandler()) expect(() => parser.parseFromString(testValue)).toThrow( /^\[xmldom error\][\s]*invalid doc source[\s\S]*$/ ) }) }) }) function rethrowErrorHandler() { return { errorHandler: { error: function (errorMessage) { throw errorMessage }, }, } } xmldom-0.8.6/test/parse/test-doc-whitespace.test.js000066400000000000000000000015431433143211200223030ustar00rootroot00000000000000'use strict' const { getTestParser } = require('../get-test-parser') describe('errorHandle', () => { it('unclosed tag', () => { const { errors, parser } = getTestParser() const actual = parser.parseFromString(' { const testSource = '\n\n' const { errors, parser } = getTestParser() const actual = parser.parseFromString(testSource, 'text/xml').toString() 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 actual = parser.parseFromString(description, 'text/html').toString() expect({ actual, ...errors }).toMatchSnapshot() }) }) xmldom-0.8.6/test/parse/unclosedcomment.test.js000066400000000000000000000004651433143211200216300ustar00rootroot00000000000000'use strict' const { getTestParser } = require('../get-test-parser') describe('errorHandle', () => { it('unclosedcomment', () => { const { errors, parser } = getTestParser() const actual = parser.parseFromString('", } `; exports[`xmltest/not-wellformed standalone should match 007.xml with snapshot 1`] = ` Object { "actual": "&amp no refc", } `; exports[`xmltest/not-wellformed standalone should match 008.xml with snapshot 1`] = ` Object { "actual": "&.entity;", } `; exports[`xmltest/not-wellformed standalone should match 009.xml with snapshot 1`] = ` Object { "actual": "{!0!}", } `; exports[`xmltest/not-wellformed standalone should match 010.xml with snapshot 1`] = ` Object { "actual": "A & B", } `; exports[`xmltest/not-wellformed standalone should match 011.xml with snapshot 1`] = ` Object { "actual": "", "warning": Array [ "[xmldom warning] attribute \\"a1\\" missed value!! \\"a1\\" instead!! @#[line:1,col:1]", ], } `; exports[`xmltest/not-wellformed standalone should match 012.xml with snapshot 1`] = ` Object { "actual": "", "warning": Array [ "[xmldom warning] attribute \\"v1\\" missed quot(\\")! @#[line:1,col:1]", ], } `; exports[`xmltest/not-wellformed standalone should match 013.xml with snapshot 1`] = ` Object { "actual": "", "error": Array [ "[xmldom error] element parse error: Error: attribute value no end '\\"' match @#[line:1,col:1]", ], } `; exports[`xmltest/not-wellformed standalone should match 014.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 015.xml with snapshot 1`] = ` Object { "actual": "", "error": Array [ "[xmldom error] element parse error: Error: attribute value missed!! @#[line:1,col:1]", ], } `; exports[`xmltest/not-wellformed standalone should match 016.xml with snapshot 1`] = ` Object { "actual": "", "error": Array [ "[xmldom error] element parse error: Error: attribute value must after \\"=\\" @#[line:1,col:1]", ], } `; exports[`xmltest/not-wellformed standalone should match 017.xml with snapshot 1`] = ` Object { "actual": "<![CDATA[", } `; exports[`xmltest/not-wellformed standalone should match 018.xml with snapshot 1`] = ` Object { "actual": "<![CDATA [ stuff]]>", } `; exports[`xmltest/not-wellformed standalone should match 019.xml with snapshot 1`] = ` Object { "actual": "", "error": Array [ "[xmldom error] end tag name: > is not complete:undefined @#[line:1,col:1]", ], "warning": Array [ "[xmldom warning] unclosed xml attribute @#[line:1,col:1]", ], } `; exports[`xmltest/not-wellformed standalone should match 020.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 021.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 022.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 023.xml with snapshot 1`] = ` Object { "actual": "", "error": Array [ "[xmldom error] element parse error: Error: invalid attribute:12 @#[line:1,col:1]", ], } `; exports[`xmltest/not-wellformed standalone should match 024.xml with snapshot 1`] = ` Object { "actual": " <123> ", "error": Array [ "[xmldom error] element parse error: Error: invalid tagName:123 @#[line:2,col:1]", ], } `; exports[`xmltest/not-wellformed standalone should match 025.xml with snapshot 1`] = ` Object { "actual": "]]>", } `; exports[`xmltest/not-wellformed standalone should match 026.xml with snapshot 1`] = ` Object { "actual": "]]]>", } `; exports[`xmltest/not-wellformed standalone should match 027.xml with snapshot 1`] = ` Object { "actual": " <!-- abc ", "error": Array [ "[xmldom error] Unclosed comment @#[line:2,col:1]", ], } `; exports[`xmltest/not-wellformed standalone should match 028.xml with snapshot 1`] = ` Object { "actual": " <?a pi that is not closed ", } `; exports[`xmltest/not-wellformed standalone should match 029.xml with snapshot 1`] = ` Object { "actual": "abc]]]>def", } `; exports[`xmltest/not-wellformed standalone should match 030.xml with snapshot 1`] = ` Object { "actual": "A form feed ( ) is not legal in data", } `; exports[`xmltest/not-wellformed standalone should match 031.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 032.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 033.xml with snapshot 1`] = ` Object { "actual": "abc{!1b!}def", } `; exports[`xmltest/not-wellformed standalone should match 034.xml with snapshot 1`] = ` Object { "actual": "A form-feed is not white space or a name character", } `; exports[`xmltest/not-wellformed standalone should match 035.xml with snapshot 1`] = ` Object { "actual": "1 < 2 but not in XML", "error": Array [ "[xmldom error] element parse error: Error: invalid tagName: @#[line:1,col:8]", ], } `; exports[`xmltest/not-wellformed standalone should match 036.xml with snapshot 1`] = ` Object { "actual": " Illegal data ", } `; exports[`xmltest/not-wellformed standalone should match 037.xml with snapshot 1`] = ` Object { "actual": " &#32; ", } `; exports[`xmltest/not-wellformed standalone should match 038.xml with snapshot 1`] = ` Object { "actual": "", "fatalError": Array [ "[xmldom fatalError] Attribute x redefined @#[line:1,col:1]", ], } `; exports[`xmltest/not-wellformed standalone should match 039.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 040.xml with snapshot 1`] = ` Object { "actual": " <doc>", "error": Array [ "[xmldom error] element parse error: Error: Hierarchy request error: Only one element can be added and only after doctype @#[line:2,col:1]", ], } `; exports[`xmltest/not-wellformed standalone should match 041.xml with snapshot 1`] = ` Object { "actual": " <doc>", "error": Array [ "[xmldom error] element parse error: Error: Hierarchy request error: Only one element can be added and only after doctype @#[line:2,col:1]", ], } `; exports[`xmltest/not-wellformed standalone should match 042.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 043.xml with snapshot 1`] = ` Object { "actual": " Illegal data ", } `; exports[`xmltest/not-wellformed standalone should match 044.xml with snapshot 1`] = ` Object { "actual": "<doc/> ", "error": Array [ "[xmldom error] element parse error: Error: Hierarchy request error: Only one element can be added and only after doctype @#[line:1,col:7]", ], } `; exports[`xmltest/not-wellformed standalone should match 045.xml with snapshot 1`] = ` Object { "actual": " <a/ ", "error": Array [ "[xmldom error] element parse error: Error: elements closed character '/' and '>' must be connected to @#[line:2,col:1]", ], } `; exports[`xmltest/not-wellformed standalone should match 046.xml with snapshot 1`] = ` Object { "actual": " <a/ ", "error": Array [ "[xmldom error] element parse error: Error: elements closed character '/' and '>' must be connected to @#[line:2,col:1]", ], } `; exports[`xmltest/not-wellformed standalone should match 047.xml with snapshot 1`] = ` Object { "actual": " ", } `; exports[`xmltest/not-wellformed standalone should match 048.xml with snapshot 1`] = ` Object { "actual": " ", } `; exports[`xmltest/not-wellformed standalone should match 049.xml with snapshot 1`] = ` Object { "actual": " ", } `; exports[`xmltest/not-wellformed standalone should match 050.xml with snapshot 1`] = ` Object { "actual": undefined, "error": Array [ "[xmldom error] invalid doc source @#[line:0,col:undefined]", ], } `; exports[`xmltest/not-wellformed standalone should match 051.xml with snapshot 1`] = ` Object { "actual": " ", } `; exports[`xmltest/not-wellformed standalone should match 052.xml with snapshot 1`] = ` Object { "actual": " ", } `; exports[`xmltest/not-wellformed standalone should match 053.xml with snapshot 1`] = ` Object { "actual": "", "warning": Array [ "[xmldom warning] unclosed xml attribute @#[line:1,col:1]", ], } `; exports[`xmltest/not-wellformed standalone should match 054.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 055.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 056.xml with snapshot 1`] = ` Object { "actual": " ", } `; exports[`xmltest/not-wellformed standalone should match 057.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 058.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 059.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 060.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 061.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 062.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 063.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 064.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 065.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 066.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 067.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 068.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 069.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 070.xml with snapshot 1`] = ` Object { "actual": " ", } `; exports[`xmltest/not-wellformed standalone should match 071.xml with snapshot 1`] = ` Object { "actual": "&e1;", "error": Array [ "[xmldom error] entity not found:&e1; @#[line:1,col:1]", ], } `; exports[`xmltest/not-wellformed standalone should match 072.xml with snapshot 1`] = ` Object { "actual": "&foo;", "error": Array [ "[xmldom error] entity not found:&foo; @#[line:1,col:1]", ], } `; exports[`xmltest/not-wellformed standalone should match 073.xml with snapshot 1`] = ` Object { "actual": "&f;", "error": Array [ "[xmldom error] entity not found:&f; @#[line:1,col:1]", ], } `; exports[`xmltest/not-wellformed standalone should match 074.xml with snapshot 1`] = ` Object { "actual": " &e; ", "error": Array [ "[xmldom error] entity not found:&e; @#[line:2,col:1]", ], } `; exports[`xmltest/not-wellformed standalone should match 075.xml with snapshot 1`] = ` Object { "actual": "", "error": Array [ "[xmldom error] entity not found:&e1; @#[line:1,col:1]", ], } `; exports[`xmltest/not-wellformed standalone should match 076.xml with snapshot 1`] = ` Object { "actual": "", "error": Array [ "[xmldom error] entity not found:&foo; @#[line:1,col:1]", ], } `; exports[`xmltest/not-wellformed standalone should match 077.xml with snapshot 1`] = ` Object { "actual": "", "error": Array [ "[xmldom error] entity not found:&foo; @#[line:1,col:1]", ], } `; exports[`xmltest/not-wellformed standalone should match 078.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 079.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 080.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 081.xml with snapshot 1`] = ` Object { "actual": "", "error": Array [ "[xmldom error] entity not found:&e; @#[line:1,col:1]", ], } `; exports[`xmltest/not-wellformed standalone should match 082.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 083.xml with snapshot 1`] = ` Object { "actual": "&e;", "error": Array [ "[xmldom error] entity not found:&e; @#[line:1,col:1]", ], } `; exports[`xmltest/not-wellformed standalone should match 084.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 085.xml with snapshot 1`] = ` Object { "actual": " ", } `; exports[`xmltest/not-wellformed standalone should match 086.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 087.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 088.xml with snapshot 1`] = ` Object { "actual": "", "error": Array [ "[xmldom error] element parse error: Error: attribute value no end '\\"' match @#[line:1,col:1]", "[xmldom error] entity not found:&e; @#[line:1,col:1]", ], } `; exports[`xmltest/not-wellformed standalone should match 089.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 090.xml with snapshot 1`] = ` Object { "actual": "&e;", "error": Array [ "[xmldom error] entity not found:&e; @#[line:1,col:1]", ], } `; exports[`xmltest/not-wellformed standalone should match 091.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 092.xml with snapshot 1`] = ` Object { "actual": "&e;", "error": Array [ "[xmldom error] entity not found:&e; @#[line:1,col:1]", ], } `; exports[`xmltest/not-wellformed standalone should match 093.xml with snapshot 1`] = ` Object { "actual": "{!0!}", } `; exports[`xmltest/not-wellformed standalone should match 094.xml with snapshot 1`] = ` Object { "actual": " ", } `; exports[`xmltest/not-wellformed standalone should match 095.xml with snapshot 1`] = ` Object { "actual": " ", } `; exports[`xmltest/not-wellformed standalone should match 096.xml with snapshot 1`] = ` Object { "actual": " ", } `; exports[`xmltest/not-wellformed standalone should match 097.xml with snapshot 1`] = ` Object { "actual": " ", } `; exports[`xmltest/not-wellformed standalone should match 098.xml with snapshot 1`] = ` Object { "actual": " ", } `; exports[`xmltest/not-wellformed standalone should match 099.xml with snapshot 1`] = ` Object { "actual": " ", } `; exports[`xmltest/not-wellformed standalone should match 100.xml with snapshot 1`] = ` Object { "actual": " ", } `; exports[`xmltest/not-wellformed standalone should match 101.xml with snapshot 1`] = ` Object { "actual": " ", } `; exports[`xmltest/not-wellformed standalone should match 102.xml with snapshot 1`] = ` Object { "actual": " ", } `; exports[`xmltest/not-wellformed standalone should match 103.xml with snapshot 1`] = ` Object { "actual": "&e;", "error": Array [ "[xmldom error] entity not found:&e; @#[line:1,col:1]", ], } `; exports[`xmltest/not-wellformed standalone should match 104.xml with snapshot 1`] = ` Object { "actual": "&e;", "error": Array [ "[xmldom error] entity not found:&e; @#[line:1,col:1]", ], } `; exports[`xmltest/not-wellformed standalone should match 105.xml with snapshot 1`] = ` Object { "actual": " ", } `; exports[`xmltest/not-wellformed standalone should match 106.xml with snapshot 1`] = ` Object { "actual": " ", } `; exports[`xmltest/not-wellformed standalone should match 107.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 108.xml with snapshot 1`] = ` Object { "actual": " <![CDATA [ ]]> ", } `; exports[`xmltest/not-wellformed standalone should match 109.xml with snapshot 1`] = ` Object { "actual": "&e; ", } `; exports[`xmltest/not-wellformed standalone should match 110.xml with snapshot 1`] = ` Object { "actual": " &e; ", } `; exports[`xmltest/not-wellformed standalone should match 111.xml with snapshot 1`] = ` Object { "actual": "", "error": Array [ "[xmldom error] entity not found:&e; @#[line:1,col:1]", "[xmldom error] element parse error: Error: invalid attribute:&e; @#[line:1,col:1]", "[xmldom error] entity not found:&e; @#[line:1,col:1]", ], "warning": Array [ "[xmldom warning] attribute \\"&e;\\" missed value!! \\"&e;\\" instead!! @#[line:1,col:1]", ], } `; exports[`xmltest/not-wellformed standalone should match 112.xml with snapshot 1`] = ` Object { "actual": " <![cdata[data]]> ", } `; exports[`xmltest/not-wellformed standalone should match 113.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 114.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 115.xml with snapshot 1`] = ` Object { "actual": "", "error": Array [ "[xmldom error] entity not found:&e; @#[line:1,col:1]", ], } `; exports[`xmltest/not-wellformed standalone should match 116.xml with snapshot 1`] = ` Object { "actual": "&e;7;", "error": Array [ "[xmldom error] entity not found:&e; @#[line:1,col:1]", ], } `; exports[`xmltest/not-wellformed standalone should match 117.xml with snapshot 1`] = ` Object { "actual": "&e;#97;", "error": Array [ "[xmldom error] entity not found:&e; @#[line:1,col:1]", ], } `; exports[`xmltest/not-wellformed standalone should match 118.xml with snapshot 1`] = ` Object { "actual": "&&e;97;", "error": Array [ "[xmldom error] entity not found:&e; @#[line:1,col:1]", ], } `; exports[`xmltest/not-wellformed standalone should match 119.xml with snapshot 1`] = ` Object { "actual": " &e;#38; ", "error": Array [ "[xmldom error] entity not found:&e; @#[line:1,col:1]", ], } `; exports[`xmltest/not-wellformed standalone should match 120.xml with snapshot 1`] = ` Object { "actual": " &e; ", "error": Array [ "[xmldom error] entity not found:&e; @#[line:1,col:1]", ], } `; exports[`xmltest/not-wellformed standalone should match 121.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 122.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 123.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 124.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 125.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 126.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 127.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 128.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 129.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 130.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 131.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 132.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 133.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 134.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 135.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 136.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 137.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 138.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 139.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 140.xml with snapshot 1`] = ` Object { "actual": "&e;", "error": Array [ "[xmldom error] entity not found:&e; @#[line:1,col:1]", ], } `; exports[`xmltest/not-wellformed standalone should match 141.xml with snapshot 1`] = ` Object { "actual": "&e;", "error": Array [ "[xmldom error] entity not found:&e; @#[line:1,col:1]", ], } `; exports[`xmltest/not-wellformed standalone should match 142.xml with snapshot 1`] = ` Object { "actual": "{!0!}", } `; exports[`xmltest/not-wellformed standalone should match 143.xml with snapshot 1`] = ` Object { "actual": "{!1f!}", } `; exports[`xmltest/not-wellformed standalone should match 144.xml with snapshot 1`] = ` Object { "actual": "{!ffff!}", } `; exports[`xmltest/not-wellformed standalone should match 145.xml with snapshot 1`] = ` Object { "actual": "{!d800!}", } `; exports[`xmltest/not-wellformed standalone should match 146.xml with snapshot 1`] = ` Object { "actual": "{!dc00!}{!dc00!}", } `; exports[`xmltest/not-wellformed standalone should match 147.xml with snapshot 1`] = ` Object { "actual": " ", } `; exports[`xmltest/not-wellformed standalone should match 148.xml with snapshot 1`] = ` Object { "actual": " ", } `; exports[`xmltest/not-wellformed standalone should match 149.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 150.xml with snapshot 1`] = ` Object { "actual": " ", } `; exports[`xmltest/not-wellformed standalone should match 151.xml with snapshot 1`] = ` Object { "actual": " ", } `; exports[`xmltest/not-wellformed standalone should match 152.xml with snapshot 1`] = ` Object { "actual": " ", } `; exports[`xmltest/not-wellformed standalone should match 153.xml with snapshot 1`] = ` Object { "actual": "&e;", "error": Array [ "[xmldom error] entity not found:&e; @#[line:1,col:1]", ], } `; exports[`xmltest/not-wellformed standalone should match 154.xml with snapshot 1`] = ` Object { "actual": " ", } `; exports[`xmltest/not-wellformed standalone should match 155.xml with snapshot 1`] = ` Object { "actual": " ", } `; exports[`xmltest/not-wellformed standalone should match 156.xml with snapshot 1`] = ` Object { "actual": " ", } `; exports[`xmltest/not-wellformed standalone should match 157.xml with snapshot 1`] = ` Object { "actual": " ", } `; exports[`xmltest/not-wellformed standalone should match 158.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 159.xml with snapshot 1`] = ` Object { "actual": "&e;", "error": Array [ "[xmldom error] entity not found:&e; @#[line:5,col:1]", ], } `; exports[`xmltest/not-wellformed standalone should match 160.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 161.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 162.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 163.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 164.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 165.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 166.xml with snapshot 1`] = ` Object { "actual": "{!ffff!}", } `; exports[`xmltest/not-wellformed standalone should match 167.xml with snapshot 1`] = ` Object { "actual": "{!fffe!}", } `; exports[`xmltest/not-wellformed standalone should match 168.xml with snapshot 1`] = ` Object { "actual": "���", } `; exports[`xmltest/not-wellformed standalone should match 169.xml with snapshot 1`] = ` Object { "actual": "���", } `; exports[`xmltest/not-wellformed standalone should match 170.xml with snapshot 1`] = ` Object { "actual": "����", } `; exports[`xmltest/not-wellformed standalone should match 171.xml with snapshot 1`] = ` Object { "actual": " ", } `; exports[`xmltest/not-wellformed standalone should match 172.xml with snapshot 1`] = ` Object { "actual": " ", } `; exports[`xmltest/not-wellformed standalone should match 173.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 174.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 175.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 176.xml with snapshot 1`] = ` Object { "actual": "", "warning": Array [ "[xmldom warning] unclosed xml attribute @#[line:1,col:1]", ], } `; exports[`xmltest/not-wellformed standalone should match 177.xml with snapshot 1`] = ` Object { "actual": "A{!ffff!}", } `; exports[`xmltest/not-wellformed standalone should match 178.xml with snapshot 1`] = ` Object { "actual": "", "error": Array [ "[xmldom error] element parse error: Error: attribute value no end '\\"' match @#[line:1,col:1]", ], } `; exports[`xmltest/not-wellformed standalone should match 179.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 180.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 181.xml with snapshot 1`] = ` Object { "actual": "&e;]]>", "error": Array [ "[xmldom error] entity not found:&e; @#[line:1,col:1]", ], } `; exports[`xmltest/not-wellformed standalone should match 182.xml with snapshot 1`] = ` Object { "actual": "&e;-->", "error": Array [ "[xmldom error] entity not found:&e; @#[line:1,col:1]", ], } `; exports[`xmltest/not-wellformed standalone should match 183.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 184.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/not-wellformed standalone should match 185.xml with snapshot 1`] = ` Object { "actual": " &e;", "error": Array [ "[xmldom error] entity not found:&e; @#[line:3,col:1]", ], } `; exports[`xmltest/not-wellformed standalone should match 186.xml with snapshot 1`] = ` Object { "actual": "", "warning": Array [ "[xmldom warning] attribute space is required\\"b\\"!! @#[line:5,col:1]", ], } `; xmldom-0.8.6/test/xmltest/__snapshots__/valid.test.js.snap000066400000000000000000000532771433143211200237050ustar00rootroot00000000000000// Jest Snapshot v1, https://goo.gl/fbAQLP exports[`xmltest/valid standalone should match 001.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 002.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 003.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 004.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 005.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 006.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 007.xml with snapshot 1`] = ` Object { "actual": " ", } `; exports[`xmltest/valid standalone should match 008.xml with snapshot 1`] = ` Object { "actual": "&<>\\"'", "expected": "&<>"'", } `; exports[`xmltest/valid standalone should match 009.xml with snapshot 1`] = ` Object { "actual": " ", } `; exports[`xmltest/valid standalone should match 010.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 011.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 012.xml with snapshot 1`] = ` Object { "actual": "", "error": Array [ "[xmldom error] element parse error: Error: invalid attribute:: @#[line:1,col:1]", ], "expected": "", } `; exports[`xmltest/valid standalone should match 013.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 014.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 015.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 016.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/valid standalone should match 017.xml with snapshot 1`] = ` Object { "actual": " ", } `; exports[`xmltest/valid standalone should match 018.xml with snapshot 1`] = ` Object { "actual": "]]>", "expected": "<foo>", } `; exports[`xmltest/valid standalone should match 019.xml with snapshot 1`] = ` Object { "actual": "", "expected": "<&", } `; exports[`xmltest/valid standalone should match 020.xml with snapshot 1`] = ` Object { "actual": "]]]>", "expected": "<&]>]", } `; exports[`xmltest/valid standalone should match 021.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 022.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 023.xml with snapshot 1`] = ` Object { "actual": "&e;", "error": Array [ "[xmldom error] entity not found:&e; @#[line:1,col:1]", ], "expected": "", } `; exports[`xmltest/valid standalone should match 024.xml with snapshot 1`] = ` Object { "actual": "&e;", "error": Array [ "[xmldom error] entity not found:&e; @#[line:1,col:1]", ], "expected": "", } `; exports[`xmltest/valid standalone should match 025.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 026.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 027.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 028.xml with snapshot 1`] = ` Object { "actual": " ", "expected": "", } `; exports[`xmltest/valid standalone should match 029.xml with snapshot 1`] = ` Object { "actual": " ", "expected": "", } `; exports[`xmltest/valid standalone should match 030.xml with snapshot 1`] = ` Object { "actual": " ", "expected": "", } `; exports[`xmltest/valid standalone should match 031.xml with snapshot 1`] = ` Object { "actual": " ", "expected": "", } `; exports[`xmltest/valid standalone should match 032.xml with snapshot 1`] = ` Object { "actual": " ", "expected": "", } `; exports[`xmltest/valid standalone should match 033.xml with snapshot 1`] = ` Object { "actual": " ", "expected": "", } `; exports[`xmltest/valid standalone should match 034.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 035.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 036.xml with snapshot 1`] = ` Object { "actual": " ", "expected": "", } `; exports[`xmltest/valid standalone should match 037.xml with snapshot 1`] = ` Object { "actual": " ", "expected": "", } `; exports[`xmltest/valid standalone should match 038.xml with snapshot 1`] = ` Object { "actual": " ", "expected": "", } `; exports[`xmltest/valid standalone should match 039.xml with snapshot 1`] = ` Object { "actual": " ", "expected": "", } `; exports[`xmltest/valid standalone should match 040.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 041.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 042.xml with snapshot 1`] = ` Object { "actual": "A", } `; exports[`xmltest/valid standalone should match 043.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 044.xml with snapshot 1`] = ` Object { "actual": " ", "expected": " ", } `; exports[`xmltest/valid standalone should match 045.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 046.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 047.xml with snapshot 1`] = ` Object { "actual": "X Y", "expected": "X Y", } `; exports[`xmltest/valid standalone should match 048.xml with snapshot 1`] = ` Object { "actual": "]", } `; exports[`xmltest/valid standalone should match 049.xml with snapshot 1`] = ` Object { "actual": "{!0!}/{!0!}d{!0!}o{!0!}c{!0!}>{!0!} {!0!} {!0!}", "error": Array [ "[xmldom error] element parse error: Error: invalid tagName: @#[line:1,col:3]", "[xmldom error] element parse error: Error: invalid tagName: @#[line:3,col:2]", "[xmldom error] element parse error: Error: invalid tagName: @#[line:7,col:2]", "[xmldom error] element parse error: Error: invalid tagName: @#[line:7,col:14]", ], "expected": "£", } `; exports[`xmltest/valid standalone should match 050.xml with snapshot 1`] = ` Object { "actual": "{!0!}/{!0!}d{!0!}o{!0!}c{!0!}>{!0!} {!0!} {!0!}", "error": Array [ "[xmldom error] element parse error: Error: invalid tagName: @#[line:1,col:3]", "[xmldom error] element parse error: Error: invalid tagName: @#[line:3,col:2]", "[xmldom error] element parse error: Error: invalid tagName: @#[line:7,col:2]", "[xmldom error] element parse error: Error: invalid tagName: @#[line:7,col:22]", ], "expected": "เจมส์", } `; exports[`xmltest/valid standalone should match 051.xml with snapshot 1`] = ` Object { "actual": "{!0!}/{!0!}@!*L>{!0!} {!0!} {!0!}", "error": Array [ "[xmldom error] element parse error: Error: invalid tagName: @#[line:1,col:3]", "[xmldom error] element parse error: Error: invalid tagName: @#[line:3,col:2]", "[xmldom error] element parse error: Error: invalid tagName: @#[line:7,col:2]", "[xmldom error] element parse error: Error: invalid tagName: @#[line:7,col:16]", ], "expected": "<เจมส์>", } `; exports[`xmltest/valid standalone should match 052.xml with snapshot 1`] = ` Object { "actual": "𐀀􏿽", } `; exports[`xmltest/valid standalone should match 053.xml with snapshot 1`] = ` Object { "actual": "&e;", "error": Array [ "[xmldom error] entity not found:&e; @#[line:1,col:1]", ], "expected": "", } `; exports[`xmltest/valid standalone should match 054.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 055.xml with snapshot 1`] = ` Object { "actual": " ", "expected": "", } `; exports[`xmltest/valid standalone should match 056.xml with snapshot 1`] = ` Object { "actual": "A", } `; exports[`xmltest/valid standalone should match 057.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 058.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 059.xml with snapshot 1`] = ` Object { "actual": " ", "expected": " ", } `; exports[`xmltest/valid standalone should match 060.xml with snapshot 1`] = ` Object { "actual": "X Y", "expected": "X Y", } `; exports[`xmltest/valid standalone should match 061.xml with snapshot 1`] = ` Object { "actual": "£", } `; exports[`xmltest/valid standalone should match 062.xml with snapshot 1`] = ` Object { "actual": "เจมส์", } `; exports[`xmltest/valid standalone should match 063.xml with snapshot 1`] = ` Object { "actual": "<เจมส์/>", "expected": "<เจมส์>", } `; exports[`xmltest/valid standalone should match 064.xml with snapshot 1`] = ` Object { "actual": "𐀀􏿽", } `; exports[`xmltest/valid standalone should match 065.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 066.xml with snapshot 1`] = ` Object { "actual": "", "error": Array [ "[xmldom error] entity not found:&e1; @#[line:1,col:1]", ], "expected": "", } `; exports[`xmltest/valid standalone should match 067.xml with snapshot 1`] = ` Object { "actual": " ", "expected": " ", } `; exports[`xmltest/valid standalone should match 068.xml with snapshot 1`] = ` Object { "actual": "&e;", "error": Array [ "[xmldom error] entity not found:&e; @#[line:1,col:1]", ], "expected": " ", } `; exports[`xmltest/valid standalone should match 069.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 070.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 071.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 072.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 073.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 074.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 075.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 076.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 077.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 078.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 079.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 080.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 081.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 082.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 083.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 084.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 085.xml with snapshot 1`] = ` Object { "actual": "&e;", "error": Array [ "[xmldom error] entity not found:&e; @#[line:1,col:1]", ], "expected": "", } `; exports[`xmltest/valid standalone should match 086.xml with snapshot 1`] = ` Object { "actual": "&e;", "error": Array [ "[xmldom error] entity not found:&e; @#[line:1,col:1]", ], "expected": "", } `; exports[`xmltest/valid standalone should match 087.xml with snapshot 1`] = ` Object { "actual": "&e;", "error": Array [ "[xmldom error] entity not found:&e; @#[line:1,col:1]", ], "expected": "", } `; exports[`xmltest/valid standalone should match 088.xml with snapshot 1`] = ` Object { "actual": "&e;", "error": Array [ "[xmldom error] entity not found:&e; @#[line:1,col:1]", ], "expected": "<foo>", } `; exports[`xmltest/valid standalone should match 089.xml with snapshot 1`] = ` Object { "actual": "&e;", "error": Array [ "[xmldom error] entity not found:&e; @#[line:1,col:1]", ], "expected": "𐀀􏿽􏿿", } `; exports[`xmltest/valid standalone should match 090.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 091.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 092.xml with snapshot 1`] = ` Object { "actual": " ", "expected": " ", } `; exports[`xmltest/valid standalone should match 093.xml with snapshot 1`] = ` Object { "actual": " ", "expected": " ", } `; exports[`xmltest/valid standalone should match 094.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 095.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 096.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 097.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 098.xml with snapshot 1`] = ` Object { "actual": "", } `; exports[`xmltest/valid standalone should match 099.xml with snapshot 1`] = ` Object { "actual": " ", "expected": "", } `; exports[`xmltest/valid standalone should match 100.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 101.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 102.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 103.xml with snapshot 1`] = ` Object { "actual": "<doc>", } `; exports[`xmltest/valid standalone should match 104.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 105.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 106.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 107.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 108.xml with snapshot 1`] = ` Object { "actual": "", "error": Array [ "[xmldom error] entity not found:&e; @#[line:1,col:1]", ], "expected": "", } `; exports[`xmltest/valid standalone should match 109.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 110.xml with snapshot 1`] = ` Object { "actual": "", "error": Array [ "[xmldom error] entity not found:&e; @#[line:1,col:1]", ], "expected": "", } `; exports[`xmltest/valid standalone should match 111.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 112.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 113.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; exports[`xmltest/valid standalone should match 114.xml with snapshot 1`] = ` Object { "actual": "&e;", "error": Array [ "[xmldom error] entity not found:&e; @#[line:5,col:1]", ], "expected": "&foo;", } `; exports[`xmltest/valid standalone should match 115.xml with snapshot 1`] = ` Object { "actual": "&e1;", "error": Array [ "[xmldom error] entity not found:&e1; @#[line:1,col:1]", ], "expected": "v", } `; exports[`xmltest/valid standalone should match 116.xml with snapshot 1`] = ` Object { "actual": "", "expected": " ", } `; exports[`xmltest/valid standalone should match 117.xml with snapshot 1`] = ` Object { "actual": "&rsqb;", "error": Array [ "[xmldom error] entity not found:] @#[line:5,col:1]", ], "expected": "]", } `; exports[`xmltest/valid standalone should match 118.xml with snapshot 1`] = ` Object { "actual": "&rsqb;", "error": Array [ "[xmldom error] entity not found:] @#[line:5,col:1]", ], "expected": "]]", } `; exports[`xmltest/valid standalone should match 119.xml with snapshot 1`] = ` Object { "actual": "", "expected": "", } `; xmldom-0.8.6/test/xmltest/generate-snapshot.js000066400000000000000000000015551433143211200214710ustar00rootroot00000000000000'use strict' const { replaceNonTextChars } = require('xmltest') /** * Generate minimal snapshot representation by not adding empty lists to the * snapshots. * * @param actual {string | undefined | {toString: function(): string}} * @param errors {Partial>} * @param expected {string?} (optional) compared to actual-only added to output if different * @returns {{actual?: string} & Partial>} */ const generateSnapshot = (actual, errors, expected) => { const actualForSnapshot = replaceNonTextChars(actual) const expectedForSnapshot = replaceNonTextChars(expected) const partial = { actual: actualForSnapshot, } if (expectedForSnapshot && actualForSnapshot !== expectedForSnapshot) { partial.expected = expectedForSnapshot } return { ...partial, ...errors } } module.exports = { generateSnapshot, } xmldom-0.8.6/test/xmltest/not-wf.test.js000066400000000000000000000016751433143211200202350ustar00rootroot00000000000000'use strict' const xmltest = require('xmltest') const { getTestParser } = require('../get-test-parser') const { generateSnapshot } = require('./generate-snapshot') describe('xmltest/not-wellformed', () => { describe('standalone', () => { const entries = xmltest.getEntries( xmltest.FILTERS.NOT_WF.SA.files, xmltest.FILTERS.xml ) Object.entries(entries).forEach(([pathInZip, filename]) => { test(`should match ${filename} with snapshot`, async () => { const input = (await xmltest.getContent(pathInZip)) // TODO: The DOCTYPE totally confuses xmldom :sic: // for now we remove it and any newlines after it so we have reasonable tests .replace(/^[\r\n]*/m, '') const { errors, parser } = getTestParser() // for 050.xml the result is undefined so be careful const actual = parser.parseFromString(input) expect(generateSnapshot(actual, errors)).toMatchSnapshot() }) }) }) }) xmldom-0.8.6/test/xmltest/valid.test.js000066400000000000000000000017511433143211200201150ustar00rootroot00000000000000'use strict' const xmltest = require('xmltest') const { getTestParser } = require('../get-test-parser') const { generateSnapshot } = require('./generate-snapshot') describe('xmltest/valid', () => { describe('standalone', () => { const entries = xmltest.getEntries( xmltest.FILTERS.VALID.SA.files, xmltest.FILTERS.xml ) Object.entries(entries).forEach(([pathInZip, filename]) => { test(`should match ${filename} with snapshot`, async () => { const input = (await xmltest.getContent(pathInZip)) // TODO: The DOCTYPE totally confuses xmldom :sic: // for now we remove it and any newlines after it so we have reasonable tests .replace(/^[\r\n]*/m, '') const expected = await xmltest.getContent( xmltest.RELATED.out(pathInZip) ) const { errors, parser } = getTestParser() const actual = parser.parseFromString(input).toString() expect(generateSnapshot(actual, errors, expected)).toMatchSnapshot() }) }) }) }) xmldom-0.8.6/test/xss.test.js000066400000000000000000000026421433143211200161330ustar00rootroot00000000000000'use strict' const { DOMParser } = require('../lib') const excludeTags = new RegExp( '^(?:' + [ 'javascript', 'vbscript', 'expression', 'meta', 'xml', 'blink', 'link', 'script', 'applet', 'embed', 'object', 'iframe', 'frame', 'frameset', 'ilayer', 'layer', 'bgsound', 'base', ].join('|') + ')$', 'i' ) const excludeAttrs = /^on|style/i const urlAttrs = /(?:href|src)/i const invalidURL = /^(data|javascript|vbscript|ftp)\:/ function xss(html) { const dom = new DOMParser({ xmlns: { '': 'http://www.w3.org/1999/xhtml' }, }).parseFromString(html, 'text/html') return dom.documentElement.toString(true, function (node) { switch (node.nodeType) { case 1: //element const tagName = node.tagName if (excludeTags.test(tagName)) { return '' } return node case 2: const attrName = node.name if (excludeAttrs.test(attrName)) { return null } if (urlAttrs.test(attrName)) { const value = node.value if (invalidURL.test(value)) { return null } } return node case 3: return node } }) } describe('xss test', () => { it('documentElement.toString(true, callback)', () => { const html = '
' const actual = xss(html) expect(actual).toBe( '
' ) }) })