+++ /dev/null
-"use strict";
-
-const atRuleParamIndex = require("../../utils/atRuleParamIndex");
-const declarationValueIndex = require("../../utils/declarationValueIndex");
-const report = require("../../utils/report");
-const ruleMessages = require("../../utils/ruleMessages");
-const validateOptions = require("../../utils/validateOptions");
-const valueParser = require("postcss-value-parser");
-
-const ruleName = "number-leading-zero";
-
-const messages = ruleMessages(ruleName, {
- expected: "Expected a leading zero",
- rejected: "Unexpected leading zero"
-});
-
-const rule = function(expectation, secondary, context) {
- return (root, result) => {
- const validOptions = validateOptions(result, ruleName, {
- actual: expectation,
- possible: ["always", "never"]
- });
- if (!validOptions) {
- return;
- }
-
- root.walkAtRules(atRule => {
- if (atRule.name.toLowerCase() === "import") {
- return;
- }
-
- check(atRule, atRule.params, atRuleParamIndex);
- });
-
- root.walkDecls(decl => check(decl, decl.value, declarationValueIndex));
-
- function check(node, value, getIndex) {
- const neverFixPositions = [];
- const alwaysFixPositions = [];
-
- // Get out quickly if there are no periods
- if (value.indexOf(".") === -1) {
- return;
- }
-
- valueParser(value).walk(valueNode => {
- // Ignore `url` function
- if (
- valueNode.type === "function" &&
- valueNode.value.toLowerCase() === "url"
- ) {
- return false;
- }
-
- // Ignore strings, comments, etc
- if (valueNode.type !== "word") {
- return;
- }
-
- // Check leading zero
- if (expectation === "always") {
- const match = /(?:\D|^)(\.\d+)/.exec(valueNode.value);
-
- if (match === null) {
- return;
- }
- // The regexp above consists of 2 capturing groups (or capturing parentheses).
- // We need the index of the second group. This makes sanse when we have "-.5" as an input
- // for regex. And we need the index of ".5".
- const capturingGroupIndex = match[0].length - match[1].length;
-
- const index =
- valueNode.sourceIndex + match.index + capturingGroupIndex;
-
- if (context.fix) {
- alwaysFixPositions.unshift({
- index
- });
- return;
- } else {
- complain(messages.expected, node, getIndex(node) + index);
- }
- }
-
- if (expectation === "never") {
- const match = /(?:\D|^)(0+)(\.\d+)/.exec(valueNode.value);
-
- if (match === null) {
- return;
- }
-
- // The regexp above consists of 3 capturing groups (or capturing parentheses).
- // We need the index of the second group. This makes sanse when we have "-00.5"
- // as an input for regex. And we need the index of "00".
- const capturingGroupIndex =
- match[0].length - (match[1].length + match[2].length);
-
- const index =
- valueNode.sourceIndex + match.index + capturingGroupIndex;
-
- if (context.fix) {
- neverFixPositions.unshift({
- startIndex: index,
- // match[1].length is the length of our matched zero(s)
- endIndex: index + match[1].length
- });
- return;
- } else {
- complain(messages.rejected, node, getIndex(node) + index);
- }
- }
- });
-
- if (alwaysFixPositions.length) {
- alwaysFixPositions.forEach(function(fixPosition) {
- const index = fixPosition.index;
- if (node.type === "atrule") {
- node.params = addLeadingZero(node.params, index);
- } else {
- node.value = addLeadingZero(node.value, index);
- }
- });
- }
-
- if (neverFixPositions.length) {
- neverFixPositions.forEach(function(fixPosition) {
- const startIndex = fixPosition.startIndex;
- const endIndex = fixPosition.endIndex;
- if (node.type === "atrule") {
- node.params = removeLeadingZeros(node.params, startIndex, endIndex);
- } else {
- node.value = removeLeadingZeros(node.value, startIndex, endIndex);
- }
- });
- }
- }
-
- function complain(message, node, index) {
- report({
- result,
- ruleName,
- message,
- node,
- index
- });
- }
- };
-};
-
-function addLeadingZero(input, index) {
- return input.slice(0, index) + "0" + input.slice(index);
-}
-
-function removeLeadingZeros(input, startIndex, endIndex) {
- return input.slice(0, startIndex) + input.slice(endIndex);
-}
-
-rule.ruleName = ruleName;
-rule.messages = messages;
-module.exports = rule;