Skip to content

Commit

Permalink
Improve types for at-rule-* rules (#5418)
Browse files Browse the repository at this point in the history
This change removes `// @ts-nocheck` comments in `at-rule-*` rules.
  • Loading branch information
ybiquitous committed Jul 26, 2021
1 parent 6d2e92a commit 04be2a2
Show file tree
Hide file tree
Showing 23 changed files with 212 additions and 150 deletions.
2 changes: 1 addition & 1 deletion lib/lintPostcssResult.js
Expand Up @@ -22,7 +22,7 @@ function lintPostcssResult(stylelintOptions, postcssResult, config) {
postcssResult.stylelint.quiet = config.quiet;
postcssResult.stylelint.config = config;

/** @type {string} */
/** @type {string | undefined} */
let newline;
const postcssDoc = postcssResult.root;

Expand Down
92 changes: 64 additions & 28 deletions lib/rules/alpha-value-notation/index.js
@@ -1,5 +1,3 @@
// @ts-nocheck

'use strict';

const valueParser = require('postcss-value-parser');
Expand All @@ -23,7 +21,8 @@ const messages = ruleMessages(ruleName, {
const ALPHA_PROPS = new Set(['opacity', 'shape-image-threshold']);
const ALPHA_FUNCS = new Set(['hsl', 'hsla', 'hwb', 'lab', 'lch', 'rgb', 'rgba']);

function rule(primary, options, context) {
/** @type {import('stylelint').StylelintRule} */
const rule = (primary, secondaryOptions, context) => {
return (root, result) => {
const validOptions = validateOptions(
result,
Expand All @@ -33,7 +32,7 @@ function rule(primary, options, context) {
possible: ['number', 'percentage'],
},
{
actual: options,
actual: secondaryOptions,
possible: {
exceptProperties: [isString, isRegExp],
},
Expand All @@ -43,11 +42,23 @@ function rule(primary, options, context) {

if (!validOptions) return;

const optionFuncs = Object.freeze({
number: {
expFunc: isNumber,
fixFunc: asNumber,
},
percentage: {
expFunc: isPercentage,
fixFunc: asPercentage,
},
});

root.walkDecls((decl) => {
let needsFix = false;
const parsedValue = valueParser(getDeclarationValue(decl));

parsedValue.walk((node) => {
/** @type {import('postcss-value-parser').Node | undefined} */
let alpha;

if (ALPHA_PROPS.has(decl.prop.toLowerCase())) {
Expand All @@ -68,21 +79,15 @@ function rule(primary, options, context) {

if (!isNumber(value) && !isPercentage(value)) return;

const optionFuncs = {
number: {
expFunc: isNumber,
fixFunc: asNumber,
},
percentage: {
expFunc: isPercentage,
fixFunc: asPercentage,
},
};

/** @type {'number' | 'percentage'} */
let expectation = primary;

if (optionsMatches(options, 'exceptProperties', decl.prop)) {
expectation = Object.keys(optionFuncs).filter((key) => key !== expectation);
if (optionsMatches(secondaryOptions, 'exceptProperties', decl.prop)) {
if (expectation === 'number') {
expectation = 'percentage';
} else if (expectation === 'percentage') {
expectation = 'number';
}
}

if (optionFuncs[expectation].expFunc(value)) return;
Expand All @@ -91,7 +96,7 @@ function rule(primary, options, context) {
const unfixed = value;

if (context.fix) {
alpha.value = fixed;
alpha.value = String(fixed);
needsFix = true;

return;
Expand All @@ -111,22 +116,45 @@ function rule(primary, options, context) {
}
});
};
}
};

/**
* @param {string} value
* @returns {string | undefined}
*/
function asPercentage(value) {
return `${Number((value * 100).toPrecision(3))}%`;
const number = Number(value);

return `${Number((number * 100).toPrecision(3))}%`;
}

/**
* @param {string} value
* @returns {string | undefined}
*/
function asNumber(value) {
const { number } = valueParser.unit(value);
const dimension = valueParser.unit(value);

if (!dimension) return undefined;

const number = Number(dimension.number);

return Number((number / 100).toPrecision(3));
return Number((number / 100).toPrecision(3)).toString();
}

/**
* @template {import('postcss-value-parser').Node} T
* @param {T} node
* @returns {T | undefined}
*/
function findAlphaInValue(node) {
return node.type === 'word' || node.type === 'function' ? node : false;
return node.type === 'word' || node.type === 'function' ? node : undefined;
}

/**
* @param {import('postcss-value-parser').FunctionNode} node
* @returns {import('postcss-value-parser').Node | undefined}
*/
function findAlphaInFunction(node) {
const args = node.nodes.filter(({ type }) => type === 'word' || type === 'function');

Expand All @@ -140,19 +168,27 @@ function findAlphaInFunction(node) {
return nodesAfterSlash.find(({ type }) => type === 'word');
}

return false;
return undefined;
}

/**
* @param {string} value
* @returns {boolean}
*/
function isPercentage(value) {
const { unit } = valueParser.unit(value);
const dimension = valueParser.unit(value);

return unit && unit === '%';
return dimension && dimension.unit === '%';
}

/**
* @param {string} value
* @returns {boolean}
*/
function isNumber(value) {
const { unit } = valueParser.unit(value);
const dimension = valueParser.unit(value);

return unit === '';
return dimension && dimension.unit === '';
}

rule.ruleName = ruleName;
Expand Down
16 changes: 9 additions & 7 deletions lib/rules/at-rule-allowed-list/index.js
@@ -1,5 +1,3 @@
// @ts-nocheck

'use strict';

const isStandardSyntaxAtRule = require('../../utils/isStandardSyntaxAtRule');
Expand All @@ -15,28 +13,32 @@ const messages = ruleMessages(ruleName, {
rejected: (name) => `Unexpected at-rule "${name}"`,
});

function rule(listInput) {
/** @type {import('stylelint').StylelintRule} */
const rule = (primary) => {
// To allow for just a string as a parameter (not only arrays of strings)
const list = [].concat(listInput);
const primaryValues = [primary].flat();

return (root, result) => {
const validOptions = validateOptions(result, ruleName, {
actual: list,
actual: primaryValues,
possible: [isString],
});

if (!validOptions) {
return;
}

/** @type {string[]} */
const atRuleNames = primaryValues;

root.walkAtRules((atRule) => {
const name = atRule.name;

if (!isStandardSyntaxAtRule(atRule)) {
return;
}

if (list.includes(vendor.unprefixed(name).toLowerCase())) {
if (atRuleNames.includes(vendor.unprefixed(name).toLowerCase())) {
return;
}

Expand All @@ -48,7 +50,7 @@ function rule(listInput) {
});
});
};
}
};

rule.primaryOptionArray = true;

Expand Down
16 changes: 9 additions & 7 deletions lib/rules/at-rule-disallowed-list/index.js
@@ -1,5 +1,3 @@
// @ts-nocheck

'use strict';

const isStandardSyntaxAtRule = require('../../utils/isStandardSyntaxAtRule');
Expand All @@ -15,28 +13,32 @@ const messages = ruleMessages(ruleName, {
rejected: (name) => `Unexpected at-rule "${name}"`,
});

function rule(listInput) {
/** @type {import('stylelint').StylelintRule} */
const rule = (primary) => {
// To allow for just a string as a parameter (not only arrays of strings)
const list = [].concat(listInput);
const primaryValues = [primary].flat();

return (root, result) => {
const validOptions = validateOptions(result, ruleName, {
actual: list,
actual: primaryValues,
possible: [isString],
});

if (!validOptions) {
return;
}

/** @type {string[]} */
const atRuleNames = primaryValues;

root.walkAtRules((atRule) => {
const name = atRule.name;

if (!isStandardSyntaxAtRule(atRule)) {
return;
}

if (!list.includes(vendor.unprefixed(name).toLowerCase())) {
if (!atRuleNames.includes(vendor.unprefixed(name).toLowerCase())) {
return;
}

Expand All @@ -48,7 +50,7 @@ function rule(listInput) {
});
});
};
}
};

rule.primaryOptionArray = true;

Expand Down

0 comments on commit 04be2a2

Please sign in to comment.