diff --git a/lib/index.d.ts b/lib/index.d.ts
index 18d4262..a7e8d74 100644
--- a/lib/index.d.ts
+++ b/lib/index.d.ts
@@ -24,6 +24,20 @@ declare namespace render {
* @default true
*/
quoteAllAttributes: boolean;
+
+ /**
+ * Quote style
+ *
+ * 0 - Smart quotes
+ *
+ * 1 - Single quotes
+ *
+ * 2 - double quotes
+ *
+ *
+ * @default 2
+ */
+ quoteStyle: 0 | 1 | 2
};
// PostHTML Tree
diff --git a/lib/index.js b/lib/index.js
index 1b78caa..6cfcf14 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -59,12 +59,17 @@ function render(tree, options) {
replaceQuote = true;
}
+ let {quoteStyle} = options;
+ if (quoteStyle === undefined) {
+ quoteStyle = 2;
+ }
+
return html(tree);
/** @private */
function isSingleTag(tag) {
if (singleRegExp.length > 0) {
- return singleRegExp.some(reg => reg.test(tag))
+ return singleRegExp.some(reg => reg.test(tag));
}
if (!singleTags.includes(tag)) {
@@ -87,7 +92,7 @@ function render(tree, options) {
attrValue = object[key].replace(/"/g, '"');
}
- attr += ' ' + key + '="' + attrValue + '"';
+ attr += makeAttr(key, attrValue, quoteStyle);
} else if (object[key] === '') {
attr += ' ' + key;
} else {
@@ -96,7 +101,7 @@ function render(tree, options) {
} else if (object[key] === true) {
attr += ' ' + key;
} else if (typeof object[key] === 'number') {
- attr += ' ' + key + '="' + object[key] + '"';
+ attr += makeAttr(key, object[key], quoteStyle);
}
}
@@ -112,6 +117,26 @@ function render(tree, options) {
}
}
+ /** @private */
+ function makeAttr(key, attrValue, quoteStyle = 1) {
+ if (quoteStyle === 1) {
+ // Single Quote
+ return ` ${key}='${attrValue}'`;
+ }
+
+ if (quoteStyle === 2) {
+ // Double Quote
+ return ` ${key}="${attrValue}"`;
+ }
+
+ // Smart Quote
+ if (attrValue.includes('"')) {
+ return ` ${key}='${attrValue}'`;
+ }
+
+ return ` ${key}="${attrValue}"`;
+ }
+
/**
* HTML Stringifier
*
@@ -129,10 +154,10 @@ function render(tree, options) {
traverse(tree, node => {
// Undefined, null, '', [], NaN
if (node === undefined ||
- node === null ||
- node === false ||
- node.length === 0 ||
- Number.isNaN(node)) {
+ node === null ||
+ node === false ||
+ node.length === 0 ||
+ Number.isNaN(node)) {
return;
}
diff --git a/readme.md b/readme.md
index 936d6e0..23f7c56 100644
--- a/readme.md
+++ b/readme.md
@@ -89,6 +89,7 @@ const html = render(tree, options)
|**[`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.|
|**[`replaceQuote`](#replaceQuote)**|`{Boolean}`|[`true`](#default)|Replaces quotes in attribute values with `"e;`.|
+|**[`quoteStyle`](#quoteStyle)**|`{0|1|2}`|[`2`](#default)|Specify the style of quote arround the attribute values|
### `singleTags`
@@ -200,6 +201,33 @@ Replaces quotes in attribute values with `"e;`.
">
```
+### `quoteStyle`
+
+##### `2 (Default)`
+
+Attribute values are wrapped in double quotes:
+
+```html
+
+```
+
+##### `1`
+
+Attribute values are wrapped in single quote:
+
+```html
+
+```
+
+##### `0`
+
+Quote style is based on attribute values (an alternative for `replaceQuote` option):
+
+```html
+
+```
+
+
[npm]: https://img.shields.io/npm/v/posthtml-render.svg
[npm-url]: https://npmjs.com/package/posthtml-render
diff --git a/test/render.test.js b/test/render.test.js
index c1324ef..c1bddec 100644
--- a/test/render.test.js
+++ b/test/render.test.js
@@ -371,5 +371,37 @@ describe('PostHTML Render', () => {
expect(render(fixture, options)).to.eql(expected);
});
});
+
+ describe('quoteStyle', () => {
+ it('1 - single quote', () => {
+ const options = {replaceQuote: false, quoteStyle: 1};
+
+ const fixture = {tag: 'img', attrs: {src: 'https://example.com/example.png', onload: 'testFunc("test")'}};
+ const expected = '
';
+
+ fs.writeFileSync('test.html', render(fixture, options));
+ expect(render(fixture, options)).to.eql(expected);
+ });
+
+ it('2 - double quote', () => {
+ const options = {replaceQuote: false, quoteStyle: 2};
+
+ const fixture = {tag: 'img', attrs: {src: 'https://example.com/example.png', onload: 'testFunc("test")'}};
+ const expected = '
';
+
+ fs.writeFileSync('test.html', render(fixture, options));
+ expect(render(fixture, options)).to.eql(expected);
+ });
+
+ it('0 - smart quote', () => {
+ const options = {replaceQuote: false, quoteStyle: 0};
+
+ const fixture = {tag: 'img', attrs: {src: 'https://example.com/example.png', onload: 'testFunc("test")'}};
+ const expected = '
';
+
+ fs.writeFileSync('test.html', render(fixture, options));
+ expect(render(fixture, options)).to.eql(expected);
+ });
+ });
});
});