-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathparse.ts
More file actions
93 lines (82 loc) · 1.84 KB
/
Copy pathparse.ts
File metadata and controls
93 lines (82 loc) · 1.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
export type Attrs = {
tag: string;
id: string;
class: string[];
};
const digits = new Set<string>([
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
]);
export const parseSelector = (selector: string, { tagMode = false } = {}) => {
selector = selector.trim();
const attrs: Partial<Attrs> = { tag: undefined, id: undefined };
const classlist = new Set<string>();
let started = false,
buffer = "",
bufferType: keyof Attrs | "tag" | undefined = undefined;
const flush = () => {
if (buffer) {
buffer = buffer.trim();
if (bufferType) {
if (bufferType === "id" && attrs.id)
throw new Error(
`Cannot declare multiple IDs: ${attrs.id} ${buffer}`,
);
if (bufferType === "tag" || bufferType == "id")
attrs[bufferType] = buffer;
else classlist.add(buffer);
}
}
buffer = "";
bufferType = undefined;
};
const update = (char: string, type?: keyof typeof attrs) => {
// !buffer implies this is the first character of current match
if (!buffer)
if (char === "-" || char === "_" || digits.has(char))
// if match starts with -_0-9, error
throw new Error(
`${bufferType || type} cannot start with char: ${char}`,
);
buffer += char;
if (type) bufferType = type;
};
for (const char of selector) {
if (char === " ") {
if (bufferType === "id") {
update(char);
} else {
flush();
}
} else if (char === ".") {
flush();
bufferType = "class";
} else if (char === "#") {
flush();
bufferType = "id";
} else if (!started && char) {
update(char, tagMode ? "tag" : "class");
} else if (bufferType) {
update(char);
} else {
update(char, "class");
}
started = true;
}
// attempt an update on end of string
flush();
attrs.class = [...classlist];
if (!attrs.tag) {
if (tagMode) attrs.tag = "div";
else attrs.tag = "";
}
return attrs;
};