| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107 | var TYPE = require('../../tokenizer').TYPE;var rawMode = require('./Raw').mode;var ATKEYWORD = TYPE.AtKeyword;var SEMICOLON = TYPE.Semicolon;var LEFTCURLYBRACKET = TYPE.LeftCurlyBracket;var RIGHTCURLYBRACKET = TYPE.RightCurlyBracket;function consumeRaw(startToken) {    return this.Raw(startToken, rawMode.leftCurlyBracketOrSemicolon, true);}function isDeclarationBlockAtrule() {    for (var offset = 1, type; type = this.scanner.lookupType(offset); offset++) {        if (type === RIGHTCURLYBRACKET) {            return true;        }        if (type === LEFTCURLYBRACKET ||            type === ATKEYWORD) {            return false;        }    }    return false;}module.exports = {    name: 'Atrule',    structure: {        name: String,        prelude: ['AtrulePrelude', 'Raw', null],        block: ['Block', null]    },    parse: function() {        var start = this.scanner.tokenStart;        var name;        var nameLowerCase;        var prelude = null;        var block = null;        this.eat(ATKEYWORD);        name = this.scanner.substrToCursor(start + 1);        nameLowerCase = name.toLowerCase();        this.scanner.skipSC();        // parse prelude        if (this.scanner.eof === false &&            this.scanner.tokenType !== LEFTCURLYBRACKET &&            this.scanner.tokenType !== SEMICOLON) {            if (this.parseAtrulePrelude) {                prelude = this.parseWithFallback(this.AtrulePrelude.bind(this, name), consumeRaw);                // turn empty AtrulePrelude into null                if (prelude.type === 'AtrulePrelude' && prelude.children.head === null) {                    prelude = null;                }            } else {                prelude = consumeRaw.call(this, this.scanner.tokenIndex);            }            this.scanner.skipSC();        }        switch (this.scanner.tokenType) {            case SEMICOLON:                this.scanner.next();                break;            case LEFTCURLYBRACKET:                if (this.atrule.hasOwnProperty(nameLowerCase) &&                    typeof this.atrule[nameLowerCase].block === 'function') {                    block = this.atrule[nameLowerCase].block.call(this);                } else {                    // TODO: should consume block content as Raw?                    block = this.Block(isDeclarationBlockAtrule.call(this));                }                break;        }        return {            type: 'Atrule',            loc: this.getLocation(start, this.scanner.tokenStart),            name: name,            prelude: prelude,            block: block        };    },    generate: function(node) {        this.chunk('@');        this.chunk(node.name);        if (node.prelude !== null) {            this.chunk(' ');            this.node(node.prelude);        }        if (node.block) {            this.node(node.block);        } else {            this.chunk(';');        }    },    walkContext: 'atrule'};
 |