123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- var isCustomProperty = require('../../utils/names').isCustomProperty;
- var TYPE = require('../../tokenizer').TYPE;
- var IDENTIFIER = TYPE.Identifier;
- var COLON = TYPE.Colon;
- var EXCLAMATIONMARK = TYPE.ExclamationMark;
- var SOLIDUS = TYPE.Solidus;
- var ASTERISK = TYPE.Asterisk;
- var DOLLARSIGN = TYPE.DollarSign;
- var HYPHENMINUS = TYPE.HyphenMinus;
- var SEMICOLON = TYPE.Semicolon;
- var PLUSSIGN = TYPE.PlusSign;
- var NUMBERSIGN = TYPE.NumberSign;
- function consumeValueRaw(startToken) {
- return this.Raw(startToken, EXCLAMATIONMARK, SEMICOLON, false, true);
- }
- function consumeCustomPropertyRaw(startToken) {
- return this.Raw(startToken, EXCLAMATIONMARK, SEMICOLON, false, false);
- }
- function consumeValue() {
- var startValueToken = this.scanner.currentToken;
- var value = this.Value();
- if (value.type !== 'Raw' &&
- this.scanner.eof === false &&
- this.scanner.tokenType !== SEMICOLON &&
- this.scanner.tokenType !== EXCLAMATIONMARK &&
- this.scanner.isBalanceEdge(startValueToken) === false) {
- this.scanner.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.currentToken;
- 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.scanner.eat(COLON);
- if (!customProperty) {
- this.scanner.skipSC();
- }
- if (parseValue) {
- value = this.parseWithFallback(consumeValue, consumeRaw);
- } else {
- value = consumeRaw.call(this, this.scanner.currentToken);
- }
- if (this.scanner.tokenType === EXCLAMATIONMARK) {
- important = getImportant(this.scanner);
- 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.scanner.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
- switch (this.scanner.tokenType) {
- case ASTERISK:
- case DOLLARSIGN:
- case PLUSSIGN:
- case NUMBERSIGN:
- prefix = 1;
- break;
- // TODO: not sure we should support this hack
- case SOLIDUS:
- prefix = this.scanner.lookupType(1) === SOLIDUS ? 2 : 1;
- break;
- }
- if (this.scanner.lookupType(prefix) === HYPHENMINUS) {
- prefix++;
- }
- if (prefix) {
- this.scanner.skip(prefix);
- }
- this.scanner.eat(IDENTIFIER);
- return this.scanner.substrToCursor(start);
- }
- // ! ws* important
- function getImportant(scanner) {
- scanner.eat(EXCLAMATIONMARK);
- scanner.skipSC();
- var important = scanner.consume(IDENTIFIER);
- // store original value in case it differ from `important`
- // for better original source restoring and hacks like `!ie` support
- return important === 'important' ? true : important;
- }
|