142 lines
3.3 KiB
JavaScript
142 lines
3.3 KiB
JavaScript
// @ts-nocheck
|
|
|
|
'use strict';
|
|
|
|
const _ = require('lodash');
|
|
const declarationValueIndex = require('../../utils/declarationValueIndex');
|
|
const keywordSets = require('../../reference/keywordSets');
|
|
const optionsMatches = require('../../utils/optionsMatches');
|
|
const postcss = require('postcss');
|
|
const report = require('../../utils/report');
|
|
const ruleMessages = require('../../utils/ruleMessages');
|
|
const validateOptions = require('../../utils/validateOptions');
|
|
const valueParser = require('postcss-value-parser');
|
|
|
|
const ruleName = 'time-min-milliseconds';
|
|
|
|
const messages = ruleMessages(ruleName, {
|
|
expected: (time) => `Expected a minimum of ${time} milliseconds`,
|
|
});
|
|
|
|
const DELAY_PROPERTIES = ['animation-delay', 'transition-delay'];
|
|
|
|
function rule(minimum, options) {
|
|
return (root, result) => {
|
|
const validOptions = validateOptions(
|
|
result,
|
|
ruleName,
|
|
{
|
|
actual: minimum,
|
|
possible: _.isNumber,
|
|
},
|
|
{
|
|
actual: options,
|
|
possible: {
|
|
ignore: ['delay'],
|
|
},
|
|
optional: true,
|
|
},
|
|
);
|
|
|
|
if (!validOptions) {
|
|
return;
|
|
}
|
|
|
|
root.walkDecls((decl) => {
|
|
const propertyName = postcss.vendor.unprefixed(decl.prop.toLowerCase());
|
|
|
|
if (
|
|
keywordSets.longhandTimeProperties.has(propertyName) &&
|
|
!isIgnoredProperty(propertyName) &&
|
|
!isAcceptableTime(decl.value)
|
|
) {
|
|
complain(decl);
|
|
}
|
|
|
|
if (keywordSets.shorthandTimeProperties.has(propertyName)) {
|
|
const valueListList = postcss.list.comma(decl.value);
|
|
|
|
for (const valueListString of valueListList) {
|
|
const valueList = postcss.list.space(valueListString);
|
|
|
|
if (optionsMatches(options, 'ignore', 'delay')) {
|
|
// Check only duration time values
|
|
const duration = getDuration(valueList);
|
|
|
|
if (duration && !isAcceptableTime(duration)) {
|
|
complain(decl, decl.value.indexOf(duration));
|
|
}
|
|
} else {
|
|
// Check all time values
|
|
for (const value of valueList) {
|
|
if (!isAcceptableTime(value)) {
|
|
complain(decl, decl.value.indexOf(value));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
/**
|
|
* Get the duration within an `animation` or `transition` shorthand property value.
|
|
*
|
|
* @param {Node[]} valueList
|
|
*
|
|
* @returns {Node}
|
|
*/
|
|
function getDuration(valueList) {
|
|
for (const value of valueList) {
|
|
const parsedTime = valueParser.unit(value);
|
|
|
|
if (!parsedTime) continue;
|
|
|
|
// The first numeric value in an animation shorthand is the duration.
|
|
return value;
|
|
}
|
|
}
|
|
|
|
function isIgnoredProperty(propertyName) {
|
|
if (optionsMatches(options, 'ignore', 'delay') && DELAY_PROPERTIES.includes(propertyName)) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
function isAcceptableTime(time) {
|
|
const parsedTime = valueParser.unit(time);
|
|
|
|
if (!parsedTime) return true;
|
|
|
|
if (parsedTime.number <= 0) {
|
|
return true;
|
|
}
|
|
|
|
if (parsedTime.unit.toLowerCase() === 'ms' && parsedTime.number < minimum) {
|
|
return false;
|
|
}
|
|
|
|
if (parsedTime.unit.toLowerCase() === 's' && parsedTime.number * 1000 < minimum) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
function complain(decl, offset = 0) {
|
|
report({
|
|
result,
|
|
ruleName,
|
|
message: messages.expected(minimum),
|
|
index: declarationValueIndex(decl) + offset,
|
|
node: decl,
|
|
});
|
|
}
|
|
};
|
|
}
|
|
|
|
rule.ruleName = ruleName;
|
|
rule.messages = messages;
|
|
module.exports = rule;
|