nehan
Version:
Html layout engine for paged-media written in Typescript
83 lines • 3.4 kB
JavaScript
import { SelectorTokenType, Lexer, Utils, } from "./public-api";
export class SelectorLexer extends Lexer {
normalize(source) {
let norm = source.trim();
norm = Utils.String.multiSpaceToSingle(source);
norm = norm.replace(/\s*([=>~+])\s*/g, "$1");
return norm;
}
addToken(token) {
this.tokens.unshift(token);
}
createToken() {
let c1 = this.peekChar();
if (c1 === ",") {
throw new Error("comma separator is not allowed");
}
if (c1 === "*") {
this.stepBuff(1);
return { type: SelectorTokenType.UNIVERSAL_SELECTOR, value: c1 };
}
let type_match = SelectorLexer.rexTypeSelector.exec(this.buff);
if (type_match !== null) {
let selector = type_match[0];
this.stepBuff(selector.length);
return { type: SelectorTokenType.TYPE_SELECTOR, value: selector };
}
let class_match = SelectorLexer.rexClassSelector.exec(this.buff);
if (class_match !== null) {
let selector = class_match[0];
let value = selector.substring(1);
this.stepBuff(selector.length);
return { type: SelectorTokenType.CLASS_SELECTOR, value: value };
}
let id_match = SelectorLexer.rexIdSelector.exec(this.buff);
if (id_match !== null) {
let selector = id_match[0];
let value = selector.substring(1);
this.stepBuff(selector.length);
return { type: SelectorTokenType.ID_SELECTOR, value: value };
}
let attr_match = SelectorLexer.rexAttrSelector.exec(this.buff);
if (attr_match !== null) {
let selector = attr_match[0];
let value = RegExp.$1;
this.stepBuff(selector.length);
return { type: SelectorTokenType.ATTR_SELECTOR, value: value };
}
let pc_match = SelectorLexer.rexPseudoClass.exec(this.buff);
if (pc_match !== null) {
let selector = pc_match[0];
let value = selector.substring(1);
this.stepBuff(selector.length);
return { type: SelectorTokenType.PSEUDO_CLASS, value: value };
}
let pe_match = SelectorLexer.rexPseudoElement.exec(this.buff);
if (pe_match !== null) {
let selector = pe_match[0];
let value = selector.substring(2);
this.stepBuff(selector.length);
if (this.src == selector) {
return { type: SelectorTokenType.TYPE_SELECTOR, value: selector };
}
return { type: SelectorTokenType.PSEUDO_ELEMENT, value: value };
}
switch (c1) {
case " ":
case "+":
case "~":
case ">":
this.stepBuff(1);
return { type: SelectorTokenType.COMBINATOR, value: c1 };
}
throw new Error(this.src);
}
}
SelectorLexer.rexMediaSelector = /^@[a-z]*/;
SelectorLexer.rexTypeSelector = /^[a-zA-Z][_a-zA-Z0-9-]*/;
SelectorLexer.rexClassSelector = /^\.[_a-zA-Z][_a-zA-Z0-9-]*/;
SelectorLexer.rexAttrSelector = /^\[(.*?)\]/;
SelectorLexer.rexIdSelector = /^#[_a-zA-Z][_a-zA-Z0-9-]*/;
SelectorLexer.rexPseudoClass = /^:[_a-z][_a-z0-9-]*[_a-z0-9-.,()]*/;
SelectorLexer.rexPseudoElement = /^::[_a-z][_a-z0-9-]*/;
//# sourceMappingURL=selector-lexer.js.map