Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/flo-bit/shapecraft. flo-bit.dev/shapecraft
Something went wrong. Try again.
3.6 kB · 147 lines
JavaScript
at commit da69385e
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148import { Ident, String as StringToken, Delim, LeftSquareBracket, RightSquareBracket} from '../../tokenizer/index.js';
const DOLLARSIGN = 0x0024; // U+0024 DOLLAR SIGN ($)const ASTERISK = 0x002A; // U+002A ASTERISK (*)const EQUALSSIGN = 0x003D; // U+003D EQUALS SIGN (=)const CIRCUMFLEXACCENT = 0x005E; // U+005E (^)const VERTICALLINE = 0x007C; // U+007C VERTICAL LINE (|)const TILDE = 0x007E; // U+007E TILDE (~)
function getAttributeName() { if (this.eof) { this.error('Unexpected end of input'); }
const start = this.tokenStart; let expectIdent = false;
if (this.isDelim(ASTERISK)) { expectIdent = true; this.next(); } else if (!this.isDelim(VERTICALLINE)) { this.eat(Ident); }
if (this.isDelim(VERTICALLINE)) { if (this.charCodeAt(this.tokenStart + 1) !== EQUALSSIGN) { this.next(); this.eat(Ident); } else if (expectIdent) { this.error('Identifier is expected', this.tokenEnd); } } else if (expectIdent) { this.error('Vertical line is expected'); }
return { type: 'Identifier', loc: this.getLocation(start, this.tokenStart), name: this.substrToCursor(start) };}
function getOperator() { const start = this.tokenStart; const code = this.charCodeAt(start);
if (code !== EQUALSSIGN && // = code !== TILDE && // ~= code !== CIRCUMFLEXACCENT && // ^= code !== DOLLARSIGN && // $= code !== ASTERISK && // *= code !== VERTICALLINE // |= ) { this.error('Attribute selector (=, ~=, ^=, $=, *=, |=) is expected'); }
this.next();
if (code !== EQUALSSIGN) { if (!this.isDelim(EQUALSSIGN)) { this.error('Equal sign is expected'); }
this.next(); }
return this.substrToCursor(start);}
// '[' <wq-name> ']'// '[' <wq-name> <attr-matcher> [ <string-token> | <ident-token> ] <attr-modifier>? ']'export const name = 'AttributeSelector';export const structure = { name: 'Identifier', matcher: [String, null], value: ['String', 'Identifier', null], flags: [String, null]};
export function parse() { const start = this.tokenStart; let name; let matcher = null; let value = null; let flags = null;
this.eat(LeftSquareBracket); this.skipSC();
name = getAttributeName.call(this); this.skipSC();
if (this.tokenType !== RightSquareBracket) { // avoid case `[name i]` if (this.tokenType !== Ident) { matcher = getOperator.call(this);
this.skipSC();
value = this.tokenType === StringToken ? this.String() : this.Identifier();
this.skipSC(); }
// attribute flags if (this.tokenType === Ident) { flags = this.consume(Ident);
this.skipSC(); } }
this.eat(RightSquareBracket);
return { type: 'AttributeSelector', loc: this.getLocation(start, this.tokenStart), name, matcher, value, flags };}
export function generate(node) { this.token(Delim, '['); this.node(node.name);
if (node.matcher !== null) { this.tokenize(node.matcher); this.node(node.value); }
if (node.flags !== null) { this.token(Ident, node.flags); }
this.token(Delim, ']');}