Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #331 from rambleraptor/map-quotes
Ensure that all map keys are quoted
- Loading branch information
Showing
4 changed files
with
140 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
# map-keys-quotes | ||
|
||
All map keys should be quoted. | ||
|
||
```scss | ||
$test: (Helvetica: 14px, Arial: 25px); | ||
/** ↑ ↑ | ||
* These words should be quoted. | ||
*/ | ||
``` | ||
|
||
## Options | ||
|
||
### `always` | ||
|
||
The following patterns are considered violations: | ||
|
||
```scss | ||
$test: (Helvetica: 14px, Arial: 25px); | ||
``` | ||
|
||
The following patterns are _not_ considered violations: | ||
|
||
```scss | ||
$test: ("foo": 14px, "bar": 25px); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import rule, { ruleName, messages } from ".."; | ||
|
||
testRule(rule, { | ||
ruleName, | ||
config: ["always"], | ||
syntax: "scss", | ||
|
||
accept: [ | ||
{ | ||
code: ` | ||
$test: ("foo": 14px, "bar": 25px); | ||
`, | ||
description: "accepts strings without quotes" | ||
} | ||
], | ||
|
||
reject: [ | ||
{ | ||
code: ` | ||
$test: (Helvetica: 25px, Arial: 50px) | ||
`, | ||
message: messages.expected, | ||
description: | ||
"does not accept variables representing strings that are quoted.", | ||
location: 1 | ||
} | ||
] | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
import { utils } from "stylelint"; | ||
import { namespace } from "../../utils"; | ||
import valueParser from "postcss-value-parser"; | ||
|
||
export const ruleName = namespace("map-keys-quotes"); | ||
|
||
export const messages = utils.ruleMessages(ruleName, { | ||
expected: "Expected keys in map to be quoted." | ||
}); | ||
|
||
function rule(primary) { | ||
return (root, result) => { | ||
const validOptions = utils.validateOptions(result, ruleName, { | ||
actual: primary, | ||
possible: ["always"] | ||
}); | ||
|
||
if (!validOptions) { | ||
return; | ||
} | ||
|
||
root.walkDecls(decl => { | ||
if (decl.prop[0] !== "$") { | ||
return; | ||
} | ||
|
||
valueParser(decl.value).walk(node => { | ||
if ( | ||
node.type === "function" && | ||
node.value === "" && | ||
isMap(node.nodes) | ||
) { | ||
// Identify all of the map-keys and see if they're strings (not words). | ||
const mapKeys = returnMapKeys(node.nodes); | ||
|
||
mapKeys.forEach(map_key => { | ||
if (map_key.type === "word") { | ||
utils.report({ | ||
message: messages.expected, | ||
node: decl, | ||
result, | ||
ruleName | ||
}); | ||
} | ||
}); | ||
} | ||
}); | ||
}); | ||
}; | ||
} | ||
|
||
// Takes in a list of map nodes and identifies if they are a map. | ||
// A map is identified by the pattern: [string/word colon(div) anything comma(div) ...] | ||
function isMap(nodes) { | ||
if (nodes.length < 4) { | ||
return false; | ||
} | ||
|
||
if (nodes[0].type !== "word" && nodes[0].type !== "string") { | ||
return false; | ||
} | ||
|
||
if (nodes[1].value !== ":") { | ||
return false; | ||
} | ||
|
||
if (nodes[3].value !== ",") { | ||
return false; | ||
} | ||
|
||
return true; | ||
} | ||
|
||
function returnMapKeys(array) { | ||
const new_array = []; | ||
|
||
for (let i = 0; i < array.length; i += 4) { | ||
new_array.push(array[i]); | ||
} | ||
|
||
return new_array; | ||
} | ||
|
||
export default rule; |