123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- 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 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);
- if (!customProperty) {
- this.scanner.skipSC();
- }
- if (parseValue) {
- value = this.parseWithFallback(consumeValue, consumeRaw);
- } else {
- value = consumeRaw.call(this, this.scanner.tokenIndex);
- }
- 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;
- }
|