├── .editorconfig ├── .gitignore ├── CHANGELOG.md ├── README.md ├── index.js ├── package-lock.json ├── package.json └── test ├── gulp-tasks ├── index.js ├── scripts │ └── build │ │ └── index.js └── styles │ ├── build.js │ └── clean.js └── gulpfile.js /.editorconfig: -------------------------------------------------------------------------------- 1 | 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | end_of_line = lf 7 | insert_final_newline = true 8 | trim_trailing_whitespace = true 9 | 10 | [*.js] 11 | indent_style = space 12 | indent_size = 2 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea/ 2 | /node_modules/ 3 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # gulp-require-tasks changelog 2 | 3 | Below is the list of most important changes and versions. 4 | 5 | ## Version 1.3.0 6 | (28 April 2020) 7 | 8 | - Added deprecation notice 9 | - Updated README 10 | 11 | 12 | ## Version 1.2.0 13 | (30 July 2017) 14 | 15 | - Usage of `arguments` option is deprecated, use globals or imports instead 16 | - Usage of `module.dep` property is deprecated, use `module.deps` instead 17 | 18 | 19 | ## Version 1.1.1 20 | (31 May 2017) 21 | 22 | - Fixed backward compatibility with older LTS Node versions 23 | 24 | 25 | ## Version 1.1.0 26 | (16 May 2017) 27 | 28 | - Implemented [root directory tasks](README.md#using-root-directory-tasks) 29 | - `index.js` in the root of tasks directory is now registered as a default task 30 | - `module.dep` renamed to `module.deps`, `module.dep` is deprecated and will be removed in `2.0` 31 | - Introduced yarn 32 | 33 | 34 | ## Version 1.0.3 35 | (16 Mar 2016) 36 | 37 | - Dependencies are now explicitly specified 38 | - Improved support for Windows™ path separators 39 | 40 | 41 | ## Version 1.0.0 42 | (07 Mar 2016) 43 | 44 | - Initial release 45 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # gulp-require-tasks 2 | 3 | [![npm version](https://badge.fury.io/js/gulp-require-tasks.svg)](http://badge.fury.io/js/gulp-require-tasks) 4 | 5 | 6 | This convenient extension for **Gulp 3** allows you to load tasks from 7 | multiple individual files in a directory hierarchy. 8 | 9 | 10 | # Deprecation Notice 11 | 12 | > This extension is deprecated and archived! Use [Gulp 4][gulp-4] with [Gulp Hub][gulp-hub] instead. 13 | > 14 | > PRs are not being accepted. Consider creating a fork if you really want it. 15 | 16 | 17 | ## Features 18 | 19 | - Loads individual task files recursively from the specified directory 20 | - The name of the task is inferred from the directory structure, e.g. `styles:preprocess:clean` 21 | - Easily integrates into the `gulpfile.js` without breaking your existing tasks 22 | - Gulp instance and task callback are automatically passed to your task function 23 | - Very flexible: almost all aspects of the module is configurable 24 | - Each task is stored in it's own local node module to completely separate concerns 25 | 26 | 27 | ## Installation 28 | 29 | ### `npm i -D gulp gulp-require-tasks` 30 | 31 | 32 | ## Usage 33 | 34 | Create a directory alongside your `gulpfile.js` to store your individual 35 | task modules, e.g. `./gulp-tasks`. Place your tasks into this directory. 36 | One task per JavaScript file. Use sub-directories to structure your tasks. 37 | 38 | Load tasks from your `gulpfile.js`: 39 | 40 | ```js 41 | 42 | // gulpfile.js: 43 | 44 | // Require the module. 45 | const gulpRequireTasks = require('gulp-require-tasks'); 46 | 47 | // Invoke the module with options. 48 | gulpRequireTasks({ 49 | 50 | // Specify path to your tasks directory. 51 | path: process.cwd() + '/gulp-tasks' // This is default! 52 | 53 | // Additionally pass any options to it from the table below. 54 | // ... 55 | 56 | }); 57 | 58 | // Or, use minimal invocation possible with all options set to defaults. 59 | gulpRequireTasks(); 60 | 61 | ``` 62 | 63 | 64 | ### Minimal Gulp file possible 65 | 66 | ```js 67 | // gulpfile.js: 68 | require('gulp-require-tasks')(); 69 | ``` 70 | 71 | Or with options: 72 | 73 | ```js 74 | // gulpfile.js: 75 | require('gulp-require-tasks')({ 76 | separator: '.' 77 | }); 78 | ``` 79 | 80 | 81 | ## Options 82 | 83 | | Property | Default Value | Description 84 | | ------------ | ----------------- | -------------------------------------------------------- 85 | | path | `'./gulp-tasks'` | Path to directory from which to load your tasks modules 86 | | separator | `:` | Task name separator, your tasks would be named, e.g. `foo:bar:baz` for `./tasks/foo/bar/baz.js` 87 | | passGulp | `true` | Whether to pass Gulp instance as a first argument to your task function 88 | | passCallback | `true` | Whether to pass task callback function as a last argument to your task function 89 | | gulp | `require('gulp')` | You could pass your existing Gulp instance if you have one, or it will be required automatically 90 | 91 | 92 | ## Task module format 93 | 94 | Consider you have the following task module: `gulp-tasks/styles/build.js`. 95 | 96 | 97 | ### Module as a function 98 | 99 | You could define module as a task function. Gulp instance and 100 | callback function would be passed to it, if not configured otherwise. 101 | 102 | You could configure the library to pass additional arguments as well. 103 | 104 | ```javascript 105 | 106 | // gulp-tasks/styles/build.js: 107 | 108 | const compass = require('compass'); 109 | 110 | module.exports = function (gulp, callback) { 111 | return gulp.src('...') 112 | .pipe(compass()) 113 | .pipe(gulp.dest('...')) 114 | ; 115 | }; 116 | ``` 117 | 118 | 119 | ### Module as an object 120 | 121 | Also, you could define your task module as an object. 122 | This will allow you to provide additional configuration. 123 | 124 | ```javascript 125 | 126 | // gulp-tasks/styles/build.js: 127 | 128 | const compass = require('compass'); 129 | 130 | module.exports = { 131 | deps: ['styles:clean', 'icons:build'], 132 | fn: function (gulp, callback) { 133 | return gulp.src('...') 134 | .pipe(compass()) 135 | .pipe(gulp.dest('...')) 136 | ; 137 | } 138 | }; 139 | ``` 140 | 141 | You will have to define your task function as `fn` parameter. 142 | You could use `deps` parameter to define your task dependencies. 143 | 144 | Also, you could use `nativeTask` instead of `fn` property to make your 145 | task function executed by Gulp directly. That way, additional arguments 146 | will not be passed to it. This feature is useful when using, 147 | e.g. [gulp-sequence][gulp-sequence] plugin or for [synchronous tasks](#synchronous-tasks). 148 | 149 | 150 | ### Task function return value 151 | 152 | To make sure, that task is finished correctly you must either: 153 | 154 | - Return a proper Gulp stream from the task function, e.g.: `return gulp.src().pipe(gulp.dest());` 155 | - Return a valid Promise (thenable object), e.g.: `return del();` or `return new Promise();` 156 | - Call a callback function passed to it, e.g.: `callback();` 157 | 158 | > WARNING: If your task function is synchronous — please read the section below! 159 | 160 | 161 | ### Using root directory tasks 162 | 163 | Starting from version `1.1.0` you can place `index.js` inside of the task directories. 164 | The actual task, registered with Gulp will have the name of the directory itself, 165 | e.g.: `scripts/build/index.js` will become: `scripts:build`. 166 | 167 | The `index.js`, placed in the root of tasks directory, will be registered as a `default` task. 168 | 169 | 170 | ### Passing data to the task function 171 | 172 | If you need to pass something to the task function from your gulpfile you can use globals. 173 | 174 | Define your custom properties on the `global` object: 175 | 176 | ```js 177 | // gulpfile.js 178 | 179 | global.SOURCES_BASE_PATH = __dirname + '/src'; 180 | ``` 181 | 182 | And then use it in your task module: 183 | 184 | ```js 185 | // gulp/tasks/styles/build.js 186 | module.exports = gulp => 187 | gulp.src(global.SOURCES_BASE_PATH + '/styles/*.scss') 188 | .pipe(compass()) 189 | .pipe(gulp.dest('…')) 190 | ; 191 | ``` 192 | 193 | 194 | ### Synchronous tasks 195 | 196 | If you are using synchronous tasks, i.e. tasks which execute synchronously 197 | without returning streams, promises or accepting callbacks, you will have 198 | to use one of the workarounds specified below: 199 | 200 | 1). The simplest method is to use `nativeTask` functionality, here's the 201 | example of the module with native task synchronous function: 202 | 203 | ```js 204 | module.exports = { 205 | nativeTask: function () { 206 | console.log('This is the synchronous native task without a callback!'); 207 | } 208 | }; 209 | ``` 210 | 211 | 2). You should call a callback explicitly: 212 | 213 | ```js 214 | module.exports = function (gulp, callback) { 215 | console.log('This is the synchronous native task with explicit callback!'); 216 | callback(); // Don't forget this, otherwise task will never finish! 217 | }; 218 | ``` 219 | 220 | However, if `config.passCallback == false` you won't be able to use the second method. 221 | 222 | These workarounds must be used due to architectural limitation of this module integration with orchestrator. 223 | Please see the issue 224 | [#9: Synchronous tasks without callback don't finish](https://github.com/betsol/gulp-require-tasks/issues/9) 225 | for more technical details. 226 | 227 | 228 | ## Changelog 229 | 230 | Please see the [changelog][changelog] for list of changes. 231 | 232 | 233 | ## Feedback 234 | 235 | If you have found a bug or have another issue with the library — 236 | please [create an issue][new-issue]. 237 | 238 | If you have a question regarding the library or it's integration with your project — 239 | consider asking a question at [StackOverflow][so-ask] and sending me a 240 | link via [E-Mail][email]. I will be glad to help. 241 | 242 | Have any ideas or propositions? Feel free to contact me by [E-Mail][email]. 243 | 244 | Cheers! 245 | 246 | 247 | ## Support 248 | 249 | If you like this library consider to add star on [GitHub repository][repo-gh]. 250 | 251 | Thank you! 252 | 253 | 254 | ## License 255 | 256 | The MIT License (MIT) 257 | 258 | Copyright (c) 2016-2020 Slava Fomin II 259 | 260 | Permission is hereby granted, free of charge, to any person obtaining a copy 261 | of this software and associated documentation files (the "Software"), to deal 262 | in the Software without restriction, including without limitation the rights 263 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 264 | copies of the Software, and to permit persons to whom the Software is 265 | furnished to do so, subject to the following conditions: 266 | 267 | The above copyright notice and this permission notice shall be included in 268 | all copies or substantial portions of the Software. 269 | 270 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 271 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 272 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 273 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 274 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 275 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 276 | THE SOFTWARE. 277 | 278 | [changelog]: CHANGELOG.md 279 | [so-ask]: http://stackoverflow.com/questions/ask?tags=node.js,javascript 280 | [email]: mailto:s.fomin@betsol.ru 281 | [new-issue]: https://github.com/betsol/gulp-require-tasks/issues/new 282 | [gulp]: http://gulpjs.com/ 283 | [repo-gh]: https://github.com/betsol/gulp-require-tasks 284 | [gulp-sequence]: https://github.com/teambition/gulp-sequence 285 | [gulp-4]: https://gulpjs.com/ 286 | [gulp-hub]: https://github.com/frankwallis/gulp-hub/tree/registry-init 287 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = gulpRequireTasks; 3 | 4 | 5 | const path = require('path'); 6 | const requireDirectory = require('require-directory'); 7 | 8 | 9 | const DEFAULT_OPTIONS = { 10 | path: process.cwd() + '/gulp-tasks', 11 | separator: ':', 12 | passGulp: true, 13 | passCallback: true, 14 | gulp: null 15 | }; 16 | 17 | 18 | function gulpRequireTasks (options) { 19 | 20 | options = Object.assign({}, DEFAULT_OPTIONS, options); 21 | 22 | const gulp = options.gulp || require('gulp'); 23 | 24 | // Recursively visiting all modules in the specified directory 25 | // and registering Gulp tasks. 26 | requireDirectory(module, options.path, { 27 | visit: moduleVisitor 28 | }); 29 | 30 | 31 | /** 32 | * Registers the specified module. Task name is deducted from the specified path. 33 | * 34 | * @param {object|function} module 35 | * @param {string} modulePath 36 | */ 37 | function moduleVisitor (module, modulePath) { 38 | 39 | module = normalizeModule(module); 40 | 41 | const taskName = taskNameFromPath(modulePath); 42 | 43 | if (module.dep) { 44 | console.warn( 45 | 'Usage of "module.dep" property is deprecated and will be removed in next major version. ' + 46 | 'Use "deps" instead.' 47 | ); 48 | } 49 | 50 | gulp.task( 51 | taskName, 52 | // @todo: deprecate `module.dep` in 2.0.0 53 | module.deps || module.dep || [], 54 | module.nativeTask || taskFunction 55 | ); 56 | 57 | 58 | /** 59 | * Wrapper around user task function. 60 | * It passes special arguments to the user function according 61 | * to the configuration. 62 | * 63 | * @param {function} callback 64 | * 65 | * @returns {*} 66 | */ 67 | function taskFunction (callback) { 68 | 69 | if ('function' !== typeof module.fn) { 70 | callback(); 71 | return; 72 | } 73 | 74 | let args = []; 75 | 76 | // @deprecated 77 | // @todo: remove this in 2.0.0 78 | if (options.arguments) { 79 | console.warn( 80 | 'Usage of "arguments" option is deprecated and will be removed in next major version. ' + 81 | 'Use globals or module imports instead.' 82 | ); 83 | args = Array.from(options.arguments); 84 | } 85 | 86 | if (options.passGulp) { 87 | args.unshift(gulp); 88 | } 89 | 90 | if (options.passCallback) { 91 | args.push(callback); 92 | } 93 | 94 | return module.fn.apply(module, args); 95 | 96 | } 97 | 98 | /** 99 | * Deducts task name from the specified module path. 100 | * 101 | * @returns {string} 102 | */ 103 | function taskNameFromPath (modulePath) { 104 | 105 | const relativePath = path.relative(options.path, modulePath); 106 | 107 | // Registering root index.js as a default task. 108 | if ('index.js' === relativePath) { 109 | return 'default'; 110 | } 111 | 112 | const pathInfo = path.parse(relativePath); 113 | const taskNameParts = []; 114 | 115 | if (pathInfo.dir) { 116 | taskNameParts.push.apply(taskNameParts, pathInfo.dir.split(path.sep)); 117 | } 118 | if ('index' !== pathInfo.name) { 119 | taskNameParts.push(pathInfo.name); 120 | } 121 | 122 | return taskNameParts.join(options.separator); 123 | 124 | } 125 | 126 | } 127 | 128 | } 129 | 130 | /** 131 | * Normalizes module definition. 132 | * 133 | * @param {function|object} module 134 | * 135 | * @returns {object} 136 | */ 137 | function normalizeModule (module) { 138 | if ('function' === typeof module) { 139 | return { 140 | fn: module, 141 | deps: [] 142 | }; 143 | } else { 144 | return module; 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gulp-require-tasks", 3 | "version": "1.2.1", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "require-directory": { 8 | "version": "2.1.1", 9 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 10 | "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gulp-require-tasks", 3 | "version": "1.3.0", 4 | "description": "Loads Gulp tasks from directories and individual files", 5 | "main": "index.js", 6 | "keywords": [ 7 | "gulp", 8 | "gulpfile" 9 | ], 10 | "repository": "https://github.com/betsol/gulp-require-tasks.git", 11 | "author": "Slava Fomin II (https://slava.fomin.io)", 12 | "bugs": "https://github.com/betsol/gulp-require-tasks/issues", 13 | "homepage": "https://github.com/betsol/gulp-require-tasks#readme", 14 | "engines": { 15 | "node": ">=4.8" 16 | }, 17 | "license": "MIT", 18 | "dependencies": { 19 | "gulp": "^3.9.1", 20 | "require-directory": "^2.1.1" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /test/gulp-tasks/index.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = { 3 | deps: ['styles:clean', 'styles:build', 'scripts:build'], 4 | fn: (gulp, callback) => callback() 5 | }; 6 | -------------------------------------------------------------------------------- /test/gulp-tasks/scripts/build/index.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = function (gulp, callback) { 3 | console.log('Building scripts...'); 4 | callback(); 5 | }; 6 | -------------------------------------------------------------------------------- /test/gulp-tasks/styles/build.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = function (gulp, callback) { 3 | console.log('Building styles...'); 4 | callback(); 5 | }; 6 | -------------------------------------------------------------------------------- /test/gulp-tasks/styles/clean.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = function (gulp, callback) { 3 | console.log('Cleaning styles...'); 4 | callback(); 5 | }; 6 | -------------------------------------------------------------------------------- /test/gulpfile.js: -------------------------------------------------------------------------------- 1 | 2 | const gulpRequireTasks = require('../index'); 3 | 4 | 5 | gulpRequireTasks(); 6 | --------------------------------------------------------------------------------