<commit_before>'use strict';
module.exports = {
    "extends"    : [],
    "plugins"    : [],
    "ignoreFiles": [],
    "rules"      : {
        "color-hex-case"                                   : [
            "lower",
            {
                "severity": "error"
            }
        ],
        "color-hex-length"                                 : [
            "short",
            {
                "severity": "error"
            }
        ],
        "color-named"                                      : [
            "always-where-possible",
            {
                "severity": "error"
            }
        ],
        "color-no-hex"                                     : [
            null,
            {
                "severity": "error"
            }
        ],
        "color-no-invalid-hex"                             : [
            true,
            {
                "severity": "error"
            }
        ],
        "font-family-name-quotes"                          : [
            "single-where-recommended",
            {
                "severity": "error"
            }
        ],
        "font-weight-notation"                             : [
            "named-where-possible",
            {
                "ignore"  : [],
                "severity": "error"
            }
        ],
        "function-blacklist"                               : [
            null,
            {
                "severity": "error"
            }
        ],
        "function-calc-no-unspaced-operator"               : [
            true,
            {
                "severity": "error"
            }
        ],
        "function-comma-newline-after"                     : [
            "always-multi-line",
            {
                "severity": "error"
            }
        ],
        "function-comma-newline-before"                    : [
            "never-multi-line",
            {
                "severity": "error"
            }
        ],
        "function-comma-space-after"                       : [
            "always",
            {
                "severity": "error"
            }
        ],
        "function-comma-space-before"                      : [
            "never",
            {
                "severity": "error"
            }
        ],
        "function-linear-gradient-no-nonstandard-direction": [
            true,
            {
                "severity": "error"
            }
        ],
        "function-parentheses-newline-inside"              : [
            "never-multi-line",
            {
                "severity": "error"
            }
        ],
        "function-parentheses-space-inside"                : [
            "never-single-line",
            {
                "severity": "error"
            }
        ],
        "function-url-quotes"                              : [
            "none",
            {
                "severity": "error"
            }
        ],
        "function-whitelist"                               : [
            null,
            {
                "severity": "error"
            }
        ],
        "function-whitespace-after"                        : [
            "always",
            {
                "severity": "error"
            }
        ],
        "number-leading-zero"                              : [
            "never",
            {
                "severity": "error"
            }
        ],
        "number-max-precision"                             : [
            5,
            {
                "severity": "error"
            }
        ],
        "number-no-trailing-zeros"                         : [
            true,
            {
                "severity": "error"
            }
        ],
        "number-zero-length-no-unit"                       : [
            true,
            {
                "severity": "error"
            }
        ],
        "string-no-newline"                                : [
            true,
            {
                "severity": "error"
            }
        ],
        "string-quotes"                                    : [
            "single",
            {
                "severity": "error"
            }
        ],
        "time-no-imperceptible"                            : [
            true,
            {
                "severity": "error"
            }
        ],
        "unit-blacklist"                                   : [
            null,
            {
                "severity": "error"
            }
        ],
        "unit-whitelist"                                   : [
            null,
            {
                "severity": "error"
            }
        ],
        "value-no-vendor-prefix"                           : [
            true,
            {
                "severity": "error"
            }
        ],
        "value-list-comma-newline-after"                   : [
            "always-multi-line",
            {
                "severity": "error"
            }
        ],
        "value-list-comma-newline-before"                  : [
            "never-multi-line",
            {
                "severity": "error"
            }
        ],
        "value-list-comma-space-after"                     : [
            "always",
            {
                "severity": "error"
            }
        ],
        "value-list-comma-space-before"                    : [
            "never",
            {
                "severity": "error"
            }
        ],
        "custom-property-no-outside-root"                  : [
            true,
            {
                "severity": "error"
            }
        ],
        "custom-property-pattern"                          : [
            null,
            {
                "severity": "error"
            }
        ],
        "property-blacklist"                               : [
            null,
            {
                "severity": "error"
            }
        ],
        "property-no-vendor-prefix"                        : [
            true,
            {
                "severity": "error"
            }
        ],
        "property-unit-blacklist"                          : [
            null,
            {
                "severity": "error"
            }
        ],
        "property-unit-whitelist"                          : [
            null,
            {
                "severity": "error"
            }
        ],
        "property-value-blacklist"                         : [
            null,
            {
                "severity": "error"
            }
        ],
        "property-value-whitelist"                         : [
            null,
            {
                "severity": "error"
            }
        ],
        "property-whitelist"                               : [
            null,
            {
                "severity": "error"
            }
        ],
        "declaration-bang-space-after"                     : [
            "always",
            {
                "severity": "error"
            }
        ],
        "declaration-bang-space-before"                    : [
            "never",
            {
                "severity": "error"
            }
        ],
        "declaration-colon-newline-after"                  : [
            "always-multi-line",
            {
                "severity": "error"
            }
        ],
        "declaration-colon-space-after"                    : [
            "always",
            {
                "severity": "error"
            }
        ],
        "declaration-colon-space-before"                   : [
            "never",
            {
                "severity": "error"
            }
        ],
        "declaration-no-important"                         : [
            true,
            {
                "severity": "warning"
            }
        ],
        "declaration-block-no-duplicate-properties"        : [
            true,
            {
                "severity": "warning"
            }
        ],
        "declaration-block-no-shorthand-property-overrides": [
            true,
            {
                "severity": "error"
            }
        ],
        "declaration-block-properties-order"               : [
            null,
            {
                "unspecified": "bottomAlphabetical",
                "severity"   : "error"
            }
        ],
        "declaration-block-semicolon-newline-after"        : [
            "always",
            {
                "severity": "error"
            }
        ],
        "declaration-block-semicolon-newline-before"       : [
            "never-multi-line",
            {
                "severity": "error"
            }
        ],
        "declaration-block-semicolon-space-after"          : [
            "always-single-line",
            {
                "severity": "error"
            }
        ],
        "declaration-block-semicolon-space-before"         : [
            "never",
            {
                "severity": "error"
            }
        ],
        "declaration-block-single-line-max-declarations"   : [
            1,
            {
                "severity": "error"
            }
        ],
        "declaration-block-trailing-semicolon"             : [
            "always",
            {
                "severity": "error"
            }
        ],
        "block-closing-brace-newline-after"                : [
            "always",
            {
                "ignoreAtRules": [],
                "severity"     : "error"
            }
        ],
        "block-closing-brace-newline-before"               : [
            "always",
            {
                "severity": "error"
            }
        ],
        "block-closing-brace-space-after"                  : [
            "always-single-line",
            {
                "severity": "error"
            }
        ],
        "block-closing-brace-space-before"                 : [
            "always-single-line",
            {
                "severity": "error"
            }
        ],
        "block-no-empty"                                   : [
            true,
            {
                "severity": "warning"
            }
        ],
        "block-no-single-line"                             : [
            true,
            {
                "severity": "error"
            }
        ],
        "block-opening-brace-newline-after"                : [
            "always",
            {
                "severity": "error"
            }
        ],
        "block-opening-brace-newline-before"               : [
            "always",
            {
                "ignoreAtRules": [],
                "severity"     : "error"
            }
        ],
        "block-opening-brace-space-after"                  : [
            "always-single-line",
            {
                "severity": "error"
            }
        ],
        "block-opening-brace-space-before"                 : [
            "always-single-line",
            {
                "ignoreAtRules": [],
                "severity"     : "error"
            }
        ],
        "selector-class-pattern"                           : [
            "^[a-z][-_a-z0-9]*$",
            {
                "resolveNestedSelectors": true,
                "severity"              : "error"
            }
        ],
        "selector-combinator-space-after"                  : [
            "always",
            {
                "severity": "error"
            }
        ],
        "selector-combinator-space-before"                 : [
            "always",
            {
                "severity": "error"
            }
        ],
        "selector-id-pattern"                              : [
            "^[a-z][-_a-z0-9]*$",
            {
                "severity": "error"
            }
        ],
        "selector-max-specificity"                         : [
            "0,2,0",
            {
                "severity": "warning"
            }
        ],
        "selector-no-attribute"                            : [
            null,
            {
                "severity": "error"
            }
        ],
        "selector-no-combinator"                           : [
            null,
            {
                "severity": "error"
            }
        ],
        "selector-no-id"                                   : [
            true,
            {
                "severity": "warning"
            }
        ],
        "selector-no-type"                                 : [
            true,
            {
                "ignore"  : [
                    "descendant"
                ],
                "severity": "error"
            }
        ],
        "selector-no-universal"                            : [
            true,
            {
                "severity": "warning"
            }
        ],
        "selector-no-vendor-prefix"                        : [
            true,
            {
                "severity": "error"
            }
        ],
        "selector-pseudo-element-colon-notation"           : [
            "double",
            {
                "severity": "error"
            }
        ],
        "selector-root-no-composition"                     : [
            true,
            {
                "severity": "error"
            }
        ],
        "selector-type-case"                               : [
            "lower",
            {
                "severity": "error"
            }
        ],
        "selector-list-comma-newline-after"                : [
            "always",
            {
                "severity": "error"
            }
        ],
        "selector-list-comma-newline-before"               : [
            "never-multi-line",
            {
                "severity": "error"
            }
        ],
        "selector-list-comma-space-after"                  : [
            "always-single-line",
            {
                "severity": "error"
            }
        ],
        "selector-list-comma-space-before"                 : [
            "never",
            {
                "severity": "error"
            }
        ],
        "root-no-standard-properties"                      : [
            true,
            {
                "severity": "error"
            }
        ],
        "rule-nested-empty-line-before"                    : [
            "always",
            {
                "except"  : [
                    "first-nested"
                ],
                "ignore"  : [
                    "after-comment"
                ],
                "severity": "error"
            }
        ],
        "rule-non-nested-empty-line-before"                : [
            "always-multi-line",
            {
                "ignore"  : [
                    "after-comment"
                ],
                "severity": "error"
            }
        ],
        "media-feature-colon-space-after"                  : [
            "always",
            {
                "severity": "error"
            }
        ],
        "media-feature-colon-space-before"                 : [
            "never",
            {
                "severity": "error"
            }
        ],
        "media-feature-name-no-vendor-prefix"              : [
            true,
            {
                "severity": "error"
            }
        ],
        "media-feature-no-missing-punctuation"             : [
            true,
            {
                "severity": "error"
            }
        ],
        "media-feature-range-operator-space-after"         : [
            "always",
            {
                "severity": "error"
            }
        ],
        "media-feature-range-operator-space-before"        : [
            "always",
            {
                "severity": "error"
            }
        ],
        "custom-media-pattern"                             : [
            null,
            {
                "severity": "error"
            }
        ],
        "media-query-parentheses-space-inside"             : [
            "never",
            {
                "severity": "error"
            }
        ],
        "media-query-list-comma-newline-after"             : [
            "always-multi-line",
            {
                "severity": "error"
            }
        ],
        "media-query-list-comma-newline-before"            : [
            "never-multi-line",
            {
                "severity": "error"
            }
        ],
        "media-query-list-comma-space-after"               : [
            "always-single-line",
            {
                "severity": "error"
            }
        ],
        "media-query-list-comma-space-before"              : [
            "never",
            {
                "severity": "error"
            }
        ],
        "at-rule-empty-line-before"                        : [
            "always",
            {
                "except"  : [
                    "blockless-group",
                    "first-nested"
                ],
                "ignore"  : [
                    "after-comment"
                ],
                "severity": "error"
            }
        ],
        "at-rule-no-vendor-prefix"                         : [
            true,
            {
                "severity": "error"
            }
        ],
        "comment-empty-line-before"                        : [
            "always",
            {
                "except"  : [
                    "first-nested"
                ],
                "ignore"  : [],
                "severity": "error"
            }
        ],
        "comment-whitespace-inside"                        : [
            "always",
            {
                "severity": "error"
            }
        ],
        "indentation"                                      : [
            4,
            {
                "except"               : [],
                "ignore"               : [],
                "hierarchicalSelectors": true,
                "severity"             : "error"
            }
        ],
        "max-empty-lines"                                  : [
            1,
            {
                "severity": "error"
            }
        ],
        "max-line-length"                                  : [
            120,
            {
                "ignore"  : [],
                "severity": "error"
            }
        ],
        "max-nesting-depth"                                : [
            2,
            {
                "ignore"  : [
                    "at-rules-without-declaration-blocks"
                ],
                "severity": "warning"
            }
        ],
        "no-browser-hacks"                                 : [
            true,
            {
                "severity": "error"
            }
        ],
        "no-descending-specificity"                        : [
            true,
            {
                "severity": "error"
            }
        ],
        "no-duplicate-selectors"                           : [
            true,
            {
                "severity": "error"
            }
        ],
        "no-eol-whitespace"                                : [
            true,
            {
                "severity": "error"
            }
        ],
        "no-indistinguishable-colors"                      : [
            true,
            {
                "threshold": 3,
                "ignore"   : [],
                "whitelist": [],
                "severity" : "warning"
            }
        ],
        "no-invalid-double-slash-comments"                 : [
            true,
            {
                "severity": "error"
            }
        ],
        "no-missing-eof-newline"                           : [
            true,
            {
                "severity": "error"
            }
        ],
        "no-unknown-animations"                            : [
            true,
            {
                "severity": "error"
            }
        ],
        "no-unsupported-browser-features"                  : [
            true,
            {
                "ignore"  : [],
                "severity": "warning"
            }
        ]
    }
};
<commit_msg>add new `at-rule-blockless-newline-after` rule<commit_after>'use strict';
module.exports = {
    "extends"    : [],
    "plugins"    : [],
    "ignoreFiles": [],
    "rules"      : {
        "color-hex-case"                                   : [
            "lower",
            {
                "severity": "error"
            }
        ],
        "color-hex-length"                                 : [
            "short",
            {
                "severity": "error"
            }
        ],
        "color-named"                                      : [
            "always-where-possible",
            {
                "severity": "error"
            }
        ],
        "color-no-hex"                                     : [
            null,
            {
                "severity": "error"
            }
        ],
        "color-no-invalid-hex"                             : [
            true,
            {
                "severity": "error"
            }
        ],
        "font-family-name-quotes"                          : [
            "single-where-recommended",
            {
                "severity": "error"
            }
        ],
        "font-weight-notation"                             : [
            "named-where-possible",
            {
                "ignore"  : [],
                "severity": "error"
            }
        ],
        "function-blacklist"                               : [
            null,
            {
                "severity": "error"
            }
        ],
        "function-calc-no-unspaced-operator"               : [
            true,
            {
                "severity": "error"
            }
        ],
        "function-comma-newline-after"                     : [
            "always-multi-line",
            {
                "severity": "error"
            }
        ],
        "function-comma-newline-before"                    : [
            "never-multi-line",
            {
                "severity": "error"
            }
        ],
        "function-comma-space-after"                       : [
            "always",
            {
                "severity": "error"
            }
        ],
        "function-comma-space-before"                      : [
            "never",
            {
                "severity": "error"
            }
        ],
        "function-linear-gradient-no-nonstandard-direction": [
            true,
            {
                "severity": "error"
            }
        ],
        "function-parentheses-newline-inside"              : [
            "never-multi-line",
            {
                "severity": "error"
            }
        ],
        "function-parentheses-space-inside"                : [
            "never-single-line",
            {
                "severity": "error"
            }
        ],
        "function-url-quotes"                              : [
            "none",
            {
                "severity": "error"
            }
        ],
        "function-whitelist"                               : [
            null,
            {
                "severity": "error"
            }
        ],
        "function-whitespace-after"                        : [
            "always",
            {
                "severity": "error"
            }
        ],
        "number-leading-zero"                              : [
            "never",
            {
                "severity": "error"
            }
        ],
        "number-max-precision"                             : [
            5,
            {
                "severity": "error"
            }
        ],
        "number-no-trailing-zeros"                         : [
            true,
            {
                "severity": "error"
            }
        ],
        "number-zero-length-no-unit"                       : [
            true,
            {
                "severity": "error"
            }
        ],
        "string-no-newline"                                : [
            true,
            {
                "severity": "error"
            }
        ],
        "string-quotes"                                    : [
            "single",
            {
                "severity": "error"
            }
        ],
        "time-no-imperceptible"                            : [
            true,
            {
                "severity": "error"
            }
        ],
        "unit-blacklist"                                   : [
            null,
            {
                "severity": "error"
            }
        ],
        "unit-whitelist"                                   : [
            null,
            {
                "severity": "error"
            }
        ],
        "value-no-vendor-prefix"                           : [
            true,
            {
                "severity": "error"
            }
        ],
        "value-list-comma-newline-after"                   : [
            "always-multi-line",
            {
                "severity": "error"
            }
        ],
        "value-list-comma-newline-before"                  : [
            "never-multi-line",
            {
                "severity": "error"
            }
        ],
        "value-list-comma-space-after"                     : [
            "always",
            {
                "severity": "error"
            }
        ],
        "value-list-comma-space-before"                    : [
            "never",
            {
                "severity": "error"
            }
        ],
        "custom-property-no-outside-root"                  : [
            true,
            {
                "severity": "error"
            }
        ],
        "custom-property-pattern"                          : [
            null,
            {
                "severity": "error"
            }
        ],
        "property-blacklist"                               : [
            null,
            {
                "severity": "error"
            }
        ],
        "property-no-vendor-prefix"                        : [
            true,
            {
                "severity": "error"
            }
        ],
        "property-unit-blacklist"                          : [
            null,
            {
                "severity": "error"
            }
        ],
        "property-unit-whitelist"                          : [
            null,
            {
                "severity": "error"
            }
        ],
        "property-value-blacklist"                         : [
            null,
            {
                "severity": "error"
            }
        ],
        "property-value-whitelist"                         : [
            null,
            {
                "severity": "error"
            }
        ],
        "property-whitelist"                               : [
            null,
            {
                "severity": "error"
            }
        ],
        "declaration-bang-space-after"                     : [
            "always",
            {
                "severity": "error"
            }
        ],
        "declaration-bang-space-before"                    : [
            "never",
            {
                "severity": "error"
            }
        ],
        "declaration-colon-newline-after"                  : [
            "always-multi-line",
            {
                "severity": "error"
            }
        ],
        "declaration-colon-space-after"                    : [
            "always",
            {
                "severity": "error"
            }
        ],
        "declaration-colon-space-before"                   : [
            "never",
            {
                "severity": "error"
            }
        ],
        "declaration-no-important"                         : [
            true,
            {
                "severity": "warning"
            }
        ],
        "declaration-block-no-duplicate-properties"        : [
            true,
            {
                "severity": "warning"
            }
        ],
        "declaration-block-no-shorthand-property-overrides": [
            true,
            {
                "severity": "error"
            }
        ],
        "declaration-block-properties-order"               : [
            null,
            {
                "unspecified": "bottomAlphabetical",
                "severity"   : "error"
            }
        ],
        "declaration-block-semicolon-newline-after"        : [
            "always",
            {
                "severity": "error"
            }
        ],
        "declaration-block-semicolon-newline-before"       : [
            "never-multi-line",
            {
                "severity": "error"
            }
        ],
        "declaration-block-semicolon-space-after"          : [
            "always-single-line",
            {
                "severity": "error"
            }
        ],
        "declaration-block-semicolon-space-before"         : [
            "never",
            {
                "severity": "error"
            }
        ],
        "declaration-block-single-line-max-declarations"   : [
            1,
            {
                "severity": "error"
            }
        ],
        "declaration-block-trailing-semicolon"             : [
            "always",
            {
                "severity": "error"
            }
        ],
        "block-closing-brace-newline-after"                : [
            "always",
            {
                "ignoreAtRules": [],
                "severity"     : "error"
            }
        ],
        "block-closing-brace-newline-before"               : [
            "always",
            {
                "severity": "error"
            }
        ],
        "block-closing-brace-space-after"                  : [
            "always-single-line",
            {
                "severity": "error"
            }
        ],
        "block-closing-brace-space-before"                 : [
            "always-single-line",
            {
                "severity": "error"
            }
        ],
        "block-no-empty"                                   : [
            true,
            {
                "severity": "warning"
            }
        ],
        "block-no-single-line"                             : [
            true,
            {
                "severity": "error"
            }
        ],
        "block-opening-brace-newline-after"                : [
            "always",
            {
                "severity": "error"
            }
        ],
        "block-opening-brace-newline-before"               : [
            "always",
            {
                "ignoreAtRules": [],
                "severity"     : "error"
            }
        ],
        "block-opening-brace-space-after"                  : [
            "always-single-line",
            {
                "severity": "error"
            }
        ],
        "block-opening-brace-space-before"                 : [
            "always-single-line",
            {
                "ignoreAtRules": [],
                "severity"     : "error"
            }
        ],
        "selector-class-pattern"                           : [
            "^[a-z][-_a-z0-9]*$",
            {
                "resolveNestedSelectors": true,
                "severity"              : "error"
            }
        ],
        "selector-combinator-space-after"                  : [
            "always",
            {
                "severity": "error"
            }
        ],
        "selector-combinator-space-before"                 : [
            "always",
            {
                "severity": "error"
            }
        ],
        "selector-id-pattern"                              : [
            "^[a-z][-_a-z0-9]*$",
            {
                "severity": "error"
            }
        ],
        "selector-max-specificity"                         : [
            "0,2,0",
            {
                "severity": "warning"
            }
        ],
        "selector-no-attribute"                            : [
            null,
            {
                "severity": "error"
            }
        ],
        "selector-no-combinator"                           : [
            null,
            {
                "severity": "error"
            }
        ],
        "selector-no-id"                                   : [
            true,
            {
                "severity": "warning"
            }
        ],
        "selector-no-type"                                 : [
            true,
            {
                "ignore"  : [
                    "descendant"
                ],
                "severity": "error"
            }
        ],
        "selector-no-universal"                            : [
            true,
            {
                "severity": "warning"
            }
        ],
        "selector-no-vendor-prefix"                        : [
            true,
            {
                "severity": "error"
            }
        ],
        "selector-pseudo-element-colon-notation"           : [
            "double",
            {
                "severity": "error"
            }
        ],
        "selector-root-no-composition"                     : [
            true,
            {
                "severity": "error"
            }
        ],
        "selector-type-case"                               : [
            "lower",
            {
                "severity": "error"
            }
        ],
        "selector-list-comma-newline-after"                : [
            "always",
            {
                "severity": "error"
            }
        ],
        "selector-list-comma-newline-before"               : [
            "never-multi-line",
            {
                "severity": "error"
            }
        ],
        "selector-list-comma-space-after"                  : [
            "always-single-line",
            {
                "severity": "error"
            }
        ],
        "selector-list-comma-space-before"                 : [
            "never",
            {
                "severity": "error"
            }
        ],
        "root-no-standard-properties"                      : [
            true,
            {
                "severity": "error"
            }
        ],
        "rule-nested-empty-line-before"                    : [
            "always",
            {
                "except"  : [
                    "first-nested"
                ],
                "ignore"  : [
                    "after-comment"
                ],
                "severity": "error"
            }
        ],
        "rule-non-nested-empty-line-before"                : [
            "always-multi-line",
            {
                "ignore"  : [
                    "after-comment"
                ],
                "severity": "error"
            }
        ],
        "media-feature-colon-space-after"                  : [
            "always",
            {
                "severity": "error"
            }
        ],
        "media-feature-colon-space-before"                 : [
            "never",
            {
                "severity": "error"
            }
        ],
        "media-feature-name-no-vendor-prefix"              : [
            true,
            {
                "severity": "error"
            }
        ],
        "media-feature-no-missing-punctuation"             : [
            true,
            {
                "severity": "error"
            }
        ],
        "media-feature-range-operator-space-after"         : [
            "always",
            {
                "severity": "error"
            }
        ],
        "media-feature-range-operator-space-before"        : [
            "always",
            {
                "severity": "error"
            }
        ],
        "custom-media-pattern"                             : [
            null,
            {
                "severity": "error"
            }
        ],
        "media-query-parentheses-space-inside"             : [
            "never",
            {
                "severity": "error"
            }
        ],
        "media-query-list-comma-newline-after"             : [
            "always-multi-line",
            {
                "severity": "error"
            }
        ],
        "media-query-list-comma-newline-before"            : [
            "never-multi-line",
            {
                "severity": "error"
            }
        ],
        "media-query-list-comma-space-after"               : [
            "always-single-line",
            {
                "severity": "error"
            }
        ],
        "media-query-list-comma-space-before"              : [
            "never",
            {
                "severity": "error"
            }
        ],
        "at-rule-blockless-newline-after"                  : [
            "always",
            {
                "severity": "error"
            }
        ],
        "at-rule-empty-line-before"                        : [
            "always",
            {
                "except"  : [
                    "blockless-group",
                    "first-nested"
                ],
                "ignore"  : [
                    "after-comment"
                ],
                "severity": "error"
            }
        ],
        "at-rule-no-vendor-prefix"                         : [
            true,
            {
                "severity": "error"
            }
        ],
        "comment-empty-line-before"                        : [
            "always",
            {
                "except"  : [
                    "first-nested"
                ],
                "ignore"  : [],
                "severity": "error"
            }
        ],
        "comment-whitespace-inside"                        : [
            "always",
            {
                "severity": "error"
            }
        ],
        "indentation"                                      : [
            4,
            {
                "except"               : [],
                "ignore"               : [],
                "hierarchicalSelectors": true,
                "severity"             : "error"
            }
        ],
        "max-empty-lines"                                  : [
            1,
            {
                "severity": "error"
            }
        ],
        "max-line-length"                                  : [
            120,
            {
                "ignore"  : [],
                "severity": "error"
            }
        ],
        "max-nesting-depth"                                : [
            2,
            {
                "ignore"  : [
                    "at-rules-without-declaration-blocks"
                ],
                "severity": "warning"
            }
        ],
        "no-browser-hacks"                                 : [
            true,
            {
                "severity": "error"
            }
        ],
        "no-descending-specificity"                        : [
            true,
            {
                "severity": "error"
            }
        ],
        "no-duplicate-selectors"                           : [
            true,
            {
                "severity": "error"
            }
        ],
        "no-eol-whitespace"                                : [
            true,
            {
                "severity": "error"
            }
        ],
        "no-indistinguishable-colors"                      : [
            true,
            {
                "threshold": 3,
                "ignore"   : [],
                "whitelist": [],
                "severity" : "warning"
            }
        ],
        "no-invalid-double-slash-comments"                 : [
            true,
            {
                "severity": "error"
            }
        ],
        "no-missing-eof-newline"                           : [
            true,
            {
                "severity": "error"
            }
        ],
        "no-unknown-animations"                            : [
            true,
            {
                "severity": "error"
            }
        ],
        "no-unsupported-browser-features"                  : [
            true,
            {
                "ignore"  : [],
                "severity": "warning"
            }
        ]
    }
};
<|endoftext|>


<commit_before>module.exports = require(__dirname + "/src/fast-sms").setConfig(require(__dirname + "/src/configuration"));;<commit_msg>removed extra semi<commit_after>module.exports = require(__dirname + "/src/fast-sms").setConfig(require(__dirname + "/src/configuration"));
<|endoftext|>


<commit_before>const fs = require('fs');
const path = require('path');
const jsdom = require('jsdom');
const Task = require('./lib/Task');
const actions = require('./lib/actions');
const EventEmitter = require('events').EventEmitter;

const jsdomConfig = {
    /**
     * @type {Object}
     * @see https://github.com/tmpvar/jsdom#flexibility
     */
    features: {
        FetchExternalResources: false,
        ProcessExternalResources: false,
        SkipExternalResources: true
    }
};

const Tasks = Symbol('tasks');

class Inflect extends EventEmitter {
    constructor(file) {
        super();
        if (file) this.init(file);
    }

    get basename() {
        return path.basename(this.file);
    }

    get report() {
        const report = {
            file: this.basename,
            tasks: this.count
        };
        if (Object.keys(this.data).length) report.data = this.data;
        if (Object.keys(this.errors).length) report.errors = this.errors;
        return report;
    }

    get tasks() {
        return this[Tasks];
    }

    set tasks(value) {
        if (typeof value !== 'object') {
            throw new Error(`${value} is not a valid task.`);
        }

        let arr = value;
        if (value.constructor !== Array) {
            arr = [value];
        }
        this.addTask(arr);

        return this;
    }

    init(file) {
        this.file = file;

        /** setup jsdom */
        const data = fs.readFileSync(this.file);
        this.doc = jsdom.jsdom(data, jsdomConfig);

        this[Tasks] = [];

        this.count = {};
        this.data = {};
        this.errors = {};

        /** add actions to this instance */
        Object.keys(actions).forEach((action) => {
            this[action] = actions[action];
        });

        /** setup action listener */
        this.on('actionEnd', (res, task, el) => {
            this.processResults(res, task, el);
            el.markDone();
            this.iterateCount(task.name);
            if (task.elements.every(e => e.done)) {
                task.markDone();
                this.emit('taskEnd', task);
            }
        });

        this.on('taskEnd', () => {
            if (this.tasks.every(t => t.done === true) ||
                this.tasks.length === 0) {
                this.emit('done', this.report);
            }
        });

        return this;
    }

    addTask(task) {
        if (task.constructor === Array) {
            task.forEach(t => this.addTask(t));
            return this;
        }
        this[Tasks].push(new Task(task, this.doc));
        return this;
    }

    inflect() {
        this.tasks.forEach(task => this.runTask(task));
    }

    runTask(task) {
        task.loadElements(this.doc);
        this.emit('elementsLoaded', task.elements.length);
        task.elements.forEach((el) => {
            this.emit('actionStart', task);

            if (!el.element) {
                this.emit('actionEnd', null, task, el);
                return;
            }

            const results = task.action.call(
                this, el.element, task.parameter
            );

            /** handle results */
            /** .then signals that a promise was returned */
            if (results && results.then) {
                results
                    .then(res => this.emit('actionEnd', res, task, el))
                    .catch(err => this.emit('actionEnd', err, task, el));
            } else {
                this.emit('actionEnd', results, task, el);
            }
        });

        return this;
    }

    handleError(err, taskName) {
        if (err.constructor === Array) {
            err.forEach(e => this.handleError(e, taskName));
            return this;
        }
        this.errors[taskName] = this.errors[taskName] || [];
        this.errors[taskName].push(err.message);
        this.emit('error', err.stack, taskName);

        return this;
    }

    processResults(result, task, el) {
        if (result) {
            if (result.constructor === Array) {
                result.forEach(r => this.processResults(r, task, el));
            } else if (result instanceof Error) {
                this.handleError(result, task.name);
            } else {
                let res = result;
                if (this.debug && el.nodeLocation) {
                    res = {
                        val: result,
                        loc: el.nodeLocation
                    };
                }
                this.data[task.name] = this.data[task.name] || [];
                this.data[task.name].push(res);
            }
        }

        return this;
    }

    iterateCount(taskName) {
        this.count[taskName] = this.count[taskName] || 0;
        this.count[taskName] += 1;
    }
}

module.exports = Inflect;
<commit_msg>the user can generate their own report with .taskCount, .data, and .errors objects<commit_after>const fs = require('fs');
const path = require('path');
const jsdom = require('jsdom');
const Task = require('./lib/Task');
const actions = require('./lib/actions');
const EventEmitter = require('events').EventEmitter;

const jsdomConfig = {
    /**
     * @type {Object}
     * @see https://github.com/tmpvar/jsdom#flexibility
     */
    features: {
        FetchExternalResources: false,
        ProcessExternalResources: false,
        SkipExternalResources: true
    }
};

const Tasks = Symbol('tasks');

class Inflect extends EventEmitter {
    constructor(file) {
        super();
        if (file) this.init(file);
    }

    get basename() {
        return path.basename(this.file);
    }

    get tasks() {
        return this[Tasks];
    }

    set tasks(value) {
        if (typeof value !== 'object') {
            throw new Error(`${value} is not a valid task.`);
        }

        let arr = value;
        if (value.constructor !== Array) {
            arr = [value];
        }
        this.addTask(arr);

        return this;
    }

    init(file) {
        this.file = file;

        /** setup jsdom */
        const data = fs.readFileSync(this.file);
        this.doc = jsdom.jsdom(data, jsdomConfig);

        this[Tasks] = [];

        this.taskCount = {};
        this.data = {};
        this.errors = {};

        /** add actions to this instance */
        Object.keys(actions).forEach((action) => {
            this[action] = actions[action];
        });

        /** setup action listener */
        this.on('actionEnd', (res, task, el) => {
            this.processResults(res, task, el);
            el.markDone();
            this.iterateCount(task.name);
            if (task.elements.every(e => e.done)) {
                task.markDone();
                this.emit('taskEnd', task);
            }
        });

        this.on('taskEnd', () => {
            if (this.tasks.every(t => t.done === true) ||
                this.tasks.length === 0) {
                this.emit('done');
            }
        });

        return this;
    }

    addTask(task) {
        if (task.constructor === Array) {
            task.forEach(t => this.addTask(t));
            return this;
        }
        this[Tasks].push(new Task(task, this.doc));
        return this;
    }

    inflect() {
        this.tasks.forEach(task => this.runTask(task));
    }

    runTask(task) {
        task.loadElements(this.doc);
        this.emit('elementsLoaded', task.elements.length);
        task.elements.forEach((el) => {
            this.emit('actionStart', task);

            if (!el.element) {
                this.emit('actionEnd', null, task, el);
                return;
            }

            const results = task.action.call(
                this, el.element, task.parameter
            );

            /** handle results */
            /** .then signals that a promise was returned */
            if (results && results.then) {
                results
                    .then(res => this.emit('actionEnd', res, task, el))
                    .catch(err => this.emit('actionEnd', err, task, el));
            } else {
                this.emit('actionEnd', results, task, el);
            }
        });

        return this;
    }

    handleError(err, taskName) {
        if (err.constructor === Array) {
            err.forEach(e => this.handleError(e, taskName));
            return this;
        }
        this.errors[taskName] = this.errors[taskName] || [];
        this.errors[taskName].push(err.message);
        this.emit('error', err.stack, taskName);

        return this;
    }

    processResults(result, task, el) {
        if (result) {
            if (result.constructor === Array) {
                result.forEach(r => this.processResults(r, task, el));
            } else if (result instanceof Error) {
                this.handleError(result, task.name);
            } else {
                let res = result;
                if (this.debug && el.nodeLocation) {
                    res = {
                        val: result,
                        loc: el.nodeLocation
                    };
                }
                this.data[task.name] = this.data[task.name] || [];
                this.data[task.name].push(res);
            }
        }

        return this;
    }

    iterateCount(taskName) {
        this.taskCount[taskName] = this.taskCount[taskName] || 0;
        this.taskCount[taskName] += 1;
    }
}

module.exports = Inflect;
<|endoftext|>


<commit_before>const querystring = require('querystring')

const HttpError = require('./HttpError')
const Validator = require('../common/Validator')

class Request {
  constructor (event, encrypter) {
    this.singleEmailFields = ['_to']
    this.delimeteredEmailFields = ['_cc', '_bcc', '_replyTo']
    this.recipients = {
      to: '',
      cc: [],
      bcc: [],
      replyTo: []
    }

    this.responseFormat = 'html'
    this.redirectUrl = null

    this.pathParameters = event.pathParameters || {}
    this.queryStringParameters = event.queryStringParameters || {}
    this.userParameters = querystring.parse(event.body)
    this.encrypter = encrypter
  }

  validate () {
    return Promise.resolve()
      .then(() => this._validateNoHoneyPot())
      .then(() => this._validateSingleEmails())
      .then(() => this._validateDelimiteredEmails())
      .then(() => this._validateToRecipient())
      .then(() => this._validateResponseFormat())
      .then(() => this._validateRedirect())
  }

  _validateNoHoneyPot () {
    if ('_honeypot' in this.userParameters && this.userParameters._honeypot !== '') {
      return Promise.reject(new HttpError().forbidden('You shall not pass'))
    }

    return Promise.resolve()
  }

  _validateToRecipient () {
    if (this.recipients.to === '') {
      return Promise.reject(new HttpError().unprocessableEntity("Please provide a recipient in '_to' field"))
    }
  }

  _validateSingleEmails () {
    for (let field of this.singleEmailFields) {
      if (field in this.userParameters) {
        let input = this.userParameters[field]
        if (!this._parseEmail(input, field)) {
          return Promise.reject(new HttpError().unprocessableEntity(`Invalid email in '${field}' field`))
        }
      }
    }

    return Promise.resolve()
  }

  _validateDelimiteredEmails () {
    for (let field of this.delimeteredEmailFields) {
      if (field in this.userParameters) {
        let inputs = this.userParameters[field].split(';')
        for (let input of inputs) {
          if (!this._parseEmail(input, field)) {
            return Promise.reject(new HttpError().unprocessableEntity(`Invalid email in '${field}' field`))
          }
        }
      }
    }

    return Promise.resolve()
  }

  _validateResponseFormat () {
    if ('format' in this.queryStringParameters) {
      if (this.queryStringParameters.format === 'json' || this.queryStringParameters.format === 'html') {
        this.responseFormat = this.queryStringParameters.format
        return Promise.resolve()
      } else {
        return Promise.reject(new HttpError().unprocessableEntity('Invalid response format in the query string'))
      }
    }
  }

  _validateRedirect () {
    if ('_redirect' in this.userParameters) {
      if (Validator.isWebsite(this.userParameters['_redirect'])) {
        this.responseFormat = 'plain'
        this.redirectUrl = this.userParameters['_redirect']
        return Promise.resolve()
      } else {
        return Promise.reject(new HttpError().unprocessableEntity("Invalid website URL in '_redirect'"))
      }
    }
  }

  _parseEmail (input, field) {
    // check for plain text email addresses
    if (Validator.isEmail(input)) {
      this._addEmail(input, field)
      return true
    }

    // check for encrypted email addresses
    let inputDecrypted = this.encrypter.decrypt(input)
    if (Validator.isEmail(inputDecrypted)) {
      this._addEmail(inputDecrypted, field)
      return true
    }
  }

  _addEmail (email, field) {
    if (this.delimeteredEmailFields.indexOf(field) === -1) {
      this.recipients[field.substring(1)] = email
    } else {
      this.recipients[field.substring(1)].push(email)
    }
  }
}

module.exports = Request
<commit_msg>improve Request promise validate structure to catch errors<commit_after>const querystring = require('querystring')

const HttpError = require('./HttpError')
const Validator = require('../common/Validator')

class Request {
  constructor (event, encrypter) {
    this.singleEmailFields = ['_to']
    this.delimeteredEmailFields = ['_cc', '_bcc', '_replyTo']
    this.recipients = {
      to: '',
      cc: [],
      bcc: [],
      replyTo: []
    }

    this.responseFormat = 'html'
    this.redirectUrl = null

    this.pathParameters = event.pathParameters || {}
    this.queryStringParameters = event.queryStringParameters || {}
    this.userParameters = querystring.parse(event.body)
    this.encrypter = encrypter
  }

  validate () {
    return Promise.resolve()
      .then(() => this._validateNoHoneyPot())
      .then(() => this._validateSingleEmails())
      .then(() => this._validateDelimiteredEmails())
      .then(() => this._validateToRecipient())
      .then(() => this._validateResponseFormat())
      .then(() => this._validateRedirect())
  }

  _validateNoHoneyPot () {
    if ('_honeypot' in this.userParameters && this.userParameters._honeypot !== '') {
      return Promise.reject(new HttpError().forbidden('You shall not pass'))
    }

    return Promise.resolve()
  }

  _validateToRecipient () {
    if (this.recipients.to === '') {
      return Promise.reject(new HttpError().unprocessableEntity("Please provide a recipient in '_to' field"))
    }
  }

  _validateSingleEmails () {
    return new Promise((resolve, reject) => {
      this.singleEmailFields
        .filter((field) => field in this.userParameters)
        .forEach((field) => {
          let input = this.userParameters[field]
          if (!this._parseEmail(input, field)) {
            return reject(new HttpError().unprocessableEntity(`Invalid email in '${field}' field`))
          }
        })

      return resolve()
    })
  }

  _validateDelimiteredEmails () {
    return new Promise((resolve, reject) => {
      this.delimeteredEmailFields
        .filter((field) => field in this.userParameters)
        .forEach((field) => {
          let inputs = this.userParameters[field].split(';')
          inputs.forEach((input) => {
            if (!this._parseEmail(input, field)) {
              return reject(new HttpError().unprocessableEntity(`Invalid email in '${field}' field`))
            }
          })
        })

      return resolve()
    })
  }

  _validateResponseFormat () {
    if ('format' in this.queryStringParameters) {
      if (this.queryStringParameters.format !== 'json' && this.queryStringParameters.format !== 'html') {
        return Promise.reject(new HttpError().unprocessableEntity('Invalid response format in the query string'))
      } else {
        this.responseFormat = this.queryStringParameters.format
      }
    }

    return Promise.resolve()
  }

  _validateRedirect () {
    if ('_redirect' in this.userParameters) {
      if (!Validator.isWebsite(this.userParameters['_redirect'])) {
        return Promise.reject(new HttpError().unprocessableEntity("Invalid website URL in '_redirect'"))
      } else {
        this.responseFormat = 'plain'
        this.redirectUrl = this.userParameters['_redirect']
      }
    }

    return Promise.resolve()
  }

  _parseEmail (input, field) {
    // check for plain text email addresses
    if (Validator.isEmail(input)) {
      this._addEmail(input, field)
      return true
    }

    // check for encrypted email addresses
    let inputDecrypted = this.encrypter.decrypt(input)
    if (Validator.isEmail(inputDecrypted)) {
      this._addEmail(inputDecrypted, field)
      return true
    }
  }

  _addEmail (email, field) {
    if (this.delimeteredEmailFields.indexOf(field) === -1) {
      this.recipients[field.substring(1)] = email
    } else {
      this.recipients[field.substring(1)].push(email)
    }
  }
}

module.exports = Request
<|endoftext|>


<commit_before>import T from "../constants/ActionTypes";
import { MAIN_IDS, IDS } from "../constants/Categories";

const initialState = {
  text: null,
  city: null,
  result: [],
  current: null,
  categories: MAIN_IDS.filter((c) => c !== IDS.EVENT),
  highlight: [],
  invisible: [],
  addresses: [],
  cities: []
};

const isCity = x =>
  (
    (
      (x["class"] === 'place' && (x.type === 'city' || x.type === 'village')) ||
      (x["class"] === 'boundary' && x.type === 'administrative')
    )
    &&
      (x.address != null)
    &&
    (
      (x.address.city     != null) ||
      (x.address.county   != null) ||
      (x.address.village  != null)
    )
  )

module.exports = (state = initialState, action = {}) => {

  switch (action.type) {

    case T.TOGGLE_SEARCH_CATEGORY:
      const c = action.payload;
      if (c == null) {
        return state;
      }
      //TODO: beautify
      var cats = indexOf.call(state.categories, c) >= 0 ? (() => {
        var x, i, len, ref1, results;
        ref1 = state.categories;
        results = [];
        for (i = 0, len = ref1.length; i < len; i++) {
          x = ref1[i];
          if (x !== c) {
            results.push(x);
          }
        }
        return results;
      })() : [c].concat(slice.call(state.categories));

      return {
        ...state,
        categories: cats
      }

    case T.SET_SEARCH_TEXT:
      return {
        ...state,
        text: action.payload
      }

    case T.SET_CITY_SEARCH_TEXT:
      return {
        ...state,
        city: action.payload
      }

    case T.SEARCH_RESULT:
      if (!action.error) {
        return {
          ...state,
          result: action.payload.visible,
          invisible: action.payload.invisible
        }
      }
      return state;
      break;

    case T.SEARCH_ADDRESS_RESULT:
      if (!action.error) {
        const d = action.payload || [];
        return {
          ...state,
          addresses: d,
          cities: d.filter(isCity)
        }
      }
      return {
        ...state,
        addresses: [],
        cities: []
      }
      break;

    case T.NEW_ENTRY_RESULT:
      if (!action.error) {
        var o = {};
        o[state.result.length] = action.payload;
        return {
          ...state,
          result: o
        }
      }
      break;

    case T.SET_CURRENT_ENTRY:
      const p = action.payload;
      if (p != null) {
        return {
          ...state,
          current: p,
          highlight: [p]
        }
      }
      return {
        ...state,
        current: null
      }
      break;

    case T.HIGHLIGHT_ENTRIES:
      return {
        ...state,
        highlight: action.payload
      }

    default:
      return state;
  }
};
<commit_msg>fix(search): toggle category filter<commit_after>import T from "../constants/ActionTypes";
import { MAIN_IDS, IDS } from "../constants/Categories";

const initialState = {
  text: null,
  city: null,
  result: [],
  current: null,
  categories: MAIN_IDS.filter((c) => c !== IDS.EVENT),
  highlight: [],
  invisible: [],
  addresses: [],
  cities: []
};

const isCity = x =>
  (
    (
      (x["class"] === 'place' && (x.type === 'city' || x.type === 'village')) ||
      (x["class"] === 'boundary' && x.type === 'administrative')
    )
    &&
      (x.address != null)
    &&
    (
      (x.address.city     != null) ||
      (x.address.county   != null) ||
      (x.address.village  != null)
    )
  )

module.exports = (state = initialState, action = {}) => {

  switch (action.type) {

    case T.TOGGLE_SEARCH_CATEGORY:
      const c = action.payload;
      if (c == null) {
        return state;
      }
      //TODO: beautify
      const cats = state.categories.indexOf(c) >= 0
        ? (() => {
          var ref1 = state.categories;
          var results = [];
          var x, i, len;
          for (i = 0, len = ref1.length; i < len; i++) {
            x = ref1[i];
            if (x !== c) {
              results.push(x);
            }
          }
          return results;
        })()
      : [c].concat([].slice.call(state.categories));

      return {
        ...state,
        categories: cats
      }

    case T.SET_SEARCH_TEXT:
      return {
        ...state,
        text: action.payload
      }

    case T.SET_CITY_SEARCH_TEXT:
      return {
        ...state,
        city: action.payload
      }

    case T.SEARCH_RESULT:
      if (!action.error) {
        return {
          ...state,
          result: action.payload.visible,
          invisible: action.payload.invisible
        }
      }
      return state;
      break;

    case T.SEARCH_ADDRESS_RESULT:
      if (!action.error) {
        const d = action.payload || [];
        return {
          ...state,
          addresses: d,
          cities: d.filter(isCity)
        }
      }
      return {
        ...state,
        addresses: [],
        cities: []
      }
      break;

    case T.NEW_ENTRY_RESULT:
      if (!action.error) {
        var o = {};
        o[state.result.length] = action.payload;
        return {
          ...state,
          result: o
        }
      }
      break;

    case T.SET_CURRENT_ENTRY:
      const p = action.payload;
      if (p != null) {
        return {
          ...state,
          current: p,
          highlight: [p]
        }
      }
      return {
        ...state,
        current: null
      }
      break;

    case T.HIGHLIGHT_ENTRIES:
      return {
        ...state,
        highlight: action.payload
      }

    default:
      return state;
  }
};
<|endoftext|>


<commit_before>/*
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

'use strict';

var _ = require('lodash');
var Vorpal = require('vorpal');
var cleanupHandler = require('death');
var CliTable = require('cli-table');
require('colors');

/**
 * fuge run -> executes through here - runs all and starts a log tail
 * hitting any key will stop the tail
 * need a command history
 */
module.exports = function() {
  var _config;
  var _runner;
  var _proxy;
  var vorpal =  new Vorpal();
  var tableChars = { 'top': '' , 'top-mid': '' , 'top-left': '' , 'top-right': '',
                     'bottom': '' , 'bottom-mid': '' , 'bottom-left': '' , 'bottom-right': '',
                     'left': '' , 'left-mid': '' , 'mid': '' , 'mid-mid': '',
                     'right': '' , 'right-mid': '' , 'middle': ' ' };
  var tableStyle = { 'padding-left': 0, 'padding-right': 0 };

  var stopSystem = function(system) {
    _runner.stopAll(system, function() {
      process.exit(0);
    });
  };

  var psList = function(args, system, cb) {
    var table = new CliTable({chars: tableChars, style: tableStyle,
                              head: ['name'.white, 'type'.white, 'status'.white, 'watch'.white, 'tail'.white, 'count'.white], colWidths: [30, 15, 15, 15, 15, 5]});
    var procs = _runner.processes();
    var counts = _.countBy(_.keys(procs), function(key) { return procs[key].identifier; });

    _.each(system.topology.containers, function(container) {
      if (!(container.name === '__proxy' || container.type === 'blank-container')) {
        if (container.type === 'docker' && _config.runDocker === false) {
          table.push([container.name.gray, container.type.gray, 'not managed'.gray, '', '']);
        }
        else {
          var procKey = _.find(_.keys(procs), function(key) { return procs[key].identifier === container.name; });
          if (procKey) {
            var proc = procs[procKey];
            table.push([container.name.green,
                        container.type.green,
                        'running'.green,
                        proc.monitor ? 'yes'.green : 'no'.red,
                        proc.tail ? 'yes'.green : 'no'.red,
                        counts[container.name] ? ('' + counts[container.name]).green : '0'.red]);
          }
          else {
            table.push([container.name.red,
                        container.type.red,
                        'stopped'.red,
                        container.monitor ? 'yes'.green : 'no'.red,
                        container.tail ? 'yes'.green : 'no'.red,
                        '0'.red]);
          }
        }
      }
    });
    console.log(table.toString());
    cb();
  };

  var proxy = function(args, system, cb) {
    _proxy.previewAll(system, function(err) {
      cb(err);
    });
  };

  var showInfo = function(args, system, cb) {
    if (args.length === 2) {
      _runner.preview(system, args[1], function(err, command) {
        if (command && command.detail) {
          var env = '';
          console.log('command: ' + command.detail.cmd);
          console.log('directory: ' + command.detail.cwd);
          _.each(_.keys(command.detail.environment), function(key) {
            env += '  ' + key + '=' + command.detail.environment[key] + '\n';
          });
          console.log('environment:\n' + env);
        }
        else {
          console.log('not managed or unknown process');
        }
        cb();
      });
    }
    else {
      cb('process not specified');
    }
  };

  var stopProcess = function(args, system, cb) {
    if (args.length === 1 || args[1] === 'all') {
      _runner.stopAll(system, function(err) {
        cb(err);
      });
    }
    else {
      _runner.stop(system, args[1], args[2] || 1, function(err) {
        cb(err);
      });
    }
  };

  var startProcess = function(args, system, cb) {
    if (args.length === 1 || args[1] === 'all') {
      _runner.startAll(system, args[2] || 1, function(err) {
        cb(err);
      });
    }
    else {
      _runner.start(system, args[1], args[2] || 1, function(err) {
        cb(err);
      });
    }
  };

  var debugProcess = function(args, system, cb) {
    if (args.length === 2) {
      if (!_runner.isProcessRunning(args[1])) {
        _runner.debug(system, args[1], function(err) {
          cb(err);
        });
      }
      else {
        console.log('process already running - terminate to debug');
        cb();
      }
    }
    else {
      cb();
    }
  };

  var watchProcess = function(args, system, cb) {
    var err = null;
    if (args.length === 1 || args[1] === 'all') {
      _runner.watchAll(system);
    }
    else if (args.length >= 2) {
      err = _runner.watch(system, args[1]);
    }
    cb(err);
  };

  var unwatchProcess = function(args, system, cb) {
    var err = null;
    if (args.length === 1 || args[1] === 'all') {
      _runner.unwatchAll(system);
    }
    else if (args.length >= 2) {
      err = _runner.unwatch(system, args[1]);
    }
    cb(err);
  };

  var tailProcess = function(args, system, cb) {
    var err = null;
    if (args.length === 1 || args[1] === 'all') {
      _runner.tailAll(system);
    }
    else if (args.length >= 2) {
      err = _runner.tail(system, args[1], args[2] || 0);
    }
    cb(err);
  };

  var untailProcess = function(args, system, cb) {
    var err = null;
    if (args.length === 1 || args[1] === 'all') {
      _runner.untailAll(system);
    }
    else if (args.length >= 2) {
      err = _runner.untail(system, args[1]);
    }
    cb(err);
  };

  var grepLogs = function(args, system, cb) {
    if (args.length === 2 || args[2] === 'all') {
      _runner.grepAll(system, _config, args[1], cb);
    }
    else if (args.length >= 2) {
      _runner.grep(args[2], _config, args[1], cb);
    }
  };

  var sendMessage = function(args, system, cb) {
    console.log('not implemented');
    cb();
  };

  var commands = [{
    command: 'ps',
    action: psList,
    description: 'list managed processes and containers'
  },
  {
    command: 'proxy',
    action: proxy,
    description: 'list proxy status and port forwarding'
  },
  {
    command: 'info',
    action: showInfo,
    description: 'list environment block injected into each process'
  },
  {
    command: 'stop',
    action: stopProcess,
    description: 'stop [count] process instances and watchers'
  },
  {
    command: 'start',
    action: startProcess,
    description: 'start [count] processes with watch'
  },
  {
    command: 'debug',
    action: debugProcess,
    description: 'start a process in debug mode'
  },
  {
    command: 'watch',
    action: watchProcess,
    description: 'turn on watching for a process'
  },
  {
    command: 'unwatch',
    action: unwatchProcess,
    description: 'turn off watching for a process'
  },
  {
    command: 'tail',
    action: tailProcess,
    description: 'tail output for all processes'
  },
  {
    command: 'untail',
    action: untailProcess,
    description: 'tail output for a specific processes'
  },
  {
    command: 'grep',
    action: grepLogs,
    description: 'searches logs for specific process or all logs'
  },
  {
    command: 'send',
    action: sendMessage,
    description: 'sends a message to a specific process'
  },
];

  var inputStructure = function(command, type, description, action, system){
    // structures the commands and creates the vorpal instances
    if (type !== null){
      vorpal
      .command(command + type)
      .description(description)
      .action(function (args, cb) {
        var opt = args.process; // optional argument
        var arr = [command];
          if (command === 'send'){
            if (opt !== undefined){
              for (var i=0; i<opt.length; i++){
              arr.push(opt[i]);
              }
            }
            action(arr, system, cb);
          }
          else {
            if (opt !== undefined){
            arr.push(opt);
          }
          action(arr, system, cb);
          }
        });
      }
      // if no additional arguments are available
    else {
      vorpal
      .command(command)
      .description(description)
      .action(function (args, cb) {
        var arr = [command];
        action(arr, system, cb);
      });
    }
  };

  var repl = function(system) {
    vorpal.delimiter('?'.green +' fuge>'.bold).show();
    commands.forEach(function (com) {
      //creates a vorpal instance for each object in commands
      if (com.command === 'start' || com.command === 'watch'||
      com.command === 'unwatch' || com.command === 'grep'||
      com.command === 'stop'  || com.command === 'info' ||
      com.command === 'tail'){
        inputStructure(com.command,'[process]',
          com.description, com.action, system);
      }
      else if (com.command === 'debug' || com.command === 'untail') {
        inputStructure(com.command,'<process>',
          com.description, com.action, system);
      }
      else if (com.command === 'send') {
        inputStructure(com.command,'<process> <message>',
          com.description, com.action, system);
      }
      else {
        inputStructure(com.command,null, com.description,
          com.action, system);
      }
    });
  };

  var run = function(system, config) {
    _config = config;
    _runner = require('fuge-runner')(_config);
    _proxy = require('fuge-proxy')(_config);

    cleanupHandler(function() {
      stopSystem(system);
    });

    console.log('starting proxy...');
    _proxy.startAll(system, function(err) {
      if (err) { console.log(err); process.exit(0); }
      console.log('starting shell..');
      repl(system);
    });

  };

  var runSingleCommand = function(system, config, command) {
    _config = config;
    _runner = require('fuge-runner')(_config);
    _proxy = require('fuge-proxy')(_config);

    cleanupHandler(function() {
      stopSystem(system);
    });

    console.log('starting proxy...');
    _proxy.startAll(system, function(err) {
      if (err) { console.log(err); process.exit(0); }

      var s = command.split(' ');
      commands[s[0]](s, system, function(err){
        if (err) { console.log(err); }
      });
    });
  };

  return {
    run: run,
    runSingleCommand: runSingleCommand
  };
};

<commit_msg>added support for untail all<commit_after>/*
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

'use strict';

var _ = require('lodash');
var Vorpal = require('vorpal');
var cleanupHandler = require('death');
var CliTable = require('cli-table');
require('colors');

/**
 * fuge run -> executes through here - runs all and starts a log tail
 * hitting any key will stop the tail
 * need a command history
 */
module.exports = function() {
  var _config;
  var _runner;
  var _proxy;
  var vorpal =  new Vorpal();
  var tableChars = { 'top': '' , 'top-mid': '' , 'top-left': '' , 'top-right': '',
                     'bottom': '' , 'bottom-mid': '' , 'bottom-left': '' , 'bottom-right': '',
                     'left': '' , 'left-mid': '' , 'mid': '' , 'mid-mid': '',
                     'right': '' , 'right-mid': '' , 'middle': ' ' };
  var tableStyle = { 'padding-left': 0, 'padding-right': 0 };

  var stopSystem = function(system) {
    _runner.stopAll(system, function() {
      process.exit(0);
    });
  };

  var psList = function(args, system, cb) {
    var table = new CliTable({chars: tableChars, style: tableStyle,
                              head: ['name'.white, 'type'.white, 'status'.white, 'watch'.white, 'tail'.white, 'count'.white], colWidths: [30, 15, 15, 15, 15, 5]});
    var procs = _runner.processes();
    var counts = _.countBy(_.keys(procs), function(key) { return procs[key].identifier; });

    _.each(system.topology.containers, function(container) {
      if (!(container.name === '__proxy' || container.type === 'blank-container')) {
        if (container.type === 'docker' && _config.runDocker === false) {
          table.push([container.name.gray, container.type.gray, 'not managed'.gray, '', '']);
        }
        else {
          var procKey = _.find(_.keys(procs), function(key) { return procs[key].identifier === container.name; });
          if (procKey) {
            var proc = procs[procKey];
            table.push([container.name.green,
                        container.type.green,
                        'running'.green,
                        proc.monitor ? 'yes'.green : 'no'.red,
                        proc.tail ? 'yes'.green : 'no'.red,
                        counts[container.name] ? ('' + counts[container.name]).green : '0'.red]);
          }
          else {
            table.push([container.name.red,
                        container.type.red,
                        'stopped'.red,
                        container.monitor ? 'yes'.green : 'no'.red,
                        container.tail ? 'yes'.green : 'no'.red,
                        '0'.red]);
          }
        }
      }
    });
    console.log(table.toString());
    cb();
  };

  var proxy = function(args, system, cb) {
    _proxy.previewAll(system, function(err) {
      cb(err);
    });
  };

  var showInfo = function(args, system, cb) {
    if (args.length === 2) {
      _runner.preview(system, args[1], function(err, command) {
        if (command && command.detail) {
          var env = '';
          console.log('command: ' + command.detail.cmd);
          console.log('directory: ' + command.detail.cwd);
          _.each(_.keys(command.detail.environment), function(key) {
            env += '  ' + key + '=' + command.detail.environment[key] + '\n';
          });
          console.log('environment:\n' + env);
        }
        else {
          console.log('not managed or unknown process');
        }
        cb();
      });
    }
    else {
      cb('process not specified');
    }
  };

  var stopProcess = function(args, system, cb) {
    if (args.length === 1 || args[1] === 'all') {
      _runner.stopAll(system, function(err) {
        cb(err);
      });
    }
    else {
      _runner.stop(system, args[1], args[2] || 1, function(err) {
        cb(err);
      });
    }
  };

  var startProcess = function(args, system, cb) {
    if (args.length === 1 || args[1] === 'all') {
      _runner.startAll(system, args[2] || 1, function(err) {
        cb(err);
      });
    }
    else {
      _runner.start(system, args[1], args[2] || 1, function(err) {
        cb(err);
      });
    }
  };

  var debugProcess = function(args, system, cb) {
    if (args.length === 2) {
      if (!_runner.isProcessRunning(args[1])) {
        _runner.debug(system, args[1], function(err) {
          cb(err);
        });
      }
      else {
        console.log('process already running - terminate to debug');
        cb();
      }
    }
    else {
      cb();
    }
  };

  var watchProcess = function(args, system, cb) {
    var err = null;
    if (args.length === 1 || args[1] === 'all') {
      _runner.watchAll(system);
    }
    else if (args.length >= 2) {
      err = _runner.watch(system, args[1]);
    }
    cb(err);
  };

  var unwatchProcess = function(args, system, cb) {
    var err = null;
    if (args.length === 1 || args[1] === 'all') {
      _runner.unwatchAll(system);
    }
    else if (args.length >= 2) {
      err = _runner.unwatch(system, args[1]);
    }
    cb(err);
  };

  var tailProcess = function(args, system, cb) {
    var err = null;
    if (args.length === 1 || args[1] === 'all') {
      _runner.tailAll(system);
    }
    else if (args.length >= 2) {
      err = _runner.tail(system, args[1], args[2] || 0);
    }
    cb(err);
  };

  var untailProcess = function(args, system, cb) {
    var err = null;
    if (args.length === 1 || args[1] === 'all') {
      _runner.untailAll(system);
    }
    else if (args.length >= 2) {
      err = _runner.untail(system, args[1]);
    }
    cb(err);
  };

  var grepLogs = function(args, system, cb) {
    if (args.length === 2 || args[2] === 'all') {
      _runner.grepAll(system, _config, args[1], cb);
    }
    else if (args.length >= 2) {
      _runner.grep(args[2], _config, args[1], cb);
    }
  };

  var sendMessage = function(args, system, cb) {
    console.log('not implemented');
    cb();
  };

  var commands = [{
    command: 'ps',
    action: psList,
    description: 'list managed processes and containers'
  },
  {
    command: 'proxy',
    action: proxy,
    description: 'list proxy status and port forwarding'
  },
  {
    command: 'info',
    action: showInfo,
    description: 'list environment block injected into each process'
  },
  {
    command: 'stop',
    action: stopProcess,
    description: 'stop [count] process instances and watchers'
  },
  {
    command: 'start',
    action: startProcess,
    description: 'start [count] processes with watch'
  },
  {
    command: 'debug',
    action: debugProcess,
    description: 'start a process in debug mode'
  },
  {
    command: 'watch',
    action: watchProcess,
    description: 'turn on watching for a process'
  },
  {
    command: 'unwatch',
    action: unwatchProcess,
    description: 'turn off watching for a process'
  },
  {
    command: 'tail',
    action: tailProcess,
    description: 'tail output for all processes'
  },
  {
    command: 'untail',
    action: untailProcess,
    description: 'tail output for a specific processes'
  },
  {
    command: 'grep',
    action: grepLogs,
    description: 'searches logs for specific process or all logs'
  },
  {
    command: 'send',
    action: sendMessage,
    description: 'sends a message to a specific process'
  },
];

  var inputStructure = function(command, type, description, action, system){
    // structures the commands and creates the vorpal instances
    if (type !== null){
      vorpal
      .command(command + type)
      .description(description)
      .action(function (args, cb) {
        var opt = args.process; // optional argument
        var arr = [command];
          if (command === 'send'){
            if (opt !== undefined){
              for (var i=0; i<opt.length; i++){
              arr.push(opt[i]);
              }
            }
            action(arr, system, cb);
          }
          else {
            if (opt !== undefined){
            arr.push(opt);
          }
          action(arr, system, cb);
          }
        });
      }
      // if no additional arguments are available
    else {
      vorpal
      .command(command)
      .description(description)
      .action(function (args, cb) {
        var arr = [command];
        action(arr, system, cb);
      });
    }
  };

  var repl = function(system) {
    vorpal.delimiter('?'.green +' fuge>'.bold).show();
    commands.forEach(function (com) {
      //creates a vorpal instance for each object in commands
      if (com.command === 'start' || com.command === 'watch'||
      com.command === 'unwatch' || com.command === 'grep'||
      com.command === 'stop'  || com.command === 'info' ||
      com.command === 'tail' || com.command === 'untail'){
        inputStructure(com.command,'[process]',
          com.description, com.action, system);
      }
      else if (com.command === 'debug') {
        inputStructure(com.command,'<process>',
          com.description, com.action, system);
      }
      else if (com.command === 'send') {
        inputStructure(com.command,'<process> <message>',
          com.description, com.action, system);
      }
      else {
        inputStructure(com.command,null, com.description,
          com.action, system);
      }
    });
  };

  var run = function(system, config) {
    _config = config;
    _runner = require('fuge-runner')(_config);
    _proxy = require('fuge-proxy')(_config);

    cleanupHandler(function() {
      stopSystem(system);
    });

    console.log('starting proxy...');
    _proxy.startAll(system, function(err) {
      if (err) { console.log(err); process.exit(0); }
      console.log('starting shell..');
      repl(system);
    });

  };

  var runSingleCommand = function(system, config, command) {
    _config = config;
    _runner = require('fuge-runner')(_config);
    _proxy = require('fuge-proxy')(_config);

    cleanupHandler(function() {
      stopSystem(system);
    });

    console.log('starting proxy...');
    _proxy.startAll(system, function(err) {
      if (err) { console.log(err); process.exit(0); }

      var s = command.split(' ');
      commands[s[0]](s, system, function(err){
        if (err) { console.log(err); }
      });
    });
  };

  return {
    run: run,
    runSingleCommand: runSingleCommand
  };
};

<|endoftext|>