Skip to content

Commit

Permalink
feat: normalize generated ids
Browse files Browse the repository at this point in the history
BREAKING CHANGE: IDs are no longer always preserved
  • Loading branch information
DylanPiercey committed Apr 20, 2020
1 parent 02e90b2 commit 966f3e9
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 9 deletions.
68 changes: 59 additions & 9 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,24 +99,70 @@ const SHOW_ELEMENT = 1;
const SHOW_COMMENT = 128;
const COMMENT_NODE = 8;
export function defaultNormalizer(container: ContainerNode) {
const idMap: Map<string, number> = new Map();
const clone = container.cloneNode(true) as ContainerNode;
const document = container.ownerDocument!;
const treeWalker = document.createTreeWalker(
const commentAndElementWalker = document.createTreeWalker(
clone,
SHOW_ELEMENT | SHOW_COMMENT
);

let node: Comment | Element;
let nextNode = treeWalker.nextNode();
let nextNode = commentAndElementWalker.nextNode();
while ((node = nextNode as Comment | Element)) {
nextNode = treeWalker.nextNode();
if (node.nodeType === COMMENT_NODE) {
(node as Comment).remove();
nextNode = commentAndElementWalker.nextNode();
if (isComment(node)) {
node.remove();
} else {
Array.from((node as Element).attributes)
.map(attr => attr.name)
.filter(attrName => /^data-(w-|widget$|marko(-|$))/.test(attrName))
.forEach(attrName => (node as Element).removeAttribute(attrName));
const { id, attributes } = node;
if (/\d/.test(id)) {
let idIndex = idMap.get(id);

if (idIndex === undefined) {
idIndex = idMap.size;
idMap.set(id, idIndex);
}

node.id = `GENERATED-${idIndex}`;
}

for (let i = attributes.length; i--; ) {
const attr = attributes[i];

if (/^data-(w-|widget$|marko(-|$))/.test(attr.name)) {
node.removeAttributeNode(attr);
}
}
}
}

if (idMap.size) {
const elementWalker = document.createTreeWalker(clone, SHOW_ELEMENT);

nextNode = elementWalker.nextNode();
while ((node = nextNode as Element)) {
nextNode = elementWalker.nextNode();
const { attributes } = node;

for (let i = attributes.length; i--; ) {
const attr = attributes[i];
const { value } = attr;
const updated = value
.split(" ")
.map(part => {
const idIndex = idMap.get(part);
if (idIndex === undefined) {
return part;
}

return `GENERATED-${idIndex}`;
})
.join(" ");

if (value !== updated) {
attr.value = updated;
}
}
}
}

Expand All @@ -132,3 +178,7 @@ function inferName(p: string) {
const indexOrTemplate = match[2] === "index" || match[2] === "template";
return indexOrTemplate ? match[1] : match[2];
}

function isComment(node: Node): node is Comment {
return node.nodeType === COMMENT_NODE;
}
20 changes: 20 additions & 0 deletions test/components/fancy-form/fixtures/data.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<label
for="GENERATED-0"
>
First Name
</label>
<input
id="GENERATED-0"
name="firstName"
value="Michael"
/>
<label
for="GENERATED-1"
>
Last Name
</label>
<input
id="GENERATED-1"
name="lastName"
value="Rawlings"
/>
4 changes: 4 additions & 0 deletions test/components/fancy-form/fixtures/data.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"firstName": "Michael",
"lastName": "Rawlings"
}
5 changes: 5 additions & 0 deletions test/components/fancy-form/index.marko
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<label for:scoped="first-name">First Name</label>
<input id:scoped="first-name" name="firstName" value=input.firstName>

<label for:scoped="last-name">Last Name</label>
<input id:scoped="last-name" name="lastName" value=input.lastName>
19 changes: 19 additions & 0 deletions test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,25 @@ describe("findProjectFixtures", () => {
"name": "container",
"path": "(cwd)/test/components/container/index.marko",
},
Object {
"component": [Component "(cwd)/test/components/fancy-form/index.marko"],
"fixtures": Object {
"data": Object {
"ext": ".json",
"fixture": Object {
"firstName": "Michael",
"lastName": "Rawlings",
},
"name": "data",
"path": "(cwd)/test/components/fancy-form/fixtures/data.json",
"render": [Function],
"toString": [Function],
},
},
"fixturesPath": "(cwd)/test/components/fancy-form/fixtures",
"name": "fancy-form",
"path": "(cwd)/test/components/fancy-form/index.marko",
},
Object {
"component": [Component "(cwd)/test/components/hello/index.marko"],
"fixtures": Object {
Expand Down

0 comments on commit 966f3e9

Please sign in to comment.