You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
142 lines
3.3 KiB
142 lines
3.3 KiB
// @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;
|
|
|