1
0
mirror of https://github.com/thangisme/notes.git synced 2024-11-01 04:27:17 -04:00
notes/node_modules/stylelint/lib/rules/length-zero-no-unit/index.js
Patrick Marsceill b7b0d0d7bf
Initial commit
2017-03-09 13:16:08 -05:00

120 lines
3.9 KiB
JavaScript

"use strict"
const beforeBlockString = require("../../utils/beforeBlockString")
const blurComments = require("../../utils/blurComments")
const hasBlock = require("../../utils/hasBlock")
const report = require("../../utils/report")
const ruleMessages = require("../../utils/ruleMessages")
const validateOptions = require("../../utils/validateOptions")
const _ = require("lodash")
const keywordSets = require("../../reference/keywordSets")
const styleSearch = require("style-search")
const valueParser = require("postcss-value-parser")
const ruleName = "length-zero-no-unit"
const messages = ruleMessages(ruleName, {
rejected: "Unexpected unit",
})
const rule = function (actual) {
return (root, result) => {
const validOptions = validateOptions(result, ruleName, { actual })
if (!validOptions) {
return
}
root.walkDecls(decl => {
check(blurComments(decl.toString()), decl)
})
root.walkAtRules(atRule => {
const source = hasBlock(atRule) ? beforeBlockString(atRule, { noRawBefore: true }) : atRule.toString()
check(source, atRule)
})
function check(value, node) {
const ignorableIndexes = new Set()
styleSearch({ source: value, target: "0" }, match => {
const index = match.startIndex
// Given a 0 somewhere in the full property value (not in a string, thanks
// to styleSearch) we need to isolate the value that contains the zero.
// To do so, we'll find the last index before the 0 of a character that would
// divide one value in a list from another, and the next index of such a
// character; then we build a substring from those indexes, which we can
// assess.
// If a single value includes multiple 0's (e.g. 100.01px), we don't want
// each 0 to be treated as a separate value, possibly resulting in multiple
// warnings for the same value (e.g. 0.00px).
//
// This check prevents that from happening: we build and check against a
// Set containing all the indexes that are part of a value already validated.
if (ignorableIndexes.has(index)) {
return
}
const prevValueBreakIndex = _.findLastIndex(value.substr(0, index), char => {
return [
" ",
",",
")",
"(",
"#",
].indexOf(char) !== -1
})
// Ignore hex colors
if (value[prevValueBreakIndex] === "#") {
return
}
// If no prev break was found, this value starts at 0
const valueWithZeroStart = prevValueBreakIndex === -1 ? 0 : prevValueBreakIndex + 1
const nextValueBreakIndex = _.findIndex(value.substr(valueWithZeroStart), char => {
return [
" ",
",",
")",
].indexOf(char) !== -1
})
// If no next break was found, this value ends at the end of the string
const valueWithZeroEnd = nextValueBreakIndex === -1 ? value.length : nextValueBreakIndex + valueWithZeroStart
const valueWithZero = value.slice(valueWithZeroStart, valueWithZeroEnd)
const parsedValue = valueParser.unit(valueWithZero)
if (!parsedValue || parsedValue && !parsedValue.unit) {
return
}
// Add the indexes to ignorableIndexes so the same value will not
// be checked multiple times.
_.range(valueWithZeroStart, valueWithZeroEnd).forEach(i => ignorableIndexes.add(i))
// Only pay attention if the value parses to 0
// and units with lengths
if (parseFloat(valueWithZero, 10) !== 0 || !keywordSets.lengthUnits.has(parsedValue.unit.toLowerCase())) {
return
}
report({
message: messages.rejected,
node,
index: valueWithZeroEnd - parsedValue.unit.length,
result,
ruleName,
})
})
}
}
}
rule.ruleName = ruleName
rule.messages = messages
module.exports = rule