From 3492483c499586ced255e83d2a1aed34211750fc Mon Sep 17 00:00:00 2001 From: Kevin Cox Date: Fri, 21 Feb 2020 16:17:41 +0000 Subject: [PATCH] Add support for keeping tags unquoted. This reduces the size of the HTML and improves readability. The current default behaviour is kept the same but an option is provided to enable the new behaviour. On a future version bump I would flip the default value. --- README.md | 16 ++++++++++++++ lib/index.js | 25 ++++++++++++++------- test/render.test.js | 53 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 0df2453..524329b 100644 --- a/README.md +++ b/README.md @@ -87,6 +87,7 @@ const html = render(tree, options) |:--:|:--:|:-----:|:----------| |**[`singleTags`](#singletags)**|`{Array}`|`[]`|Specify custom single tags (self closing)| |**[`closingSingleTag`](#closingSingleTag)**|`{String}`|[`>`](#default)|Specify the single tag closing format| +|**[`quoteAllAttributes`](#quoteAllAttributes)**|`{Boolean}`|[`true`](#default)|Put double quotes around all tags, even when not necessary.| ### `singleTags` @@ -166,6 +167,21 @@ const html = render(tree) ``` +### `quoteAllAttributes` + +Specify if all attributes should be quoted. + +##### `true (Default)` + +```html + +``` + +##### `false` + +```html + +``` [npm]: https://img.shields.io/npm/v/posthtml-render.svg [npm-url]: https://npmjs.com/package/posthtml-render diff --git a/lib/index.js b/lib/index.js index e31ef13..f959e17 100644 --- a/lib/index.js +++ b/lib/index.js @@ -22,22 +22,23 @@ var SINGLE_TAGS = [ 'extend' ] -/** - * Render PostHTML Tree to HTML +var ATTRIBUTE_QUOTES_REQUIRED = /[\t\n\f\r " '`=<>]/ + +/** Render PostHTML Tree to HTML * - * @param {Array|Object} tree PostHTML Tree - * @param {Object} options Options + * @param {Array|Object} tree PostHTML Tree @param {Object} options Options * * @return {String} HTML */ function render (tree, options) { - /** - * Options + /** Options * * @type {Object} * * @prop {Array} singleTags Custom single tags (selfClosing) - * @prop {String} closingSingleTag Closing format for single tag + * @prop {String} closingSingleTag Closing format for single tag @prop + * @prop {Boolean} quoteAllAttributes If all attributes should be quoted. + * Otherwise attributes will be unquoted when allowed. * * Formats: * @@ -51,6 +52,10 @@ function render (tree, options) { }) var closingSingleTag = options.closingSingleTag + var quoteAllAttributes = options.quoteAllAttributes + if (typeof quoteAllAttributes === 'undefined') { + quoteAllAttributes = true + } return html(tree) @@ -75,7 +80,11 @@ function render (tree, options) { for (var key in obj) { if (typeof obj[key] === 'string') { - attr += ' ' + key + '="' + obj[key].replace(/"/g, '"') + '"' + if (quoteAllAttributes || obj[key].match(ATTRIBUTE_QUOTES_REQUIRED)) { + attr += ' ' + key + '="' + obj[key].replace(/"/g, '"') + '"' + } else { + attr += ' ' + key + '=' + obj[key] + } } else if (obj[key] === true) { attr += ' ' + key } else if (typeof obj[key] === 'number') { diff --git a/test/render.test.js b/test/render.test.js index a3407a5..25153f7 100644 --- a/test/render.test.js +++ b/test/render.test.js @@ -289,5 +289,58 @@ describe('PostHTML Render', function () { expect(render(fixture, options)).to.eql(expected) }) }) + + describe('quoteAllAttributes', function () { + it('True', function () { + var options = { quoteAllAttributes: true } + + var fixture = { tag: 'a', attrs: { href: '/about/me/' } } + var expected = '' + + expect(render(fixture, options)).to.eql(expected) + }) + + it('False', function () { + var options = { quoteAllAttributes: false } + + var fixture = { tag: 'a', attrs: { href: '/about/me/' } } + var expected = '' + + expect(render(fixture, options)).to.eql(expected) + }) + + it('Required Space', function () { + var options = { quoteAllAttributes: false } + + var fixture = { 'tag': 'p', 'attrs': { 'id': 'asd adsasd' } } + var expected = '

' + + expect(render(fixture, options)).to.eql(expected) + }) + + it('Required Tab', function () { + var options = { quoteAllAttributes: false } + + var fixture = { tag: 'a', attrs: { href: '/about-\t-characters' } } + var expected = '' + + expect(render(fixture, options)).to.eql(expected) + }) + + it('Closing slash', function () { + var options = { + closingSingleTag: 'slash', + quoteAllAttributes: false + } + + // Note that is incorrect as that is parsed as + // . + + var fixture = { tag: 'area', attrs: { href: 'foobar' } } + var expected = '' + + expect(render(fixture, options)).to.eql(expected) + }) + }) }) })