parserlib: consume unknown @-rules per CSS grammar
This commit is contained in:
parent
07ba44cc2c
commit
aa43507478
|
@ -2722,6 +2722,10 @@ self.parserlib = (() => {
|
||||||
|
|
||||||
constructor(input) {
|
constructor(input) {
|
||||||
this._reader = new StringReader(input ? input.toString() : '');
|
this._reader = new StringReader(input ? input.toString() : '');
|
||||||
|
this.resetLT();
|
||||||
|
}
|
||||||
|
|
||||||
|
resetLT() {
|
||||||
// Token object for the last consumed token.
|
// Token object for the last consumed token.
|
||||||
this._token = null;
|
this._token = null;
|
||||||
// Lookahead token buffer.
|
// Lookahead token buffer.
|
||||||
|
@ -3148,8 +3152,7 @@ self.parserlib = (() => {
|
||||||
*/
|
*/
|
||||||
atRuleToken(first, pos) {
|
atRuleToken(first, pos) {
|
||||||
this._reader.mark();
|
this._reader.mark();
|
||||||
const ident = this.readName();
|
let rule = first + this.readName();
|
||||||
let rule = first + ident;
|
|
||||||
let tt = Tokens.type(lower(rule));
|
let tt = Tokens.type(lower(rule));
|
||||||
// if it's not valid, use the first character only and reset the reader
|
// if it's not valid, use the first character only and reset the reader
|
||||||
if (tt === Tokens.CHAR || tt === Tokens.UNKNOWN) {
|
if (tt === Tokens.CHAR || tt === Tokens.UNKNOWN) {
|
||||||
|
@ -5296,19 +5299,62 @@ self.parserlib = (() => {
|
||||||
throw new SyntaxError('Unknown @ rule.', lt0);
|
throw new SyntaxError('Unknown @ rule.', lt0);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.fire({
|
this._ws();
|
||||||
type: 'error',
|
const simpleValue =
|
||||||
error: null,
|
stream.match([Tokens.IDENT, Tokens.CUSTOM_PROP]) && SyntaxUnit.fromToken(stream._token) ||
|
||||||
message: 'Unknown @ rule: ' + lt0.value + '.',
|
stream.peek() === Tokens.FUNCTION && this._function({asText: true}) ||
|
||||||
}, lt0);
|
this._unknownBlock([Tokens.LBRACKET, Tokens.LPAREN]);
|
||||||
|
|
||||||
// skip {} block
|
this._ws();
|
||||||
let count = 0;
|
const blockValue = this._unknownBlock();
|
||||||
do {
|
if (!blockValue) {
|
||||||
const brace = stream.advance([Tokens.LBRACE, Tokens.RBRACE]);
|
stream.match(Tokens.SEMICOLON);
|
||||||
count += brace === Tokens.LBRACE ? 1 : -1;
|
}
|
||||||
} while (count > 0 && !stream._reader.eof());
|
|
||||||
if (count < 0) stream.unget();
|
this.fire({
|
||||||
|
type: 'unknown-at-rule',
|
||||||
|
name: lt0.value,
|
||||||
|
simpleValue,
|
||||||
|
blockValue,
|
||||||
|
}, lt0);
|
||||||
|
this._ws();
|
||||||
|
}
|
||||||
|
|
||||||
|
_unknownBlock(canStartWith = [Tokens.LBRACE]) {
|
||||||
|
const stream = this._tokenStream;
|
||||||
|
if (!canStartWith.includes(stream.peek())) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
stream.get();
|
||||||
|
const start = stream._token;
|
||||||
|
const reader = stream._reader;
|
||||||
|
reader.mark();
|
||||||
|
reader._cursor = start.offset;
|
||||||
|
reader._line = start.startLine;
|
||||||
|
reader._col = start.startCol;
|
||||||
|
const value = [];
|
||||||
|
const endings = [];
|
||||||
|
let blockEnd;
|
||||||
|
while (!reader.eof()) {
|
||||||
|
const chunk = reader.readMatch(/[^{}()[\]]*[{}()[\]]?/y);
|
||||||
|
const c = chunk.slice(-1);
|
||||||
|
value.push(chunk);
|
||||||
|
if (c === '{' || c === '(' || c === '[') {
|
||||||
|
endings.push(blockEnd);
|
||||||
|
blockEnd = c === '{' ? '}' : c === '(' ? ')' : ']';
|
||||||
|
} else if (c === '}' || c === ')' || c === ']') {
|
||||||
|
if (c !== blockEnd) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
blockEnd = endings.pop();
|
||||||
|
if (!blockEnd) {
|
||||||
|
stream.resetLT();
|
||||||
|
return new SyntaxUnit(value.join(''), start);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reader.reset();
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
_unexpectedToken(token) {
|
_unexpectedToken(token) {
|
||||||
|
@ -5406,18 +5452,28 @@ self.parserlib = (() => {
|
||||||
Object.assign(Parser.prototype, TYPES);
|
Object.assign(Parser.prototype, TYPES);
|
||||||
Parser.prototype._readWhitespace = Parser.prototype._ws;
|
Parser.prototype._readWhitespace = Parser.prototype._ws;
|
||||||
|
|
||||||
|
const symDocument = [Tokens.DOCUMENT_SYM, Parser.prototype._document];
|
||||||
|
const symDocMisplaced = [Tokens.DOCUMENT_SYM, Parser.prototype._documentMisplaced];
|
||||||
|
const symFontFace = [Tokens.FONT_FACE_SYM, Parser.prototype._fontFace];
|
||||||
|
const symKeyframes = [Tokens.KEYFRAMES_SYM, Parser.prototype._keyframes];
|
||||||
|
const symMedia = [Tokens.MEDIA_SYM, Parser.prototype._media];
|
||||||
|
const symPage = [Tokens.PAGE_SYM, Parser.prototype._page];
|
||||||
|
const symSupports = [Tokens.SUPPORTS_SYM, Parser.prototype._supports];
|
||||||
|
const symUnknown = [Tokens.UNKNOWN_SYM, Parser.prototype._unknownSym];
|
||||||
|
const symViewport = [Tokens.VIEWPORT_SYM, Parser.prototype._viewport];
|
||||||
|
|
||||||
Parser.ACTIONS = {
|
Parser.ACTIONS = {
|
||||||
|
|
||||||
stylesheet: new Map([
|
stylesheet: new Map([
|
||||||
[Tokens.MEDIA_SYM, Parser.prototype._media],
|
symMedia,
|
||||||
[Tokens.DOCUMENT_SYM, Parser.prototype._document],
|
symDocument,
|
||||||
[Tokens.SUPPORTS_SYM, Parser.prototype._supports],
|
symSupports,
|
||||||
[Tokens.PAGE_SYM, Parser.prototype._page],
|
symPage,
|
||||||
[Tokens.FONT_FACE_SYM, Parser.prototype._fontFace],
|
symFontFace,
|
||||||
[Tokens.KEYFRAMES_SYM, Parser.prototype._keyframes],
|
symKeyframes,
|
||||||
[Tokens.VIEWPORT_SYM, Parser.prototype._viewport],
|
symViewport,
|
||||||
|
symUnknown,
|
||||||
[Tokens.S, Parser.prototype._ws],
|
[Tokens.S, Parser.prototype._ws],
|
||||||
[Tokens.UNKNOWN_SYM, Parser.prototype._unknownSym],
|
|
||||||
]),
|
]),
|
||||||
|
|
||||||
stylesheetMisplaced: new Map([
|
stylesheetMisplaced: new Map([
|
||||||
|
@ -5427,31 +5483,34 @@ self.parserlib = (() => {
|
||||||
]),
|
]),
|
||||||
|
|
||||||
document: new Map([
|
document: new Map([
|
||||||
[Tokens.MEDIA_SYM, Parser.prototype._media],
|
symMedia,
|
||||||
[Tokens.DOCUMENT_SYM, Parser.prototype._documentMisplaced],
|
symDocMisplaced,
|
||||||
[Tokens.SUPPORTS_SYM, Parser.prototype._supports],
|
symSupports,
|
||||||
[Tokens.PAGE_SYM, Parser.prototype._page],
|
symPage,
|
||||||
[Tokens.FONT_FACE_SYM, Parser.prototype._fontFace],
|
symFontFace,
|
||||||
[Tokens.VIEWPORT_SYM, Parser.prototype._viewport],
|
symViewport,
|
||||||
[Tokens.KEYFRAMES_SYM, Parser.prototype._keyframes],
|
symKeyframes,
|
||||||
|
symUnknown,
|
||||||
]),
|
]),
|
||||||
|
|
||||||
supports: new Map([
|
supports: new Map([
|
||||||
[Tokens.KEYFRAMES_SYM, Parser.prototype._keyframes],
|
symKeyframes,
|
||||||
[Tokens.MEDIA_SYM, Parser.prototype._media],
|
symMedia,
|
||||||
[Tokens.SUPPORTS_SYM, Parser.prototype._supports],
|
symSupports,
|
||||||
[Tokens.DOCUMENT_SYM, Parser.prototype._documentMisplaced],
|
symDocMisplaced,
|
||||||
[Tokens.VIEWPORT_SYM, Parser.prototype._viewport],
|
symViewport,
|
||||||
|
symUnknown,
|
||||||
]),
|
]),
|
||||||
|
|
||||||
media: new Map([
|
media: new Map([
|
||||||
[Tokens.KEYFRAMES_SYM, Parser.prototype._keyframes],
|
symKeyframes,
|
||||||
[Tokens.MEDIA_SYM, Parser.prototype._media],
|
symMedia,
|
||||||
[Tokens.DOCUMENT_SYM, Parser.prototype._documentMisplaced],
|
symDocMisplaced,
|
||||||
[Tokens.SUPPORTS_SYM, Parser.prototype._supports],
|
symSupports,
|
||||||
[Tokens.PAGE_SYM, Parser.prototype._page],
|
symPage,
|
||||||
[Tokens.FONT_FACE_SYM, Parser.prototype._fontFace],
|
symFontFace,
|
||||||
[Tokens.VIEWPORT_SYM, Parser.prototype._viewport],
|
symViewport,
|
||||||
|
symUnknown,
|
||||||
]),
|
]),
|
||||||
|
|
||||||
simpleSelectorSequence: new Map([
|
simpleSelectorSequence: new Map([
|
||||||
|
|
Loading…
Reference in New Issue
Block a user