123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 |
- // @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 vendor = require('../../utils/vendor');
-
- const ruleName = 'time-min-milliseconds';
-
- const messages = ruleMessages(ruleName, {
- expected: (time) => `Expected a minimum of ${time} milliseconds`,
- });
-
- const DELAY_PROPERTIES = new Set(['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 = 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.has(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;
|