Let's build browser engine! in typescript vol7 Selector matching
Murahashi [Matt] Kenichi
Posted on May 10, 2019
for selector matching, I create some shortcut.
test("element id found", () => {
expect(new ElementData("no mean", new Map([["id", "target"]])).id()).toEqual("target");
});
test("element id not found", () => {
expect(new ElementData("no mean", new Map([["no mean", "no mean"]])).id()).toBeNull();
});
export class ElementData {
(snip)
id(): string | null {
return this.attributes.get("id") || null;
}
}
test("element class 1 found", () => {
expect(new ElementData("no mean", new Map([["class", "target1"]])).classes()).toEqual(
new Set(["target1"])
);
});
test("element class 2 found", () => {
expect(new ElementData("no mean", new Map([["class", "target1 target2"]])).classes()).toEqual(
new Set(["target1", "target2"])
);
});
test("element class 0 found", () => {
expect(new ElementData("no mean", new Map([])).classes()).toEqual(new Set([]));
});
export class ElementData {
(snip)
classes(): Set<string> {
const classes = this.attributes.get("class");
if (!classes) {
return new Set([]);
}
return new Set(classes.split(" "));
}
}
selector matching. using this simple selector.
test("matches simple selector", () => {
expect(
matchesSimpleSelector(
new ElementData("no mean", new Map([])),
new SimpleSelector(null, null, [])
)
).toBe(true);
});
test("matches simple selector different tag", () => {
expect(
matchesSimpleSelector(
new ElementData("other", new Map([])),
new SimpleSelector("some", null, [])
)
).toBe(false);
});
test("matches simple selector same tag", () => {
expect(
matchesSimpleSelector(
new ElementData("target", new Map([])),
new SimpleSelector("target", null, [])
)
).toBe(true);
});
test("matches simple selector different id", () => {
expect(
matchesSimpleSelector(
new ElementData("no mean1", new Map([["id", "other"]])),
new SimpleSelector(null, "some", [])
)
).toBe(false);
});
test("matches simple selector same id", () => {
expect(
matchesSimpleSelector(
new ElementData("no mean1", new Map([["id", "target"]])),
new SimpleSelector(null, "target", [])
)
).toBe(true);
});
test("matches simple selector different class", () => {
expect(
matchesSimpleSelector(
new ElementData("no mean1", new Map([["class", "other1 other2"]])),
new SimpleSelector(null, null, ["some1", "some2"])
)
).toBe(false);
});
test("matches simple selector same class", () => {
expect(
matchesSimpleSelector(
new ElementData("no mean1", new Map([["class", "target1 other2"]])),
new SimpleSelector(null, null, ["target1", "some2"])
)
).toBe(true);
});
test("matches simple selector same tag, other id", () => {
expect(
matchesSimpleSelector(
new ElementData("same", new Map([["id", "other"]])),
new SimpleSelector("same", "some", [])
)
).toBe(false);
});
test("matches simple selector same tag, same id, different class", () => {
expect(
matchesSimpleSelector(
new ElementData("same", new Map([["id", "same"], ["class", "other1 other2"]])),
new SimpleSelector("same", "same", ["some1", "some2"])
)
).toBe(false);
});
// returns true if there are no none-match
export function matchesSimpleSelector(elem: ElementData, selector: SimpleSelector): boolean {
const tagName = selector.tagName;
if (tagName && tagName !== elem.tagName) {
return false;
}
const id = selector.id;
if (id && id !== elem.id()) {
return false;
}
const classes = selector.classValue;
if (classes.length !== 0) {
let included = false;
for (let className of classes) {
if (elem.classes().has(className)) {
included = true;
break;
}
}
if (!included) {
return false;
}
}
return true;
}
test("matches no none-match", () => {
expect(
matches(
new ElementData("no mean", new Map([])),
new Selector.Simple(new SimpleSelector(null, null, []))
)
).toBe(true);
});
test("matches none-match", () => {
expect(
matches(
new ElementData("no mean", new Map([])),
new Selector.Simple(new SimpleSelector(null, "some", []))
)
).toBe(false);
});
test("matches match", () => {
expect(
matches(
new ElementData("no mean", new Map([["id", "target"]])),
new Selector.Simple(new SimpleSelector(null, "target", []))
)
).toBe(true);
});
export function matches(elem: ElementData, selector: Selector): boolean {
switch (selector.format) {
case Selector.Format.Simple:
return matchesSimpleSelector(elem, selector.selector);
}
}
references
- Let's build a browser engine! Part 1: Getting started
- mbrubeck/robinson
- sanemat/js-toy-engine
- sanemat/ts-toy-engine
series
- Let's build browser engine! in typescript vol0 Toy browser engine
- Let's build browser engine! in typescript vol1 Canvas with Color
- Let's build browser engine! in typescript vol2 Display Command
- Let's build browser engine! in typescript vol3 Layout Box, Dimensions
- Let's build browser engine! in typescript vol4 Layout Tree to Display List
- Let's build browser engine! in typescript vol5 DOM Shortcut
- Let's build browser engine! in typescript vol6 CSS Shortcut
- Let's build browser engine! in typescript vol7 Selector matching
💖 💪 🙅 🚩
Murahashi [Matt] Kenichi
Posted on May 10, 2019
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
webdev Understanding HTTP, Cookies, Email Protocols, and DNS: A Guide to Key Internet Technologies
November 30, 2024
react Axios NPM Package: A Beginner's Guide to Installing and Making HTTP Requests
November 30, 2024
webdev Guide to Cookies, Local Storage, Session Storage, and Other Web Storage Mechanisms
November 30, 2024