🎉 initiate project *astro_rewrite*

This commit is contained in:
sindrekjelsrud 2023-07-19 21:31:30 +02:00
parent ffd4d5e86c
commit 2ba37bfbe3
8658 changed files with 2268794 additions and 2538 deletions

View file

@ -0,0 +1,60 @@
(function (factory) {
if (typeof module === "object" && typeof module.exports === "object") {
var v = factory(require, exports);
if (v !== undefined) module.exports = v;
}
else if (typeof define === "function" && define.amd) {
define(["require", "exports", "@vscode/l10n"], factory);
}
})(function (require, exports) {
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
exports.ParseError = exports.CSSIssueType = void 0;
const l10n = require("@vscode/l10n");
class CSSIssueType {
constructor(id, message) {
this.id = id;
this.message = message;
}
}
exports.CSSIssueType = CSSIssueType;
exports.ParseError = {
NumberExpected: new CSSIssueType('css-numberexpected', l10n.t("number expected")),
ConditionExpected: new CSSIssueType('css-conditionexpected', l10n.t("condition expected")),
RuleOrSelectorExpected: new CSSIssueType('css-ruleorselectorexpected', l10n.t("at-rule or selector expected")),
DotExpected: new CSSIssueType('css-dotexpected', l10n.t("dot expected")),
ColonExpected: new CSSIssueType('css-colonexpected', l10n.t("colon expected")),
SemiColonExpected: new CSSIssueType('css-semicolonexpected', l10n.t("semi-colon expected")),
TermExpected: new CSSIssueType('css-termexpected', l10n.t("term expected")),
ExpressionExpected: new CSSIssueType('css-expressionexpected', l10n.t("expression expected")),
OperatorExpected: new CSSIssueType('css-operatorexpected', l10n.t("operator expected")),
IdentifierExpected: new CSSIssueType('css-identifierexpected', l10n.t("identifier expected")),
PercentageExpected: new CSSIssueType('css-percentageexpected', l10n.t("percentage expected")),
URIOrStringExpected: new CSSIssueType('css-uriorstringexpected', l10n.t("uri or string expected")),
URIExpected: new CSSIssueType('css-uriexpected', l10n.t("URI expected")),
VariableNameExpected: new CSSIssueType('css-varnameexpected', l10n.t("variable name expected")),
VariableValueExpected: new CSSIssueType('css-varvalueexpected', l10n.t("variable value expected")),
PropertyValueExpected: new CSSIssueType('css-propertyvalueexpected', l10n.t("property value expected")),
LeftCurlyExpected: new CSSIssueType('css-lcurlyexpected', l10n.t("{ expected")),
RightCurlyExpected: new CSSIssueType('css-rcurlyexpected', l10n.t("} expected")),
LeftSquareBracketExpected: new CSSIssueType('css-rbracketexpected', l10n.t("[ expected")),
RightSquareBracketExpected: new CSSIssueType('css-lbracketexpected', l10n.t("] expected")),
LeftParenthesisExpected: new CSSIssueType('css-lparentexpected', l10n.t("( expected")),
RightParenthesisExpected: new CSSIssueType('css-rparentexpected', l10n.t(") expected")),
CommaExpected: new CSSIssueType('css-commaexpected', l10n.t("comma expected")),
PageDirectiveOrDeclarationExpected: new CSSIssueType('css-pagedirordeclexpected', l10n.t("page directive or declaraton expected")),
UnknownAtRule: new CSSIssueType('css-unknownatrule', l10n.t("at-rule unknown")),
UnknownKeyword: new CSSIssueType('css-unknownkeyword', l10n.t("unknown keyword")),
SelectorExpected: new CSSIssueType('css-selectorexpected', l10n.t("selector expected")),
StringLiteralExpected: new CSSIssueType('css-stringliteralexpected', l10n.t("string literal expected")),
WhitespaceExpected: new CSSIssueType('css-whitespaceexpected', l10n.t("whitespace expected")),
MediaQueryExpected: new CSSIssueType('css-mediaqueryexpected', l10n.t("media query expected")),
IdentifierOrWildcardExpected: new CSSIssueType('css-idorwildcardexpected', l10n.t("identifier or wildcard expected")),
WildcardExpected: new CSSIssueType('css-wildcardexpected', l10n.t("wildcard expected")),
IdentifierOrVariableExpected: new CSSIssueType('css-idorvarexpected', l10n.t("identifier or variable expected")),
};
});

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,606 @@
(function (factory) {
if (typeof module === "object" && typeof module.exports === "object") {
var v = factory(require, exports);
if (v !== undefined) module.exports = v;
}
else if (typeof define === "function" && define.amd) {
define(["require", "exports"], factory);
}
})(function (require, exports) {
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
exports.Scanner = exports.MultiLineStream = exports.TokenType = void 0;
var TokenType;
(function (TokenType) {
TokenType[TokenType["Ident"] = 0] = "Ident";
TokenType[TokenType["AtKeyword"] = 1] = "AtKeyword";
TokenType[TokenType["String"] = 2] = "String";
TokenType[TokenType["BadString"] = 3] = "BadString";
TokenType[TokenType["UnquotedString"] = 4] = "UnquotedString";
TokenType[TokenType["Hash"] = 5] = "Hash";
TokenType[TokenType["Num"] = 6] = "Num";
TokenType[TokenType["Percentage"] = 7] = "Percentage";
TokenType[TokenType["Dimension"] = 8] = "Dimension";
TokenType[TokenType["UnicodeRange"] = 9] = "UnicodeRange";
TokenType[TokenType["CDO"] = 10] = "CDO";
TokenType[TokenType["CDC"] = 11] = "CDC";
TokenType[TokenType["Colon"] = 12] = "Colon";
TokenType[TokenType["SemiColon"] = 13] = "SemiColon";
TokenType[TokenType["CurlyL"] = 14] = "CurlyL";
TokenType[TokenType["CurlyR"] = 15] = "CurlyR";
TokenType[TokenType["ParenthesisL"] = 16] = "ParenthesisL";
TokenType[TokenType["ParenthesisR"] = 17] = "ParenthesisR";
TokenType[TokenType["BracketL"] = 18] = "BracketL";
TokenType[TokenType["BracketR"] = 19] = "BracketR";
TokenType[TokenType["Whitespace"] = 20] = "Whitespace";
TokenType[TokenType["Includes"] = 21] = "Includes";
TokenType[TokenType["Dashmatch"] = 22] = "Dashmatch";
TokenType[TokenType["SubstringOperator"] = 23] = "SubstringOperator";
TokenType[TokenType["PrefixOperator"] = 24] = "PrefixOperator";
TokenType[TokenType["SuffixOperator"] = 25] = "SuffixOperator";
TokenType[TokenType["Delim"] = 26] = "Delim";
TokenType[TokenType["EMS"] = 27] = "EMS";
TokenType[TokenType["EXS"] = 28] = "EXS";
TokenType[TokenType["Length"] = 29] = "Length";
TokenType[TokenType["Angle"] = 30] = "Angle";
TokenType[TokenType["Time"] = 31] = "Time";
TokenType[TokenType["Freq"] = 32] = "Freq";
TokenType[TokenType["Exclamation"] = 33] = "Exclamation";
TokenType[TokenType["Resolution"] = 34] = "Resolution";
TokenType[TokenType["Comma"] = 35] = "Comma";
TokenType[TokenType["Charset"] = 36] = "Charset";
TokenType[TokenType["EscapedJavaScript"] = 37] = "EscapedJavaScript";
TokenType[TokenType["BadEscapedJavaScript"] = 38] = "BadEscapedJavaScript";
TokenType[TokenType["Comment"] = 39] = "Comment";
TokenType[TokenType["SingleLineComment"] = 40] = "SingleLineComment";
TokenType[TokenType["EOF"] = 41] = "EOF";
TokenType[TokenType["CustomToken"] = 42] = "CustomToken";
})(TokenType = exports.TokenType || (exports.TokenType = {}));
class MultiLineStream {
constructor(source) {
this.source = source;
this.len = source.length;
this.position = 0;
}
substring(from, to = this.position) {
return this.source.substring(from, to);
}
eos() {
return this.len <= this.position;
}
pos() {
return this.position;
}
goBackTo(pos) {
this.position = pos;
}
goBack(n) {
this.position -= n;
}
advance(n) {
this.position += n;
}
nextChar() {
return this.source.charCodeAt(this.position++) || 0;
}
peekChar(n = 0) {
return this.source.charCodeAt(this.position + n) || 0;
}
lookbackChar(n = 0) {
return this.source.charCodeAt(this.position - n) || 0;
}
advanceIfChar(ch) {
if (ch === this.source.charCodeAt(this.position)) {
this.position++;
return true;
}
return false;
}
advanceIfChars(ch) {
if (this.position + ch.length > this.source.length) {
return false;
}
let i = 0;
for (; i < ch.length; i++) {
if (this.source.charCodeAt(this.position + i) !== ch[i]) {
return false;
}
}
this.advance(i);
return true;
}
advanceWhileChar(condition) {
const posNow = this.position;
while (this.position < this.len && condition(this.source.charCodeAt(this.position))) {
this.position++;
}
return this.position - posNow;
}
}
exports.MultiLineStream = MultiLineStream;
const _a = 'a'.charCodeAt(0);
const _f = 'f'.charCodeAt(0);
const _z = 'z'.charCodeAt(0);
const _u = 'u'.charCodeAt(0);
const _A = 'A'.charCodeAt(0);
const _F = 'F'.charCodeAt(0);
const _Z = 'Z'.charCodeAt(0);
const _0 = '0'.charCodeAt(0);
const _9 = '9'.charCodeAt(0);
const _TLD = '~'.charCodeAt(0);
const _HAT = '^'.charCodeAt(0);
const _EQS = '='.charCodeAt(0);
const _PIP = '|'.charCodeAt(0);
const _MIN = '-'.charCodeAt(0);
const _USC = '_'.charCodeAt(0);
const _PRC = '%'.charCodeAt(0);
const _MUL = '*'.charCodeAt(0);
const _LPA = '('.charCodeAt(0);
const _RPA = ')'.charCodeAt(0);
const _LAN = '<'.charCodeAt(0);
const _RAN = '>'.charCodeAt(0);
const _ATS = '@'.charCodeAt(0);
const _HSH = '#'.charCodeAt(0);
const _DLR = '$'.charCodeAt(0);
const _BSL = '\\'.charCodeAt(0);
const _FSL = '/'.charCodeAt(0);
const _NWL = '\n'.charCodeAt(0);
const _CAR = '\r'.charCodeAt(0);
const _LFD = '\f'.charCodeAt(0);
const _DQO = '"'.charCodeAt(0);
const _SQO = '\''.charCodeAt(0);
const _WSP = ' '.charCodeAt(0);
const _TAB = '\t'.charCodeAt(0);
const _SEM = ';'.charCodeAt(0);
const _COL = ':'.charCodeAt(0);
const _CUL = '{'.charCodeAt(0);
const _CUR = '}'.charCodeAt(0);
const _BRL = '['.charCodeAt(0);
const _BRR = ']'.charCodeAt(0);
const _CMA = ','.charCodeAt(0);
const _DOT = '.'.charCodeAt(0);
const _BNG = '!'.charCodeAt(0);
const _QSM = '?'.charCodeAt(0);
const _PLS = '+'.charCodeAt(0);
const staticTokenTable = {};
staticTokenTable[_SEM] = TokenType.SemiColon;
staticTokenTable[_COL] = TokenType.Colon;
staticTokenTable[_CUL] = TokenType.CurlyL;
staticTokenTable[_CUR] = TokenType.CurlyR;
staticTokenTable[_BRR] = TokenType.BracketR;
staticTokenTable[_BRL] = TokenType.BracketL;
staticTokenTable[_LPA] = TokenType.ParenthesisL;
staticTokenTable[_RPA] = TokenType.ParenthesisR;
staticTokenTable[_CMA] = TokenType.Comma;
const staticUnitTable = {};
staticUnitTable['em'] = TokenType.EMS;
staticUnitTable['ex'] = TokenType.EXS;
staticUnitTable['px'] = TokenType.Length;
staticUnitTable['cm'] = TokenType.Length;
staticUnitTable['mm'] = TokenType.Length;
staticUnitTable['in'] = TokenType.Length;
staticUnitTable['pt'] = TokenType.Length;
staticUnitTable['pc'] = TokenType.Length;
staticUnitTable['deg'] = TokenType.Angle;
staticUnitTable['rad'] = TokenType.Angle;
staticUnitTable['grad'] = TokenType.Angle;
staticUnitTable['ms'] = TokenType.Time;
staticUnitTable['s'] = TokenType.Time;
staticUnitTable['hz'] = TokenType.Freq;
staticUnitTable['khz'] = TokenType.Freq;
staticUnitTable['%'] = TokenType.Percentage;
staticUnitTable['fr'] = TokenType.Percentage;
staticUnitTable['dpi'] = TokenType.Resolution;
staticUnitTable['dpcm'] = TokenType.Resolution;
class Scanner {
constructor() {
this.stream = new MultiLineStream('');
this.ignoreComment = true;
this.ignoreWhitespace = true;
this.inURL = false;
}
setSource(input) {
this.stream = new MultiLineStream(input);
}
finishToken(offset, type, text) {
return {
offset: offset,
len: this.stream.pos() - offset,
type: type,
text: text || this.stream.substring(offset)
};
}
substring(offset, len) {
return this.stream.substring(offset, offset + len);
}
pos() {
return this.stream.pos();
}
goBackTo(pos) {
this.stream.goBackTo(pos);
}
scanUnquotedString() {
const offset = this.stream.pos();
const content = [];
if (this._unquotedString(content)) {
return this.finishToken(offset, TokenType.UnquotedString, content.join(''));
}
return null;
}
scan() {
// processes all whitespaces and comments
const triviaToken = this.trivia();
if (triviaToken !== null) {
return triviaToken;
}
const offset = this.stream.pos();
// End of file/input
if (this.stream.eos()) {
return this.finishToken(offset, TokenType.EOF);
}
return this.scanNext(offset);
}
/**
* Read the range as described in https://www.w3.org/TR/CSS21/syndata.html#tokenization
* Assume the `u` has aleady been consumed
* @returns if reading the unicode was successful
*/
tryScanUnicode() {
const offset = this.stream.pos();
if (!this.stream.eos() && this._unicodeRange()) {
return this.finishToken(offset, TokenType.UnicodeRange);
}
this.stream.goBackTo(offset);
return undefined;
}
scanNext(offset) {
// CDO <!--
if (this.stream.advanceIfChars([_LAN, _BNG, _MIN, _MIN])) {
return this.finishToken(offset, TokenType.CDO);
}
// CDC -->
if (this.stream.advanceIfChars([_MIN, _MIN, _RAN])) {
return this.finishToken(offset, TokenType.CDC);
}
let content = [];
if (this.ident(content)) {
return this.finishToken(offset, TokenType.Ident, content.join(''));
}
// at-keyword
if (this.stream.advanceIfChar(_ATS)) {
content = ['@'];
if (this._name(content)) {
const keywordText = content.join('');
if (keywordText === '@charset') {
return this.finishToken(offset, TokenType.Charset, keywordText);
}
return this.finishToken(offset, TokenType.AtKeyword, keywordText);
}
else {
return this.finishToken(offset, TokenType.Delim);
}
}
// hash
if (this.stream.advanceIfChar(_HSH)) {
content = ['#'];
if (this._name(content)) {
return this.finishToken(offset, TokenType.Hash, content.join(''));
}
else {
return this.finishToken(offset, TokenType.Delim);
}
}
// Important
if (this.stream.advanceIfChar(_BNG)) {
return this.finishToken(offset, TokenType.Exclamation);
}
// Numbers
if (this._number()) {
const pos = this.stream.pos();
content = [this.stream.substring(offset, pos)];
if (this.stream.advanceIfChar(_PRC)) {
// Percentage 43%
return this.finishToken(offset, TokenType.Percentage);
}
else if (this.ident(content)) {
const dim = this.stream.substring(pos).toLowerCase();
const tokenType = staticUnitTable[dim];
if (typeof tokenType !== 'undefined') {
// Known dimension 43px
return this.finishToken(offset, tokenType, content.join(''));
}
else {
// Unknown dimension 43ft
return this.finishToken(offset, TokenType.Dimension, content.join(''));
}
}
return this.finishToken(offset, TokenType.Num);
}
// String, BadString
content = [];
let tokenType = this._string(content);
if (tokenType !== null) {
return this.finishToken(offset, tokenType, content.join(''));
}
// single character tokens
tokenType = staticTokenTable[this.stream.peekChar()];
if (typeof tokenType !== 'undefined') {
this.stream.advance(1);
return this.finishToken(offset, tokenType);
}
// includes ~=
if (this.stream.peekChar(0) === _TLD && this.stream.peekChar(1) === _EQS) {
this.stream.advance(2);
return this.finishToken(offset, TokenType.Includes);
}
// DashMatch |=
if (this.stream.peekChar(0) === _PIP && this.stream.peekChar(1) === _EQS) {
this.stream.advance(2);
return this.finishToken(offset, TokenType.Dashmatch);
}
// Substring operator *=
if (this.stream.peekChar(0) === _MUL && this.stream.peekChar(1) === _EQS) {
this.stream.advance(2);
return this.finishToken(offset, TokenType.SubstringOperator);
}
// Substring operator ^=
if (this.stream.peekChar(0) === _HAT && this.stream.peekChar(1) === _EQS) {
this.stream.advance(2);
return this.finishToken(offset, TokenType.PrefixOperator);
}
// Substring operator $=
if (this.stream.peekChar(0) === _DLR && this.stream.peekChar(1) === _EQS) {
this.stream.advance(2);
return this.finishToken(offset, TokenType.SuffixOperator);
}
// Delim
this.stream.nextChar();
return this.finishToken(offset, TokenType.Delim);
}
trivia() {
while (true) {
const offset = this.stream.pos();
if (this._whitespace()) {
if (!this.ignoreWhitespace) {
return this.finishToken(offset, TokenType.Whitespace);
}
}
else if (this.comment()) {
if (!this.ignoreComment) {
return this.finishToken(offset, TokenType.Comment);
}
}
else {
return null;
}
}
}
comment() {
if (this.stream.advanceIfChars([_FSL, _MUL])) {
let success = false, hot = false;
this.stream.advanceWhileChar((ch) => {
if (hot && ch === _FSL) {
success = true;
return false;
}
hot = ch === _MUL;
return true;
});
if (success) {
this.stream.advance(1);
}
return true;
}
return false;
}
_number() {
let npeek = 0, ch;
if (this.stream.peekChar() === _DOT) {
npeek = 1;
}
ch = this.stream.peekChar(npeek);
if (ch >= _0 && ch <= _9) {
this.stream.advance(npeek + 1);
this.stream.advanceWhileChar((ch) => {
return ch >= _0 && ch <= _9 || npeek === 0 && ch === _DOT;
});
return true;
}
return false;
}
_newline(result) {
const ch = this.stream.peekChar();
switch (ch) {
case _CAR:
case _LFD:
case _NWL:
this.stream.advance(1);
result.push(String.fromCharCode(ch));
if (ch === _CAR && this.stream.advanceIfChar(_NWL)) {
result.push('\n');
}
return true;
}
return false;
}
_escape(result, includeNewLines) {
let ch = this.stream.peekChar();
if (ch === _BSL) {
this.stream.advance(1);
ch = this.stream.peekChar();
let hexNumCount = 0;
while (hexNumCount < 6 && (ch >= _0 && ch <= _9 || ch >= _a && ch <= _f || ch >= _A && ch <= _F)) {
this.stream.advance(1);
ch = this.stream.peekChar();
hexNumCount++;
}
if (hexNumCount > 0) {
try {
const hexVal = parseInt(this.stream.substring(this.stream.pos() - hexNumCount), 16);
if (hexVal) {
result.push(String.fromCharCode(hexVal));
}
}
catch (e) {
// ignore
}
// optional whitespace or new line, not part of result text
if (ch === _WSP || ch === _TAB) {
this.stream.advance(1);
}
else {
this._newline([]);
}
return true;
}
if (ch !== _CAR && ch !== _LFD && ch !== _NWL) {
this.stream.advance(1);
result.push(String.fromCharCode(ch));
return true;
}
else if (includeNewLines) {
return this._newline(result);
}
}
return false;
}
_stringChar(closeQuote, result) {
// not closeQuote, not backslash, not newline
const ch = this.stream.peekChar();
if (ch !== 0 && ch !== closeQuote && ch !== _BSL && ch !== _CAR && ch !== _LFD && ch !== _NWL) {
this.stream.advance(1);
result.push(String.fromCharCode(ch));
return true;
}
return false;
}
_string(result) {
if (this.stream.peekChar() === _SQO || this.stream.peekChar() === _DQO) {
const closeQuote = this.stream.nextChar();
result.push(String.fromCharCode(closeQuote));
while (this._stringChar(closeQuote, result) || this._escape(result, true)) {
// loop
}
if (this.stream.peekChar() === closeQuote) {
this.stream.nextChar();
result.push(String.fromCharCode(closeQuote));
return TokenType.String;
}
else {
return TokenType.BadString;
}
}
return null;
}
_unquotedChar(result) {
// not closeQuote, not backslash, not newline
const ch = this.stream.peekChar();
if (ch !== 0 && ch !== _BSL && ch !== _SQO && ch !== _DQO && ch !== _LPA && ch !== _RPA && ch !== _WSP && ch !== _TAB && ch !== _NWL && ch !== _LFD && ch !== _CAR) {
this.stream.advance(1);
result.push(String.fromCharCode(ch));
return true;
}
return false;
}
_unquotedString(result) {
let hasContent = false;
while (this._unquotedChar(result) || this._escape(result)) {
hasContent = true;
}
return hasContent;
}
_whitespace() {
const n = this.stream.advanceWhileChar((ch) => {
return ch === _WSP || ch === _TAB || ch === _NWL || ch === _LFD || ch === _CAR;
});
return n > 0;
}
_name(result) {
let matched = false;
while (this._identChar(result) || this._escape(result)) {
matched = true;
}
return matched;
}
ident(result) {
const pos = this.stream.pos();
const hasMinus = this._minus(result);
if (hasMinus) {
if (this._minus(result) /* -- */ || this._identFirstChar(result) || this._escape(result)) {
while (this._identChar(result) || this._escape(result)) {
// loop
}
return true;
}
}
else if (this._identFirstChar(result) || this._escape(result)) {
while (this._identChar(result) || this._escape(result)) {
// loop
}
return true;
}
this.stream.goBackTo(pos);
return false;
}
_identFirstChar(result) {
const ch = this.stream.peekChar();
if (ch === _USC || // _
ch >= _a && ch <= _z || // a-z
ch >= _A && ch <= _Z || // A-Z
ch >= 0x80 && ch <= 0xFFFF) { // nonascii
this.stream.advance(1);
result.push(String.fromCharCode(ch));
return true;
}
return false;
}
_minus(result) {
const ch = this.stream.peekChar();
if (ch === _MIN) {
this.stream.advance(1);
result.push(String.fromCharCode(ch));
return true;
}
return false;
}
_identChar(result) {
const ch = this.stream.peekChar();
if (ch === _USC || // _
ch === _MIN || // -
ch >= _a && ch <= _z || // a-z
ch >= _A && ch <= _Z || // A-Z
ch >= _0 && ch <= _9 || // 0/9
ch >= 0x80 && ch <= 0xFFFF) { // nonascii
this.stream.advance(1);
result.push(String.fromCharCode(ch));
return true;
}
return false;
}
_unicodeRange() {
// follow https://www.w3.org/TR/CSS21/syndata.html#tokenization and https://www.w3.org/TR/css-syntax-3/#urange-syntax
// assume u has already been parsed
if (this.stream.advanceIfChar(_PLS)) {
const isHexDigit = (ch) => (ch >= _0 && ch <= _9 || ch >= _a && ch <= _f || ch >= _A && ch <= _F);
const codePoints = this.stream.advanceWhileChar(isHexDigit) + this.stream.advanceWhileChar(ch => ch === _QSM);
if (codePoints >= 1 && codePoints <= 6) {
if (this.stream.advanceIfChar(_MIN)) {
const digits = this.stream.advanceWhileChar(isHexDigit);
if (digits >= 1 && digits <= 6) {
return true;
}
}
else {
return true;
}
}
}
return false;
}
}
exports.Scanner = Scanner;
});

View file

@ -0,0 +1,328 @@
(function (factory) {
if (typeof module === "object" && typeof module.exports === "object") {
var v = factory(require, exports);
if (v !== undefined) module.exports = v;
}
else if (typeof define === "function" && define.amd) {
define(["require", "exports", "./cssNodes", "../utils/arrays"], factory);
}
})(function (require, exports) {
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
exports.Symbols = exports.ScopeBuilder = exports.Symbol = exports.GlobalScope = exports.Scope = void 0;
const nodes = require("./cssNodes");
const arrays_1 = require("../utils/arrays");
class Scope {
constructor(offset, length) {
this.offset = offset;
this.length = length;
this.symbols = [];
this.parent = null;
this.children = [];
}
addChild(scope) {
this.children.push(scope);
scope.setParent(this);
}
setParent(scope) {
this.parent = scope;
}
findScope(offset, length = 0) {
if (this.offset <= offset && this.offset + this.length > offset + length || this.offset === offset && this.length === length) {
return this.findInScope(offset, length);
}
return null;
}
findInScope(offset, length = 0) {
// find the first scope child that has an offset larger than offset + length
const end = offset + length;
const idx = (0, arrays_1.findFirst)(this.children, s => s.offset > end);
if (idx === 0) {
// all scopes have offsets larger than our end
return this;
}
const res = this.children[idx - 1];
if (res.offset <= offset && res.offset + res.length >= offset + length) {
return res.findInScope(offset, length);
}
return this;
}
addSymbol(symbol) {
this.symbols.push(symbol);
}
getSymbol(name, type) {
for (let index = 0; index < this.symbols.length; index++) {
const symbol = this.symbols[index];
if (symbol.name === name && symbol.type === type) {
return symbol;
}
}
return null;
}
getSymbols() {
return this.symbols;
}
}
exports.Scope = Scope;
class GlobalScope extends Scope {
constructor() {
super(0, Number.MAX_VALUE);
}
}
exports.GlobalScope = GlobalScope;
class Symbol {
constructor(name, value, node, type) {
this.name = name;
this.value = value;
this.node = node;
this.type = type;
}
}
exports.Symbol = Symbol;
class ScopeBuilder {
constructor(scope) {
this.scope = scope;
}
addSymbol(node, name, value, type) {
if (node.offset !== -1) {
const current = this.scope.findScope(node.offset, node.length);
if (current) {
current.addSymbol(new Symbol(name, value, node, type));
}
}
}
addScope(node) {
if (node.offset !== -1) {
const current = this.scope.findScope(node.offset, node.length);
if (current && (current.offset !== node.offset || current.length !== node.length)) { // scope already known?
const newScope = new Scope(node.offset, node.length);
current.addChild(newScope);
return newScope;
}
return current;
}
return null;
}
addSymbolToChildScope(scopeNode, node, name, value, type) {
if (scopeNode && scopeNode.offset !== -1) {
const current = this.addScope(scopeNode); // create the scope or gets the existing one
if (current) {
current.addSymbol(new Symbol(name, value, node, type));
}
}
}
visitNode(node) {
switch (node.type) {
case nodes.NodeType.Keyframe:
this.addSymbol(node, node.getName(), void 0, nodes.ReferenceType.Keyframe);
return true;
case nodes.NodeType.CustomPropertyDeclaration:
return this.visitCustomPropertyDeclarationNode(node);
case nodes.NodeType.VariableDeclaration:
return this.visitVariableDeclarationNode(node);
case nodes.NodeType.Ruleset:
return this.visitRuleSet(node);
case nodes.NodeType.MixinDeclaration:
this.addSymbol(node, node.getName(), void 0, nodes.ReferenceType.Mixin);
return true;
case nodes.NodeType.FunctionDeclaration:
this.addSymbol(node, node.getName(), void 0, nodes.ReferenceType.Function);
return true;
case nodes.NodeType.FunctionParameter: {
return this.visitFunctionParameterNode(node);
}
case nodes.NodeType.Declarations:
this.addScope(node);
return true;
case nodes.NodeType.For:
const forNode = node;
const scopeNode = forNode.getDeclarations();
if (scopeNode && forNode.variable) {
this.addSymbolToChildScope(scopeNode, forNode.variable, forNode.variable.getName(), void 0, nodes.ReferenceType.Variable);
}
return true;
case nodes.NodeType.Each: {
const eachNode = node;
const scopeNode = eachNode.getDeclarations();
if (scopeNode) {
const variables = eachNode.getVariables().getChildren();
for (const variable of variables) {
this.addSymbolToChildScope(scopeNode, variable, variable.getName(), void 0, nodes.ReferenceType.Variable);
}
}
return true;
}
}
return true;
}
visitRuleSet(node) {
const current = this.scope.findScope(node.offset, node.length);
if (current) {
for (const child of node.getSelectors().getChildren()) {
if (child instanceof nodes.Selector) {
if (child.getChildren().length === 1) { // only selectors with a single element can be extended
current.addSymbol(new Symbol(child.getChild(0).getText(), void 0, child, nodes.ReferenceType.Rule));
}
}
}
}
return true;
}
visitVariableDeclarationNode(node) {
const value = node.getValue() ? node.getValue().getText() : void 0;
this.addSymbol(node, node.getName(), value, nodes.ReferenceType.Variable);
return true;
}
visitFunctionParameterNode(node) {
// parameters are part of the body scope
const scopeNode = node.getParent().getDeclarations();
if (scopeNode) {
const valueNode = node.getDefaultValue();
const value = valueNode ? valueNode.getText() : void 0;
this.addSymbolToChildScope(scopeNode, node, node.getName(), value, nodes.ReferenceType.Variable);
}
return true;
}
visitCustomPropertyDeclarationNode(node) {
const value = node.getValue() ? node.getValue().getText() : '';
this.addCSSVariable(node.getProperty(), node.getProperty().getName(), value, nodes.ReferenceType.Variable);
return true;
}
addCSSVariable(node, name, value, type) {
if (node.offset !== -1) {
this.scope.addSymbol(new Symbol(name, value, node, type));
}
}
}
exports.ScopeBuilder = ScopeBuilder;
class Symbols {
constructor(node) {
this.global = new GlobalScope();
node.acceptVisitor(new ScopeBuilder(this.global));
}
findSymbolsAtOffset(offset, referenceType) {
let scope = this.global.findScope(offset, 0);
const result = [];
const names = {};
while (scope) {
const symbols = scope.getSymbols();
for (let i = 0; i < symbols.length; i++) {
const symbol = symbols[i];
if (symbol.type === referenceType && !names[symbol.name]) {
result.push(symbol);
names[symbol.name] = true;
}
}
scope = scope.parent;
}
return result;
}
internalFindSymbol(node, referenceTypes) {
let scopeNode = node;
if (node.parent instanceof nodes.FunctionParameter && node.parent.getParent() instanceof nodes.BodyDeclaration) {
scopeNode = node.parent.getParent().getDeclarations();
}
if (node.parent instanceof nodes.FunctionArgument && node.parent.getParent() instanceof nodes.Function) {
const funcId = node.parent.getParent().getIdentifier();
if (funcId) {
const functionSymbol = this.internalFindSymbol(funcId, [nodes.ReferenceType.Function]);
if (functionSymbol) {
scopeNode = functionSymbol.node.getDeclarations();
}
}
}
if (!scopeNode) {
return null;
}
const name = node.getText();
let scope = this.global.findScope(scopeNode.offset, scopeNode.length);
while (scope) {
for (let index = 0; index < referenceTypes.length; index++) {
const type = referenceTypes[index];
const symbol = scope.getSymbol(name, type);
if (symbol) {
return symbol;
}
}
scope = scope.parent;
}
return null;
}
evaluateReferenceTypes(node) {
if (node instanceof nodes.Identifier) {
const referenceTypes = node.referenceTypes;
if (referenceTypes) {
return referenceTypes;
}
else {
if (node.isCustomProperty) {
return [nodes.ReferenceType.Variable];
}
// are a reference to a keyframe?
const decl = nodes.getParentDeclaration(node);
if (decl) {
const propertyName = decl.getNonPrefixedPropertyName();
if ((propertyName === 'animation' || propertyName === 'animation-name')
&& decl.getValue() && decl.getValue().offset === node.offset) {
return [nodes.ReferenceType.Keyframe];
}
}
}
}
else if (node instanceof nodes.Variable) {
return [nodes.ReferenceType.Variable];
}
const selector = node.findAParent(nodes.NodeType.Selector, nodes.NodeType.ExtendsReference);
if (selector) {
return [nodes.ReferenceType.Rule];
}
return null;
}
findSymbolFromNode(node) {
if (!node) {
return null;
}
while (node.type === nodes.NodeType.Interpolation) {
node = node.getParent();
}
const referenceTypes = this.evaluateReferenceTypes(node);
if (referenceTypes) {
return this.internalFindSymbol(node, referenceTypes);
}
return null;
}
matchesSymbol(node, symbol) {
if (!node) {
return false;
}
while (node.type === nodes.NodeType.Interpolation) {
node = node.getParent();
}
if (!node.matches(symbol.name)) {
return false;
}
const referenceTypes = this.evaluateReferenceTypes(node);
if (!referenceTypes || referenceTypes.indexOf(symbol.type) === -1) {
return false;
}
const nodeSymbol = this.internalFindSymbol(node, referenceTypes);
return nodeSymbol === symbol;
}
findSymbol(name, type, offset) {
let scope = this.global.findScope(offset);
while (scope) {
const symbol = scope.getSymbol(name, type);
if (symbol) {
return symbol;
}
scope = scope.parent;
}
return null;
}
}
exports.Symbols = Symbols;
});

View file

@ -0,0 +1,729 @@
(function (factory) {
if (typeof module === "object" && typeof module.exports === "object") {
var v = factory(require, exports);
if (v !== undefined) module.exports = v;
}
else if (typeof define === "function" && define.amd) {
define(["require", "exports", "./lessScanner", "./cssScanner", "./cssParser", "./cssNodes", "./cssErrors"], factory);
}
})(function (require, exports) {
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
exports.LESSParser = void 0;
const lessScanner = require("./lessScanner");
const cssScanner_1 = require("./cssScanner");
const cssParser = require("./cssParser");
const nodes = require("./cssNodes");
const cssErrors_1 = require("./cssErrors");
/// <summary>
/// A parser for LESS
/// http://lesscss.org/
/// </summary>
class LESSParser extends cssParser.Parser {
constructor() {
super(new lessScanner.LESSScanner());
}
_parseStylesheetStatement(isNested = false) {
if (this.peek(cssScanner_1.TokenType.AtKeyword)) {
return this._parseVariableDeclaration()
|| this._parsePlugin()
|| super._parseStylesheetAtStatement(isNested);
}
return this._tryParseMixinDeclaration()
|| this._tryParseMixinReference()
|| this._parseFunction()
|| this._parseRuleset(true);
}
_parseImport() {
if (!this.peekKeyword('@import') && !this.peekKeyword('@import-once') /* deprecated in less 1.4.1 */) {
return null;
}
const node = this.create(nodes.Import);
this.consumeToken();
// less 1.4.1: @import (css) "lib"
if (this.accept(cssScanner_1.TokenType.ParenthesisL)) {
if (!this.accept(cssScanner_1.TokenType.Ident)) {
return this.finish(node, cssErrors_1.ParseError.IdentifierExpected, [cssScanner_1.TokenType.SemiColon]);
}
do {
if (!this.accept(cssScanner_1.TokenType.Comma)) {
break;
}
} while (this.accept(cssScanner_1.TokenType.Ident));
if (!this.accept(cssScanner_1.TokenType.ParenthesisR)) {
return this.finish(node, cssErrors_1.ParseError.RightParenthesisExpected, [cssScanner_1.TokenType.SemiColon]);
}
}
if (!node.addChild(this._parseURILiteral()) && !node.addChild(this._parseStringLiteral())) {
return this.finish(node, cssErrors_1.ParseError.URIOrStringExpected, [cssScanner_1.TokenType.SemiColon]);
}
if (!this.peek(cssScanner_1.TokenType.SemiColon) && !this.peek(cssScanner_1.TokenType.EOF)) {
node.setMedialist(this._parseMediaQueryList());
}
return this.finish(node);
}
_parsePlugin() {
if (!this.peekKeyword('@plugin')) {
return null;
}
const node = this.createNode(nodes.NodeType.Plugin);
this.consumeToken(); // @import
if (!node.addChild(this._parseStringLiteral())) {
return this.finish(node, cssErrors_1.ParseError.StringLiteralExpected);
}
if (!this.accept(cssScanner_1.TokenType.SemiColon)) {
return this.finish(node, cssErrors_1.ParseError.SemiColonExpected);
}
return this.finish(node);
}
_parseMediaQuery() {
const node = super._parseMediaQuery();
if (!node) {
const node = this.create(nodes.MediaQuery);
if (node.addChild(this._parseVariable())) {
return this.finish(node);
}
return null;
}
return node;
}
_parseMediaDeclaration(isNested = false) {
return this._tryParseRuleset(isNested)
|| this._tryToParseDeclaration()
|| this._tryParseMixinDeclaration()
|| this._tryParseMixinReference()
|| this._parseDetachedRuleSetMixin()
|| this._parseStylesheetStatement(isNested);
}
_parseMediaFeatureName() {
return this._parseIdent() || this._parseVariable();
}
_parseVariableDeclaration(panic = []) {
const node = this.create(nodes.VariableDeclaration);
const mark = this.mark();
if (!node.setVariable(this._parseVariable(true))) {
return null;
}
if (this.accept(cssScanner_1.TokenType.Colon)) {
if (this.prevToken) {
node.colonPosition = this.prevToken.offset;
}
if (node.setValue(this._parseDetachedRuleSet())) {
node.needsSemicolon = false;
}
else if (!node.setValue(this._parseExpr())) {
return this.finish(node, cssErrors_1.ParseError.VariableValueExpected, [], panic);
}
node.addChild(this._parsePrio());
}
else {
this.restoreAtMark(mark);
return null; // at keyword, but no ':', not a variable declaration but some at keyword
}
if (this.peek(cssScanner_1.TokenType.SemiColon)) {
node.semicolonPosition = this.token.offset; // not part of the declaration, but useful information for code assist
}
return this.finish(node);
}
_parseDetachedRuleSet() {
let mark = this.mark();
// "Anonymous mixin" used in each() and possibly a generic type in the future
if (this.peekDelim('#') || this.peekDelim('.')) {
this.consumeToken();
if (!this.hasWhitespace() && this.accept(cssScanner_1.TokenType.ParenthesisL)) {
let node = this.create(nodes.MixinDeclaration);
if (node.getParameters().addChild(this._parseMixinParameter())) {
while (this.accept(cssScanner_1.TokenType.Comma) || this.accept(cssScanner_1.TokenType.SemiColon)) {
if (this.peek(cssScanner_1.TokenType.ParenthesisR)) {
break;
}
if (!node.getParameters().addChild(this._parseMixinParameter())) {
this.markError(node, cssErrors_1.ParseError.IdentifierExpected, [], [cssScanner_1.TokenType.ParenthesisR]);
}
}
}
if (!this.accept(cssScanner_1.TokenType.ParenthesisR)) {
this.restoreAtMark(mark);
return null;
}
}
else {
this.restoreAtMark(mark);
return null;
}
}
if (!this.peek(cssScanner_1.TokenType.CurlyL)) {
return null;
}
const content = this.create(nodes.BodyDeclaration);
this._parseBody(content, this._parseDetachedRuleSetBody.bind(this));
return this.finish(content);
}
_parseDetachedRuleSetBody() {
return this._tryParseKeyframeSelector() || this._parseRuleSetDeclaration();
}
_addLookupChildren(node) {
if (!node.addChild(this._parseLookupValue())) {
return false;
}
let expectsValue = false;
while (true) {
if (this.peek(cssScanner_1.TokenType.BracketL)) {
expectsValue = true;
}
if (!node.addChild(this._parseLookupValue())) {
break;
}
expectsValue = false;
}
return !expectsValue;
}
_parseLookupValue() {
const node = this.create(nodes.Node);
const mark = this.mark();
if (!this.accept(cssScanner_1.TokenType.BracketL)) {
this.restoreAtMark(mark);
return null;
}
if (((node.addChild(this._parseVariable(false, true)) ||
node.addChild(this._parsePropertyIdentifier())) &&
this.accept(cssScanner_1.TokenType.BracketR)) || this.accept(cssScanner_1.TokenType.BracketR)) {
return node;
}
this.restoreAtMark(mark);
return null;
}
_parseVariable(declaration = false, insideLookup = false) {
const isPropertyReference = !declaration && this.peekDelim('$');
if (!this.peekDelim('@') && !isPropertyReference && !this.peek(cssScanner_1.TokenType.AtKeyword)) {
return null;
}
const node = this.create(nodes.Variable);
const mark = this.mark();
while (this.acceptDelim('@') || (!declaration && this.acceptDelim('$'))) {
if (this.hasWhitespace()) {
this.restoreAtMark(mark);
return null;
}
}
if (!this.accept(cssScanner_1.TokenType.AtKeyword) && !this.accept(cssScanner_1.TokenType.Ident)) {
this.restoreAtMark(mark);
return null;
}
if (!insideLookup && this.peek(cssScanner_1.TokenType.BracketL)) {
if (!this._addLookupChildren(node)) {
this.restoreAtMark(mark);
return null;
}
}
return node;
}
_parseTermExpression() {
return this._parseVariable() ||
this._parseEscaped() ||
super._parseTermExpression() || // preference for colors before mixin references
this._tryParseMixinReference(false);
}
_parseEscaped() {
if (this.peek(cssScanner_1.TokenType.EscapedJavaScript) ||
this.peek(cssScanner_1.TokenType.BadEscapedJavaScript)) {
const node = this.createNode(nodes.NodeType.EscapedValue);
this.consumeToken();
return this.finish(node);
}
if (this.peekDelim('~')) {
const node = this.createNode(nodes.NodeType.EscapedValue);
this.consumeToken();
if (this.accept(cssScanner_1.TokenType.String) || this.accept(cssScanner_1.TokenType.EscapedJavaScript)) {
return this.finish(node);
}
else {
return this.finish(node, cssErrors_1.ParseError.TermExpected);
}
}
return null;
}
_parseOperator() {
const node = this._parseGuardOperator();
if (node) {
return node;
}
else {
return super._parseOperator();
}
}
_parseGuardOperator() {
if (this.peekDelim('>')) {
const node = this.createNode(nodes.NodeType.Operator);
this.consumeToken();
this.acceptDelim('=');
return node;
}
else if (this.peekDelim('=')) {
const node = this.createNode(nodes.NodeType.Operator);
this.consumeToken();
this.acceptDelim('<');
return node;
}
else if (this.peekDelim('<')) {
const node = this.createNode(nodes.NodeType.Operator);
this.consumeToken();
this.acceptDelim('=');
return node;
}
return null;
}
_parseRuleSetDeclaration() {
if (this.peek(cssScanner_1.TokenType.AtKeyword)) {
return this._parseKeyframe()
|| this._parseMedia(true)
|| this._parseImport()
|| this._parseSupports(true) // @supports
|| this._parseLayer() // @layer
|| this._parsePropertyAtRule() // @property
|| this._parseDetachedRuleSetMixin() // less detached ruleset mixin
|| this._parseVariableDeclaration() // Variable declarations
|| this._parseRuleSetDeclarationAtStatement();
}
return this._tryParseMixinDeclaration()
|| this._tryParseRuleset(true) // nested ruleset
|| this._tryParseMixinReference() // less mixin reference
|| this._parseFunction()
|| this._parseExtend() // less extend declaration
|| this._parseDeclaration(); // try css ruleset declaration as the last option
}
_parseKeyframeIdent() {
return this._parseIdent([nodes.ReferenceType.Keyframe]) || this._parseVariable();
}
_parseKeyframeSelector() {
return this._parseDetachedRuleSetMixin() // less detached ruleset mixin
|| super._parseKeyframeSelector();
}
// public _parseSimpleSelectorBody(): nodes.Node | null {
// return this._parseNestingSelector() || super._parseSimpleSelectorBody();
// }
_parseSelector(isNested) {
// CSS Guards
const node = this.create(nodes.Selector);
let hasContent = false;
if (isNested) {
// nested selectors can start with a combinator
hasContent = node.addChild(this._parseCombinator());
}
while (node.addChild(this._parseSimpleSelector())) {
hasContent = true;
const mark = this.mark();
if (node.addChild(this._parseGuard()) && this.peek(cssScanner_1.TokenType.CurlyL)) {
break;
}
this.restoreAtMark(mark);
node.addChild(this._parseCombinator()); // optional
}
return hasContent ? this.finish(node) : null;
}
_parseNestingSelector() {
if (this.peekDelim('&')) {
const node = this.createNode(nodes.NodeType.SelectorCombinator);
this.consumeToken();
while (!this.hasWhitespace() && (this.acceptDelim('-') || this.accept(cssScanner_1.TokenType.Num) || this.accept(cssScanner_1.TokenType.Dimension) || node.addChild(this._parseIdent()) || this.acceptDelim('&'))) {
// support &-foo
}
return this.finish(node);
}
return null;
}
_parseSelectorIdent() {
if (!this.peekInterpolatedIdent()) {
return null;
}
const node = this.createNode(nodes.NodeType.SelectorInterpolation);
const hasContent = this._acceptInterpolatedIdent(node);
return hasContent ? this.finish(node) : null;
}
_parsePropertyIdentifier(inLookup = false) {
const propertyRegex = /^[\w-]+/;
if (!this.peekInterpolatedIdent() && !this.peekRegExp(this.token.type, propertyRegex)) {
return null;
}
const mark = this.mark();
const node = this.create(nodes.Identifier);
node.isCustomProperty = this.acceptDelim('-') && this.acceptDelim('-');
let childAdded = false;
if (!inLookup) {
if (node.isCustomProperty) {
childAdded = this._acceptInterpolatedIdent(node);
}
else {
childAdded = this._acceptInterpolatedIdent(node, propertyRegex);
}
}
else {
if (node.isCustomProperty) {
childAdded = node.addChild(this._parseIdent());
}
else {
childAdded = node.addChild(this._parseRegexp(propertyRegex));
}
}
if (!childAdded) {
this.restoreAtMark(mark);
return null;
}
if (!inLookup && !this.hasWhitespace()) {
this.acceptDelim('+');
if (!this.hasWhitespace()) {
this.acceptIdent('_');
}
}
return this.finish(node);
}
peekInterpolatedIdent() {
return this.peek(cssScanner_1.TokenType.Ident) ||
this.peekDelim('@') ||
this.peekDelim('$') ||
this.peekDelim('-');
}
_acceptInterpolatedIdent(node, identRegex) {
let hasContent = false;
const indentInterpolation = () => {
const pos = this.mark();
if (this.acceptDelim('-')) {
if (!this.hasWhitespace()) {
this.acceptDelim('-');
}
if (this.hasWhitespace()) {
this.restoreAtMark(pos);
return null;
}
}
return this._parseInterpolation();
};
const accept = identRegex ?
() => this.acceptRegexp(identRegex) :
() => this.accept(cssScanner_1.TokenType.Ident);
while (accept() ||
node.addChild(this._parseInterpolation() ||
this.try(indentInterpolation))) {
hasContent = true;
if (this.hasWhitespace()) {
break;
}
}
return hasContent;
}
_parseInterpolation() {
// @{name} Variable or
// ${name} Property
const mark = this.mark();
if (this.peekDelim('@') || this.peekDelim('$')) {
const node = this.createNode(nodes.NodeType.Interpolation);
this.consumeToken();
if (this.hasWhitespace() || !this.accept(cssScanner_1.TokenType.CurlyL)) {
this.restoreAtMark(mark);
return null;
}
if (!node.addChild(this._parseIdent())) {
return this.finish(node, cssErrors_1.ParseError.IdentifierExpected);
}
if (!this.accept(cssScanner_1.TokenType.CurlyR)) {
return this.finish(node, cssErrors_1.ParseError.RightCurlyExpected);
}
return this.finish(node);
}
return null;
}
_tryParseMixinDeclaration() {
const mark = this.mark();
const node = this.create(nodes.MixinDeclaration);
if (!node.setIdentifier(this._parseMixinDeclarationIdentifier()) || !this.accept(cssScanner_1.TokenType.ParenthesisL)) {
this.restoreAtMark(mark);
return null;
}
if (node.getParameters().addChild(this._parseMixinParameter())) {
while (this.accept(cssScanner_1.TokenType.Comma) || this.accept(cssScanner_1.TokenType.SemiColon)) {
if (this.peek(cssScanner_1.TokenType.ParenthesisR)) {
break;
}
if (!node.getParameters().addChild(this._parseMixinParameter())) {
this.markError(node, cssErrors_1.ParseError.IdentifierExpected, [], [cssScanner_1.TokenType.ParenthesisR]);
}
}
}
if (!this.accept(cssScanner_1.TokenType.ParenthesisR)) {
this.restoreAtMark(mark);
return null;
}
node.setGuard(this._parseGuard());
if (!this.peek(cssScanner_1.TokenType.CurlyL)) {
this.restoreAtMark(mark);
return null;
}
return this._parseBody(node, this._parseMixInBodyDeclaration.bind(this));
}
_parseMixInBodyDeclaration() {
return this._parseFontFace() || this._parseRuleSetDeclaration();
}
_parseMixinDeclarationIdentifier() {
let identifier;
if (this.peekDelim('#') || this.peekDelim('.')) {
identifier = this.create(nodes.Identifier);
this.consumeToken(); // # or .
if (this.hasWhitespace() || !identifier.addChild(this._parseIdent())) {
return null;
}
}
else if (this.peek(cssScanner_1.TokenType.Hash)) {
identifier = this.create(nodes.Identifier);
this.consumeToken(); // TokenType.Hash
}
else {
return null;
}
identifier.referenceTypes = [nodes.ReferenceType.Mixin];
return this.finish(identifier);
}
_parsePseudo() {
if (!this.peek(cssScanner_1.TokenType.Colon)) {
return null;
}
const mark = this.mark();
const node = this.create(nodes.ExtendsReference);
this.consumeToken(); // :
if (this.acceptIdent('extend')) {
return this._completeExtends(node);
}
this.restoreAtMark(mark);
return super._parsePseudo();
}
_parseExtend() {
if (!this.peekDelim('&')) {
return null;
}
const mark = this.mark();
const node = this.create(nodes.ExtendsReference);
this.consumeToken(); // &
if (this.hasWhitespace() || !this.accept(cssScanner_1.TokenType.Colon) || !this.acceptIdent('extend')) {
this.restoreAtMark(mark);
return null;
}
return this._completeExtends(node);
}
_completeExtends(node) {
if (!this.accept(cssScanner_1.TokenType.ParenthesisL)) {
return this.finish(node, cssErrors_1.ParseError.LeftParenthesisExpected);
}
const selectors = node.getSelectors();
if (!selectors.addChild(this._parseSelector(true))) {
return this.finish(node, cssErrors_1.ParseError.SelectorExpected);
}
while (this.accept(cssScanner_1.TokenType.Comma)) {
if (!selectors.addChild(this._parseSelector(true))) {
return this.finish(node, cssErrors_1.ParseError.SelectorExpected);
}
}
if (!this.accept(cssScanner_1.TokenType.ParenthesisR)) {
return this.finish(node, cssErrors_1.ParseError.RightParenthesisExpected);
}
return this.finish(node);
}
_parseDetachedRuleSetMixin() {
if (!this.peek(cssScanner_1.TokenType.AtKeyword)) {
return null;
}
const mark = this.mark();
const node = this.create(nodes.MixinReference);
if (node.addChild(this._parseVariable(true)) && (this.hasWhitespace() || !this.accept(cssScanner_1.TokenType.ParenthesisL))) {
this.restoreAtMark(mark);
return null;
}
if (!this.accept(cssScanner_1.TokenType.ParenthesisR)) {
return this.finish(node, cssErrors_1.ParseError.RightParenthesisExpected);
}
return this.finish(node);
}
_tryParseMixinReference(atRoot = true) {
const mark = this.mark();
const node = this.create(nodes.MixinReference);
let identifier = this._parseMixinDeclarationIdentifier();
while (identifier) {
this.acceptDelim('>');
const nextId = this._parseMixinDeclarationIdentifier();
if (nextId) {
node.getNamespaces().addChild(identifier);
identifier = nextId;
}
else {
break;
}
}
if (!node.setIdentifier(identifier)) {
this.restoreAtMark(mark);
return null;
}
let hasArguments = false;
if (this.accept(cssScanner_1.TokenType.ParenthesisL)) {
hasArguments = true;
if (node.getArguments().addChild(this._parseMixinArgument())) {
while (this.accept(cssScanner_1.TokenType.Comma) || this.accept(cssScanner_1.TokenType.SemiColon)) {
if (this.peek(cssScanner_1.TokenType.ParenthesisR)) {
break;
}
if (!node.getArguments().addChild(this._parseMixinArgument())) {
return this.finish(node, cssErrors_1.ParseError.ExpressionExpected);
}
}
}
if (!this.accept(cssScanner_1.TokenType.ParenthesisR)) {
return this.finish(node, cssErrors_1.ParseError.RightParenthesisExpected);
}
identifier.referenceTypes = [nodes.ReferenceType.Mixin];
}
else {
identifier.referenceTypes = [nodes.ReferenceType.Mixin, nodes.ReferenceType.Rule];
}
if (this.peek(cssScanner_1.TokenType.BracketL)) {
if (!atRoot) {
this._addLookupChildren(node);
}
}
else {
node.addChild(this._parsePrio());
}
if (!hasArguments && !this.peek(cssScanner_1.TokenType.SemiColon) && !this.peek(cssScanner_1.TokenType.CurlyR) && !this.peek(cssScanner_1.TokenType.EOF)) {
this.restoreAtMark(mark);
return null;
}
return this.finish(node);
}
_parseMixinArgument() {
// [variableName ':'] expression | variableName '...'
const node = this.create(nodes.FunctionArgument);
const pos = this.mark();
const argument = this._parseVariable();
if (argument) {
if (!this.accept(cssScanner_1.TokenType.Colon)) {
this.restoreAtMark(pos);
}
else {
node.setIdentifier(argument);
}
}
if (node.setValue(this._parseDetachedRuleSet() || this._parseExpr(true))) {
return this.finish(node);
}
this.restoreAtMark(pos);
return null;
}
_parseMixinParameter() {
const node = this.create(nodes.FunctionParameter);
// special rest variable: @rest...
if (this.peekKeyword('@rest')) {
const restNode = this.create(nodes.Node);
this.consumeToken();
if (!this.accept(lessScanner.Ellipsis)) {
return this.finish(node, cssErrors_1.ParseError.DotExpected, [], [cssScanner_1.TokenType.Comma, cssScanner_1.TokenType.ParenthesisR]);
}
node.setIdentifier(this.finish(restNode));
return this.finish(node);
}
// special const args: ...
if (this.peek(lessScanner.Ellipsis)) {
const varargsNode = this.create(nodes.Node);
this.consumeToken();
node.setIdentifier(this.finish(varargsNode));
return this.finish(node);
}
let hasContent = false;
// default variable declaration: @param: 12 or @name
if (node.setIdentifier(this._parseVariable())) {
this.accept(cssScanner_1.TokenType.Colon);
hasContent = true;
}
if (!node.setDefaultValue(this._parseDetachedRuleSet() || this._parseExpr(true)) && !hasContent) {
return null;
}
return this.finish(node);
}
_parseGuard() {
if (!this.peekIdent('when')) {
return null;
}
const node = this.create(nodes.LessGuard);
this.consumeToken(); // when
node.isNegated = this.acceptIdent('not');
if (!node.getConditions().addChild(this._parseGuardCondition())) {
return this.finish(node, cssErrors_1.ParseError.ConditionExpected);
}
while (this.acceptIdent('and') || this.accept(cssScanner_1.TokenType.Comma)) {
if (!node.getConditions().addChild(this._parseGuardCondition())) {
return this.finish(node, cssErrors_1.ParseError.ConditionExpected);
}
}
return this.finish(node);
}
_parseGuardCondition() {
if (!this.peek(cssScanner_1.TokenType.ParenthesisL)) {
return null;
}
const node = this.create(nodes.GuardCondition);
this.consumeToken(); // ParenthesisL
if (!node.addChild(this._parseExpr())) {
// empty (?)
}
if (!this.accept(cssScanner_1.TokenType.ParenthesisR)) {
return this.finish(node, cssErrors_1.ParseError.RightParenthesisExpected);
}
return this.finish(node);
}
_parseFunction() {
const pos = this.mark();
const node = this.create(nodes.Function);
if (!node.setIdentifier(this._parseFunctionIdentifier())) {
return null;
}
if (this.hasWhitespace() || !this.accept(cssScanner_1.TokenType.ParenthesisL)) {
this.restoreAtMark(pos);
return null;
}
if (node.getArguments().addChild(this._parseMixinArgument())) {
while (this.accept(cssScanner_1.TokenType.Comma) || this.accept(cssScanner_1.TokenType.SemiColon)) {
if (this.peek(cssScanner_1.TokenType.ParenthesisR)) {
break;
}
if (!node.getArguments().addChild(this._parseMixinArgument())) {
return this.finish(node, cssErrors_1.ParseError.ExpressionExpected);
}
}
}
if (!this.accept(cssScanner_1.TokenType.ParenthesisR)) {
return this.finish(node, cssErrors_1.ParseError.RightParenthesisExpected);
}
return this.finish(node);
}
_parseFunctionIdentifier() {
if (this.peekDelim('%')) {
const node = this.create(nodes.Identifier);
node.referenceTypes = [nodes.ReferenceType.Function];
this.consumeToken();
return this.finish(node);
}
return super._parseFunctionIdentifier();
}
_parseURLArgument() {
const pos = this.mark();
const node = super._parseURLArgument();
if (!node || !this.peek(cssScanner_1.TokenType.ParenthesisR)) {
this.restoreAtMark(pos);
const node = this.create(nodes.Node);
node.addChild(this._parseBinaryExpr());
return this.finish(node);
}
return node;
}
}
exports.LESSParser = LESSParser;
});

View file

@ -0,0 +1,70 @@
(function (factory) {
if (typeof module === "object" && typeof module.exports === "object") {
var v = factory(require, exports);
if (v !== undefined) module.exports = v;
}
else if (typeof define === "function" && define.amd) {
define(["require", "exports", "./cssScanner"], factory);
}
})(function (require, exports) {
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
exports.LESSScanner = exports.Ellipsis = void 0;
const scanner = require("./cssScanner");
const _FSL = '/'.charCodeAt(0);
const _NWL = '\n'.charCodeAt(0);
const _CAR = '\r'.charCodeAt(0);
const _LFD = '\f'.charCodeAt(0);
const _TIC = '`'.charCodeAt(0);
const _DOT = '.'.charCodeAt(0);
let customTokenValue = scanner.TokenType.CustomToken;
exports.Ellipsis = customTokenValue++;
class LESSScanner extends scanner.Scanner {
scanNext(offset) {
// LESS: escaped JavaScript code `const a = "dddd"`
const tokenType = this.escapedJavaScript();
if (tokenType !== null) {
return this.finishToken(offset, tokenType);
}
if (this.stream.advanceIfChars([_DOT, _DOT, _DOT])) {
return this.finishToken(offset, exports.Ellipsis);
}
return super.scanNext(offset);
}
comment() {
if (super.comment()) {
return true;
}
if (!this.inURL && this.stream.advanceIfChars([_FSL, _FSL])) {
this.stream.advanceWhileChar((ch) => {
switch (ch) {
case _NWL:
case _CAR:
case _LFD:
return false;
default:
return true;
}
});
return true;
}
else {
return false;
}
}
escapedJavaScript() {
const ch = this.stream.peekChar();
if (ch === _TIC) {
this.stream.advance(1);
this.stream.advanceWhileChar((ch) => { return ch !== _TIC; });
return this.stream.advanceIfChar(_TIC) ? scanner.TokenType.EscapedJavaScript : scanner.TokenType.BadEscapedJavaScript;
}
return null;
}
}
exports.LESSScanner = LESSScanner;
});

View file

@ -0,0 +1,30 @@
(function (factory) {
if (typeof module === "object" && typeof module.exports === "object") {
var v = factory(require, exports);
if (v !== undefined) module.exports = v;
}
else if (typeof define === "function" && define.amd) {
define(["require", "exports", "@vscode/l10n"], factory);
}
})(function (require, exports) {
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
exports.SCSSParseError = exports.SCSSIssueType = void 0;
const l10n = require("@vscode/l10n");
class SCSSIssueType {
constructor(id, message) {
this.id = id;
this.message = message;
}
}
exports.SCSSIssueType = SCSSIssueType;
exports.SCSSParseError = {
FromExpected: new SCSSIssueType('scss-fromexpected', l10n.t("'from' expected")),
ThroughOrToExpected: new SCSSIssueType('scss-throughexpected', l10n.t("'through' or 'to' expected")),
InExpected: new SCSSIssueType('scss-fromexpected', l10n.t("'in' expected")),
};
});

View file

@ -0,0 +1,823 @@
(function (factory) {
if (typeof module === "object" && typeof module.exports === "object") {
var v = factory(require, exports);
if (v !== undefined) module.exports = v;
}
else if (typeof define === "function" && define.amd) {
define(["require", "exports", "./scssScanner", "./cssScanner", "./cssParser", "./cssNodes", "./scssErrors", "./cssErrors"], factory);
}
})(function (require, exports) {
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
exports.SCSSParser = void 0;
const scssScanner = require("./scssScanner");
const cssScanner_1 = require("./cssScanner");
const cssParser = require("./cssParser");
const nodes = require("./cssNodes");
const scssErrors_1 = require("./scssErrors");
const cssErrors_1 = require("./cssErrors");
/// <summary>
/// A parser for scss
/// http://sass-lang.com/documentation/file.SASS_REFERENCE.html
/// </summary>
class SCSSParser extends cssParser.Parser {
constructor() {
super(new scssScanner.SCSSScanner());
}
_parseStylesheetStatement(isNested = false) {
if (this.peek(cssScanner_1.TokenType.AtKeyword)) {
return this._parseWarnAndDebug() // @warn, @debug and @error statements
|| this._parseControlStatement() // @if, @while, @for, @each
|| this._parseMixinDeclaration() // @mixin
|| this._parseMixinContent() // @content
|| this._parseMixinReference() // @include
|| this._parseFunctionDeclaration() // @function
|| this._parseForward() // @forward
|| this._parseUse() // @use
|| this._parseRuleset(isNested) // @at-rule
|| super._parseStylesheetAtStatement(isNested);
}
return this._parseRuleset(true) || this._parseVariableDeclaration();
}
_parseImport() {
if (!this.peekKeyword('@import')) {
return null;
}
const node = this.create(nodes.Import);
this.consumeToken();
if (!node.addChild(this._parseURILiteral()) && !node.addChild(this._parseStringLiteral())) {
return this.finish(node, cssErrors_1.ParseError.URIOrStringExpected);
}
while (this.accept(cssScanner_1.TokenType.Comma)) {
if (!node.addChild(this._parseURILiteral()) && !node.addChild(this._parseStringLiteral())) {
return this.finish(node, cssErrors_1.ParseError.URIOrStringExpected);
}
}
if (!this.peek(cssScanner_1.TokenType.SemiColon) && !this.peek(cssScanner_1.TokenType.EOF)) {
node.setMedialist(this._parseMediaQueryList());
}
return this.finish(node);
}
// scss variables: $font-size: 12px;
_parseVariableDeclaration(panic = []) {
if (!this.peek(scssScanner.VariableName)) {
return null;
}
const node = this.create(nodes.VariableDeclaration);
if (!node.setVariable(this._parseVariable())) {
return null;
}
if (!this.accept(cssScanner_1.TokenType.Colon)) {
return this.finish(node, cssErrors_1.ParseError.ColonExpected);
}
if (this.prevToken) {
node.colonPosition = this.prevToken.offset;
}
if (!node.setValue(this._parseExpr())) {
return this.finish(node, cssErrors_1.ParseError.VariableValueExpected, [], panic);
}
while (this.peek(cssScanner_1.TokenType.Exclamation)) {
if (node.addChild(this._tryParsePrio())) {
// !important
}
else {
this.consumeToken();
if (!this.peekRegExp(cssScanner_1.TokenType.Ident, /^(default|global)$/)) {
return this.finish(node, cssErrors_1.ParseError.UnknownKeyword);
}
this.consumeToken();
}
}
if (this.peek(cssScanner_1.TokenType.SemiColon)) {
node.semicolonPosition = this.token.offset; // not part of the declaration, but useful information for code assist
}
return this.finish(node);
}
_parseMediaCondition() {
return this._parseInterpolation() || super._parseMediaCondition();
}
_parseMediaFeatureRangeOperator() {
return this.accept(scssScanner.SmallerEqualsOperator) || this.accept(scssScanner.GreaterEqualsOperator) || super._parseMediaFeatureRangeOperator();
}
_parseMediaFeatureName() {
return this._parseModuleMember()
|| this._parseFunction() // function before ident
|| this._parseIdent()
|| this._parseVariable();
}
_parseKeyframeSelector() {
return this._tryParseKeyframeSelector()
|| this._parseControlStatement(this._parseKeyframeSelector.bind(this))
|| this._parseVariableDeclaration()
|| this._parseMixinContent();
}
_parseVariable() {
if (!this.peek(scssScanner.VariableName)) {
return null;
}
const node = this.create(nodes.Variable);
this.consumeToken();
return node;
}
_parseModuleMember() {
const pos = this.mark();
const node = this.create(nodes.Module);
if (!node.setIdentifier(this._parseIdent([nodes.ReferenceType.Module]))) {
return null;
}
if (this.hasWhitespace()
|| !this.acceptDelim('.')
|| this.hasWhitespace()) {
this.restoreAtMark(pos);
return null;
}
if (!node.addChild(this._parseVariable() || this._parseFunction())) {
return this.finish(node, cssErrors_1.ParseError.IdentifierOrVariableExpected);
}
return node;
}
_parseIdent(referenceTypes) {
if (!this.peek(cssScanner_1.TokenType.Ident) && !this.peek(scssScanner.InterpolationFunction) && !this.peekDelim('-')) {
return null;
}
const node = this.create(nodes.Identifier);
node.referenceTypes = referenceTypes;
node.isCustomProperty = this.peekRegExp(cssScanner_1.TokenType.Ident, /^--/);
let hasContent = false;
const indentInterpolation = () => {
const pos = this.mark();
if (this.acceptDelim('-')) {
if (!this.hasWhitespace()) {
this.acceptDelim('-');
}
if (this.hasWhitespace()) {
this.restoreAtMark(pos);
return null;
}
}
return this._parseInterpolation();
};
while (this.accept(cssScanner_1.TokenType.Ident) || node.addChild(indentInterpolation()) || (hasContent && this.acceptRegexp(/^[\w-]/))) {
hasContent = true;
if (this.hasWhitespace()) {
break;
}
}
return hasContent ? this.finish(node) : null;
}
_parseTermExpression() {
return this._parseModuleMember() ||
this._parseVariable() ||
this._parseNestingSelector() ||
//this._tryParsePrio() ||
super._parseTermExpression();
}
_parseInterpolation() {
if (this.peek(scssScanner.InterpolationFunction)) {
const node = this.create(nodes.Interpolation);
this.consumeToken();
if (!node.addChild(this._parseExpr()) && !this._parseNestingSelector()) {
if (this.accept(cssScanner_1.TokenType.CurlyR)) {
return this.finish(node);
}
return this.finish(node, cssErrors_1.ParseError.ExpressionExpected);
}
if (!this.accept(cssScanner_1.TokenType.CurlyR)) {
return this.finish(node, cssErrors_1.ParseError.RightCurlyExpected);
}
return this.finish(node);
}
return null;
}
_parseOperator() {
if (this.peek(scssScanner.EqualsOperator) || this.peek(scssScanner.NotEqualsOperator)
|| this.peek(scssScanner.GreaterEqualsOperator) || this.peek(scssScanner.SmallerEqualsOperator)
|| this.peekDelim('>') || this.peekDelim('<')
|| this.peekIdent('and') || this.peekIdent('or')
|| this.peekDelim('%')) {
const node = this.createNode(nodes.NodeType.Operator);
this.consumeToken();
return this.finish(node);
}
return super._parseOperator();
}
_parseUnaryOperator() {
if (this.peekIdent('not')) {
const node = this.create(nodes.Node);
this.consumeToken();
return this.finish(node);
}
return super._parseUnaryOperator();
}
_parseRuleSetDeclaration() {
if (this.peek(cssScanner_1.TokenType.AtKeyword)) {
return this._parseKeyframe() // nested @keyframe
|| this._parseImport() // nested @import
|| this._parseMedia(true) // nested @media
|| this._parseFontFace() // nested @font-face
|| this._parseWarnAndDebug() // @warn, @debug and @error statements
|| this._parseControlStatement() // @if, @while, @for, @each
|| this._parseFunctionDeclaration() // @function
|| this._parseExtends() // @extends
|| this._parseMixinReference() // @include
|| this._parseMixinContent() // @content
|| this._parseMixinDeclaration() // nested @mixin
|| this._parseRuleset(true) // @at-rule
|| this._parseSupports(true) // @supports
|| this._parseLayer() // @layer
|| this._parsePropertyAtRule() // @property
|| this._parseRuleSetDeclarationAtStatement();
}
return this._parseVariableDeclaration() // variable declaration
|| this._tryParseRuleset(true) // nested ruleset
|| this._parseDeclaration(); // try css ruleset declaration as last so in the error case, the ast will contain a declaration
}
_parseDeclaration(stopTokens) {
const custonProperty = this._tryParseCustomPropertyDeclaration(stopTokens);
if (custonProperty) {
return custonProperty;
}
const node = this.create(nodes.Declaration);
if (!node.setProperty(this._parseProperty())) {
return null;
}
if (!this.accept(cssScanner_1.TokenType.Colon)) {
return this.finish(node, cssErrors_1.ParseError.ColonExpected, [cssScanner_1.TokenType.Colon], stopTokens || [cssScanner_1.TokenType.SemiColon]);
}
if (this.prevToken) {
node.colonPosition = this.prevToken.offset;
}
let hasContent = false;
if (node.setValue(this._parseExpr())) {
hasContent = true;
node.addChild(this._parsePrio());
}
if (this.peek(cssScanner_1.TokenType.CurlyL)) {
node.setNestedProperties(this._parseNestedProperties());
}
else {
if (!hasContent) {
return this.finish(node, cssErrors_1.ParseError.PropertyValueExpected);
}
}
if (this.peek(cssScanner_1.TokenType.SemiColon)) {
node.semicolonPosition = this.token.offset; // not part of the declaration, but useful information for code assist
}
return this.finish(node);
}
_parseNestedProperties() {
const node = this.create(nodes.NestedProperties);
return this._parseBody(node, this._parseDeclaration.bind(this));
}
_parseExtends() {
if (this.peekKeyword('@extend')) {
const node = this.create(nodes.ExtendsReference);
this.consumeToken();
if (!node.getSelectors().addChild(this._parseSimpleSelector())) {
return this.finish(node, cssErrors_1.ParseError.SelectorExpected);
}
while (this.accept(cssScanner_1.TokenType.Comma)) {
node.getSelectors().addChild(this._parseSimpleSelector());
}
if (this.accept(cssScanner_1.TokenType.Exclamation)) {
if (!this.acceptIdent('optional')) {
return this.finish(node, cssErrors_1.ParseError.UnknownKeyword);
}
}
return this.finish(node);
}
return null;
}
_parseSimpleSelectorBody() {
return this._parseSelectorPlaceholder() || super._parseSimpleSelectorBody();
}
_parseNestingSelector() {
if (this.peekDelim('&')) {
const node = this.createNode(nodes.NodeType.SelectorCombinator);
this.consumeToken();
while (!this.hasWhitespace() && (this.acceptDelim('-') || this.accept(cssScanner_1.TokenType.Num) || this.accept(cssScanner_1.TokenType.Dimension) || node.addChild(this._parseIdent()) || this.acceptDelim('&'))) {
// support &-foo-1
}
return this.finish(node);
}
return null;
}
_parseSelectorPlaceholder() {
if (this.peekDelim('%')) {
const node = this.createNode(nodes.NodeType.SelectorPlaceholder);
this.consumeToken();
this._parseIdent();
return this.finish(node);
}
else if (this.peekKeyword('@at-root')) {
const node = this.createNode(nodes.NodeType.SelectorPlaceholder);
this.consumeToken();
if (this.accept(cssScanner_1.TokenType.ParenthesisL)) {
if (!this.acceptIdent('with') && !this.acceptIdent('without')) {
return this.finish(node, cssErrors_1.ParseError.IdentifierExpected);
}
if (!this.accept(cssScanner_1.TokenType.Colon)) {
return this.finish(node, cssErrors_1.ParseError.ColonExpected);
}
if (!node.addChild(this._parseIdent())) {
return this.finish(node, cssErrors_1.ParseError.IdentifierExpected);
}
if (!this.accept(cssScanner_1.TokenType.ParenthesisR)) {
return this.finish(node, cssErrors_1.ParseError.RightParenthesisExpected, [cssScanner_1.TokenType.CurlyR]);
}
}
return this.finish(node);
}
return null;
}
_parseElementName() {
const pos = this.mark();
const node = super._parseElementName();
if (node && !this.hasWhitespace() && this.peek(cssScanner_1.TokenType.ParenthesisL)) { // for #49589
this.restoreAtMark(pos);
return null;
}
return node;
}
_tryParsePseudoIdentifier() {
return this._parseInterpolation() || super._tryParsePseudoIdentifier(); // for #49589
}
_parseWarnAndDebug() {
if (!this.peekKeyword('@debug')
&& !this.peekKeyword('@warn')
&& !this.peekKeyword('@error')) {
return null;
}
const node = this.createNode(nodes.NodeType.Debug);
this.consumeToken(); // @debug, @warn or @error
node.addChild(this._parseExpr()); // optional
return this.finish(node);
}
_parseControlStatement(parseStatement = this._parseRuleSetDeclaration.bind(this)) {
if (!this.peek(cssScanner_1.TokenType.AtKeyword)) {
return null;
}
return this._parseIfStatement(parseStatement) || this._parseForStatement(parseStatement)
|| this._parseEachStatement(parseStatement) || this._parseWhileStatement(parseStatement);
}
_parseIfStatement(parseStatement) {
if (!this.peekKeyword('@if')) {
return null;
}
return this._internalParseIfStatement(parseStatement);
}
_internalParseIfStatement(parseStatement) {
const node = this.create(nodes.IfStatement);
this.consumeToken(); // @if or if
if (!node.setExpression(this._parseExpr(true))) {
return this.finish(node, cssErrors_1.ParseError.ExpressionExpected);
}
this._parseBody(node, parseStatement);
if (this.acceptKeyword('@else')) {
if (this.peekIdent('if')) {
node.setElseClause(this._internalParseIfStatement(parseStatement));
}
else if (this.peek(cssScanner_1.TokenType.CurlyL)) {
const elseNode = this.create(nodes.ElseStatement);
this._parseBody(elseNode, parseStatement);
node.setElseClause(elseNode);
}
}
return this.finish(node);
}
_parseForStatement(parseStatement) {
if (!this.peekKeyword('@for')) {
return null;
}
const node = this.create(nodes.ForStatement);
this.consumeToken(); // @for
if (!node.setVariable(this._parseVariable())) {
return this.finish(node, cssErrors_1.ParseError.VariableNameExpected, [cssScanner_1.TokenType.CurlyR]);
}
if (!this.acceptIdent('from')) {
return this.finish(node, scssErrors_1.SCSSParseError.FromExpected, [cssScanner_1.TokenType.CurlyR]);
}
if (!node.addChild(this._parseBinaryExpr())) {
return this.finish(node, cssErrors_1.ParseError.ExpressionExpected, [cssScanner_1.TokenType.CurlyR]);
}
if (!this.acceptIdent('to') && !this.acceptIdent('through')) {
return this.finish(node, scssErrors_1.SCSSParseError.ThroughOrToExpected, [cssScanner_1.TokenType.CurlyR]);
}
if (!node.addChild(this._parseBinaryExpr())) {
return this.finish(node, cssErrors_1.ParseError.ExpressionExpected, [cssScanner_1.TokenType.CurlyR]);
}
return this._parseBody(node, parseStatement);
}
_parseEachStatement(parseStatement) {
if (!this.peekKeyword('@each')) {
return null;
}
const node = this.create(nodes.EachStatement);
this.consumeToken(); // @each
const variables = node.getVariables();
if (!variables.addChild(this._parseVariable())) {
return this.finish(node, cssErrors_1.ParseError.VariableNameExpected, [cssScanner_1.TokenType.CurlyR]);
}
while (this.accept(cssScanner_1.TokenType.Comma)) {
if (!variables.addChild(this._parseVariable())) {
return this.finish(node, cssErrors_1.ParseError.VariableNameExpected, [cssScanner_1.TokenType.CurlyR]);
}
}
this.finish(variables);
if (!this.acceptIdent('in')) {
return this.finish(node, scssErrors_1.SCSSParseError.InExpected, [cssScanner_1.TokenType.CurlyR]);
}
if (!node.addChild(this._parseExpr())) {
return this.finish(node, cssErrors_1.ParseError.ExpressionExpected, [cssScanner_1.TokenType.CurlyR]);
}
return this._parseBody(node, parseStatement);
}
_parseWhileStatement(parseStatement) {
if (!this.peekKeyword('@while')) {
return null;
}
const node = this.create(nodes.WhileStatement);
this.consumeToken(); // @while
if (!node.addChild(this._parseBinaryExpr())) {
return this.finish(node, cssErrors_1.ParseError.ExpressionExpected, [cssScanner_1.TokenType.CurlyR]);
}
return this._parseBody(node, parseStatement);
}
_parseFunctionBodyDeclaration() {
return this._parseVariableDeclaration() || this._parseReturnStatement() || this._parseWarnAndDebug()
|| this._parseControlStatement(this._parseFunctionBodyDeclaration.bind(this));
}
_parseFunctionDeclaration() {
if (!this.peekKeyword('@function')) {
return null;
}
const node = this.create(nodes.FunctionDeclaration);
this.consumeToken(); // @function
if (!node.setIdentifier(this._parseIdent([nodes.ReferenceType.Function]))) {
return this.finish(node, cssErrors_1.ParseError.IdentifierExpected, [cssScanner_1.TokenType.CurlyR]);
}
if (!this.accept(cssScanner_1.TokenType.ParenthesisL)) {
return this.finish(node, cssErrors_1.ParseError.LeftParenthesisExpected, [cssScanner_1.TokenType.CurlyR]);
}
if (node.getParameters().addChild(this._parseParameterDeclaration())) {
while (this.accept(cssScanner_1.TokenType.Comma)) {
if (this.peek(cssScanner_1.TokenType.ParenthesisR)) {
break;
}
if (!node.getParameters().addChild(this._parseParameterDeclaration())) {
return this.finish(node, cssErrors_1.ParseError.VariableNameExpected);
}
}
}
if (!this.accept(cssScanner_1.TokenType.ParenthesisR)) {
return this.finish(node, cssErrors_1.ParseError.RightParenthesisExpected, [cssScanner_1.TokenType.CurlyR]);
}
return this._parseBody(node, this._parseFunctionBodyDeclaration.bind(this));
}
_parseReturnStatement() {
if (!this.peekKeyword('@return')) {
return null;
}
const node = this.createNode(nodes.NodeType.ReturnStatement);
this.consumeToken(); // @function
if (!node.addChild(this._parseExpr())) {
return this.finish(node, cssErrors_1.ParseError.ExpressionExpected);
}
return this.finish(node);
}
_parseMixinDeclaration() {
if (!this.peekKeyword('@mixin')) {
return null;
}
const node = this.create(nodes.MixinDeclaration);
this.consumeToken();
if (!node.setIdentifier(this._parseIdent([nodes.ReferenceType.Mixin]))) {
return this.finish(node, cssErrors_1.ParseError.IdentifierExpected, [cssScanner_1.TokenType.CurlyR]);
}
if (this.accept(cssScanner_1.TokenType.ParenthesisL)) {
if (node.getParameters().addChild(this._parseParameterDeclaration())) {
while (this.accept(cssScanner_1.TokenType.Comma)) {
if (this.peek(cssScanner_1.TokenType.ParenthesisR)) {
break;
}
if (!node.getParameters().addChild(this._parseParameterDeclaration())) {
return this.finish(node, cssErrors_1.ParseError.VariableNameExpected);
}
}
}
if (!this.accept(cssScanner_1.TokenType.ParenthesisR)) {
return this.finish(node, cssErrors_1.ParseError.RightParenthesisExpected, [cssScanner_1.TokenType.CurlyR]);
}
}
return this._parseBody(node, this._parseRuleSetDeclaration.bind(this));
}
_parseParameterDeclaration() {
const node = this.create(nodes.FunctionParameter);
if (!node.setIdentifier(this._parseVariable())) {
return null;
}
if (this.accept(scssScanner.Ellipsis)) {
// ok
}
if (this.accept(cssScanner_1.TokenType.Colon)) {
if (!node.setDefaultValue(this._parseExpr(true))) {
return this.finish(node, cssErrors_1.ParseError.VariableValueExpected, [], [cssScanner_1.TokenType.Comma, cssScanner_1.TokenType.ParenthesisR]);
}
}
return this.finish(node);
}
_parseMixinContent() {
if (!this.peekKeyword('@content')) {
return null;
}
const node = this.create(nodes.MixinContentReference);
this.consumeToken();
if (this.accept(cssScanner_1.TokenType.ParenthesisL)) {
if (node.getArguments().addChild(this._parseFunctionArgument())) {
while (this.accept(cssScanner_1.TokenType.Comma)) {
if (this.peek(cssScanner_1.TokenType.ParenthesisR)) {
break;
}
if (!node.getArguments().addChild(this._parseFunctionArgument())) {
return this.finish(node, cssErrors_1.ParseError.ExpressionExpected);
}
}
}
if (!this.accept(cssScanner_1.TokenType.ParenthesisR)) {
return this.finish(node, cssErrors_1.ParseError.RightParenthesisExpected);
}
}
return this.finish(node);
}
_parseMixinReference() {
if (!this.peekKeyword('@include')) {
return null;
}
const node = this.create(nodes.MixinReference);
this.consumeToken();
// Could be module or mixin identifier, set as mixin as default.
const firstIdent = this._parseIdent([nodes.ReferenceType.Mixin]);
if (!node.setIdentifier(firstIdent)) {
return this.finish(node, cssErrors_1.ParseError.IdentifierExpected, [cssScanner_1.TokenType.CurlyR]);
}
// Is a module accessor.
if (!this.hasWhitespace() && this.acceptDelim('.') && !this.hasWhitespace()) {
const secondIdent = this._parseIdent([nodes.ReferenceType.Mixin]);
if (!secondIdent) {
return this.finish(node, cssErrors_1.ParseError.IdentifierExpected, [cssScanner_1.TokenType.CurlyR]);
}
const moduleToken = this.create(nodes.Module);
// Re-purpose first matched ident as identifier for module token.
firstIdent.referenceTypes = [nodes.ReferenceType.Module];
moduleToken.setIdentifier(firstIdent);
// Override identifier with second ident.
node.setIdentifier(secondIdent);
node.addChild(moduleToken);
}
if (this.accept(cssScanner_1.TokenType.ParenthesisL)) {
if (node.getArguments().addChild(this._parseFunctionArgument())) {
while (this.accept(cssScanner_1.TokenType.Comma)) {
if (this.peek(cssScanner_1.TokenType.ParenthesisR)) {
break;
}
if (!node.getArguments().addChild(this._parseFunctionArgument())) {
return this.finish(node, cssErrors_1.ParseError.ExpressionExpected);
}
}
}
if (!this.accept(cssScanner_1.TokenType.ParenthesisR)) {
return this.finish(node, cssErrors_1.ParseError.RightParenthesisExpected);
}
}
if (this.peekIdent('using') || this.peek(cssScanner_1.TokenType.CurlyL)) {
node.setContent(this._parseMixinContentDeclaration());
}
return this.finish(node);
}
_parseMixinContentDeclaration() {
const node = this.create(nodes.MixinContentDeclaration);
if (this.acceptIdent('using')) {
if (!this.accept(cssScanner_1.TokenType.ParenthesisL)) {
return this.finish(node, cssErrors_1.ParseError.LeftParenthesisExpected, [cssScanner_1.TokenType.CurlyL]);
}
if (node.getParameters().addChild(this._parseParameterDeclaration())) {
while (this.accept(cssScanner_1.TokenType.Comma)) {
if (this.peek(cssScanner_1.TokenType.ParenthesisR)) {
break;
}
if (!node.getParameters().addChild(this._parseParameterDeclaration())) {
return this.finish(node, cssErrors_1.ParseError.VariableNameExpected);
}
}
}
if (!this.accept(cssScanner_1.TokenType.ParenthesisR)) {
return this.finish(node, cssErrors_1.ParseError.RightParenthesisExpected, [cssScanner_1.TokenType.CurlyL]);
}
}
if (this.peek(cssScanner_1.TokenType.CurlyL)) {
this._parseBody(node, this._parseMixinReferenceBodyStatement.bind(this));
}
return this.finish(node);
}
_parseMixinReferenceBodyStatement() {
return this._tryParseKeyframeSelector() || this._parseRuleSetDeclaration();
}
_parseFunctionArgument() {
// [variableName ':'] expression | variableName '...'
const node = this.create(nodes.FunctionArgument);
const pos = this.mark();
const argument = this._parseVariable();
if (argument) {
if (!this.accept(cssScanner_1.TokenType.Colon)) {
if (this.accept(scssScanner.Ellipsis)) { // optional
node.setValue(argument);
return this.finish(node);
}
else {
this.restoreAtMark(pos);
}
}
else {
node.setIdentifier(argument);
}
}
if (node.setValue(this._parseExpr(true))) {
this.accept(scssScanner.Ellipsis); // #43746
node.addChild(this._parsePrio()); // #9859
return this.finish(node);
}
else if (node.setValue(this._tryParsePrio())) {
return this.finish(node);
}
return null;
}
_parseURLArgument() {
const pos = this.mark();
const node = super._parseURLArgument();
if (!node || !this.peek(cssScanner_1.TokenType.ParenthesisR)) {
this.restoreAtMark(pos);
const node = this.create(nodes.Node);
node.addChild(this._parseBinaryExpr());
return this.finish(node);
}
return node;
}
_parseOperation() {
if (!this.peek(cssScanner_1.TokenType.ParenthesisL)) {
return null;
}
const node = this.create(nodes.Node);
this.consumeToken();
while (node.addChild(this._parseListElement())) {
this.accept(cssScanner_1.TokenType.Comma); // optional
}
if (!this.accept(cssScanner_1.TokenType.ParenthesisR)) {
return this.finish(node, cssErrors_1.ParseError.RightParenthesisExpected);
}
return this.finish(node);
}
_parseListElement() {
const node = this.create(nodes.ListEntry);
const child = this._parseBinaryExpr();
if (!child) {
return null;
}
if (this.accept(cssScanner_1.TokenType.Colon)) {
node.setKey(child);
if (!node.setValue(this._parseBinaryExpr())) {
return this.finish(node, cssErrors_1.ParseError.ExpressionExpected);
}
}
else {
node.setValue(child);
}
return this.finish(node);
}
_parseUse() {
if (!this.peekKeyword('@use')) {
return null;
}
const node = this.create(nodes.Use);
this.consumeToken(); // @use
if (!node.addChild(this._parseStringLiteral())) {
return this.finish(node, cssErrors_1.ParseError.StringLiteralExpected);
}
if (!this.peek(cssScanner_1.TokenType.SemiColon) && !this.peek(cssScanner_1.TokenType.EOF)) {
if (!this.peekRegExp(cssScanner_1.TokenType.Ident, /as|with/)) {
return this.finish(node, cssErrors_1.ParseError.UnknownKeyword);
}
if (this.acceptIdent('as') &&
(!node.setIdentifier(this._parseIdent([nodes.ReferenceType.Module])) && !this.acceptDelim('*'))) {
return this.finish(node, cssErrors_1.ParseError.IdentifierOrWildcardExpected);
}
if (this.acceptIdent('with')) {
if (!this.accept(cssScanner_1.TokenType.ParenthesisL)) {
return this.finish(node, cssErrors_1.ParseError.LeftParenthesisExpected, [cssScanner_1.TokenType.ParenthesisR]);
}
// First variable statement, no comma.
if (!node.getParameters().addChild(this._parseModuleConfigDeclaration())) {
return this.finish(node, cssErrors_1.ParseError.VariableNameExpected);
}
while (this.accept(cssScanner_1.TokenType.Comma)) {
if (this.peek(cssScanner_1.TokenType.ParenthesisR)) {
break;
}
if (!node.getParameters().addChild(this._parseModuleConfigDeclaration())) {
return this.finish(node, cssErrors_1.ParseError.VariableNameExpected);
}
}
if (!this.accept(cssScanner_1.TokenType.ParenthesisR)) {
return this.finish(node, cssErrors_1.ParseError.RightParenthesisExpected);
}
}
}
if (!this.accept(cssScanner_1.TokenType.SemiColon) && !this.accept(cssScanner_1.TokenType.EOF)) {
return this.finish(node, cssErrors_1.ParseError.SemiColonExpected);
}
return this.finish(node);
}
_parseModuleConfigDeclaration() {
const node = this.create(nodes.ModuleConfiguration);
if (!node.setIdentifier(this._parseVariable())) {
return null;
}
if (!this.accept(cssScanner_1.TokenType.Colon) || !node.setValue(this._parseExpr(true))) {
return this.finish(node, cssErrors_1.ParseError.VariableValueExpected, [], [cssScanner_1.TokenType.Comma, cssScanner_1.TokenType.ParenthesisR]);
}
if (this.accept(cssScanner_1.TokenType.Exclamation)) {
if (this.hasWhitespace() || !this.acceptIdent('default')) {
return this.finish(node, cssErrors_1.ParseError.UnknownKeyword);
}
}
return this.finish(node);
}
_parseForward() {
if (!this.peekKeyword('@forward')) {
return null;
}
const node = this.create(nodes.Forward);
this.consumeToken();
if (!node.addChild(this._parseStringLiteral())) {
return this.finish(node, cssErrors_1.ParseError.StringLiteralExpected);
}
if (this.acceptIdent('as')) {
const identifier = this._parseIdent([nodes.ReferenceType.Forward]);
if (!node.setIdentifier(identifier)) {
return this.finish(node, cssErrors_1.ParseError.IdentifierExpected);
}
// Wildcard must be the next character after the identifier string.
if (this.hasWhitespace() || !this.acceptDelim('*')) {
return this.finish(node, cssErrors_1.ParseError.WildcardExpected);
}
}
if (this.acceptIdent('with')) {
if (!this.accept(cssScanner_1.TokenType.ParenthesisL)) {
return this.finish(node, cssErrors_1.ParseError.LeftParenthesisExpected, [cssScanner_1.TokenType.ParenthesisR]);
}
// First variable statement, no comma.
if (!node.getParameters().addChild(this._parseModuleConfigDeclaration())) {
return this.finish(node, cssErrors_1.ParseError.VariableNameExpected);
}
while (this.accept(cssScanner_1.TokenType.Comma)) {
if (this.peek(cssScanner_1.TokenType.ParenthesisR)) {
break;
}
if (!node.getParameters().addChild(this._parseModuleConfigDeclaration())) {
return this.finish(node, cssErrors_1.ParseError.VariableNameExpected);
}
}
if (!this.accept(cssScanner_1.TokenType.ParenthesisR)) {
return this.finish(node, cssErrors_1.ParseError.RightParenthesisExpected);
}
}
else if (this.peekIdent('hide') || this.peekIdent('show')) {
if (!node.addChild(this._parseForwardVisibility())) {
return this.finish(node, cssErrors_1.ParseError.IdentifierOrVariableExpected);
}
}
if (!this.accept(cssScanner_1.TokenType.SemiColon) && !this.accept(cssScanner_1.TokenType.EOF)) {
return this.finish(node, cssErrors_1.ParseError.SemiColonExpected);
}
return this.finish(node);
}
_parseForwardVisibility() {
const node = this.create(nodes.ForwardVisibility);
// Assume to be "hide" or "show".
node.setIdentifier(this._parseIdent());
while (node.addChild(this._parseVariable() || this._parseIdent())) {
// Consume all variables and idents ahead.
this.accept(cssScanner_1.TokenType.Comma);
}
// More than just identifier
return node.getChildren().length > 1 ? node : null;
}
_parseSupportsCondition() {
return this._parseInterpolation() || super._parseSupportsCondition();
}
}
exports.SCSSParser = SCSSParser;
});

View file

@ -0,0 +1,108 @@
(function (factory) {
if (typeof module === "object" && typeof module.exports === "object") {
var v = factory(require, exports);
if (v !== undefined) module.exports = v;
}
else if (typeof define === "function" && define.amd) {
define(["require", "exports", "./cssScanner"], factory);
}
})(function (require, exports) {
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
exports.SCSSScanner = exports.Module = exports.Ellipsis = exports.SmallerEqualsOperator = exports.GreaterEqualsOperator = exports.NotEqualsOperator = exports.EqualsOperator = exports.Default = exports.InterpolationFunction = exports.VariableName = void 0;
const cssScanner_1 = require("./cssScanner");
const _FSL = '/'.charCodeAt(0);
const _NWL = '\n'.charCodeAt(0);
const _CAR = '\r'.charCodeAt(0);
const _LFD = '\f'.charCodeAt(0);
const _DLR = '$'.charCodeAt(0);
const _HSH = '#'.charCodeAt(0);
const _CUL = '{'.charCodeAt(0);
const _EQS = '='.charCodeAt(0);
const _BNG = '!'.charCodeAt(0);
const _LAN = '<'.charCodeAt(0);
const _RAN = '>'.charCodeAt(0);
const _DOT = '.'.charCodeAt(0);
const _ATS = '@'.charCodeAt(0);
let customTokenValue = cssScanner_1.TokenType.CustomToken;
exports.VariableName = customTokenValue++;
exports.InterpolationFunction = customTokenValue++;
exports.Default = customTokenValue++;
exports.EqualsOperator = customTokenValue++;
exports.NotEqualsOperator = customTokenValue++;
exports.GreaterEqualsOperator = customTokenValue++;
exports.SmallerEqualsOperator = customTokenValue++;
exports.Ellipsis = customTokenValue++;
exports.Module = customTokenValue++;
class SCSSScanner extends cssScanner_1.Scanner {
scanNext(offset) {
// scss variable
if (this.stream.advanceIfChar(_DLR)) {
const content = ['$'];
if (this.ident(content)) {
return this.finishToken(offset, exports.VariableName, content.join(''));
}
else {
this.stream.goBackTo(offset);
}
}
// scss: interpolation function #{..})
if (this.stream.advanceIfChars([_HSH, _CUL])) {
return this.finishToken(offset, exports.InterpolationFunction);
}
// operator ==
if (this.stream.advanceIfChars([_EQS, _EQS])) {
return this.finishToken(offset, exports.EqualsOperator);
}
// operator !=
if (this.stream.advanceIfChars([_BNG, _EQS])) {
return this.finishToken(offset, exports.NotEqualsOperator);
}
// operators <, <=
if (this.stream.advanceIfChar(_LAN)) {
if (this.stream.advanceIfChar(_EQS)) {
return this.finishToken(offset, exports.SmallerEqualsOperator);
}
return this.finishToken(offset, cssScanner_1.TokenType.Delim);
}
// ooperators >, >=
if (this.stream.advanceIfChar(_RAN)) {
if (this.stream.advanceIfChar(_EQS)) {
return this.finishToken(offset, exports.GreaterEqualsOperator);
}
return this.finishToken(offset, cssScanner_1.TokenType.Delim);
}
// ellipis
if (this.stream.advanceIfChars([_DOT, _DOT, _DOT])) {
return this.finishToken(offset, exports.Ellipsis);
}
return super.scanNext(offset);
}
comment() {
if (super.comment()) {
return true;
}
if (!this.inURL && this.stream.advanceIfChars([_FSL, _FSL])) {
this.stream.advanceWhileChar((ch) => {
switch (ch) {
case _NWL:
case _CAR:
case _LFD:
return false;
default:
return true;
}
});
return true;
}
else {
return false;
}
}
}
exports.SCSSScanner = SCSSScanner;
});