Skip to content

Commit

Permalink
Fix errors reported from non-CSS blocks for string-no-newline
Browse files Browse the repository at this point in the history
  • Loading branch information
gucong3000 committed Mar 20, 2018
1 parent c3f4abe commit ffdb273
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 18 deletions.
30 changes: 29 additions & 1 deletion lib/rules/string-no-newline/__tests__/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,22 +37,50 @@ testRule(rule, {
}`,

description: "attribute containing double-slash"
},
{
code: `<span
class="
className
"
/>
<style>
.selector {
--property: value;
}
</style>`,
description: "newline in html"
}
],

reject: [
{
code: "a::before { content: 'one\ntwo'; }",
description: "content LF",
message: messages.rejected,
line: 1,
column: 26
},
{
code: "a::before { content: 'one\r\ntwo'; }",
description: "CRLF",
description: "content CRLF",
message: messages.rejected,
line: 1,
column: 26
},
{
code: "a[href^='one\r\ntwo'] { display: block; }",
description: "attribute CRLF",
message: messages.rejected,
line: 1,
column: 12
},
{
code: "@charset 'utf-8\n';",
description: "atRule CRLF",
message: messages.rejected,
line: 1,
column: 16
}
]
});
Expand Down
90 changes: 73 additions & 17 deletions lib/rules/string-no-newline/index.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
"use strict";

const atRuleParamIndex = require("../../utils/atRuleParamIndex");
const declarationValueIndex = require("../../utils/declarationValueIndex");
const parseSelector = require("../../utils/parseSelector");
const report = require("../../utils/report");
const ruleMessages = require("../../utils/ruleMessages");
const styleSearch = require("style-search");
const validateOptions = require("../../utils/validateOptions");
const valueParser = require("postcss-value-parser");

const ruleName = "string-no-newline";
const reNewLine = /(\r?\n)/;

const messages = ruleMessages(ruleName, {
rejected: "Unexpected newline in string"
Expand All @@ -17,30 +21,82 @@ const rule = function(actual) {
if (!validOptions) {
return;
}
root.walk(node => {
switch (node.type) {
case "atrule":
checkDeclOrAtRule(node, node.params, atRuleParamIndex);
break;
case "decl":
checkDeclOrAtRule(node, node.value, declarationValueIndex);
break;
case "rule":
checkRule(node);
break;
}
});
function checkRule(rule) {
// Get out quickly if there are no new line
if (!reNewLine.test(rule.selector)) {
return;
}

parseSelector(rule.selector, result, rule, selectorTree => {
selectorTree.walkAttributes(attributeNode => {
if (!reNewLine.test(attributeNode.value)) {
return;
}

const openIndex = [
// length of our attribute
attributeNode.attribute,
// length of our operator , ie '='
attributeNode.operator,
// length of the contents before newline
RegExp.leftContext,
].reduce(
(index, str) => index + str.length,
// index of the start of our attribute node in our source
attributeNode.sourceIndex
);

report({
message: messages.rejected,
node: rule,
index: openIndex,
result,
ruleName
});
});
});
}

const cssString = root.toString();
styleSearch(
{
source: cssString,
target: "\n",
strings: "only"
},
match => {
const charBefore = cssString[match.startIndex - 1];
let index = match.startIndex;
if (charBefore === "\\") {
function checkDeclOrAtRule(node, value, getIndex) {
// Get out quickly if there are no new line
if (!reNewLine.test(value)) {
return;
}

valueParser(value).walk(valueNode => {
if (valueNode.type !== "string" || !reNewLine.test(valueNode.value)) {
return;
}
if (charBefore === "\r") index -= 1;

const openIndex = [
// length of the quote
valueNode.quote,
// length of the contents before newline
RegExp.leftContext,
].reduce((index, str) => index + str.length, valueNode.sourceIndex);

report({
message: messages.rejected,
node: root,
index,
node,
index: getIndex(node) + openIndex,
result,
ruleName
});
}
);
});
}
};
};

Expand Down

0 comments on commit ffdb273

Please sign in to comment.