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