Skip to content

Commit 2de7798

Browse files
authored
Merge pull request #47 from SukkaW/feat-quote-style
feat: quoteStyle option
2 parents 86f2c9d + 3ee8d58 commit 2de7798

File tree

4 files changed

+106
-7
lines changed

4 files changed

+106
-7
lines changed

lib/index.d.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,20 @@ declare namespace render {
2424
* @default true
2525
*/
2626
quoteAllAttributes: boolean;
27+
28+
/**
29+
* Quote style
30+
*
31+
* 0 - Smart quotes
32+
* <img src="https://example.com/example.png" onload='testFunc("test")'>
33+
* 1 - Single quotes
34+
* <img src='https://example.com/example.png' onload='testFunc("test")'>
35+
* 2 - double quotes
36+
* <img src="https://example.com/example.png" onload="testFunc("test")">
37+
*
38+
* @default 2
39+
*/
40+
quoteStyle: 0 | 1 | 2
2741
};
2842

2943
// PostHTML Tree

lib/index.js

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,17 @@ function render(tree, options) {
5959
replaceQuote = true;
6060
}
6161

62+
let {quoteStyle} = options;
63+
if (quoteStyle === undefined) {
64+
quoteStyle = 2;
65+
}
66+
6267
return html(tree);
6368

6469
/** @private */
6570
function isSingleTag(tag) {
6671
if (singleRegExp.length > 0) {
67-
return singleRegExp.some(reg => reg.test(tag))
72+
return singleRegExp.some(reg => reg.test(tag));
6873
}
6974

7075
if (!singleTags.includes(tag)) {
@@ -87,7 +92,7 @@ function render(tree, options) {
8792
attrValue = object[key].replace(/"/g, '&quot;');
8893
}
8994

90-
attr += ' ' + key + '="' + attrValue + '"';
95+
attr += makeAttr(key, attrValue, quoteStyle);
9196
} else if (object[key] === '') {
9297
attr += ' ' + key;
9398
} else {
@@ -96,7 +101,7 @@ function render(tree, options) {
96101
} else if (object[key] === true) {
97102
attr += ' ' + key;
98103
} else if (typeof object[key] === 'number') {
99-
attr += ' ' + key + '="' + object[key] + '"';
104+
attr += makeAttr(key, object[key], quoteStyle);
100105
}
101106
}
102107

@@ -112,6 +117,26 @@ function render(tree, options) {
112117
}
113118
}
114119

120+
/** @private */
121+
function makeAttr(key, attrValue, quoteStyle = 1) {
122+
if (quoteStyle === 1) {
123+
// Single Quote
124+
return ` ${key}='${attrValue}'`;
125+
}
126+
127+
if (quoteStyle === 2) {
128+
// Double Quote
129+
return ` ${key}="${attrValue}"`;
130+
}
131+
132+
// Smart Quote
133+
if (attrValue.includes('"')) {
134+
return ` ${key}='${attrValue}'`;
135+
}
136+
137+
return ` ${key}="${attrValue}"`;
138+
}
139+
115140
/**
116141
* HTML Stringifier
117142
*
@@ -129,10 +154,10 @@ function render(tree, options) {
129154
traverse(tree, node => {
130155
// Undefined, null, '', [], NaN
131156
if (node === undefined ||
132-
node === null ||
133-
node === false ||
134-
node.length === 0 ||
135-
Number.isNaN(node)) {
157+
node === null ||
158+
node === false ||
159+
node.length === 0 ||
160+
Number.isNaN(node)) {
136161
return;
137162
}
138163

readme.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ const html = render(tree, options)
8989
|**[`closingSingleTag`](#closingSingleTag)**|`{String}`|[`>`](#default)|Specify the single tag closing format|
9090
|**[`quoteAllAttributes`](#quoteAllAttributes)**|`{Boolean}`|[`true`](#default)|Put double quotes around all tags, even when not necessary.|
9191
|**[`replaceQuote`](#replaceQuote)**|`{Boolean}`|[`true`](#default)|Replaces quotes in attribute values with `&quote;`.|
92+
|**[`quoteStyle`](#quoteStyle)**|`{0|1|2}`|[`2`](#default)|Specify the style of quote arround the attribute values|
9293

9394
### `singleTags`
9495

@@ -200,6 +201,33 @@ Replaces quotes in attribute values with `&quote;`.
200201
<img src="<?php echo $foo["bar"] ?>">
201202
```
202203

204+
### `quoteStyle`
205+
206+
##### `2 (Default)`
207+
208+
Attribute values are wrapped in double quotes:
209+
210+
```html
211+
<img src="https://example.com/example.png" onload="testFunc("test")">
212+
```
213+
214+
##### `1`
215+
216+
Attribute values are wrapped in single quote:
217+
218+
```html
219+
<img src='https://example.com/example.png' onload='testFunc("test")'>
220+
```
221+
222+
##### `0`
223+
224+
Quote style is based on attribute values (an alternative for `replaceQuote` option):
225+
226+
```html
227+
<img src="https://example.com/example.png" onload='testFunc("test")'>
228+
```
229+
230+
203231
[npm]: https://img.shields.io/npm/v/posthtml-render.svg
204232
[npm-url]: https://npmjs.com/package/posthtml-render
205233

test/render.test.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,5 +371,37 @@ describe('PostHTML Render', () => {
371371
expect(render(fixture, options)).to.eql(expected);
372372
});
373373
});
374+
375+
describe('quoteStyle', () => {
376+
it('1 - single quote', () => {
377+
const options = {replaceQuote: false, quoteStyle: 1};
378+
379+
const fixture = {tag: 'img', attrs: {src: 'https://example.com/example.png', onload: 'testFunc("test")'}};
380+
const expected = '<img src=\'https://example.com/example.png\' onload=\'testFunc("test")\'>';
381+
382+
fs.writeFileSync('test.html', render(fixture, options));
383+
expect(render(fixture, options)).to.eql(expected);
384+
});
385+
386+
it('2 - double quote', () => {
387+
const options = {replaceQuote: false, quoteStyle: 2};
388+
389+
const fixture = {tag: 'img', attrs: {src: 'https://example.com/example.png', onload: 'testFunc("test")'}};
390+
const expected = '<img src="https://example.com/example.png" onload="testFunc("test")">';
391+
392+
fs.writeFileSync('test.html', render(fixture, options));
393+
expect(render(fixture, options)).to.eql(expected);
394+
});
395+
396+
it('0 - smart quote', () => {
397+
const options = {replaceQuote: false, quoteStyle: 0};
398+
399+
const fixture = {tag: 'img', attrs: {src: 'https://example.com/example.png', onload: 'testFunc("test")'}};
400+
const expected = '<img src="https://example.com/example.png" onload=\'testFunc("test")\'>';
401+
402+
fs.writeFileSync('test.html', render(fixture, options));
403+
expect(render(fixture, options)).to.eql(expected);
404+
});
405+
});
374406
});
375407
});

0 commit comments

Comments
 (0)