Initial commit

This commit is contained in:
Patrick Marsceill
2017-03-09 13:16:08 -05:00
commit b7b0d0d7bf
4147 changed files with 401224 additions and 0 deletions

294
node_modules/stylelint/lib/rules/indentation/README.md generated vendored Normal file
View File

@@ -0,0 +1,294 @@
# indentation
Specify indentation.
```css
|@media print {
| a {
| background-position: top left,
| top right;
| }
|}
/** ↑ ↑ ↑
* The indentation at these three points */
```
## Options
`int|"tab"`, where `int` is the number of spaces
### `2`
Always indent at-rules, rules, comments, declarations, inside parentheses and multi-line values by 2 spaces.
The following patterns are considered warnings:
```css
@media print {
a {
background-position: top left,
top right;
}
}
```
```css
@media print {
a {
background-position: top left,
top right;
}
}
```
```css
@media print {
a {
background-position: top left,
top right;
}
}
```
```css
@media print {
a,
b {
background-position: top left,
top right;
}
}
```
```css
a {
/* blergh */
color: pink;
}
/* blergh */
```
```css
@media print,
(-webkit-min-device-pixel-ratio: 1.25),
(min-resolution: 120dpi) {}
```
```css
a {
color: rgb(
255,
255,
255
);
top: 0;
}
```
The following patterns are *not* considered warnings:
```css
@media print {
a {
background-position: top left,
top right;
}
}
```
```css
@media print {
a,
b {
background-position: top left,
top right;
}
}
```
```css
a {
/* blergh */
color: pink;
}
/* blergh */
```
```css
@media print,
(-webkit-min-device-pixel-ratio: 1.25),
(min-resolution: 120dpi) {}
```
```css
a {
color: rgb(
255,
255,
255
);
top: 0;
}
```
## Optional secondary options
### `indentInsideParens: "twice"|"once-at-root-twice-in-block"`
By default, *one extra* indentation (of your specified type) is expected after newlines inside parentheses, and the closing parenthesis is expected to have no extra indentation.
If you would like to change the quantity of extra indentation inside parentheses, use this option.
`"twice"` means you expect two extra indentations (of your specified type) after newlines inside parentheses, and expect the closing parenthesis to have one extra indentation. For example:
```css
a {
color: rgb(
255,
255,
255
);
top: 0;
}
```
`"once-at-root-twice-in-block"` means two things: You want the behavior of `"once"`, as documented above, when the parenthetical expression is part of a node that is an immediate descendent of the root — i.e. not inside a block. And you want the behavior of `"twice"`, as documented above, when the parenthetical expression is part of a node that is inside a block. For example, with a SCSS map:
```scss
$foo: (
bar: 1,
baz: 2
);
a {
color: rgb(
255,
255,
255
);
top: 0;
}
```
### `indentClosingBrace: true|false`
If `true`, the closing brace of a block (rule or at-rule) will be expected at the same indentation level as the block's inner nodes.
For example, with `indentClosingBrace: true`.
The following patterns are considered warnings:
```css
a {
color: pink;
}
```
```css
@media print {
a {
color: pink;
}
}
```
The following patterns are *not* considered warnings:
```css
a {
color: pink;
}
```
```css
@media print {
a {
color: pink;
}
}
```
### `except: ["block", "param", "value"]`
Do *not* indent for these things.
For example, with `2`.
The following patterns are considered warnings:
```css
@media print,
(-webkit-min-device-pixel-ratio: 1.25),
(min-resolution: 120dpi) {
a {
background-position: top left,
top right;
}
}
```
The following patterns are *not* considered warnings:
```css
@media print,
(-webkit-min-device-pixel-ratio: 1.25),
(min-resolution: 120dpi) {
a {
background-position: top left,
top right;
}
}
```
### `ignore: ["inside-parens", "param", "value"]`
#### `"inside-parens"`
Ignore the indentation inside parentheses.
For example, with `2`.
The following patterns are *not* considered warnings:
```css
a {
color: rgb(
255,
255,
255
);
top: 0;
}
```
#### `"param"`
Ignore the indentation of at-rule params.
For example, with `2`.
The following patterns are *not* considered warnings:
```css
@media print,
(-webkit-min-device-pixel-ratio: 1.25),
(min-resolution: 120dpi) {
}
```
#### `"value"`
Ignore the indentation of values.
For example, with `2`.
The following patterns are *not* considered warnings:
```css
a {
background-position: top left,
top right,
bottom left,
bottom right;
}
```

275
node_modules/stylelint/lib/rules/indentation/index.js generated vendored Normal file
View File

@@ -0,0 +1,275 @@
"use strict"
const beforeBlockString = require("../../utils/beforeBlockString")
const hasBlock = require("../../utils/hasBlock")
const optionsMatches = require("../../utils/optionsMatches")
const report = require("../../utils/report")
const ruleMessages = require("../../utils/ruleMessages")
const validateOptions = require("../../utils/validateOptions")
const _ = require("lodash")
const styleSearch = require("style-search")
const ruleName = "indentation"
const messages = ruleMessages(ruleName, {
expected: x => `Expected indentation of ${x}`,
})
/**
* @param {number|"tab"} space - Number of whitespaces to expect, or else
* keyword "tab" for single `\t`
* @param {object} [options]
*/
const rule = function (space) {
const options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}
const isTab = space === "tab"
const indentChar = isTab ? "\t" : _.repeat(" ", space)
const warningWord = isTab ? "tab" : "space"
return (root, result) => {
const validOptions = validateOptions(result, ruleName, {
actual: space,
possible: [
_.isNumber,
"tab",
],
}, {
actual: options,
possible: {
except: [
"block",
"value",
"param",
],
ignore: [
"value",
"param",
"inside-parens",
],
indentInsideParens: [
"twice",
"once-at-root-twice-in-block",
],
indentClosingBrace: [_.isBoolean],
},
optional: true,
})
if (!validOptions) {
return
}
// Cycle through all nodes using walk.
root.walk(node => {
const nodeLevel = indentationLevel(node)
const expectedWhitespace = _.repeat(indentChar, nodeLevel)
let before = (node.raws.before || "")
const after = (node.raws.after || "")
// Only inspect the spaces before the node
// if this is the first node in root
// or there is a newline in the `before` string.
// (If there is no newline before a node,
// there is no "indentation" to check.)
const inspectBefore = root.first === node || before.indexOf("\n") !== -1
// Cut out any * hacks from `before`
before = before[before.length - 1] === "*" || before[before.length - 1] === "_" ? before.slice(0, before.length - 1) : before
// Inspect whitespace in the `before` string that is
// *after* the *last* newline character,
// because anything besides that is not indentation for this node:
// it is some other kind of separation, checked by some separate rule
if (inspectBefore && before.slice(before.lastIndexOf("\n") + 1) !== expectedWhitespace) {
report({
message: messages.expected(legibleExpectation(nodeLevel)),
node,
result,
ruleName,
})
}
// Only blocks have the `after` string to check.
// Only inspect `after` strings that start with a newline;
// otherwise there's no indentation involved.
// And check `indentClosingBrace` to see if it should be indented an extra level.
const closingBraceLevel = options.indentClosingBrace ? nodeLevel + 1 : nodeLevel
if (hasBlock(node) && after && after.indexOf("\n") !== -1 && after.slice(after.lastIndexOf("\n") + 1) !== _.repeat(indentChar, closingBraceLevel)) {
report({
message: messages.expected(legibleExpectation(closingBraceLevel)),
node,
index: node.toString().length - 1,
result,
ruleName,
})
}
// If this is a declaration, check the value
if (node.value) {
checkValue(node, nodeLevel)
}
// If this is a rule, check the selector
if (node.selector) {
checkSelector(node, nodeLevel)
}
// If this is an at rule, check the params
if (node.type === "atrule") {
checkAtRuleParams(node, nodeLevel)
}
})
function indentationLevel(node) {
const level = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0
if (node.parent.type === "root") {
return level
}
let calculatedLevel
// Indentation level equals the ancestor nodes
// separating this node from root; so recursively
// run this operation
calculatedLevel = indentationLevel(node.parent, level + 1)
// If options.except includes "block",
// blocks are taken down one from their calculated level
// (all blocks are the same level as their parents)
if (optionsMatches(options, "except", "block") && (node.type === "rule" || node.type === "atrule") && hasBlock(node)) {
calculatedLevel--
}
return calculatedLevel
}
function checkValue(decl, declLevel) {
if (decl.value.indexOf("\n") === -1) {
return
}
if (optionsMatches(options, "ignore", "value")) {
return
}
const declString = decl.toString()
const valueLevel = optionsMatches(options, "except", "value") ? declLevel : declLevel + 1
checkMultilineBit(declString, valueLevel, decl)
}
function checkSelector(rule, ruleLevel) {
const selector = rule.selector
// Less mixins have params, and they should be indented extra
if (rule.params) {
ruleLevel += 1
}
checkMultilineBit(selector, ruleLevel, rule)
}
function checkAtRuleParams(atRule, ruleLevel) {
if (optionsMatches(options, "ignore", "param")) {
return
}
// @nest rules should be treated like regular rules, not expected
// to have their params (selectors) indented
const paramLevel = optionsMatches(options, "except", "param") || atRule.name === "nest" ? ruleLevel : ruleLevel + 1
checkMultilineBit(beforeBlockString(atRule).trim(), paramLevel, atRule)
}
function checkMultilineBit(source, newlineIndentLevel, node) {
if (source.indexOf("\n") === -1) {
return
}
// `outsideParens` because function arguments and also non-standard parenthesized stuff like
// Sass maps are ignored to allow for arbitrary indentation
let parentheticalDepth = 0
styleSearch({
source,
target: "\n",
outsideParens: optionsMatches(options, "ignore", "inside-parens"),
}, (match, matchCount) => {
const precedesClosingParenthesis = /^[ \t]*\)/.test(source.slice(match.startIndex + 1))
if (optionsMatches(options, "ignore", "inside-parens") && (precedesClosingParenthesis || match.insideParens)) {
return
}
let expectedIndentLevel = newlineIndentLevel
// Modififications for parenthetical content
if (!optionsMatches(options, "ignore", "inside-parens") && match.insideParens) {
// If the first match in is within parentheses, reduce the parenthesis penalty
if (matchCount === 1) parentheticalDepth -= 1
// Account for windows line endings
let newlineIndex = match.startIndex
if (source[match.startIndex - 1] === "\r") {
newlineIndex--
}
const followsOpeningParenthesis = /\([ \t]*$/.test(source.slice(0, newlineIndex))
if (followsOpeningParenthesis) {
parentheticalDepth += 1
}
expectedIndentLevel += parentheticalDepth
if (precedesClosingParenthesis) {
parentheticalDepth -= 1
}
switch (options.indentInsideParens) {
case "twice":
if (!precedesClosingParenthesis || options.indentClosingBrace) {
expectedIndentLevel += 1
}
break
case "once-at-root-twice-in-block":
if (node.parent === root) {
if (precedesClosingParenthesis && !options.indentClosingBrace) {
expectedIndentLevel -= 1
}
break
}
if (!precedesClosingParenthesis || options.indentClosingBrace) {
expectedIndentLevel += 1
}
break
default:
if (precedesClosingParenthesis && !options.indentClosingBrace) {
expectedIndentLevel -= 1
}
}
}
// Starting at the index after the newline, we want to
// check that the whitespace characters (excluding newlines) before the first
// non-whitespace character equal the expected indentation
const afterNewlineSpaceMatches = /^([ \t]*)\S/.exec(source.slice(match.startIndex + 1))
if (!afterNewlineSpaceMatches) {
return
}
const afterNewlineSpace = afterNewlineSpaceMatches[1]
if (afterNewlineSpace !== _.repeat(indentChar, expectedIndentLevel)) {
report({
message: messages.expected(legibleExpectation(expectedIndentLevel)),
node,
index: match.startIndex + afterNewlineSpace.length + 1,
result,
ruleName,
})
}
})
}
}
function legibleExpectation(level) {
const count = isTab ? level : level * space
const quantifiedWarningWord = count === 1 ? warningWord : warningWord + "s"
return `${count} ${quantifiedWarningWord}`
}
}
rule.ruleName = ruleName
rule.messages = messages
module.exports = rule