diff --git a/changelog.md b/changelog.md index e5013a3..ac7124b 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,22 @@ +## 0.9.1 (2021-07-26) + +* test: dom nest parsing issues #76 ([fdfe82e](https://github.com/posthtml/posthtml-parser/commit/fdfe82e)), closes [#76](https://github.com/posthtml/posthtml-parser/issues/76) +* test: remove only ([78b7fc7](https://github.com/posthtml/posthtml-parser/commit/78b7fc7)) +* style: after prettier ([ccbfd69](https://github.com/posthtml/posthtml-parser/commit/ccbfd69)) +* style: after prettier ([72f2092](https://github.com/posthtml/posthtml-parser/commit/72f2092)) +* build: set object-curly-spacing always ([47dceb6](https://github.com/posthtml/posthtml-parser/commit/47dceb6)) +* build(deps): bump handlebars from 4.7.6 to 4.7.7 ([e6bc6cd](https://github.com/posthtml/posthtml-parser/commit/e6bc6cd)) +* build(deps): bump hosted-git-info from 2.8.8 to 2.8.9 ([2137591](https://github.com/posthtml/posthtml-parser/commit/2137591)) +* build(deps): bump lodash from 4.17.20 to 4.17.21 ([e9b8d04](https://github.com/posthtml/posthtml-parser/commit/e9b8d04)) +* build(deps): bump normalize-url from 4.5.0 to 4.5.1 ([9e0d1f9](https://github.com/posthtml/posthtml-parser/commit/9e0d1f9)) +* perf: type for replace ([94ebb8d](https://github.com/posthtml/posthtml-parser/commit/94ebb8d)) +* Update readme.md ([7081062](https://github.com/posthtml/posthtml-parser/commit/7081062)) + + + ## 0.9.0 (2021-05-11) +* 0.9.0 ([d725e83](https://github.com/posthtml/posthtml-parser/commit/d725e83)) * Add description to docs ([d61007b](https://github.com/posthtml/posthtml-parser/commit/d61007b)) * Move location tracker to a separate file and refactor into class ([7d6f76b](https://github.com/posthtml/posthtml-parser/commit/7d6f76b)) * feat: add optional support for source locations ([6faf50d](https://github.com/posthtml/posthtml-parser/commit/6faf50d)) diff --git a/package-lock.json b/package-lock.json index bfeae47..4317535 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "posthtml-parser", - "version": "0.9.0", + "version": "0.9.1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -7155,9 +7155,9 @@ } }, "handlebars": { - "version": "4.7.6", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz", - "integrity": "sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==", + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", + "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", "dev": true, "requires": { "minimist": "^1.2.5", @@ -7302,9 +7302,9 @@ } }, "hosted-git-info": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", - "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true }, "html-escaper": { @@ -8405,9 +8405,9 @@ } }, "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, "lodash._reinterpolate": { @@ -9116,9 +9116,9 @@ }, "dependencies": { "hosted-git-info": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.7.tgz", - "integrity": "sha512-fWqc0IcuXs+BmE9orLDyVykAG9GJtGLGuZAAqgcckPgv5xad4AcXGIv8galtQvlwutxSlaMcdw7BUtq2EIvqCQ==", + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.8.tgz", + "integrity": "sha512-aXpmwoOhRBrw6X3j0h5RloK4x1OzsxMPyxqIHyNfSe2pypkVTZFpEiRoSipPEPlMrh0HW/XsjkJ5WgnCirpNUw==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -9133,9 +9133,9 @@ "dev": true }, "normalize-url": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", - "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==", + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", + "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", "dev": true }, "npm-run-path": { diff --git a/package.json b/package.json index 32cb246..d4a39d2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "posthtml-parser", - "version": "0.9.0", + "version": "0.9.1", "description": "Parse HTML/XML to PostHTMLTree", "license": "MIT", "repository": "posthtml/posthtml-parser", diff --git a/readme.md b/readme.md index 0a58363..0257988 100644 --- a/readme.md +++ b/readme.md @@ -115,9 +115,9 @@ Type: `Boolean` Default: `false` Description: *If set to true, self-closing tags will trigger the `onclosetag` event even if `xmlMode` is not set to `true`. NOTE: If `xmlMode` is set to `true` then self-closing tags will always be recognized.* -### `sourceLocations` -Type: `Boolean` -Default: `false` +### `sourceLocations` +Type: `Boolean` +Default: `false` Description: *If set to true, AST nodes will have a `location` property containing the `start` and `end` line and column position of the node.* ## License diff --git a/src/index.ts b/src/index.ts index 9e60796..68ecb7d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,6 @@ -import {Parser, ParserOptions} from 'htmlparser2'; -import {Directive, Node, NodeTag, Options, Attributes} from '../types/index.d'; -import {LocationTracker} from './location-tracker'; +import { Parser, ParserOptions } from 'htmlparser2'; +import { Directive, Node, NodeTag, Options, Attributes } from '../types/index.d'; +import { LocationTracker } from './location-tracker'; const defaultOptions: ParserOptions = { lowerCaseTags: false, @@ -44,7 +44,7 @@ const parser = (html: string, options: Options = {}): Node[] => { Object.keys(attrs).forEach((key: string) => { const object: Attributes = {}; - object[key] = attrs[key].replace(/"/g, '"'); + object[key] = String(attrs[key]).replace(/"/g, '"'); Object.assign(result, object); }); @@ -95,7 +95,7 @@ const parser = (html: string, options: Options = {}): Node[] => { function onopentag(tag: string, attrs: Attributes) { const start = locationTracker.getPosition(parser.startIndex); - const buf: NodeTag = {tag}; + const buf: NodeTag = { tag }; if (options.sourceLocations) { buf.location = { @@ -167,7 +167,7 @@ const parser = (html: string, options: Options = {}): Node[] => { onopentag, onclosetag, ontext - }, {...defaultOptions, ...options}); + }, { ...defaultOptions, ...options }); parser.write(html); parser.end(); diff --git a/src/location-tracker.ts b/src/location-tracker.ts index 95d5ba2..e5e82a2 100644 --- a/src/location-tracker.ts +++ b/src/location-tracker.ts @@ -1,4 +1,4 @@ -import {Position} from '../types/index.d'; +import { Position } from '../types/index.d'; export class LocationTracker { private readonly source: string; diff --git a/test/test-core.spec.ts b/test/test-core.spec.ts index e1f8673..546abb3 100644 --- a/test/test-core.spec.ts +++ b/test/test-core.spec.ts @@ -14,8 +14,8 @@ test('should be parse comment', t => { }); test('should be parse CDATA', t => { - const tree = parser('', {xmlMode: true}); - const expected = [{tag: 'script', content: ['console.log(1);']}]; + const tree = parser('', { xmlMode: true }); + const expected = [{ tag: 'script', content: ['console.log(1);'] }]; t.deepEqual(tree, expected); }); @@ -52,7 +52,7 @@ test.skip('should be parse tag with object in attribute data witchout escape', t }); test.skip('should be parse tag with object in attribute data escape', t => { - const json = JSON.stringify({button: {checkedView: 'extra'}}); + const json = JSON.stringify({ button: { checkedView: 'extra' } }); const html = ''; const tree = parser(html); @@ -70,25 +70,25 @@ test.skip('should be parse tag with object in attribute data escape', t => { test('should be parse isolated comment', t => { const tree = parser('
'); - const expected = [{tag: 'div', content: ['']}]; + const expected = [{ tag: 'div', content: [''] }]; t.deepEqual(tree, expected); }); test('should be parse comment before text content', t => { const tree = parser('
Text after comment
'); - const expected = [{tag: 'div', content: ['', 'Text after comment']}]; + const expected = [{ tag: 'div', content: ['', 'Text after comment'] }]; t.deepEqual(tree, expected); }); test('should be parse comment after text content', t => { const tree = parser('
Text before comment.
'); - const expected = [{tag: 'div', content: ['Text before comment.', '']}]; + const expected = [{ tag: 'div', content: ['Text before comment.', ''] }]; t.deepEqual(tree, expected); }); test('should be parse comment in the middle of text content', t => { const tree = parser('
Text surrounding a comment.
'); - const expected = [{tag: 'div', content: ['Text surrounding ', '', ' a comment.']}]; + const expected = [{ tag: 'div', content: ['Text surrounding ', '', ' a comment.'] }]; t.deepEqual(tree, expected); }); @@ -101,7 +101,7 @@ test('should be parse doctype', t => { test('should be parse directive', t => { const options = { directives: [ - {name: '?php', start: '<', end: '>'} + { name: '?php', start: '<', end: '>' } ] }; const tree = parser('', options); @@ -112,7 +112,7 @@ test('should be parse directive', t => { test('should be parse regular expression directive', t => { const options = { directives: [ - {name: /\?(php|=).*/, start: '<', end: '>'} + { name: /\?(php|=).*/, start: '<', end: '>' } ] }; const tree1 = parser('', options); @@ -127,8 +127,8 @@ test('should be parse regular expression directive', t => { test('should be parse directives and tag', t => { const options = { directives: [ - {name: '!doctype', start: '<', end: '>'}, - {name: '?php', start: '<', end: '>'} + { name: '!doctype', start: '<', end: '>' }, + { name: '?php', start: '<', end: '>' } ] }; const html = '
{{%njk test %}}'; @@ -149,20 +149,20 @@ test('should be parse directives and tag', t => { test('should be parse tag', t => { const tree = parser(''); - const expected = [{tag: 'html'}]; + const expected = [{ tag: 'html' }]; t.deepEqual(tree, expected); }); test('should be parse doctype and tag', t => { const tree = parser(''); - const expected = ['', {tag: 'html'}]; + const expected = ['', { tag: 'html' }]; t.deepEqual(tree, expected); }); test('should be parse tag attrs', t => { const tree = parser('
'); const expected = [{ - tag: 'div', attrs: {id: 'id', class: 'class'} + tag: 'div', attrs: { id: 'id', class: 'class' } }]; t.deepEqual(tree, expected); }); @@ -175,14 +175,14 @@ test('should be parse text', t => { test('should be parse text in content', t => { const tree = parser('
Text
'); - const expected = [{tag: 'div', content: ['Text']}]; + const expected = [{ tag: 'div', content: ['Text'] }]; t.deepEqual(tree, expected); }); test('should be parse not a single node in tree', t => { const tree = parser('Text1Text2Text3'); const expected = [ - {tag: 'span', content: ['Text1']}, {tag: 'span', content: ['Text2']}, 'Text3' + { tag: 'span', content: ['Text1'] }, { tag: 'span', content: ['Text2'] }, 'Text3' ]; t.deepEqual(tree, expected); }); @@ -190,7 +190,7 @@ test('should be parse not a single node in tree', t => { test('should be parse not a single node in parent content', t => { const tree = parser('
Text1Text2Text3
'); const expected = [ - {tag: 'div', content: [{tag: 'span', content: ['Text1']}, {tag: 'span', content: ['Text2']}, 'Text3']} + { tag: 'div', content: [{ tag: 'span', content: ['Text1'] }, { tag: 'span', content: ['Text2'] }, 'Text3'] } ]; t.deepEqual(tree, expected); }); @@ -198,7 +198,7 @@ test('should be parse not a single node in parent content', t => { test('should be parse camelCase tag name', t => { const tree = parser(''); const expected = [ - {tag: 'mySuperTag'} + { tag: 'mySuperTag' } ]; t.deepEqual(tree, expected); }); @@ -207,7 +207,7 @@ test('should be parse simple contents are split with "<" in comment', t => { const html = ' /* width < 800px */
test
'; const tree = parser(html); const expected = [ - {tag: 'a', content: [' /* width < 800px */ ', {tag: 'hr'}, ' test']} + { tag: 'a', content: [' /* width < 800px */ ', { tag: 'hr' }, ' test'] } ]; t.deepEqual(tree, expected); }); @@ -216,7 +216,7 @@ test('should be parse style contents are split with "<" in comment', t => { const html = ''; const tree = parser(html); const expected = [ - {tag: 'style', content: [' /* width < 800px */ @media (max-width: 800px) { /* selectors */} ']} + { tag: 'style', content: [' /* width < 800px */ @media (max-width: 800px) { /* selectors */} '] } ]; t.deepEqual(tree, expected); }); @@ -229,7 +229,8 @@ test('should be parse script contents are split with "<" in comment', t => { tag: 'script', content: [ ' var str = \'hey { test('should parse with source locations', t => { const html = '

Test

\n

Foo

'; - const tree = parser(html, {sourceLocations: true}); + const tree = parser(html, { sourceLocations: true }); const expected = [ { tag: 'h1', @@ -292,3 +293,25 @@ test('should parse with source locations', t => { ]; t.deepEqual(tree, expected); }); + +test('should parse with input in button', t => { + const html = ''; + const tree = parser(html, { xmlMode: true }); + const expected = [ + { + tag: 'button', + content: [ + 'Hello ', + { + tag: 'input', + attrs: { + type: 'file', + 'ng-hide': 'true' + } + }, + 'PostHtml' + ] + } + ]; + t.deepEqual(tree, expected); +}); diff --git a/types/index.d.ts b/types/index.d.ts index a86913e..1b57b0f 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -1,4 +1,4 @@ -import {ParserOptions} from 'htmlparser2'; +import { ParserOptions } from 'htmlparser2'; declare const parser: (html: string, options?: Options) => Node[]; diff --git a/xo.config.js b/xo.config.js index da99e0a..59bfa3e 100644 --- a/xo.config.js +++ b/xo.config.js @@ -3,6 +3,7 @@ module.exports = { rules: { '@typescript-eslint/prefer-readonly-parameter-types': 'off', 'ava/no-skip-test': 'off', - 'ava/no-only-test': 'off' + 'ava/no-only-test': 'off', + 'object-curly-spacing': ['error', 'always'] } };