├── test ├── directories │ ├── directory-1 │ │ ├── index.html │ │ ├── fonts │ │ │ └── font.woff │ │ ├── scripts │ │ │ ├── main.js │ │ │ └── app │ │ │ │ └── class.js │ │ └── styles │ │ │ ├── styles.css │ │ │ └── sass │ │ │ ├── styles.scss │ │ │ └── partials │ │ │ └── _component.scss │ ├── directory-2 │ │ ├── idea │ │ │ └── idea.js │ │ ├── src │ │ │ ├── index.html │ │ │ ├── scripts │ │ │ │ └── scripts.js │ │ │ └── styles │ │ │ │ └── styles.css │ │ └── bower_components │ │ │ └── gsap │ │ │ └── gsap.js │ ├── directory-3 │ │ ├── index.html │ │ ├── travis.yml │ │ └── src │ │ │ └── .ignored_file │ ├── directory-4 │ │ ├── index.html │ │ ├── gulpfile.js │ │ └── src │ │ │ └── script.js │ ├── directory-5 │ │ ├── index.html │ │ ├── src │ │ │ ├── lib │ │ │ │ ├── main.min.js │ │ │ │ └── main.pretty.long.min.js │ │ │ └── some.lib │ │ │ │ └── main.js │ │ └── gulpfile.js │ └── empty-directory │ │ └── .ignored_file ├── maps │ ├── directory-3-map.js │ ├── directory-4-map.js │ ├── directory-2-map.js │ ├── directory-5-map.js │ └── directory-1-map.js └── test.js ├── .travis.yml ├── lib ├── utils │ ├── default-ignored.js │ ├── join.js │ └── is-ignored.js └── map-dir.js ├── .editorconfig ├── .eslintrc ├── index.js ├── .gitignore ├── package.json ├── LICENSE └── README.md /test/directories/directory-1/index.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/directories/directory-2/idea/idea.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/directories/directory-2/src/index.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/directories/directory-3/index.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/directories/directory-3/travis.yml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/directories/directory-4/index.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/directories/directory-5/index.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/directories/directory-1/fonts/font.woff: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/directories/directory-1/scripts/main.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/directories/directory-1/styles/styles.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/directories/directory-3/src/.ignored_file: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/directories/directory-5/src/lib/main.min.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/directories/empty-directory/.ignored_file: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/directories/directory-1/scripts/app/class.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/directories/directory-1/styles/sass/styles.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/directories/directory-2/src/scripts/scripts.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/directories/directory-2/src/styles/styles.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/directories/directory-4/gulpfile.js: -------------------------------------------------------------------------------- 1 | gulpfile.js -------------------------------------------------------------------------------- /test/directories/directory-5/gulpfile.js: -------------------------------------------------------------------------------- 1 | gulpfile.js -------------------------------------------------------------------------------- /test/directories/directory-5/src/some.lib/main.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/directories/directory-2/bower_components/gsap/gsap.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/directories/directory-4/src/script.js: -------------------------------------------------------------------------------- 1 | console.log('hi'); -------------------------------------------------------------------------------- /test/directories/directory-5/src/lib/main.pretty.long.min.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/directories/directory-1/styles/sass/partials/_component.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "4.1" 4 | - "4.0" 5 | - "0.12" 6 | - "iojs" -------------------------------------------------------------------------------- /lib/utils/default-ignored.js: -------------------------------------------------------------------------------- 1 | module.exports = [ 2 | 'bower_components', 3 | 'node_modules', 4 | '.ignored_file' 5 | ]; -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | insert_final_newline = true 3 | 4 | [*.js] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 -------------------------------------------------------------------------------- /lib/utils/join.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var path = require('path'); 4 | 5 | module.exports = function join(path1, path2) { 6 | return path.join(path1, path2); 7 | }; -------------------------------------------------------------------------------- /lib/utils/is-ignored.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = function isIgnored(fileName, ignoredDirs) { 4 | return ignoredDirs.some(function(dir) { 5 | return dir === fileName; 6 | }); 7 | }; -------------------------------------------------------------------------------- /test/maps/directory-3-map.js: -------------------------------------------------------------------------------- 1 | var directoryMap = { 2 | map: 3 | [ 4 | { 5 | name: 'src', 6 | type: 'dir' 7 | } 8 | ] 9 | }; 10 | 11 | module.exports = directoryMap.map; -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "node": true 5 | }, 6 | "rules": { 7 | "quotes": [2, "single"], 8 | "eol-last": [0], 9 | "no-mixed-requires": [0], 10 | "no-underscore-dangle": [0] 11 | } 12 | } -------------------------------------------------------------------------------- /test/maps/directory-4-map.js: -------------------------------------------------------------------------------- 1 | var directoryMap = { 2 | map: 3 | [ 4 | { 5 | name: 'gulpfile', 6 | extension: '.js', 7 | type: 'file' 8 | }, 9 | { 10 | name: 'src', 11 | type: 'dir', 12 | children: [ 13 | { 14 | name: 'script', 15 | extension: '.js', 16 | type: 'file' 17 | } 18 | ] 19 | } 20 | ] 21 | }; 22 | 23 | module.exports = directoryMap.map; -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var mapDir = require('./lib/map-dir'); 4 | var ignoredDirs = require('./lib/utils/default-ignored'); 5 | 6 | module.exports = function(directory, ignoreArgs) { 7 | var currentDir = directory || process.cwd(); 8 | var toIgnore = ignoreArgs ? ignoreArgs : ignoredDirs; 9 | return new Promise(function(resolve, reject) { 10 | try { 11 | resolve(mapDir(currentDir, toIgnore)); 12 | } catch(error) { 13 | reject(error); 14 | } 15 | }); 16 | }; -------------------------------------------------------------------------------- /.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 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # node-waf configuration 20 | .lock-wscript 21 | 22 | # Compiled binary addons (http://nodejs.org/api/addons.html) 23 | build/Release 24 | 25 | # Dependency directory 26 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 27 | node_modules 28 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-map-directory", 3 | "version": "0.1.0", 4 | "description": "Map directory structure into a JavaScript object", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "mocha test" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/dcamilleri/node-map-directory.git" 12 | }, 13 | "engines" : { 14 | "node" : ">=0.12" 15 | }, 16 | "keywords": [ 17 | "node", 18 | "map", 19 | "directory", 20 | "structure", 21 | "asynchronous" 22 | ], 23 | "author": "Dorian Camilleri", 24 | "license": "MIT", 25 | "bugs": { 26 | "url": "https://github.com/dcamilleri/node-map-directory/issues" 27 | }, 28 | "devDependencies": { 29 | "chai": "^3.2.0", 30 | "mocha": "^2.2.5" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /test/maps/directory-2-map.js: -------------------------------------------------------------------------------- 1 | var directoryMap = { 2 | map: 3 | [ 4 | { 5 | name: 'src', 6 | type: 'dir', 7 | children: [ 8 | { 9 | name: 'index', 10 | extension: '.html', 11 | type: 'file' 12 | }, 13 | { 14 | name: 'scripts', 15 | type: 'dir', 16 | children: [ 17 | { 18 | name: 'scripts', 19 | extension: '.js', 20 | type: 'file' 21 | } 22 | ] 23 | }, 24 | { 25 | name: 'styles', 26 | type: 'dir', 27 | children: [ 28 | { 29 | name: 'styles', 30 | extension: '.css', 31 | type: 'file' 32 | } 33 | ] 34 | } 35 | ] 36 | } 37 | ] 38 | }; 39 | 40 | module.exports = directoryMap.map; -------------------------------------------------------------------------------- /test/maps/directory-5-map.js: -------------------------------------------------------------------------------- 1 | var directoryMap = { 2 | map: 3 | [ 4 | { 5 | name: 'src', 6 | type: 'dir', 7 | children: [ 8 | { 9 | name: 'lib', 10 | type: 'dir', 11 | children: [ 12 | { 13 | name: 'main.min', 14 | extension: '.js', 15 | type: 'file' 16 | }, 17 | { 18 | name: 'main.pretty.long.min', 19 | extension: '.js', 20 | type: 'file' 21 | } 22 | ] 23 | }, 24 | { 25 | name: 'some.lib', 26 | type: 'dir', 27 | children: [ 28 | { 29 | name: 'main', 30 | extension: '.js', 31 | type: 'file' 32 | } 33 | ] 34 | } 35 | ] 36 | } 37 | ] 38 | }; 39 | 40 | module.exports = directoryMap.map; -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Dorian Camilleri 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /lib/map-dir.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var fs = require('fs'); 4 | var join = require('./utils/join'); 5 | var isIgnored = require('./utils/is-ignored'); 6 | 7 | module.exports = function mapDir(directory, ignoredDirs) { 8 | var dirMap = fs.readdirSync(directory); 9 | return dirMap 10 | .map(function(dir) { 11 | var dirPath = join(directory, dir); 12 | var stats = fs.lstatSync(dirPath); 13 | if(!isIgnored(dir, ignoredDirs)) { 14 | if(stats.isDirectory()) { 15 | var newDirMap = mapDir(dirPath, ignoredDirs); 16 | var res = { 17 | name: dir, 18 | type: 'dir' 19 | }; 20 | if(newDirMap.length) { 21 | res.children = newDirMap; 22 | } 23 | return res; 24 | } else { 25 | var splits = dir.split('.'); 26 | var extension = '.' + splits[splits.length - 1]; 27 | return { 28 | name: dir.substring(0, dir.length - extension.length), 29 | extension: extension, 30 | type: 'file' 31 | }; 32 | } 33 | } 34 | }) 35 | .filter(function(x) { 36 | return x !== undefined; 37 | }); 38 | }; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # node-map-directory 2 | Asyncronously map directory file structure into a JavaScript object 3 | 4 | ## Install 5 | 6 | [![NPM](https://nodei.co/npm/node-map-directory.png)](https://www.npmjs.com/package/node-map-directory) 7 | 8 | [![Build Status](https://travis-ci.org/dcamilleri/node-map-directory.svg)](https://travis-ci.org/dcamilleri/node-map-directory) 9 | 10 | ``` 11 | $ npm install node-map-directory 12 | ``` 13 | 14 | ## Usage 15 | 16 | ```js 17 | var mapDir = require('node-map-directory'); 18 | mapDir('./') 19 | .then(function(currentDirMap) { 20 | // some code 21 | }); 22 | 23 | /* You will get an array of file and directory objects 24 | 25 | Directory structure 26 | - currentDir 27 | - index.html 28 | - scripts 29 | - myScript.js 30 | 31 | Output: 32 | [ 33 | { 34 | name: 'index', 35 | extension: '.html', 36 | type: 'file' 37 | }, 38 | { 39 | name: 'scripts', 40 | type: 'dir', 41 | children: [ 42 | { 43 | name: 'myScript', 44 | extension: '.js', 45 | type: 'file' 46 | } 47 | ] 48 | } 49 | ] 50 | */ 51 | ``` 52 | 53 | ## API 54 | 55 | ### mapDir(directory, toIgnore) 56 | 57 | #### options 58 | 59 | ##### directory 60 | 61 | Type: `String` 62 | Default: `./` 63 | 64 | The root directory to get the map from. 65 | 66 | ##### toIgnore 67 | 68 | Type: `array` 69 | Default: `['node_modules', 'bower_components', '.ignored_file']` 70 | 71 | The directories and files to exclude from mapping. 72 | 73 | ## License 74 | 75 | MIT © [Dorian Camilleri](https://github.com/dcamilleri>) 76 | 77 | -------------------------------------------------------------------------------- /test/maps/directory-1-map.js: -------------------------------------------------------------------------------- 1 | var directoryMap = { 2 | map: 3 | [ 4 | { 5 | name: 'fonts', 6 | type: 'dir', 7 | children: [ 8 | { 9 | name: 'font', 10 | extension: '.woff', 11 | type: 'file' 12 | } 13 | ] 14 | }, 15 | { 16 | name: 'index', 17 | extension: '.html', 18 | type: 'file' 19 | }, 20 | { 21 | name: 'scripts', 22 | type: 'dir', 23 | children: [ 24 | { 25 | name: 'app', 26 | type: 'dir', 27 | children: [ 28 | { 29 | name: 'class', 30 | extension: '.js', 31 | type: 'file' 32 | } 33 | ] 34 | }, 35 | { 36 | name: 'main', 37 | extension: '.js', 38 | type: 'file' 39 | } 40 | ] 41 | }, 42 | { 43 | name: 'styles', 44 | type: 'dir', 45 | children: [ 46 | { 47 | name: 'sass', 48 | type: 'dir', 49 | children: [ 50 | { 51 | name: 'partials', 52 | type: 'dir', 53 | children: [ 54 | { 55 | name: '_component', 56 | extension: '.scss', 57 | type: 'file' 58 | } 59 | ] 60 | }, 61 | { 62 | name: 'styles', 63 | extension: '.scss', 64 | type: 'file' 65 | } 66 | ] 67 | }, 68 | { 69 | name: 'styles', 70 | extension: '.css', 71 | type: 'file' 72 | } 73 | ] 74 | } 75 | ] 76 | }; 77 | 78 | module.exports = directoryMap.map; -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | /* globals describe it */ 2 | 3 | 'use strict'; 4 | 5 | var expect = require('chai').expect; 6 | var join = require('../lib/utils/join'); 7 | var mapDir = require('../index'); 8 | 9 | describe('Asyncronous API Testing', function() { 10 | it('should return a valid object tree when a directory is passed', function () { 11 | var exampleDir = join(__dirname, 'directories/directory-1'); 12 | var dirMap = mapDir(exampleDir, null, false); 13 | var realDirMap = require('./maps/directory-1-map'); 14 | 15 | return mapDir(exampleDir) 16 | .then(function(asyncDirMap) { 17 | expect(asyncDirMap).to.deep.equal(realDirMap); 18 | }); 19 | }); 20 | 21 | it('should return an empty array when the directory is empty', function () { 22 | var exampleDir = join(__dirname, 'directories/empty-directory'); 23 | var dirMap = mapDir(exampleDir, null, false); 24 | 25 | return mapDir(exampleDir) 26 | .then(function(asyncDirMap) { 27 | expect(asyncDirMap.length).to.equal(0); 28 | }); 29 | }); 30 | 31 | it('should ignore directories passed as arguments', function () { 32 | var exampleDir = join(__dirname, 'directories/directory-2'); 33 | var dirMap = mapDir(exampleDir, ['node_modules', 'bower_components', 'idea'], false); 34 | var realDirMap = require('./maps/directory-2-map'); 35 | 36 | return mapDir(exampleDir, ['node_modules', 'bower_components', 'idea']) 37 | .then(function(asyncDirMap) { 38 | expect(asyncDirMap).to.deep.equal(realDirMap); 39 | }); 40 | }); 41 | 42 | it('should ignore files passed as arguments', function () { 43 | var exampleDir = join(__dirname, 'directories/directory-3'); 44 | var dirMap = mapDir(exampleDir, ['index.html', 'travis.yml', '.ignored_file'], false); 45 | var realDirMap = require('./maps/directory-3-map'); 46 | 47 | return mapDir(exampleDir, ['index.html', 'travis.yml', '.ignored_file']) 48 | .then(function(asyncDirMap) { 49 | expect(asyncDirMap).to.deep.equal(realDirMap); 50 | }); 51 | }); 52 | 53 | it('should ignore files and directories passed as arguments', function () { 54 | var exampleDir = join(__dirname, 'directories/directory-4'); 55 | var dirMap = mapDir(exampleDir, ['index.html', 'node_modules'], false); 56 | var realDirMap = require('./maps/directory-4-map'); 57 | 58 | return mapDir(exampleDir, ['index.html', 'node_modules']) 59 | .then(function(asyncDirMap) { 60 | expect(asyncDirMap).to.deep.equal(realDirMap); 61 | }); 62 | }); 63 | 64 | it('should get the correct name/extension when several dots in files or directories names', function () { 65 | var exampleDir = join(__dirname, 'directories/directory-5'); 66 | var dirMap = mapDir(exampleDir, ['index.html', 'gulpfile.js'], false); 67 | var realDirMap = require('./maps/directory-5-map'); 68 | 69 | return mapDir(exampleDir, ['index.html', 'gulpfile.js']) 70 | .then(function(asyncDirMap) { 71 | expect(asyncDirMap).to.deep.equal(realDirMap); 72 | }); 73 | }); 74 | 75 | it('should throw an error properly', function () { 76 | return mapDir('hello') 77 | .then( 78 | function() {}, 79 | function(error) { 80 | expect(error).to.not.be.undefined; 81 | }); 82 | }); 83 | }); 84 | 85 | --------------------------------------------------------------------------------