Skip to content

Commit

Permalink
refactor(stringify): Only escape what needs escaping
Browse files Browse the repository at this point in the history
  • Loading branch information
fb55 committed Dec 26, 2021
1 parent de367ca commit b3e5e59
Showing 1 changed file with 35 additions and 15 deletions.
50 changes: 35 additions & 15 deletions src/stringify.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
import { Selector, SelectorType, AttributeAction } from "./types";

const charsToEscape = new Set(
const attribValChars = ["\\", '"'];
const pseudoValChars = [...attribValChars, "(", ")"];

const charsToEscapeInAttributeValue = new Set(
attribValChars.map((c) => c.charCodeAt(0))
);
const charsToEscapeInPseudoValue = new Set(
pseudoValChars.map((c) => c.charCodeAt(0))
);
const charsToEscapeInName = new Set(
[
...pseudoValChars,
"~",
"^",
"$",
Expand All @@ -14,10 +24,6 @@ const charsToEscape = new Set(
"]",
" ",
".",
"\\",
"(",
")",
'"',
].map((c) => c.charCodeAt(0))
);

Expand Down Expand Up @@ -54,14 +60,20 @@ function stringifyToken(token: Selector): string {
return getNamespacedName(token);

case SelectorType.PseudoElement:
return `::${escapeName(token.name)}`;
return `::${escapeName(token.name, charsToEscapeInName)}`;

case SelectorType.Pseudo:
if (token.data === null) return `:${escapeName(token.name)}`;
if (token.data === null)
return `:${escapeName(token.name, charsToEscapeInName)}`;
if (typeof token.data === "string") {
return `:${escapeName(token.name)}(${escapeName(token.data)})`;
return `:${escapeName(
token.name,
charsToEscapeInName
)}(${escapeName(token.data, charsToEscapeInPseudoValue)})`;
}
return `:${escapeName(token.name)}(${stringify(token.data)})`;
return `:${escapeName(token.name, charsToEscapeInName)}(${stringify(
token.data
)})`;

case SelectorType.Attribute: {
if (
Expand All @@ -70,15 +82,15 @@ function stringifyToken(token: Selector): string {
token.ignoreCase === "quirks" &&
!token.namespace
) {
return `#${escapeName(token.value)}`;
return `#${escapeName(token.value, charsToEscapeInName)}`;
}
if (
token.name === "class" &&
token.action === AttributeAction.Element &&
token.ignoreCase === "quirks" &&
!token.namespace
) {
return `.${escapeName(token.value)}`;
return `.${escapeName(token.value, charsToEscapeInName)}`;
}

const name = getNamespacedName(token);
Expand All @@ -88,7 +100,8 @@ function stringifyToken(token: Selector): string {
}

return `[${name}${getActionValue(token.action)}="${escapeName(
token.value
token.value,
charsToEscapeInAttributeValue
)}"${
token.ignoreCase === null ? "" : token.ignoreCase ? " i" : " s"
}]`;
Expand Down Expand Up @@ -121,16 +134,23 @@ function getNamespacedName(token: {
name: string;
namespace: string | null;
}): string {
return `${getNamespace(token.namespace)}${escapeName(token.name)}`;
return `${getNamespace(token.namespace)}${escapeName(
token.name,
charsToEscapeInName
)}`;
}

function getNamespace(namespace: string | null): string {
return namespace !== null
? `${namespace === "*" ? "*" : escapeName(namespace)}|`
? `${
namespace === "*"
? "*"
: escapeName(namespace, charsToEscapeInName)
}|`
: "";
}

function escapeName(str: string): string {
function escapeName(str: string, charsToEscape: Set<number>): string {
let lastIdx = 0;
let ret = "";

Expand Down

0 comments on commit b3e5e59

Please sign in to comment.