| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479 |
- // NOTICE: This file is generated by Rollup. To modify it,
- // please instead edit the ESM counterpart and rebuild with Rollup (npm run build).
- 'use strict';
- const constants = require('./constants.cjs');
- const configurationComment = require('./utils/configurationComment.cjs');
- const validateTypes = require('./utils/validateTypes.cjs');
- const typeGuards = require('./utils/typeGuards.cjs');
- const isStandardSyntaxComment = require('./utils/isStandardSyntaxComment.cjs');
- const cssTokenizer = require('@csstools/css-tokenizer');
- /** @import {Node as PostcssNode, Comment as PostcssComment, Document as PostcssDocument, Root as PostcssRoot, Source as PostcssSource} from 'postcss' */
- /** @import {DisabledRange, DisabledRangeObject, PostcssResult} from 'stylelint' */
- /** @typedef {Pick<PostcssSource, 'start' | 'end'>} Source */
- /**
- * @param {PostcssNode} node
- * @param {number} start
- * @param {boolean} strictStart
- * @param {string|undefined} description
- * @param {number} [end]
- * @param {boolean} [strictEnd]
- * @returns {DisabledRange}
- */
- function createDisableRange(node, start, strictStart, description, end, strictEnd) {
- return {
- node,
- start,
- end: end || undefined,
- strictStart,
- strictEnd: typeof strictEnd === 'boolean' ? strictEnd : undefined,
- description,
- };
- }
- /**
- * Run it like a PostCSS plugin
- * @param {PostcssRoot | PostcssDocument} root
- * @param {PostcssResult} result
- * @returns {PostcssResult}
- */
- function assignDisabledRanges(root, result) {
- /**
- * Most of the functions below work via side effects mutating this object
- * @type {DisabledRangeObject}
- */
- const disabledRanges = result.stylelint.disabledRanges;
- /** @type {DisabledRange[]} */
- const disabledRangesAll = [];
- disabledRanges[constants.RULE_NAME_ALL] = disabledRangesAll;
- // Work around postcss/postcss-scss#109 by merging adjacent `//` comments
- // into a single node before passing to `checkComment`.
- /** @type {PostcssComment?} */
- let inlineEnd;
- const configurationComment$1 = result.stylelint.config?.configurationComment;
- root.walk((node) => {
- if (typeGuards.isComment(node)) {
- if (inlineEnd) {
- // Ignore comments already processed by grouping with a previous one.
- if (inlineEnd === node) inlineEnd = null;
- return;
- }
- const nextComment = node.next();
- // If any of these conditions are not met, do not merge comments.
- if (
- !(
- !isStandardSyntaxComment(node) &&
- configurationComment.isConfigurationComment(node.text, configurationComment$1) &&
- nextComment &&
- typeGuards.isComment(nextComment) &&
- (node.text.includes('--') || nextComment.text.startsWith('--'))
- )
- ) {
- checkComment(node, node.source, node.text);
- return;
- }
- let lastLine = node.source?.end?.line ?? 0;
- const fullComment = node.clone();
- let current = nextComment;
- while (
- !isStandardSyntaxComment(current) &&
- !configurationComment.isConfigurationComment(current.text, configurationComment$1)
- ) {
- const currentLine = current.source?.end?.line ?? 0;
- if (lastLine + 1 !== currentLine) break;
- fullComment.text += `\n${current.text}`;
- if (fullComment.source && current.source) {
- fullComment.source.end = current.source.end;
- }
- inlineEnd = current;
- const next = current.next();
- if (!next || !typeGuards.isComment(next)) break;
- current = next;
- lastLine = currentLine;
- }
- checkComment(fullComment, fullComment.source, fullComment.text);
- }
- if (typeGuards.isRule(node)) {
- let offset = 0;
- const selector = node.raws?.selector?.raw;
- checkCommentsInNode(node, selector, offset);
- offset += selector?.length ?? node.selector.length;
- const between = node.raws?.between;
- checkCommentsInNode(node, between, offset);
- }
- if (typeGuards.isAtRule(node)) {
- let offset = node.name.length + 1; // `@` + name
- const afterName = node.raws?.afterName;
- checkCommentsInNode(node, afterName, offset);
- offset += afterName?.length ?? 0;
- const params = node.raws?.params?.raw;
- checkCommentsInNode(node, params, offset);
- offset += params?.length ?? node.params.length;
- const between = node.raws?.between;
- checkCommentsInNode(node, between, offset);
- }
- if (typeGuards.isDeclaration(node)) {
- let offset = node.prop.length;
- const between = node.raws?.between;
- checkCommentsInNode(node, between, offset);
- offset += between?.length ?? 0;
- const value = node.raws?.value?.raw;
- checkCommentsInNode(node, value, offset);
- }
- });
- return result;
- /**
- * @param {PostcssNode} node
- * @param {Source} source
- * @param {string} text
- */
- function processDisableLineCommand(node, source, text) {
- if (source.start) {
- const line = source.start.line;
- const description = getDescription(text);
- for (const ruleName of getCommandRules(configurationComment.DISABLE_LINE_COMMAND, text)) {
- disableLine(node, line, ruleName, description);
- }
- }
- }
- /**
- * @param {PostcssNode} node
- * @param {Source} source
- * @param {string} text
- */
- function processDisableNextLineCommand(node, source, text) {
- if (source.end) {
- const line = source.end.line;
- const description = getDescription(text);
- for (const ruleName of getCommandRules(configurationComment.DISABLE_NEXT_LINE_COMMAND, text)) {
- disableLine(node, line + 1, ruleName, description);
- }
- }
- }
- /**
- * @param {PostcssNode} node
- * @param {number} line
- * @param {string} ruleName
- * @param {string|undefined} description
- */
- function disableLine(node, line, ruleName, description) {
- if (ruleIsDisabled(constants.RULE_NAME_ALL)) {
- throw node.error('All rules have already been disabled', {
- plugin: 'stylelint',
- });
- }
- if (ruleName === constants.RULE_NAME_ALL) {
- for (const disabledRuleName of Object.keys(disabledRanges)) {
- if (ruleIsDisabled(disabledRuleName)) continue;
- const strict = disabledRuleName === constants.RULE_NAME_ALL;
- startDisabledRange(node, line, disabledRuleName, strict, description);
- endDisabledRange(line, disabledRuleName, strict);
- }
- } else {
- if (ruleIsDisabled(ruleName)) {
- throw node.error(`"${ruleName}" has already been disabled`, {
- plugin: 'stylelint',
- });
- }
- startDisabledRange(node, line, ruleName, true, description);
- endDisabledRange(line, ruleName, true);
- }
- }
- /**
- * @param {PostcssNode} node
- * @param {Source} source
- * @param {string} text
- */
- function processDisableCommand(node, source, text) {
- const description = getDescription(text);
- for (const ruleToDisable of getCommandRules(configurationComment.DISABLE_COMMAND, text)) {
- const isAllRules = ruleToDisable === constants.RULE_NAME_ALL;
- if (ruleIsDisabled(ruleToDisable)) {
- throw node.error(
- isAllRules
- ? 'All rules have already been disabled'
- : `"${ruleToDisable}" has already been disabled`,
- {
- plugin: 'stylelint',
- },
- );
- }
- if (source.start) {
- const line = source.start.line;
- if (isAllRules) {
- for (const ruleName of Object.keys(disabledRanges)) {
- startDisabledRange(node, line, ruleName, ruleName === constants.RULE_NAME_ALL, description);
- }
- } else {
- startDisabledRange(node, line, ruleToDisable, true, description);
- }
- }
- }
- }
- /**
- * @param {PostcssNode} node
- * @param {Source} source
- * @param {string} text
- */
- function processEnableCommand(node, source, text) {
- for (const ruleToEnable of getCommandRules(configurationComment.ENABLE_COMMAND, text)) {
- // need fallback if endLine will be undefined
- const endLine = source.end?.line;
- validateTypes.assertNumber(endLine);
- if (ruleToEnable === constants.RULE_NAME_ALL) {
- if (
- Object.values(disabledRanges).every((ranges) => {
- if (ranges.length === 0) return true;
- const lastRange = ranges[ranges.length - 1];
- return lastRange && typeof lastRange.end === 'number';
- })
- ) {
- throw node.error('No rules have been disabled', {
- plugin: 'stylelint',
- });
- }
- for (const [ruleName, ranges] of Object.entries(disabledRanges)) {
- const lastRange = ranges[ranges.length - 1];
- if (!lastRange || !lastRange.end) {
- endDisabledRange(endLine, ruleName, ruleName === constants.RULE_NAME_ALL);
- }
- }
- continue;
- }
- if (ruleIsDisabled(constants.RULE_NAME_ALL) && disabledRanges[ruleToEnable] === undefined) {
- // Get a starting point from the where all rules were disabled
- disabledRanges[ruleToEnable] = disabledRangesAll.map(({ start, end, description }) =>
- createDisableRange(node, start, false, description, end, false),
- );
- endDisabledRange(endLine, ruleToEnable, true);
- continue;
- }
- if (ruleIsDisabled(ruleToEnable)) {
- endDisabledRange(endLine, ruleToEnable, true);
- continue;
- }
- throw node.error(`"${ruleToEnable}" has not been disabled`, {
- plugin: 'stylelint',
- });
- }
- }
- /**
- * @param {PostcssNode} node
- * @param {string | undefined} part
- * @param {number} offset
- */
- function checkCommentsInNode(node, part, offset) {
- if (!(part && part.includes('/*') && part.includes('*/'))) return;
- cssTokenizer.tokenize({ css: part }).forEach((token) => {
- if (!cssTokenizer.isTokenComment(token)) return;
- const [, text, start, end] = token;
- const source = node.rangeBy({
- index: start + offset,
- endIndex: end + 1 + offset,
- });
- checkComment(node, source, text.slice(2, -2).trim());
- });
- }
- /**
- * @param {PostcssNode} node
- * @param {Source | undefined} source
- * @param {string} text
- */
- function checkComment(node, source, text) {
- if (!source) return;
- // Ignore comments that are not relevant commands
- if (!configurationComment.isConfigurationComment(text, configurationComment$1)) {
- return;
- }
- switch (configurationComment.extractConfigurationComment(text, configurationComment$1)) {
- case configurationComment.DISABLE_LINE_COMMAND:
- processDisableLineCommand(node, source, text);
- break;
- case configurationComment.DISABLE_NEXT_LINE_COMMAND:
- processDisableNextLineCommand(node, source, text);
- break;
- case configurationComment.DISABLE_COMMAND:
- processDisableCommand(node, source, text);
- break;
- case configurationComment.ENABLE_COMMAND:
- processEnableCommand(node, source, text);
- break;
- }
- }
- /**
- * @param {string} command
- * @param {string} fullText
- * @returns {string[]}
- */
- function getCommandRules(command, fullText) {
- // Allow for description (f.e. /* stylelint-disable a, b -- Description */).
- const fullCommand = configurationComment.getConfigurationComment(command, configurationComment$1);
- const rulesText = fullText.slice(fullCommand.length).split(/\s-{2,}\s/u)[0];
- validateTypes.assertString(rulesText);
- const rules = rulesText
- .trim()
- .split(',')
- .filter(Boolean)
- .map((r) => r.trim());
- if (rules.length === 0) {
- return [constants.RULE_NAME_ALL];
- }
- return rules;
- }
- /**
- * @param {string} fullText
- * @returns {string|undefined}
- */
- function getDescription(fullText) {
- const descriptionStart = fullText.indexOf('--');
- if (descriptionStart === -1) return;
- return fullText.slice(descriptionStart + 2).trim();
- }
- /**
- * @param {PostcssNode} node
- * @param {number} line
- * @param {string} ruleName
- * @param {boolean} strict
- * @param {string|undefined} description
- */
- function startDisabledRange(node, line, ruleName, strict, description) {
- const rangeObj = createDisableRange(node, line, strict, description);
- ensureRuleRanges(ruleName);
- const range = disabledRanges[ruleName];
- validateTypes.assert(range);
- range.push(rangeObj);
- }
- /**
- * @param {number} line
- * @param {string} ruleName
- * @param {boolean} strict
- */
- function endDisabledRange(line, ruleName, strict) {
- const ranges = disabledRanges[ruleName];
- const lastRangeForRule = ranges ? ranges[ranges.length - 1] : null;
- if (!lastRangeForRule) {
- return;
- }
- // Add an `end` prop to the last range of that rule
- lastRangeForRule.end = line;
- lastRangeForRule.strictEnd = strict;
- }
- /**
- * @param {string} ruleName
- */
- function ensureRuleRanges(ruleName) {
- if (!disabledRanges[ruleName]) {
- disabledRanges[ruleName] = disabledRangesAll.map(({ node, start, end, description }) =>
- createDisableRange(node, start, false, description, end, false),
- );
- }
- }
- /**
- * @param {string} ruleName
- * @returns {boolean}
- */
- function ruleIsDisabled(ruleName) {
- const ranges = disabledRanges[ruleName];
- if (!ranges) return false;
- const lastRange = ranges[ranges.length - 1];
- if (!lastRange) return false;
- if (!lastRange.end) return true;
- return false;
- }
- }
- module.exports = assignDisabledRanges;
|