var isCustomProperty = require('../../utils/names').isCustomProperty; 
 | 
var TYPE = require('../../tokenizer').TYPE; 
 | 
var rawMode = require('./Raw').mode; 
 | 
  
 | 
var IDENT = TYPE.Ident; 
 | 
var HASH = TYPE.Hash; 
 | 
var COLON = TYPE.Colon; 
 | 
var SEMICOLON = TYPE.Semicolon; 
 | 
var DELIM = TYPE.Delim; 
 | 
var WHITESPACE = TYPE.WhiteSpace; 
 | 
var EXCLAMATIONMARK = 0x0021; // U+0021 EXCLAMATION MARK (!) 
 | 
var NUMBERSIGN = 0x0023;      // U+0023 NUMBER SIGN (#) 
 | 
var DOLLARSIGN = 0x0024;      // U+0024 DOLLAR SIGN ($) 
 | 
var AMPERSAND = 0x0026;       // U+0026 ANPERSAND (&) 
 | 
var ASTERISK = 0x002A;        // U+002A ASTERISK (*) 
 | 
var PLUSSIGN = 0x002B;        // U+002B PLUS SIGN (+) 
 | 
var SOLIDUS = 0x002F;         // U+002F SOLIDUS (/) 
 | 
  
 | 
function consumeValueRaw(startToken) { 
 | 
    return this.Raw(startToken, rawMode.exclamationMarkOrSemicolon, true); 
 | 
} 
 | 
  
 | 
function consumeCustomPropertyRaw(startToken) { 
 | 
    return this.Raw(startToken, rawMode.exclamationMarkOrSemicolon, false); 
 | 
} 
 | 
  
 | 
function consumeValue() { 
 | 
    var startValueToken = this.scanner.tokenIndex; 
 | 
    var value = this.Value(); 
 | 
  
 | 
    if (value.type !== 'Raw' && 
 | 
        this.scanner.eof === false && 
 | 
        this.scanner.tokenType !== SEMICOLON && 
 | 
        this.scanner.isDelim(EXCLAMATIONMARK) === false && 
 | 
        this.scanner.isBalanceEdge(startValueToken) === false) { 
 | 
        this.error(); 
 | 
    } 
 | 
  
 | 
    return value; 
 | 
} 
 | 
  
 | 
module.exports = { 
 | 
    name: 'Declaration', 
 | 
    structure: { 
 | 
        important: [Boolean, String], 
 | 
        property: String, 
 | 
        value: ['Value', 'Raw'] 
 | 
    }, 
 | 
    parse: function() { 
 | 
        var start = this.scanner.tokenStart; 
 | 
        var startToken = this.scanner.tokenIndex; 
 | 
        var property = readProperty.call(this); 
 | 
        var customProperty = isCustomProperty(property); 
 | 
        var parseValue = customProperty ? this.parseCustomProperty : this.parseValue; 
 | 
        var consumeRaw = customProperty ? consumeCustomPropertyRaw : consumeValueRaw; 
 | 
        var important = false; 
 | 
        var value; 
 | 
  
 | 
        this.scanner.skipSC(); 
 | 
        this.eat(COLON); 
 | 
  
 | 
        const valueStart = this.scanner.tokenIndex; 
 | 
  
 | 
        if (!customProperty) { 
 | 
            this.scanner.skipSC(); 
 | 
        } 
 | 
  
 | 
        if (parseValue) { 
 | 
            value = this.parseWithFallback(consumeValue, consumeRaw); 
 | 
        } else { 
 | 
            value = consumeRaw.call(this, this.scanner.tokenIndex); 
 | 
        } 
 | 
  
 | 
        if (customProperty && value.type === 'Value' && value.children.isEmpty()) { 
 | 
            for (let offset = valueStart - this.scanner.tokenIndex; offset <= 0; offset++) { 
 | 
                if (this.scanner.lookupType(offset) === WHITESPACE) { 
 | 
                    value.children.appendData({ 
 | 
                        type: 'WhiteSpace', 
 | 
                        loc: null, 
 | 
                        value: ' ' 
 | 
                    }); 
 | 
                    break; 
 | 
                } 
 | 
            } 
 | 
        } 
 | 
  
 | 
        if (this.scanner.isDelim(EXCLAMATIONMARK)) { 
 | 
            important = getImportant.call(this); 
 | 
            this.scanner.skipSC(); 
 | 
        } 
 | 
  
 | 
        // Do not include semicolon to range per spec 
 | 
        // https://drafts.csswg.org/css-syntax/#declaration-diagram 
 | 
  
 | 
        if (this.scanner.eof === false && 
 | 
            this.scanner.tokenType !== SEMICOLON && 
 | 
            this.scanner.isBalanceEdge(startToken) === false) { 
 | 
            this.error(); 
 | 
        } 
 | 
  
 | 
        return { 
 | 
            type: 'Declaration', 
 | 
            loc: this.getLocation(start, this.scanner.tokenStart), 
 | 
            important: important, 
 | 
            property: property, 
 | 
            value: value 
 | 
        }; 
 | 
    }, 
 | 
    generate: function(node) { 
 | 
        this.chunk(node.property); 
 | 
        this.chunk(':'); 
 | 
        this.node(node.value); 
 | 
  
 | 
        if (node.important) { 
 | 
            this.chunk(node.important === true ? '!important' : '!' + node.important); 
 | 
        } 
 | 
    }, 
 | 
    walkContext: 'declaration' 
 | 
}; 
 | 
  
 | 
function readProperty() { 
 | 
    var start = this.scanner.tokenStart; 
 | 
    var prefix = 0; 
 | 
  
 | 
    // hacks 
 | 
    if (this.scanner.tokenType === DELIM) { 
 | 
        switch (this.scanner.source.charCodeAt(this.scanner.tokenStart)) { 
 | 
            case ASTERISK: 
 | 
            case DOLLARSIGN: 
 | 
            case PLUSSIGN: 
 | 
            case NUMBERSIGN: 
 | 
            case AMPERSAND: 
 | 
                this.scanner.next(); 
 | 
                break; 
 | 
  
 | 
            // TODO: not sure we should support this hack 
 | 
            case SOLIDUS: 
 | 
                this.scanner.next(); 
 | 
                if (this.scanner.isDelim(SOLIDUS)) { 
 | 
                    this.scanner.next(); 
 | 
                } 
 | 
                break; 
 | 
        } 
 | 
    } 
 | 
  
 | 
    if (prefix) { 
 | 
        this.scanner.skip(prefix); 
 | 
    } 
 | 
  
 | 
    if (this.scanner.tokenType === HASH) { 
 | 
        this.eat(HASH); 
 | 
    } else { 
 | 
        this.eat(IDENT); 
 | 
    } 
 | 
  
 | 
    return this.scanner.substrToCursor(start); 
 | 
} 
 | 
  
 | 
// ! ws* important 
 | 
function getImportant() { 
 | 
    this.eat(DELIM); 
 | 
    this.scanner.skipSC(); 
 | 
  
 | 
    var important = this.consume(IDENT); 
 | 
  
 | 
    // store original value in case it differ from `important` 
 | 
    // for better original source restoring and hacks like `!ie` support 
 | 
    return important === 'important' ? true : important; 
 | 
} 
 |