Files
ry.kazcloud.dev/node_modules/@emmetio/css-parser/dist/html-matcher.cjs.js
Ryan Kazokas d181f77fb2
All checks were successful
Build and Push / build (push) Successful in 55s
Updates dockerfile
2026-02-16 15:09:37 -05:00

1225 lines
26 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var StreamReader = _interopDefault(require('@emmetio/stream-reader'));
var _emmetio_streamReaderUtils = require('@emmetio/stream-reader-utils');
/**
* A structure describing text fragment in content stream
*/
class Token {
/**
* @param {StreamReader} stream
* @param {Point} start Tokens start location in content stream
* @param {Point} end Tokens end location in content stream
*/
constructor(stream, start, end) {
this.stream = stream;
this.start = start != null ? start : stream.start;
this.end = end != null ? end : stream.pos;
this._value = null;
}
/**
* Returns token textual representation
* @return {String}
*/
toString() {
return `${this.valueOf()}: ${this.start}, ${this.end}`;
}
valueOf() {
if (this._value === null) {
const start = this.stream.start;
const end = this.stream.pos;
this.stream.start = this.start;
this.stream.pos = this.end;
this._value = this.stream.current();
this.stream.start = start;
this.stream.pos = end;
}
return this._value;
}
}
/**
* A token that contains a list of tokens
*/
class FragmentsToken extends Token {
constructor(stream, tokens) {
let start = stream.pos;
let end = stream.pos;
if (tokens && tokens.length) {
start = tokens[0].start;
end = tokens[tokens.length - 1].end;
}
super(stream, start, end);
this.type = 'fragments';
this.fragments = tokens;
}
}
const COMMA = 44; // ,
const PROP_DELIMITER = 58; // :
const PROP_TERMINATOR = 59; // ;
const RULE_START = 123; // {
const RULE_END = 125; // }
/**
* Consumes separator token from given string
*/
var separator = function(stream) {
if (isSeparator(stream.peek())) {
const start = stream.pos;
return new SeparatorToken(stream.next(), stream, start);
}
};
function isSeparator(code) {
return code === COMMA
|| code === PROP_DELIMITER || code === PROP_TERMINATOR
|| code === RULE_START || code === RULE_END;
}
class SeparatorToken extends Token {
constructor(code, stream, start, end) {
super(stream, start, end);
this.type = 'separator';
this.code = code;
this.comma = code === COMMA;
this.propertyDelimiter = code === PROP_DELIMITER;
this.propertyTerminator = code === PROP_TERMINATOR;
this.ruleStart = code === RULE_START;
this.ruleEnd = code === RULE_END;
}
}
const ARGUMENTS_START = 40; // (
const ARGUMENTS_END = 41; // )
var args = function(stream, tokenConsumer) {
const start = stream.pos;
if (stream.eat(ARGUMENTS_START)) {
const tokens = [];
let t, ch;
// in LESS, its possible to separate arguments list either by `;` or `,`.
// In first case, we should keep comma-separated item as a single argument
let usePropTerminator = false;
while (!stream.eof()) {
if (isUnexpectedTerminator(stream.peek()) || stream.eat(ARGUMENTS_END)) {
break;
}
t = tokenConsumer(stream);
if (!t) {
break;
}
if (t.propertyTerminator) {
usePropTerminator = true;
}
tokens.push(t);
}
return createArguments(stream, tokens, start, usePropTerminator);
}
};
function isUnexpectedTerminator(code) {
return code === RULE_START || code === RULE_END;
}
function createArguments(stream, tokens, start, usePropTerminator) {
const sep = usePropTerminator ? semicolonSeparator : commaSeparator;
const list = [];
let arg = [];
for (let i = 0, il = tokens.length, token; i < il; i++) {
token = tokens[i];
if (sep(token)) {
if (arg.length) {
list.push(new FragmentsToken(stream, arg));
arg = [];
} else {
list.push(new Token(stream, token.start, token.start));
}
} else {
arg.push(token);
}
}
if (arg.length) {
list.push(new FragmentsToken(stream, arg));
}
return new ArgumentsToken(list, stream, start);
}
function commaSeparator(token) {
return token.comma;
}
function semicolonSeparator(token) {
return token.propertyTerminator;
}
/**
* A token that represents a set of arguments between `(` and `)`
*/
class ArgumentsToken extends Token {
constructor(list, stream, start, end) {
super(stream, start, end);
this.list = list;
this.type = 'arguments';
}
}
const HYPHEN = 45;
const UNDERSCORE = 95;
function eatIdent(stream) {
const start = stream.pos;
stream.eat(HYPHEN);
if (stream.eat(isIdentStart)) {
stream.eatWhile(isIdent);
return new IdentToken(stream, start);
}
stream.pos = start;
return false;
}
class IdentToken extends Token {
constructor(stream, start, end) {
super(stream, start, end);
this.type = 'ident';
}
}
function isIdentStart(code) {
return code === UNDERSCORE || _emmetio_streamReaderUtils.isAlpha(code) || code >= 128;
}
function isIdent(code) {
return _emmetio_streamReaderUtils.isNumber(code) || isIdentStart(code);
}
/**
* Consumes at-keyword from given stream
*/
var atKeyword = function(stream) {
const start = stream.pos;
if (stream.eatWhile(64 /* @ */)) {
const name = eatIdent(stream);
if (name) {
return new AtKeywordToken(name, stream, start);
}
}
stream.pos = start;
};
class AtKeywordToken extends Token {
constructor(name, stream, start, end) {
super(stream, start, end);
this.type = 'at-keyword';
this.name = name;
}
}
/**
* Consumes quoted string from current string and returns token with consumed
* data or `null`, if string wasnt consumed
* @param {StreamReader} stream
* @return {StringToken}
*/
function eatString(stream) {
const start = stream.pos;
let ch = stream.peek(), pos;
if (_emmetio_streamReaderUtils.isQuote(ch)) {
stream.next();
const quote = ch;
const valueStart = stream.pos;
while (!stream.eof()) {
pos = stream.pos;
if (stream.eat(quote) || stream.eat(isNewline)) {
// found end of string or newline without preceding '\',
// which is not allowed (dont throw error, for now)
break;
} else if (stream.eat(92) /* \ */) {
// backslash allows newline in string
stream.eat(isNewline);
}
stream.next();
}
// either reached EOF or explicitly stopped at string end
return new StringToken(
String.fromCharCode(quote),
new Token(stream, valueStart, pos),
stream,
start
);
}
stream.pos = start;
return null;
}
class StringToken extends Token {
constructor(quote, value, stream, start, end) {
super(stream, start, end);
this.type = 'string';
this.quote = quote;
this.value = value;
}
}
function isNewline(code) {
return code === 10 /* LF */ || code === 13 /* CR */;
}
const SINGLE_LINE = 1;
const MULTI_LINE = 2;
const ASTERISK = 42;
const SLASH = 47;
/**
* Consumes comment from given stream: either multi-line or single-line
* @param {StreamReader} stream
* @return {CommentToken}
*/
var eatComment = function(stream) {
const start = stream.pos;
switch (isCommentStart(stream, true)) {
case SINGLE_LINE:
// single-line comment, consume till the end of line
stream.eatWhile(notLineBreak);
stream.eat(isLineBreak);
return new CommentToken(stream, start);
case MULTI_LINE:
while (!stream.eof()) {
if (stream.next() === ASTERISK && stream.eat(SLASH)) {
break;
}
}
return new CommentToken(stream, start);
}
stream.pos = start;
};
/**
* Eats comment start, if possible
* @param {StreamReader} stream
* @param {Boolean} consume Keep tream position at the end of comment start,
* if matched
* @return {Number} Returns type of comment, if consumed
*/
function isCommentStart(stream, consume) {
const start = stream.start;
const pos = stream.pos;
let result = 0;
if (stream.eat(SLASH)) {
if (stream.eat(SLASH)) {
result = SINGLE_LINE;
} else if (stream.eat(ASTERISK)) {
result = MULTI_LINE;
}
}
if (result && consume) {
stream.start = pos;
} else {
stream.pos = pos;
}
return result;
}
class CommentToken extends Token {
constructor(stream, start, end) {
super(stream, start, end);
this.type = 'comment';
}
}
function isLineBreak(code) {
return code === 10 /* LF */ || code === 13 /* CR */;
}
function notLineBreak(code) {
return !isLineBreak(code);
}
const ATTR_START = 91; // [
const ATTR_END = 93; // ]
/**
* Consumes attribute from given string, e.g. value between [ and ]
* @param {StreamReader} stream
* @return {AttributeToken}
*/
function eatAttribuite(stream) {
const start = stream.pos;
if (stream.eat(ATTR_START)) {
skip(stream);
const name = eatIdent(stream);
skip(stream);
const opStart = stream.pos;
stream.eatWhile(isOperator);
const operator = new Token(stream, opStart);
skip(stream);
const value = eatString(stream) || eatIdent(stream);
// in case of invalid attribute definition, consume till the end of attribute
while (!stream.eof()) {
if (stream.eat(ATTR_END)) {
break;
} else if (!skip(stream) && !eatIdent(stream) && !eatString(stream)) {
stream.next();
}
}
return new AttributeToken(name, value, operator, stream, start);
}
}
class AttributeToken extends Token {
constructor(name, value, operator, stream, start, end) {
super(stream, start, end);
this.type = 'attribute';
this.name = name;
this.value = value;
this.operator = operator;
}
}
function skip(stream) {
while (!stream.eof()) {
if (!stream.eatWhile(_emmetio_streamReaderUtils.isSpace) || !eatComment(stream)) {
return true;
}
}
}
function isOperator(code) {
return code === 126 /* ~ */
|| code === 124 /* | */
|| code === 94 /* ^ */
|| code === 36 /* $ */
|| code === 42 /* * */
|| code === 61; /* = */
}
/**
* Consumes class fragment from given stream, e.g. `.foo`
* @param {StreamReader} stream
* @return {ClassToken}
*/
function eatClass(stream) {
const start = stream.pos;
if (stream.eat(46 /* . */)) {
return new ClassToken(eatIdent(stream), stream, start);
}
}
class ClassToken extends Token {
constructor(name, stream, start, end) {
super(stream, start, end);
this.type = 'class';
this.name = name;
}
}
const ADJACENT_SIBLING = 43; // +
const GENERAL_SIBLING = 126; // ~
const CHILD = 62; // >
const NESTING = 38; // &
/**
* Consumes combinator token from given string
*/
var combinator = function(stream) {
if (isCombinator(stream.peek())) {
const start = stream.pos;
return new CombinatorToken(stream.next(), stream, start);
}
};
function isCombinator(code) {
return code === ADJACENT_SIBLING || code === GENERAL_SIBLING
|| code === NESTING || code === CHILD;
}
class CombinatorToken extends Token {
constructor(code, stream, start, end) {
super(stream, start, end);
this.type = 'combinator';
this.code = code;
this.adjacentSibling = code === ADJACENT_SIBLING;
this.generalSibling = code === GENERAL_SIBLING;
this.child = code === CHILD;
this.nesting = code === NESTING;
}
}
function eatHash(stream) {
const start = stream.pos;
if (stream.eat(35 /* # */)) {
stream.start = stream.pos;
stream.eatWhile(isHashValue);
return new HashToken(new Token(stream), stream, start);
}
stream.pos = start;
}
function isHashValue(code) {
return _emmetio_streamReaderUtils.isNumber(code) || _emmetio_streamReaderUtils.isAlpha(code, 65 /* A */, 70 /* F */)
|| code === 95 /* _ */ || code === 45 /* - */
|| code > 128 /* non-ASCII */
}
class HashToken extends Token {
constructor(value, stream, start, end) {
super(stream, start, end);
this.type = 'hash';
this.value = value;
}
}
/**
* Consumes id fragment from given stream, e.g. `#foo`
* @param {StreamReader} stream
* @return {IdToken}
*/
function eatId(stream) {
const start = stream.pos;
if (stream.eat(35 /* # */)) {
return new IdToken(eatIdent(stream), stream, start);
}
}
class IdToken extends Token {
constructor(name, stream, start, end) {
super(stream, start, end);
this.type = 'id';
this.name = name;
}
}
const DOT = 46; // .
/**
* Consumes number from given string, e.g. `10px`
* @param {StreamReader} stream
* @return {NumberToken}
*/
function eatNumber(stream) {
const start = stream.pos;
const num = getNumToken(stream);
if (num) {
return new NumberToken(num, eatPercent(stream) || eatIdent(stream), stream, start);
}
}
function getNumToken(stream) {
const start = stream.pos;
stream.eat(isOperator$1);
if (stream.eatWhile(_emmetio_streamReaderUtils.isNumber)) {
let end = stream.pos;
if (stream.eat(DOT) && stream.eatWhile(_emmetio_streamReaderUtils.isNumber)) {
end = stream.pos;
} else {
stream.pos = end;
}
return new NumToken(stream, start, end);
} else if (stream.eat(DOT) && stream.eatWhile(_emmetio_streamReaderUtils.isNumber)) {
return new NumToken(stream, start);
}
stream.pos = start;
}
function eatPercent(stream) {
if (stream.peek() === 37 /* % */) {
const start = stream.pos;
stream.next();
return new Token(stream, start);
}
}
function isOperator$1(code) {
return code === 45 /* - */ || code === 43 /* + */;
}
class NumberToken extends Token {
constructor(number, unit, stream, start, end) {
super(stream, start, end);
this.type = 'number';
this.number = number;
this.unit = unit;
}
}
class NumToken extends Token {
constructor(stream, start, end) {
super(stream, start, end);
this.type = 'num';
}
toNumber() {
return parseFloat(this.valueOf());
}
}
/**
* Consumes unquoted value from given stream
* @param {StreamReader} stream
* @return {UnquotedToken}
*/
var unquoted = function(stream) {
const start = stream.pos;
if (stream.eatWhile(isUnquoted)) {
return new UnquotedToken(stream, start);
}
};
function isUnquoted(code) {
return !isNaN(code) && !_emmetio_streamReaderUtils.isQuote(code) && !_emmetio_streamReaderUtils.isSpace(code)
&& code !== 40 /* ( */ && code !== 41 /* ) */ && code !== 92 /* \ */
&& !isNonPrintable(code);
}
function isNonPrintable(code) {
return (code >= 0 && code <= 8) || code === 11
|| (code >= 14 && code <= 31) || code === 127;
}
class UnquotedToken extends Token {
constructor(stream, start, end) {
super(stream, start, end);
this.type = 'unquoted';
}
}
/**
* Consumes URL token from given stream
* @param {StreamReader} stream
* @return {UrlToken}
*/
var url = function(stream) {
const start = stream.pos;
if (stream.eat(117) && stream.eat(114) && stream.eat(108) && stream.eat(40)) {
// consumed `url(`
stream.eatWhile(_emmetio_streamReaderUtils.isSpace);
const value = eatString(stream) || unquoted(stream);
stream.eatWhile(_emmetio_streamReaderUtils.isSpace);
stream.eat(41); // )
return new UrlToken(value, stream, start);
}
stream.pos = start;
};
class UrlToken extends Token {
constructor(value, stream, start, end) {
super(stream, start, end);
this.type = 'url';
this.value = value;
}
}
/**
* Consumes SCSS variable from given stream
*/
var variable = function(stream) {
const start = stream.pos;
if (stream.eatWhile(36 /* $ */)) {
const name = eatIdent(stream);
if (name) {
return new VariableToken(name, stream, start);
}
}
stream.pos = start;
};
class VariableToken extends Token {
constructor(name, stream, start, end) {
super(stream, start, end);
this.type = 'variable';
this.name = name;
}
}
/**
* Consumes white-space tokens from given stream
*/
function eatWhitespace(stream) {
const start = stream.pos;
if (stream.eatWhile(_emmetio_streamReaderUtils.isSpace)) {
return new WhiteSpaceToken(stream, start);
}
}
class WhiteSpaceToken extends Token {
constructor(stream, start, end) {
super(stream, start, end);
this.type = 'whitespace';
}
}
/**
* A token that represents a function call or definition
*/
class FunctionToken extends Token {
constructor(name, args, stream) {
super(stream, name.start, args.end);
this.name = name;
this.arguments = args;
this.type = 'function';
}
}
/**
* Group tokens by commonly used context
*/
function consumeToken(stream) {
const _token = any(stream) || args(stream, consumeToken);
if (_token && _token.type === 'ident') {
const _args = args(stream, consumeToken);
if (_args) {
// An identifier followed by arguments function call
return new FunctionToken(_token, _args, stream);
}
}
return _token;
}
function any(stream) {
return url(stream) || selector(stream) || value(stream) || keyword(stream)
|| separator(stream) || formatting(stream);
}
function selector(stream) {
return eatIdent(stream) || eatClass(stream) || eatId(stream) || eatAttribuite(stream)
|| atKeyword(stream) || combinator(stream);
}
function keyword(stream) {
return variable(stream) || atKeyword(stream) || eatIdent(stream);
}
function value(stream) {
return eatString(stream) || eatNumber(stream) || eatHash(stream) || url(stream);
}
function formatting(stream) {
return eatComment(stream) || eatWhitespace(stream);
}
function fragments(stream, items) {
return new FragmentsToken(stream, items);
}
function unknown(stream) {
return new Token(stream);
}
/**
* Consumes pseudo-selector from given stream
*/
class PseudoToken extends Token {
constructor(name, stream, start, end) {
super(stream, start, end);
this.type = 'pseudo';
this.name = name;
}
}
/**
* Separates given list of tokens by specified separator
* @param {Token[]} tokens
* @param {*|Function} sep
* @return {Array[]}
*/
function splitList(tokens, sep) {
if (!tokens.length) {
return [];
}
let itemTokens = [];
const list = [];
const test = typeof sep === 'function'
? sep
: token => token === sep || token.type === sep;
for (let i = 0; i < tokens.length; i++) {
if (test(tokens[i])) {
if (itemTokens.length) {
list.push(itemTokens);
}
itemTokens = [];
} else {
itemTokens.push(tokens[i]);
}
}
if (itemTokens.length) {
list.push(itemTokens);
}
return list;
}
/**
* Removes tokens that matches given criteria from start and end of given list
* @param {Token[]} tokens
* @param {Function} test
* @return {Token[]}
*/
function trimTokens(tokens, test) {
tokens = tokens.slice();
while (tokens.length) {
if (!test(tokens[0])) {
break;
}
tokens.shift();
}
while (tokens.length) {
if (!test(tokens[tokens.length - 1])) {
break;
}
tokens.pop();
}
return tokens;
}
/**
* Trims formatting tokens (whitespace and comments) from the beginning and end
* of given token list
* @param {Token[]} tokens
* @return {Token[]}
*/
function trimFormatting(tokens) {
return trimTokens(tokens, isFormattingToken);
}
/**
* Check if given token is a formatting one (whitespace or comment)
* @param {Token} token
* @return {Boolean}
*/
function isFormattingToken(token) {
return token.type === 'comment' || token.type === 'whitespace';
}
function commaSeparator$1(token) {
return token.comma;
}
/**
* Creates CSS rule frmo given tokens
* @param {StreamReader} stream
* @param {Token[]} tokens
* @param {Token} [contentStart]
* @param {Token} [contentEnd]
* @return {Rule}
*/
function createRule(stream, tokens, contentStart, contentEnd) {
tokens = replacePseudo(trimFormatting(tokens));
if (!tokens.length) {
return null;
}
if (tokens[0].type === 'at-keyword') {
return new AtRule(tokens.shift(), createItemList(stream, tokens),
contentStart, contentEnd);
}
return new Rule(createItemList(stream, tokens), contentStart, contentEnd);
}
/**
* Represents CSS rule
* @type {Node}
*/
class Rule {
/**
* @param {Token} name Rule name token
* @param {Token} contentStart Rules content start token
* @param {Token} [contentEnd] Rules content end token
*/
constructor(name, contentStart, contentEnd) {
this.type = 'rule';
this.nameToken = name;
this.contentStart = contentStart;
this.contentEnd = contentEnd;
this.children = [];
this.parent = null;
}
/**
* Returns node name
* @return {String}
*/
get name() {
return this.nameToken && this.nameToken.valueOf();
}
/**
* Returns nodes start position in stream
* @return {*}
*/
get start() {
return this.nameToken && this.nameToken.start;
}
/**
* Returns nodes end position in stream
* @return {*}
*/
get end() {
if (this.contentEnd) {
return this.contentEnd.end;
}
return this.contentStart ? this.contentStart.end : this.nameToken.end;
}
get firstChild() {
return this.children[0];
}
get nextSibling() {
const ix = this.getIndex();
return ix !== -1 ? this.parent.children[ix + 1] : null;
}
get previousSibling() {
const ix = this.getIndex();
return ix !== -1 ? this.parent.children[ix - 1] : null;
}
/**
* Returns current elements index in parent list of child nodes
* @return {Number}
*/
getIndex() {
return this.parent ? this.parent.children.indexOf(this) : -1;
}
/**
* Adds given node as a child
* @param {Node} node
* @return {Node} Current node
*/
addChild(node) {
if (node) {
this.removeChild(node);
this.children.push(node);
node.parent = this;
}
return this;
}
/**
* Removes given node from current nodes child list
* @param {Node} node
* @return {Node} Current node
*/
removeChild(node) {
if (node) {
const ix = this.children.indexOf(node);
if (ix !== -1) {
this.children.splice(ix, 1);
node.parent = null;
}
}
return this;
}
}
class AtRule extends Rule {
constructor(name, expressions, contentStart, contentEnd) {
super(name, contentStart, contentEnd);
this.type = 'at-rule';
this.expressionsToken = expressions;
}
get expressions() {
return this.expressionsToken ? this.expressionsToken.fragments : [];
}
}
/**
* Replaces `:` separator and following ident token with pseudo token
* @param {StreamReader} stream
* @param {Token[]} tokens
* @return {Token[]}
*/
function replacePseudo(tokens) {
let result = [];
let pseudoStart = [];
for (let i = 0, il = tokens.length, token; i < il; i++) {
token = tokens[i];
if (token.propertyDelimiter) {
pseudoStart.push(token);
} else if (token.type === 'ident' && pseudoStart.length) {
result.push(new PseudoToken(token, token.stream, pseudoStart[0].start, token.end));
pseudoStart.length = 0;
} else {
if (pseudoStart.length) {
result = result.concat(pseudoStart);
pseudoStart.length = 0;
}
result.push(token);
}
}
return result.concat(pseudoStart);
}
function createItemList(stream, tokens) {
const items = splitList(tokens, commaSeparator$1)
.map(item => fragments(stream, trimFormatting(item)));
return fragments(stream, items);
}
class Stylesheet extends Rule {
constructor() {
super();
this.type = 'stylesheet';
}
/**
* Returns node name
* @return {String}
*/
get name() {
return null;
}
/**
* Returns nodes start position in stream
* @return {*}
*/
get start() {
const node = this.children[0];
return node && node.start;
}
/**
* Returns nodes end position in stream
* @return {*}
*/
get end() {
const node = this.children[this.children.length - 1];
return node && node.end;
}
}
/**
* Factory method that creates property node from given tokens
* @param {StreamReader} stream
* @param {Token[]} tokens
* @return {Property}
*/
function createProperty(stream, tokens) {
// NB in LESS, fragmented properties without value like `.foo.bar;` must be
// treated like mixin call
tokens = trimFormatting(tokens);
if (!tokens.length) {
return null;
}
// Property terminator should be at the end of token list
let terminator = tokens[tokens.length - 1].propertyTerminator ? tokens.pop() : null;
let name = tokens, value$$1, separator$$1;
let sepIx = -1;
for (let i = 0, il = tokens.length; i < il; i++) {
if (tokens[i].propertyDelimiter) {
sepIx = i;
break;
}
}
if (sepIx !== -1) {
// Has explicit property separator
name = tokens.slice(0, sepIx);
value$$1 = tokens.slice(sepIx + 1);
separator$$1 = tokens[sepIx];
} else if (tokens[0] && tokens[0].type === 'at-keyword') {
// Edge case for properties like `@import "foo";`: treat at-keyword as
// property name, the rest tokens are value
name = [tokens[0]];
value$$1 = tokens.slice(1);
} else {
// Check for `color:red;` edge case where `:red` is parsed as pseudo-selector
for (let i = 0; i < tokens.length; i++) {
if (tokens[i].type === 'pseudo') {
name = tokens.slice(0, i);
value$$1 = [tokens[i].name].concat(tokens.slice(i + 1));
break;
}
}
}
if (value$$1) {
value$$1 = splitList(value$$1, commaSeparator$1)
.map(item => fragments(stream, trimFormatting(item)));
}
return new Property(
fragments(stream, trimFormatting(name)),
value$$1 && value$$1.length ? fragments(stream, value$$1) : null,
separator$$1,
terminator
);
}
class Property {
constructor(name, value$$1, separator$$1, terminator) {
this.type = 'property';
this.nameToken = name;
this.valueToken = value$$1;
this.separatorToken = separator$$1;
this.terminatorToken = terminator;
}
get name() {
return valueOf(this.nameToken);
}
get value() {
return valueOf(this.valueToken);
}
get separator() {
return valueOf(this.separatorToken);
}
get terminator() {
return valueOf(this.terminatorToken);
}
get start() {
return this.nameToken && this.nameToken.start;
}
get end() {
const token = this.terminatorToken || this.valueToken
|| this.separatorToken || this.nameToken;
return token && token.end;
}
}
function valueOf(token) {
return token && token.valueOf();
}
var index = function(source) {
const stream = typeof source === 'string' ? new StreamReader(source) : source;
const root = new Stylesheet();
let tokens = [];
let ctx = root, child, t;
while (!stream.eof()) {
t = consumeToken(stream);
if (!t) {
// unable to identify following character, consume it as unknown token
stream.start = stream.pos;
stream.next();
tokens.push(unknown(stream));
} else if (t.propertyTerminator) {
// Tokens consumed before are CSS property
tokens.push(t);
ctx.addChild(createProperty(stream, tokens, t));
tokens = [];
} else if (t.ruleStart) {
// Tokens consumed before are CSS rule
child = createRule(stream, tokens, t);
if (child) {
ctx.addChild(child);
ctx = child;
}
tokens = [];
} else if (t.ruleEnd) {
// Finalize previously consumed tokens as CSS property
ctx.addChild(createProperty(stream, tokens));
tokens = [];
// In case of invalid stylesheet with redundant `}`,
// dont modify root section.
if (ctx.type !== 'root') {
ctx.contentEnd = t;
}
ctx = ctx.parent || ctx;
} else {
tokens.push(t);
}
}
// save unterminated tokens as property
ctx.addChild(createProperty(stream, tokens));
return root;
};
exports['default'] = index;
exports.token = consumeToken;
exports.createProperty = createProperty;
exports.createRule = createRule;
exports.Token = Token;