summaryrefslogtreecommitdiff
path: root/tools/eslint/lib/ignored-paths.js
blob: 3d2bd9b44cd47bb5ec9c2b3d7f420125af2e3ae3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/**
 * @fileoverview Responsible for loading ignore config files and managing ignore patterns
 * @author Jonathan Rajavuori
 */
"use strict";

//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------

var fs = require("fs"),
    debug = require("debug"),
    minimatch = require("minimatch"),
    FileFinder = require("./file-finder");

debug = debug("eslint:ignored-paths");


//------------------------------------------------------------------------------
// Constants
//------------------------------------------------------------------------------

var ESLINT_IGNORE_FILENAME = ".eslintignore";


//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------

/**
 * Load and parse ignore patterns from the file at the given path
 * @param {string} filepath Path to the ignore file.
 * @returns {string[]} An array of ignore patterns or an empty array if no ignore file.
 */
function loadIgnoreFile(filepath) {
    var ignorePatterns = [];

    function nonEmpty(line) {
        return line.trim() !== "" && line[0] !== "#";
    }

    if (filepath) {
        try {
            ignorePatterns = fs.readFileSync(filepath, "utf8").split(/\r?\n/).filter(nonEmpty);
        } catch (e) {
            e.message = "Cannot read ignore file: " + filepath + "\nError: " + e.message;
            throw e;
        }
    }

    return ["node_modules/**"].concat(ignorePatterns);
}

var ignoreFileFinder;

/**
 * Find an ignore file in the current directory or a parent directory.
 * @returns {string} Path of ignore file or an empty string.
 */
function findIgnoreFile() {
    if (!ignoreFileFinder) {
        ignoreFileFinder = new FileFinder(ESLINT_IGNORE_FILENAME);
    }

    return ignoreFileFinder.findInDirectoryOrParents();
}


//------------------------------------------------------------------------------
// Public Interface
//------------------------------------------------------------------------------

/**
 * IgnoredPaths
 * @constructor
 * @class IgnoredPaths
 * @param {Array} patterns to be matched against file paths
 */
function IgnoredPaths(patterns) {
    this.patterns = patterns;
}

/**
 * IgnoredPaths initializer
 * @param {Object} options object containing 'ignore' and 'ignorePath' properties
 * @returns {IgnoredPaths} object, with patterns loaded from the ignore file
 */
IgnoredPaths.load = function (options) {
    var patterns;

    options = options || {};

    if (options.ignore) {
        patterns = loadIgnoreFile(options.ignorePath || findIgnoreFile());
    } else {
        patterns = [];
    }

    return new IgnoredPaths(patterns);
};

/**
 * Determine whether a file path is included in the configured ignore patterns
 * @param {string} filepath Path to check
 * @returns {boolean} true if the file path matches one or more patterns, false otherwise
 */
IgnoredPaths.prototype.contains = function (filepath) {
    if (this.patterns === null) {
        throw new Error("No ignore patterns loaded, call 'load' first");
    }

    filepath = filepath.replace("\\", "/");
    filepath = filepath.replace(/^\.\//, "");
    return this.patterns.reduce(function(ignored, pattern) {
        var negated = pattern[0] === "!",
            matches;

        if (negated) {
            pattern = pattern.slice(1);
        }

        // Remove leading "current folder" prefix
        if (pattern.indexOf("./") === 0) {
            pattern = pattern.slice(2);
        }

        matches = minimatch(filepath, pattern) || minimatch(filepath, pattern + "/**");

        return matches ? !negated : ignored;
    }, false);
};

module.exports = IgnoredPaths;