stylelint
Version:
A mighty CSS linter that helps you avoid errors and enforce conventions.
55 lines (38 loc) • 1.57 kB
JavaScript
import { lexer as defaultLexer, fork } from 'css-tree';
import syntaxPatchesJson from '@csstools/css-syntax-patches-for-csstree' with { type: 'json' };
import mergeSyntaxDefinitions from './mergeSyntaxDefinitions.mjs';
/** @import { Lexer as CSSTreeLexer } from 'css-tree' */
/** @import { Config as StylelintConfig } from 'stylelint' */
/** @import { SyntaxDefinition } from './mergeSyntaxDefinitions.mjs' */
const { next: syntaxPatches } = syntaxPatchesJson;
const lexerCache = new Map();
/**
* Get CSSTree lexer based on a Stylelint configuration and an additional syntax definition.
* The return value is cached for performance.
*
* @param {StylelintConfig} config
* @param {SyntaxDefinition} [additionalSyntax]
* @returns {CSSTreeLexer}
*/
export default function getLexer(config, additionalSyntax) {
const syntax = { ...config.languageOptions?.syntax, ...additionalSyntax };
if (syntax.atRules) {
syntax.atrules = syntax.atRules;
}
if (syntax.units) {
const builtInUnits = defaultLexer.units;
/** @type {Record<string, string[]>} */
const merged = {};
for (const [category, categoryUnits] of Object.entries(syntax.units)) {
const builtIn = builtInUnits[category];
merged[category] = builtIn ? [...builtIn, ...categoryUnits] : categoryUnits;
}
syntax.units = merged;
}
const cacheKey = JSON.stringify(syntax);
const lexer = lexerCache.get(cacheKey);
if (lexer) return lexer;
const { lexer: newLexer } = fork(mergeSyntaxDefinitions(syntaxPatches, syntax));
lexerCache.set(cacheKey, newLexer);
return newLexer;
}