| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 | 'use strict';const declarationValueIndex = require('../../utils/declarationValueIndex');const { longhandTimeProperties, shorthandTimeProperties } = require('../../reference/properties');const optionsMatches = require('../../utils/optionsMatches');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 { isNumber } = require('../../utils/validateTypes');const getDeclarationValue = require('../../utils/getDeclarationValue');const getDimension = require('../../utils/getDimension');const ruleName = 'time-min-milliseconds';const messages = ruleMessages(ruleName, {	expected: (time) => `Expected a minimum of ${time} milliseconds`,});const meta = {	url: 'https://stylelint.io/user-guide/rules/time-min-milliseconds',};const DELAY_PROPERTIES = new Set(['animation-delay', 'transition-delay']);/** @type {import('stylelint').Rule<number>} */const rule = (primary, secondaryOptions) => {	return (root, result) => {		const validOptions = validateOptions(			result,			ruleName,			{				actual: primary,				possible: isNumber,			},			{				actual: secondaryOptions,				possible: {					ignore: ['delay'],				},				optional: true,			},		);		if (!validOptions) {			return;		}		const minimum = primary;		const ignoreDelay = optionsMatches(secondaryOptions, 'ignore', 'delay');		root.walkDecls((decl) => {			const propertyName = vendor.unprefixed(decl.prop.toLowerCase());			const propertyValue = decl.value;			const parsedValue = valueParser(getDeclarationValue(decl));			let timeValueCount = 0;			parsedValue.walk((node) => {				const { value, sourceIndex } = node;				const dimension = getDimension(node);				if (					longhandTimeProperties.has(propertyName) &&					!isIgnoredProperty(propertyName) &&					!isAcceptableTime(dimension)				) {					complain(decl, 0, propertyValue.length);				}				if (!shorthandTimeProperties.has(propertyName)) return;				timeValueCount = calcTimeValueCount(dimension, value, timeValueCount);				if (isAcceptableTime(dimension) || (ignoreDelay && timeValueCount !== 1)) return;				complain(decl, sourceIndex, value.length);			});		});		/**		 * @param {{unit: string | null, number: string | null}} dimension		 * @param {string} value		 * @param {number} valueTimeCount		 * @returns {number}		 */		function calcTimeValueCount(dimension, value, valueTimeCount) {			const { unit } = dimension;			if (unit !== null) valueTimeCount++;			if (value === ',') valueTimeCount = 0;			return valueTimeCount;		}		/**		 * @param {string} propertyName		 * @returns {boolean}		 */		function isIgnoredProperty(propertyName) {			if (ignoreDelay && DELAY_PROPERTIES.has(propertyName)) {				return true;			}			return false;		}		/**		 * @param {import('postcss-value-parser').Dimension | {unit: null, number: null}} dimension		 * @returns {boolean}		 */		function isAcceptableTime(dimension) {			const { unit, number } = dimension;			if (unit === null || number === null) return true;			const numTime = Number(number);			if (numTime <= 0) {				return true;			}			const timeUnit = unit.toLowerCase();			if (timeUnit === 'ms' && numTime < minimum) {				return false;			}			if (timeUnit === 's' && numTime * 1000 < minimum) {				return false;			}			return true;		}		/**		 * @param {import('postcss').Declaration} decl		 * @param {number} offset		 * @param {number} length		 * @returns {void}		 */		function complain(decl, offset, length) {			const index = declarationValueIndex(decl) + offset;			const endIndex = index + length;			report({				result,				ruleName,				message: messages.expected(minimum),				index,				endIndex,				node: decl,			});		}	};};rule.ruleName = ruleName;rule.messages = messages;rule.meta = meta;module.exports = rule;
 |