UNPKG

stylelint

Version:
211 lines (182 loc) 5.52 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = function (options, callback) { var source = options.source; var target = options.target; var insideString = false; var insideComment = false; var insideSingleLineComment = false; var insideParens = false; var insideFunction = false; var openingParenCount = 0; var matchCount = 0; var openingQuote = void 0; var ignoreStrings = !options.checkStrings && !options.withinStrings; var ignoreComments = !options.checkComments && !options.withinComments; var targetIsArray = Array.isArray(target); // If the target is just a string, it is easy to check whether // some index of the source matches it. // If the target is an array of strings, though, we have to // check whether some index of the source matches *any* of // those target strings (stopping after the first match). var getMatch = function () { if (!targetIsArray) { return getMatchBase.bind(null, target); } return function (index) { for (var ti = 0, tl = target.length; ti < tl; ti++) { var checkResult = getMatchBase(target[ti], index); if (checkResult) { return checkResult; } } return false; }; }(); function getMatchBase(targetString, index) { var targetStringLength = targetString.length; // Target is a single character if (targetStringLength === 1 && source[index] !== targetString) { return false; } // Target is multiple characters if (source.substr(index, targetStringLength) !== targetString) { return false; } return { insideParens: insideParens, insideFunction: insideFunction, insideComment: insideComment, insideString: insideString, startIndex: index, endIndex: index + targetStringLength, target: targetString }; } for (var i = 0, l = source.length; i < l; i++) { var currentChar = source[i]; // Register the beginning of a comment if (!insideString && !insideComment && currentChar === "/" && source[i - 1] !== "\\" // escaping ) { // standard comments if (source[i + 1] === "*") { insideComment = true; continue; } // single-line comments if (source[i + 1] === "/") { insideComment = true; insideSingleLineComment = true; continue; } } if (insideComment) { // Register the end of a standard comment if (!insideSingleLineComment && currentChar === "*" && source[i - 1] !== "\\" // escaping && source[i + 1] === "/" && source[i - 1] !== "/" // don't end if it's /*/ ) { insideComment = false; continue; } // Register the end of a single-line comment if (insideSingleLineComment && currentChar === "\n") { insideComment = false; insideSingleLineComment = false; } if (ignoreComments) { continue; } } // Register the beginning of a string if (!insideComment && !insideString && (currentChar === "\"" || currentChar === "'")) { if (source[i - 1] === "\\") { continue; } // escaping openingQuote = currentChar; insideString = true; // For string-quotes rule if (target === currentChar) { handleMatch(getMatch(i)); } continue; } if (insideString) { // Register the end of a string if (currentChar === openingQuote) { if (source[i - 1] === "\\") { continue; } // escaping insideString = false; continue; } if (ignoreStrings) { continue; } } // Register the beginning of parens/functions if (!insideString && !insideComment && currentChar === "(") { // Keep track of opening parentheses so that we // know when the outermost function (possibly // containing nested functions) is closing openingParenCount++; insideParens = true; // Only inside a function if there is a function name // before the opening paren if (/[a-zA-Z]/.test(source[i - 1])) { insideFunction = true; } if (target === "(") { handleMatch(getMatch(i)); } continue; } if (insideParens) { // Register the end of a function if (currentChar === ")") { openingParenCount--; // Do this here so it's still technically inside a function if (target === ")") { handleMatch(getMatch(i)); } if (openingParenCount === 0) { insideParens = false; insideFunction = false; } continue; } } // If this char is part of a function name, ignore it if (!options.checkFunctionNames && /^[a-zA-Z]*\(/.test(source.slice(i))) { continue; } var match = getMatch(i); if (!match) { continue; } handleMatch(match); if (options.onlyOne) { return; } } function handleMatch(match) { if (options.outsideParens && insideParens) { return; } if (options.withinFunctionalNotation && !insideFunction) { return; } if (options.outsideFunctionalNotation && insideFunction) { return; } if (options.withinStrings && !insideString) { return; } if (options.withinComments && !insideComment) { return; } matchCount++; callback(match, matchCount); } };