Skip to content

Commit f1f7d32

Browse files
committed
use correct case for tag attributes
1 parent f705454 commit f1f7d32

File tree

6 files changed

+1666
-737
lines changed

6 files changed

+1666
-737
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,9 @@ Transform a [HAST Node][node] to DOM `Node`.
6969

7070
<!-- Definitions -->
7171

72-
[travis-badge]: https://img.shields.io/travis/kmck/hast-util-to-dom.svg
72+
[travis-badge]: https://img.shields.io/travis/syntax-tree/hast-util-to-dom.svg
7373

74-
[travis]: https://travis-ci.org/kmck/hast-util-to-dom
74+
[travis]: https://travis-ci.org/syntax-tree/hast-util-to-dom
7575

7676
[yarn]: https://yarnpkg.com/lang/en/docs/install
7777

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "hast-util-to-dom",
3-
"version": "1.0.3",
3+
"version": "1.1.0",
44
"description": "Transform HAST to DOM",
55
"main": "dist/hast-util-to-dom.js",
66
"module": "dist/hast-util-to-dom.mjs",
@@ -19,7 +19,7 @@
1919
"test:dev": "jest --watchAll"
2020
},
2121
"dependencies": {
22-
"property-information": "^3.2.0"
22+
"property-information": "^4.2.0"
2323
},
2424
"devDependencies": {
2525
"babel-core": "^6.26.3",
@@ -33,7 +33,7 @@
3333
"eslint-config-airbnb-base": "^12.1.0",
3434
"eslint-plugin-import": "^2.12.0",
3535
"glob": "^7.1.2",
36-
"hastscript": "^3.1.0",
36+
"hastscript": "^4.1.0",
3737
"jasmine-core": "^3.1.0",
3838
"jest-cli": "^23.1.0",
3939
"karma": "^2.0.2",

src/index.js

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import information from 'property-information';
1+
import info from 'property-information';
22

33
const ROOT_NODE = 'root';
44
const TEXT_NODE = 'text';
@@ -120,23 +120,23 @@ function element(node, options = {}) {
120120
const { length } = props;
121121
for (let i = 0; i < length; i += 1) {
122122
const key = props[i];
123-
const info = information(key) || {
124-
name: key,
125-
propertyName: key,
126-
};
127-
128123
const {
129-
name,
130-
propertyName,
124+
attribute,
125+
property,
131126
mustUseAttribute,
132127
mustUseProperty,
133128
boolean,
129+
booleanish,
134130
overloadedBoolean,
135-
// numeric,
136-
// positiveNumeric,
131+
// number,
132+
// defined,
137133
commaSeparated,
138134
spaceSeparated,
139-
} = info;
135+
// commaOrSpaceSeparated,
136+
} = info.find(info.html, key) || {
137+
attribute: key,
138+
property: key,
139+
};
140140

141141
let value = properties[key];
142142
if (Array.isArray(value)) {
@@ -151,20 +151,24 @@ function element(node, options = {}) {
151151

152152
try {
153153
if (mustUseProperty) {
154-
el[propertyName] = value;
154+
el[property] = value;
155155
}
156156
if (boolean || (overloadedBoolean && typeof value === 'boolean')) {
157157
if (value) {
158-
el.setAttribute(name, '');
158+
el.setAttribute(attribute, '');
159159
} else {
160-
el.removeAttribute(name);
160+
el.removeAttribute(attribute);
161161
}
162-
} else {
163-
el.setAttribute(name, value);
162+
} else if (booleanish) {
163+
el.setAttribute(attribute, value);
164+
} else if (value === true) {
165+
el.setAttribute(attribute, '');
166+
} else if (value || value === 0 || value === '') {
167+
el.setAttribute(attribute, value);
164168
}
165169
} catch (e) {
166-
if (!mustUseAttribute && propertyName) {
167-
el[propertyName] = value;
170+
if (!mustUseAttribute && property) {
171+
el[property] = value;
168172
}
169173
// Otherwise silently ignore
170174
}

src/index.test.js

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,4 +220,78 @@ describe('hast-util-to-dom', () => {
220220
const htmlExpected = '<title>Hi</title><h2>Hello world!</h2>';
221221
expect(htmlActual).toEqual(htmlExpected);
222222
});
223+
224+
describe('booleanish property', () => {
225+
it('handles booleanish attribute with `true` value correctly', () => {
226+
const tree = h('div', { ariaChecked: true });
227+
const htmlActual = serializeNodeToHtmlString(toDOM(tree));
228+
const htmlExpected = '<div aria-checked="true"></div>';
229+
expect(htmlActual).toEqual(htmlExpected);
230+
});
231+
232+
it('handles booleanish attribute with `false` value correctly', () => {
233+
const tree = h('div', { ariaChecked: false });
234+
const htmlActual = serializeNodeToHtmlString(toDOM(tree));
235+
const htmlExpected = '<div aria-checked="false"></div>';
236+
expect(htmlActual).toEqual(htmlExpected);
237+
});
238+
239+
it('handles booleanish attribute with value correctly', () => {
240+
const tree = h('div', { ariaChecked: 'mixed' });
241+
const htmlActual = serializeNodeToHtmlString(toDOM(tree));
242+
const htmlExpected = '<div aria-checked="mixed"></div>';
243+
expect(htmlActual).toEqual(htmlExpected);
244+
});
245+
});
246+
247+
describe('data properties', () => {
248+
it('ignores value when property is `false`', () => {
249+
const tree = h('div', { dataTest: false });
250+
const htmlActual = serializeNodeToHtmlString(toDOM(tree));
251+
const htmlExpected = '<div></div>';
252+
expect(htmlActual).toEqual(htmlExpected);
253+
});
254+
255+
it('ignores value when property is `NaN`', () => {
256+
const tree = h('div', { dataTest: NaN });
257+
const htmlActual = serializeNodeToHtmlString(toDOM(tree));
258+
const htmlExpected = '<div></div>';
259+
expect(htmlActual).toEqual(htmlExpected);
260+
});
261+
262+
it('encodes value as string when property is a number', () => {
263+
const tree = h('div', { dataTest: 0 });
264+
const htmlActual = serializeNodeToHtmlString(toDOM(tree));
265+
const htmlExpected = '<div data-test="0"></div>';
266+
expect(htmlActual).toEqual(htmlExpected);
267+
});
268+
269+
it('encodes without value when property is `true`', () => {
270+
const tree = h('div', { dataTest: true });
271+
const htmlActual = serializeNodeToHtmlString(toDOM(tree));
272+
const htmlExpected = '<div data-test=""></div>';
273+
expect(htmlActual).toEqual(htmlExpected);
274+
});
275+
276+
it('encodes an empty value when property is an empty string', () => {
277+
const tree = h('div', { dataTest: '' });
278+
const htmlActual = serializeNodeToHtmlString(toDOM(tree));
279+
const htmlExpected = '<div data-test=""></div>';
280+
expect(htmlActual).toEqual(htmlExpected);
281+
});
282+
283+
it('encodes a string value as-is', () => {
284+
const tree = h('div', { dataTest: 'data-test' });
285+
const htmlActual = serializeNodeToHtmlString(toDOM(tree));
286+
const htmlExpected = '<div data-test="data-test"></div>';
287+
expect(htmlActual).toEqual(htmlExpected);
288+
});
289+
290+
it('encodes a string value as-is', () => {
291+
const tree = h('div', { data123: 'dataTest' });
292+
const htmlActual = serializeNodeToHtmlString(toDOM(tree));
293+
const htmlExpected = '<div data-123="dataTest"></div>';
294+
expect(htmlActual).toEqual(htmlExpected);
295+
});
296+
});
223297
});

src/utils.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,14 @@ export function serializeNodeToString(node) {
44
}
55
if (!node) {
66
return '';
7-
} else if (node.outerHTML != null) {
7+
}
8+
if (node.outerHTML != null) {
89
return node.outerHTML;
9-
} else if (node instanceof Document) {
10+
}
11+
if (node instanceof Document) {
1012
return `${serializeNodeToString(node.doctype)}${serializeNodeToString(node.documentElement)}`;
11-
} else if (node instanceof DocumentType) {
13+
}
14+
if (node instanceof DocumentType) {
1215
const docTypeAttrs = [
1316
node.name,
1417
node.publicId ? 'PUBLIC' : '',

0 commit comments

Comments
 (0)