-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathparseSelector.ts
More file actions
73 lines (62 loc) · 1.77 KB
/
Copy pathparseSelector.ts
File metadata and controls
73 lines (62 loc) · 1.77 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
import { Attrs } from "./types";
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: Attrs & { tag?: string } = { 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;
};