UNPKG

@efficientcss/stylelint-config-ecss

Version:

Linting rules for EfficientCSS

133 lines (117 loc) 3.33 kB
import { tokenTypes as TYPE } from 'css-tree'; import * as SassVariable from './SassVariable.js'; import * as SassInterpolation from './SassInterpolation.js'; import * as SassNamespace from './SassNamespace.js'; const NUMBERSIGN = 0x0023; // U+0023 NUMBER SIGN (#) const DOLLARSIGN = 0x0024; // U+0024 DOLLAR SIGN ($) const PERCENTAGESIGN = 0x0025; // U+0025 PERCENTAGE SIGN (%) const FULLSTOP = 0x002E; // U+002E FULL STOP (.) // custom error class PreprocessorExtensionError { constructor() { this.type = 'PreprocessorExtensionError'; } } function throwOnSyntaxExtension() { let node = null; switch (this.tokenType) { case TYPE.Ident: if (this.isDelim(FULLSTOP, 1)) { node = this.SassNamespace(); } break; case TYPE.Delim: switch (this.source.charCodeAt(this.tokenStart)) { case DOLLARSIGN: // sass: $var node = this.SassVariable(); break; case NUMBERSIGN: // sass: #{ } if (this.lookupType(1) === TYPE.LeftCurlyBracket) { node = this.SassInterpolation(this.scope.Value, this.readSequence); } break; case PERCENTAGESIGN: // sass: 5 % 4 node = this.Operator(); break; } break; } // currently we can't validate values that contain less/sass extensions if (node !== null) { throw new PreprocessorExtensionError(); } } export default function sass(syntaxConfig) { // new node types syntaxConfig.node.SassVariable = SassVariable; syntaxConfig.node.SassInterpolation = SassInterpolation; syntaxConfig.node.SassNamespace = SassNamespace; // custom at-rules syntaxConfig.atrules['at-root'] = { prelude: '<any-value>' }; syntaxConfig.atrules.content = { prelude: '<any-value>' }; syntaxConfig.atrules.debug = { prelude: '<any-value>' }; syntaxConfig.atrules.each = { prelude: '<any-value>' }; syntaxConfig.atrules.else = { prelude: '<any-value>?' }; syntaxConfig.atrules.error = { prelude: '<any-value>' }; syntaxConfig.atrules.extend = { prelude: '<any-value>' }; syntaxConfig.atrules.for = { prelude: '<any-value>' }; syntaxConfig.atrules.forward = { prelude: '<any-value>' }; syntaxConfig.atrules.function = { prelude: '<any-value>' }; syntaxConfig.atrules.if = { prelude: '<any-value>' }; syntaxConfig.atrules.import = { prelude: syntaxConfig.atrules.import.prelude + '| <string>#' // FIXME: fix prelude extension in css-tree }; syntaxConfig.atrules.include = { prelude: '<any-value>' }; syntaxConfig.atrules.mixin = { prelude: '<any-value>' }; syntaxConfig.atrules.return = { prelude: '<any-value>' }; syntaxConfig.atrules.use = { prelude: '<any-value>' }; syntaxConfig.atrules.warn = { prelude: '<any-value>' }; syntaxConfig.atrules.while = { prelude: '<any-value>' }; // extend parser's at-rule preluder parser const originalAttrulePreludeGetNode = syntaxConfig.scope.AtrulePrelude.getNode; syntaxConfig.scope.AtrulePrelude.getNode = function(context) { throwOnSyntaxExtension.call(this); return originalAttrulePreludeGetNode.call(this, context); }; // extend parser's value parser const originalValueGetNode = syntaxConfig.scope.Value.getNode; syntaxConfig.scope.Value.getNode = function(context) { throwOnSyntaxExtension.call(this); return originalValueGetNode.call(this, context); }; return syntaxConfig; };