├── .eslintrc ├── .github ├── FUNDING.yml ├── SECURITY.md └── workflows │ ├── node-aught.yml │ ├── node-pretest.yml │ ├── node-tens.yml │ ├── rebase.yml │ └── require-allow-edits.yml ├── .gitignore ├── .npmrc ├── .nycrc ├── README.md ├── bin └── ignored ├── index.js ├── package.json └── test ├── .1-ignore ├── 1-expected └── index.js /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | 4 | "extends": "@ljharb", 5 | 6 | "rules": { 7 | "func-name-matching": [2, "always"], 8 | "func-style": 1, 9 | "indent": [2, 2], 10 | "max-statements": 0, 11 | "no-loop-func": 1, 12 | "no-param-reassign": 1, 13 | }, 14 | 15 | "overrides": [ 16 | { 17 | "files": "bin/**", 18 | "env": { 19 | "node": true, 20 | }, 21 | "rules": { 22 | "no-console": 0, 23 | }, 24 | }, 25 | ], 26 | } 27 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [ljharb] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: npm/dotignore 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /.github/SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security 2 | 3 | Please email [@ljharb](https://github.com/ljharb) or see https://tidelift.com/security if you have a potential security vulnerability to report. 4 | -------------------------------------------------------------------------------- /.github/workflows/node-aught.yml: -------------------------------------------------------------------------------- 1 | name: 'Tests: node.js < 10' 2 | 3 | on: [pull_request, push] 4 | 5 | jobs: 6 | tests: 7 | uses: ljharb/actions/.github/workflows/node.yml@main 8 | with: 9 | range: '< 10' 10 | type: minors 11 | command: npm run tests-only 12 | 13 | node: 14 | name: 'node < 10' 15 | needs: [tests] 16 | runs-on: ubuntu-latest 17 | steps: 18 | - run: 'echo tests completed' 19 | -------------------------------------------------------------------------------- /.github/workflows/node-pretest.yml: -------------------------------------------------------------------------------- 1 | name: 'Tests: pretest/posttest' 2 | 3 | on: [pull_request, push] 4 | 5 | jobs: 6 | tests: 7 | uses: ljharb/actions/.github/workflows/pretest.yml@main 8 | -------------------------------------------------------------------------------- /.github/workflows/node-tens.yml: -------------------------------------------------------------------------------- 1 | name: 'Tests: node.js >= 10' 2 | 3 | on: [pull_request, push] 4 | 5 | jobs: 6 | tests: 7 | uses: ljharb/actions/.github/workflows/node.yml@main 8 | with: 9 | range: '>= 10' 10 | type: minors 11 | command: npm run tests-only 12 | 13 | node: 14 | name: 'node >= 10' 15 | needs: [tests] 16 | runs-on: ubuntu-latest 17 | steps: 18 | - run: 'echo tests completed' 19 | -------------------------------------------------------------------------------- /.github/workflows/rebase.yml: -------------------------------------------------------------------------------- 1 | name: Automatic Rebase 2 | 3 | on: [pull_request_target] 4 | 5 | jobs: 6 | _: 7 | uses: ljharb/actions/.github/workflows/rebase.yml@main 8 | secrets: 9 | token: ${{ secrets.GITHUB_TOKEN }} 10 | -------------------------------------------------------------------------------- /.github/workflows/require-allow-edits.yml: -------------------------------------------------------------------------------- 1 | name: Require “Allow Edits” 2 | 3 | on: [pull_request_target] 4 | 5 | jobs: 6 | _: 7 | name: "Require “Allow Edits”" 8 | 9 | runs-on: ubuntu-latest 10 | 11 | steps: 12 | - uses: ljharb/require-allow-edits@main 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | .nyc_output/ 16 | 17 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 18 | .grunt 19 | 20 | # node-waf configuration 21 | .lock-wscript 22 | 23 | # Compiled binary addons (http://nodejs.org/api/addons.html) 24 | build/Release 25 | 26 | # Dependency directory 27 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 28 | node_modules 29 | 30 | # Only apps should have lockfiles 31 | npm-shrinkwrap.json 32 | package-lock.json 33 | yarn.lock 34 | 35 | .npmignore 36 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | -------------------------------------------------------------------------------- /.nycrc: -------------------------------------------------------------------------------- 1 | { 2 | "all": true, 3 | "check-coverage": false, 4 | "reporter": ["text-summary", "text", "html", "json"], 5 | "lines": 86, 6 | "statements": 85.93, 7 | "functions": 82.43, 8 | "branches": 76.06, 9 | "exclude": [ 10 | "coverage", 11 | "test" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # dotignore 2 | 3 | ## `ignored $IGNOREFILE` 4 | 5 | Check the ignorefile against the current directory. 6 | Print out if a file should be ignored by prefixing with a `-`. 7 | If the file should not be ignored prefix it with a `+`. 8 | 9 | ## API 10 | 11 | ### exports.createMatcher(str) 12 | 13 | Return a `Matcher` that fully matches the `str` argument. 14 | 15 | `str` should conform to the `.gitignore` specification. 16 | 17 | ### Matcher.shouldIgnore(name) 18 | 19 | Test that all the rules provided to create the matcher match the name given. 20 | `/` is expected as the path delimiter. 21 | Returns `true` if the name should be ignored. 22 | 23 | ## LICENSE 24 | 25 | MIT 26 | 27 | -------------------------------------------------------------------------------- /bin/ignored: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | 'use strict'; 4 | 5 | var fs = require('fs'); 6 | var path = require('path'); 7 | var rules = String(fs.readFileSync(process.argv[2] || '.gitignore')); 8 | var matcher = require('../').createMatcher(rules); 9 | 10 | function checkDir(dir) { 11 | fs.readdirSync(dir).forEach(function (filename) { 12 | var resolved = path.join(dir, filename); 13 | if (matcher.shouldIgnore(resolved)) { 14 | console.log('- ' + resolved); 15 | } else if (fs.statSync(resolved).isDirectory()) { 16 | checkDir(resolved); 17 | } else { 18 | console.log('+ ' + resolved); 19 | } 20 | }); 21 | } 22 | checkDir('.'); 23 | 24 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var minimatch = require('minimatch'); 4 | var path = require('path'); 5 | 6 | function IgnoreMatcher(str) { 7 | var negated = []; 8 | this.negated = negated; 9 | var rooted = []; 10 | this.rooted = rooted; 11 | this.matchers = str.split(/\r?\n|\r/).map(function (line) { 12 | var negatedLine = line[0] === '!'; 13 | var commentLine = line[0] === '#'; 14 | var rootedLine = line[0] === '/'; 15 | if (negatedLine || commentLine || rootedLine) { 16 | line = line.slice(1); 17 | } 18 | var emptyLine = line === ''; 19 | if (emptyLine) { 20 | return null; 21 | } 22 | var isShellGlob = line.indexOf('/') >= 0; 23 | negated[negated.length] = negatedLine; 24 | rooted[rooted.length] = rootedLine || isShellGlob; 25 | return minimatch.makeRe(line, { 26 | comment: commentLine, 27 | empty: emptyLine, 28 | matchBase: !rootedLine, 29 | negated: true // negated 30 | }); 31 | }).filter(Boolean); 32 | return this; 33 | } 34 | IgnoreMatcher.prototype.delimiter = path.sep; 35 | IgnoreMatcher.prototype.shouldIgnore = function (filename) { 36 | var isMatching = false; 37 | for (var i = 0; i < this.matchers.length; i++) { 38 | var matcher = this.matchers[i]; 39 | if (this.rooted[i]) { 40 | if (matcher.test(filename)) { 41 | isMatching = !this.negated[i]; 42 | } 43 | } else if (filename.split(this.delimiter).some(function (part) { // eslint-disable-line no-loop-func 44 | return matcher.test(part); 45 | })) { 46 | isMatching = !this.negated[i]; 47 | } 48 | } 49 | return isMatching; 50 | }; 51 | exports.createMatcher = function (ignoreFileStr) { 52 | return new IgnoreMatcher(ignoreFileStr); 53 | }; 54 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dotignore", 3 | "version": "0.1.2", 4 | "description": "ignorefile/includefile matching .gitignore spec", 5 | "main": "index.js", 6 | "bin": { 7 | "ignored": "bin/ignored" 8 | }, 9 | "scripts": { 10 | "prepack": "npmignore --auto --commentLines=autogenerated", 11 | "prepublishOnly": "safe-publish-latest", 12 | "prepublish": "not-in-publish || npm run prepublishOnly", 13 | "lint": "eslint --ext=js,mjs bin/* .", 14 | "pretest": "npm run lint", 15 | "tests-only": "nyc tape 'test/**/*.js'", 16 | "test": "npm run tests-only", 17 | "posttest": "aud --production" 18 | }, 19 | "repository": { 20 | "type": "git", 21 | "url": "http://github.com/bmeck/dotignore" 22 | }, 23 | "keywords": [ 24 | "ignore", 25 | "gitignore", 26 | "npmignore", 27 | "glob", 28 | "pattern" 29 | ], 30 | "author": { 31 | "name": "bradleymeck" 32 | }, 33 | "license": "MIT", 34 | "dependencies": { 35 | "minimatch": "^3.0.4" 36 | }, 37 | "devDependencies": { 38 | "@ljharb/eslint-config": "^21.0.1", 39 | "aud": "^2.0.2", 40 | "eslint": "=8.8.0", 41 | "in-publish": "^2.0.1", 42 | "npmignore": "^0.3.0", 43 | "nyc": "^10.3.2", 44 | "safe-publish-latest": "^2.0.0", 45 | "tape": "^5.6.3" 46 | }, 47 | "publishConfig": { 48 | "ignore": [ 49 | ".github/workflows" 50 | ] 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /test/.1-ignore: -------------------------------------------------------------------------------- 1 | *ignored 2 | !a/not* 3 | -------------------------------------------------------------------------------- /test/1-expected: -------------------------------------------------------------------------------- 1 | + .ignore 2 | - a/a/notignored 3 | - a/ignored 4 | + a/notignored 5 | + a/notlisted 6 | + expected 7 | + test.js 8 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var fs = require('fs'); 4 | var path = require('path'); 5 | var rules = String(fs.readFileSync(path.join(process.cwd(), 'test', '.1-ignore'))); 6 | var matcher = require('../').createMatcher(rules); 7 | var test = require('tape'); 8 | 9 | function checkDir(dir, paths, output) { 10 | if (!output) { output = ''; } 11 | paths.forEach(function (pathArr) { 12 | var isDir = Array.isArray(pathArr); 13 | var filename = isDir ? pathArr[0] : pathArr; 14 | var resolved = path.join(dir, filename); 15 | if (matcher.shouldIgnore(resolved)) { 16 | output += '- ' + resolved + '\n'; 17 | } else if (isDir) { 18 | output = checkDir(resolved, pathArr[1], output); 19 | } else { 20 | output += '+ ' + resolved + '\n'; 21 | } 22 | }); 23 | return output; 24 | } 25 | 26 | test('expected output', function (t) { 27 | process.chdir(path.join(process.cwd(), 'test')); 28 | 29 | var root = [ 30 | '.ignore', 31 | [ 32 | 'a', 33 | [ 34 | ['a', ['notignored']], 35 | 'ignored', 36 | 'notignored', 37 | 'notlisted' 38 | ] 39 | ], 40 | 'expected', 41 | 'test.js' 42 | ]; 43 | 44 | var output = checkDir('.', root); 45 | 46 | t.equal(output, String(fs.readFileSync('1-expected'))); 47 | t.end(); 48 | }); 49 | 50 | test('delimiter defaults to path.sep', function (t) { 51 | t.equal(matcher.delimiter, path.sep); 52 | t.end(); 53 | }); 54 | --------------------------------------------------------------------------------