Spaces:
Configuration error
Configuration error
import { isCustomProperty } from '../../utils/names.js'; | |
import { | |
Ident, | |
Hash, | |
Colon, | |
Semicolon, | |
Delim, | |
WhiteSpace | |
} from '../../tokenizer/index.js'; | |
const EXCLAMATIONMARK = 0x0021; // U+0021 EXCLAMATION MARK (!) | |
const NUMBERSIGN = 0x0023; // U+0023 NUMBER SIGN (#) | |
const DOLLARSIGN = 0x0024; // U+0024 DOLLAR SIGN ($) | |
const AMPERSAND = 0x0026; // U+0026 AMPERSAND (&) | |
const ASTERISK = 0x002A; // U+002A ASTERISK (*) | |
const PLUSSIGN = 0x002B; // U+002B PLUS SIGN (+) | |
const SOLIDUS = 0x002F; // U+002F SOLIDUS (/) | |
function consumeValueRaw(startToken) { | |
return this.Raw(startToken, this.consumeUntilExclamationMarkOrSemicolon, true); | |
} | |
function consumeCustomPropertyRaw(startToken) { | |
return this.Raw(startToken, this.consumeUntilExclamationMarkOrSemicolon, false); | |
} | |
function consumeValue() { | |
const startValueToken = this.tokenIndex; | |
const value = this.Value(); | |
if (value.type !== 'Raw' && | |
this.eof === false && | |
this.tokenType !== Semicolon && | |
this.isDelim(EXCLAMATIONMARK) === false && | |
this.isBalanceEdge(startValueToken) === false) { | |
this.error(); | |
} | |
return value; | |
} | |
export const name = 'Declaration'; | |
export const walkContext = 'declaration'; | |
export const structure = { | |
important: [Boolean, String], | |
property: String, | |
value: ['Value', 'Raw'] | |
}; | |
export function parse() { | |
const start = this.tokenStart; | |
const startToken = this.tokenIndex; | |
const property = readProperty.call(this); | |
const customProperty = isCustomProperty(property); | |
const parseValue = customProperty ? this.parseCustomProperty : this.parseValue; | |
const consumeRaw = customProperty ? consumeCustomPropertyRaw : consumeValueRaw; | |
let important = false; | |
let value; | |
this.skipSC(); | |
this.eat(Colon); | |
const valueStart = this.tokenIndex; | |
if (!customProperty) { | |
this.skipSC(); | |
} | |
if (parseValue) { | |
value = this.parseWithFallback(consumeValue, consumeRaw); | |
} else { | |
value = consumeRaw.call(this, this.tokenIndex); | |
} | |
if (customProperty && value.type === 'Value' && value.children.isEmpty) { | |
for (let offset = valueStart - this.tokenIndex; offset <= 0; offset++) { | |
if (this.lookupType(offset) === WhiteSpace) { | |
value.children.appendData({ | |
type: 'WhiteSpace', | |
loc: null, | |
value: ' ' | |
}); | |
break; | |
} | |
} | |
} | |
if (this.isDelim(EXCLAMATIONMARK)) { | |
important = getImportant.call(this); | |
this.skipSC(); | |
} | |
// Do not include semicolon to range per spec | |
// https://drafts.csswg.org/css-syntax/#declaration-diagram | |
if (this.eof === false && | |
this.tokenType !== Semicolon && | |
this.isBalanceEdge(startToken) === false) { | |
this.error(); | |
} | |
return { | |
type: 'Declaration', | |
loc: this.getLocation(start, this.tokenStart), | |
important, | |
property, | |
value | |
}; | |
} | |
export function generate(node) { | |
this.token(Ident, node.property); | |
this.token(Colon, ':'); | |
this.node(node.value); | |
if (node.important) { | |
this.token(Delim, '!'); | |
this.token(Ident, node.important === true ? 'important' : node.important); | |
} | |
} | |
function readProperty() { | |
const start = this.tokenStart; | |
// hacks | |
if (this.tokenType === Delim) { | |
switch (this.charCodeAt(this.tokenStart)) { | |
case ASTERISK: | |
case DOLLARSIGN: | |
case PLUSSIGN: | |
case NUMBERSIGN: | |
case AMPERSAND: | |
this.next(); | |
break; | |
// TODO: not sure we should support this hack | |
case SOLIDUS: | |
this.next(); | |
if (this.isDelim(SOLIDUS)) { | |
this.next(); | |
} | |
break; | |
} | |
} | |
if (this.tokenType === Hash) { | |
this.eat(Hash); | |
} else { | |
this.eat(Ident); | |
} | |
return this.substrToCursor(start); | |
} | |
// ! ws* important | |
function getImportant() { | |
this.eat(Delim); | |
this.skipSC(); | |
const 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; | |
} | |