parserlib: simplified media query L4

This commit is contained in:
tophf 2022-06-24 10:22:49 +03:00
parent 95a4514f15
commit 91501cce19

View File

@ -1398,6 +1398,12 @@ self.parserlib = (() => {
Tokens.RIGHTMIDDLE_SYM, Tokens.RIGHTMIDDLE_SYM,
Tokens.RIGHTBOTTOM_SYM, Tokens.RIGHTBOTTOM_SYM,
], ],
mediaValue: [
Tokens.IDENT,
Tokens.NUMBER,
Tokens.DIMENSION,
Tokens.LENGTH,
],
op: [ op: [
Tokens.SLASH, Tokens.SLASH,
Tokens.COMMA, Tokens.COMMA,
@ -3704,53 +3710,57 @@ self.parserlib = (() => {
_mediaQuery() { _mediaQuery() {
const stream = this._tokenStream; const stream = this._tokenStream;
const expressions = []; const expressions = [];
const mod = stream.match(Tokens.IDENT, ['only', 'not']);
let type = null; let type = null;
const token = stream.match(Tokens.IDENT, ['only', 'not']);
const ident = token.value || null;
this._ws(); this._ws();
const next = stream.LT(1); const next = stream.LT(1);
switch (next.type) { if (next.type === Tokens.IDENT) {
case Tokens.IDENT:
type = this._mediaFeature(); type = this._mediaFeature();
break; } else if (next.value === '(') {
case Tokens.LPAREN: expressions.push(this._mediaExpression({or: true}));
expressions.push(this._mediaExpression()); } else {
break;
default:
return; return;
} }
this._ws(); this._ws();
while (stream.match(Tokens.IDENT)) { const c = stream.match(Tokens.IDENT).value;
if (lowerCmp(stream._token.value, 'and')) { if (c) {
if (lowerCmp(c, 'and') || !type && lowerCmp(c, 'or')) {
this._ws(); this._ws();
expressions.push(this._mediaExpression()); expressions.push(this._mediaExpression());
} else { } else {
stream.throwUnexpected(undefined, ["'and'"]); stream.throwUnexpected(undefined, ["'and'", !type && "'or'"].filter(Boolean));
} }
} }
return new MediaQuery(ident, type, expressions, token || next); return new MediaQuery(mod.value || null, type, expressions, mod || next);
} }
_mediaExpression() { _mediaExpression() {
const stream = this._tokenStream; const stream = this._tokenStream;
let token;
let expression = null;
stream.mustMatch(Tokens.LPAREN); stream.mustMatch(Tokens.LPAREN);
const feature = this._mediaFeature(); const feature = this._mediaFeature(TT.mediaValue);
let b;
for (let pass = 0; ++pass <= 2;) {
this._ws(); this._ws();
if (stream.match(Tokens.COLON)) { b = stream.get(true).value;
if (/^[:=<>]$/.test(b)) {
const isRange = /[<>]/.test(b);
if (isRange) stream.match(Tokens.EQUALS);
this._ws(); this._ws();
token = stream.LT(1); b = this._expression({calc: true});
expression = this._expression({calc: true}); if (!isRange) break;
} else {
stream.unget();
b = null;
break;
}
} }
stream.mustMatch(Tokens.RPAREN); stream.mustMatch(Tokens.RPAREN);
this._ws(); this._ws();
return new MediaFeature(feature, expression ? new SyntaxUnit(expression, token) : null); return new MediaFeature(feature); // TODO: construct the value properly
} }
_mediaFeature() { _mediaFeature(type = Tokens.IDENT) {
this._tokenStream.mustMatch(Tokens.IDENT); return SyntaxUnit.fromToken(this._tokenStream.mustMatch(type));
return SyntaxUnit.fromToken(this._tokenStream._token);
} }
_page(start) { _page(start) {