Permalink
Browse files

Fix: Handle newlines in attribute values

Fix #1792

Also gracefully handle invalid selectors when generating locations.
  • Loading branch information...
antross committed Jan 30, 2019
1 parent 92d0125 commit ed20a1c9b3d7ef150380b4536562d83b753ea965
@@ -17,6 +17,14 @@ const escapeNamespace = (text: string): string => {
return text.replace(':', '\\:');
};

/**
* Escape a newline within a CSS attribute selector.
* https://stackoverflow.com/questions/20338493/css-attribute-selectors-how-to-escape-newlines-within-attribute-value
*/
const escapeNewline = (text: string): string => {
return text.replace(/\n(\s)?/g, '\\a $1');
};

/**
* Creates a CSS selector from a given element using its attributes and the type of node:
*
@@ -36,7 +44,7 @@ const selectorFromElement = (element: IAsyncHTMLElement): string => {
* so we ignore that selector.
*/
if (!attribute.name.includes('.')) {
selector += `[${escapeNamespace(attribute.name)}="${escapeQuotes(attribute.value)}"]`;
selector += `[${escapeNamespace(attribute.name)}="${escapeQuotes(escapeNewline(attribute.value))}"]`;
}
}

@@ -87,7 +95,19 @@ export const findElementLocation = async (element: IAsyncHTMLElement): Promise<P
const elementHTML: string = await element.outerHTML();
const indexOccurences: number[] = getIndicesOf(elementHTML, html);
const selector: string = selectorFromElement(element);
const elements: IAsyncHTMLElement[] = await element.ownerDocument.querySelectorAll(selector);
let elements: IAsyncHTMLElement[];

try {
elements = await element.ownerDocument.querySelectorAll(selector);
} catch (e) {
// This can happen due to invalid attribute names created by the HTML parser (e.g. "%").
debug(`Invalid selector, falling back to start of document: '${selector}'.`);

return {
column: 0,
line: 0
};
}

let similarItems: number = 0;

@@ -17,6 +17,9 @@
<a href="https://www.duplicate.org">
similar
</a>

<div class="newline" foo="bar
baz"></div>
</body>

</html>
@@ -152,6 +152,15 @@ const findElementLocationEntries = [
line: 17,
column: 5
}
},
{
name: 'element with newline in attribute',
selector: `div.newline`,
index: 0,
position: {
line: 21,
column: 5
}
}
];

0 comments on commit ed20a1c

Please sign in to comment.