Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: quoteStyle option #47

Merged
merged 4 commits into from
Nov 18, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions lib/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,20 @@ declare namespace render {
* @default true
*/
quoteAllAttributes: boolean;

/**
* Quote style
*
* 0 - Smart quotes
* <img src="https://example.com/example.png" onload='testFunc("test")'>
* 1 - Single quotes
* <img src='https://example.com/example.png' onload='testFunc("test")'>
* 2 - double quotes
* <img src="https://example.com/example.png" onload="testFunc("test")">
*
* @default 2
*/
quoteStyle: 0 | 1 | 2
};

// PostHTML Tree
Expand Down
39 changes: 32 additions & 7 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ; is added by xo --fix.

}

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

attr += ' ' + key + '="' + attrValue + '"';
attr += makeAttr(key, attrValue, quoteStyle);
} else if (object[key] === '') {
attr += ' ' + key;
} else {
Expand All @@ -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);
}
}

Expand All @@ -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
*
Expand All @@ -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)) {
Comment on lines +157 to +160
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The indent is changed by xo --fix.

return;
}

Expand Down
28 changes: 28 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 `&quote;`.|
|**[`quoteStyle`](#quoteStyle)**|`{0|1|2}`|[`2`](#default)|Specify the style of quote arround the attribute values|

### `singleTags`

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

### `quoteStyle`

##### `2 (Default)`

Attribute values are wrapped in double quotes:

```html
<img src="https://example.com/example.png" onload="testFunc("test")">
```

##### `1`

Attribute values are wrapped in single quote:

```html
<img src='https://example.com/example.png' onload='testFunc("test")'>
```

##### `0`

Quote style is based on attribute values (an alternative for `replaceQuote` option):

```html
<img src="https://example.com/example.png" onload='testFunc("test")'>
```


[npm]: https://img.shields.io/npm/v/posthtml-render.svg
[npm-url]: https://npmjs.com/package/posthtml-render

Expand Down
32 changes: 32 additions & 0 deletions test/render.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 = '<img src=\'https://example.com/example.png\' onload=\'testFunc("test")\'>';

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 = '<img src="https://example.com/example.png" onload="testFunc("test")">';

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 = '<img src="https://example.com/example.png" onload=\'testFunc("test")\'>';

fs.writeFileSync('test.html', render(fixture, options));
expect(render(fixture, options)).to.eql(expected);
});
});
});
});