├── .editorconfig ├── .gitignore ├── .jshintrc ├── .todo ├── LICENSE ├── README.md ├── bin └── index.js ├── package.json ├── resources └── icon │ ├── icon.png │ ├── icon.psd │ └── icon_error.png ├── src ├── cli.js ├── plugins │ ├── clear.js │ ├── components.js │ ├── concat.js │ ├── dependencies.js │ ├── filelog.js │ ├── forall.js │ ├── log.js │ ├── order_pinner.js │ ├── picker.js │ ├── substitute.js │ ├── tap.js │ ├── touch.js │ ├── unempty.js │ └── wrapper.js ├── project │ ├── defaults │ │ ├── components.js │ │ ├── environments.js │ │ ├── index.js │ │ ├── paths.js │ │ ├── plugins.js │ │ └── targets.js │ ├── index.js │ └── previous.js ├── tasks │ ├── build │ │ ├── css │ │ │ ├── index.js │ │ │ └── parts │ │ │ │ ├── css.js │ │ │ │ ├── index.js │ │ │ │ └── scss.js │ │ ├── fonts.js │ │ ├── html.js │ │ ├── images.js │ │ ├── index.js │ │ ├── javascript.js │ │ ├── json.js │ │ ├── markdown.js │ │ ├── notification.js │ │ ├── scss │ │ │ ├── index.js │ │ │ └── parts │ │ │ │ ├── functions.js │ │ │ │ ├── general.js │ │ │ │ ├── index.js │ │ │ │ ├── keyframes.js │ │ │ │ ├── mixins.js │ │ │ │ ├── style.js │ │ │ │ └── variables.js │ │ ├── style.js │ │ └── summary.js │ ├── clean │ │ ├── css.js │ │ ├── fonts.js │ │ ├── html.js │ │ ├── images.js │ │ ├── index.js │ │ ├── javascript.js │ │ ├── json.js │ │ ├── scss.js │ │ ├── style.js │ │ └── typescript.js │ ├── config.js │ ├── default.js │ └── watch │ │ ├── css │ │ ├── index.js │ │ └── parts │ │ │ ├── css.js │ │ │ ├── index.js │ │ │ └── scss.js │ │ ├── fonts.js │ │ ├── html.js │ │ ├── images.js │ │ ├── index.js │ │ ├── javascript.js │ │ ├── json.js │ │ ├── markdown.js │ │ ├── scss │ │ ├── index.js │ │ └── parts │ │ │ ├── functions.js │ │ │ ├── index.js │ │ │ ├── keyframes.js │ │ │ ├── mixins.js │ │ │ ├── style.js │ │ │ └── variables.js │ │ └── style.js └── utilities │ ├── build_status.js │ ├── changed.js │ ├── config.js │ ├── environments.js │ ├── file.js │ ├── gutil.js │ ├── log.js │ ├── notification.js │ ├── path.js │ ├── paths │ ├── clean.js │ ├── input.js │ ├── output.js │ ├── paths.js │ └── tokens.js │ ├── plumber.js │ ├── project.js │ └── target.js └── test ├── check ├── component │ ├── css │ │ ├── pacco.css │ │ └── pacco.min.css │ ├── javascript │ │ ├── pacco.js │ │ └── pacco.min.js │ └── scss │ │ ├── pacco.functions.scss │ │ ├── pacco.keyframes.scss │ │ ├── pacco.mixins.scss │ │ ├── pacco.scss │ │ ├── pacco.style.scss │ │ └── pacco.variables.scss ├── components │ ├── css │ │ ├── pacco.css │ │ └── pacco.min.css │ ├── javascript │ │ ├── pacco.js │ │ └── pacco.min.js │ └── scss │ │ ├── pacco.functions.scss │ │ ├── pacco.mixins.scss │ │ ├── pacco.scss │ │ ├── pacco.style.scss │ │ └── pacco.variables.scss ├── concat_content │ └── javascript │ │ ├── pacco.js │ │ └── pacco.min.js ├── css │ ├── css │ │ ├── pacco.css │ │ └── pacco.min.css │ └── scss │ │ ├── pacco.scss │ │ └── pacco.style.scss ├── dependencies │ └── javascript │ │ ├── pacco.js │ │ └── pacco.min.js ├── extend │ ├── css │ │ ├── pacco.css │ │ └── pacco.min.css │ ├── javascript │ │ ├── pacco.js │ │ └── pacco.min.js │ └── scss │ │ ├── pacco.functions.scss │ │ ├── pacco.keyframes.scss │ │ ├── pacco.mixins.scss │ │ ├── pacco.scss │ │ ├── pacco.style.scss │ │ └── pacco.variables.scss ├── lodash_template │ └── javascript │ │ ├── pacco.js │ │ └── pacco.min.js ├── priority │ └── javascript │ │ ├── pacco.js │ │ └── pacco.min.js ├── resources │ ├── fonts │ │ ├── a.eot │ │ ├── a.ttf │ │ ├── a.woff │ │ └── a.woff2 │ ├── html │ │ ├── a.html │ │ └── b.html │ ├── images │ │ ├── a.bmp │ │ ├── a.gif │ │ ├── a.jpeg │ │ ├── a.jpg │ │ ├── a.png │ │ ├── a.svg │ │ └── a.webp │ └── json │ │ └── a.json ├── substitute │ ├── css │ │ ├── pacco.css │ │ └── pacco.min.css │ ├── javascript │ │ ├── pacco.js │ │ └── pacco.min.js │ ├── json │ │ └── a.json │ └── scss │ │ ├── pacco.scss │ │ └── pacco.style.scss ├── typescript │ ├── javascript │ │ ├── pacco.js │ │ └── pacco.min.js │ └── typescript │ │ ├── pacco.d.ts │ │ └── pacco.ts ├── webpack │ └── javascript │ │ ├── pacco.js │ │ └── pacco.min.js └── wrapper │ └── javascript │ ├── pacco.js │ └── pacco.min.js ├── config ├── components.json ├── extend.json ├── general.json ├── lodash_template.json ├── substitute.json ├── webpack.json └── wrapper.json ├── index.js └── src ├── component └── a │ ├── functions.scss │ ├── index.js │ ├── index.scss │ ├── keyframes.scss │ ├── mixins.scss │ └── variables.scss ├── components └── b │ └── index.js ├── concat_content ├── a.js ├── b.js └── wrapper.js ├── css ├── a.scss ├── b.css └── c.css ├── cyclic ├── a.js ├── b.js └── c.js ├── dependencies ├── a.js ├── b.js └── c.js ├── extend ├── a.js ├── a │ ├── after.js │ ├── before.js │ ├── index.after.js │ ├── index.before.js │ └── index.override.js ├── after.js ├── before.js ├── require_a.js ├── require_b.js └── z.js ├── lodash_template └── a.js ├── priority ├── float │ ├── a.js │ ├── b.js │ ├── c.js │ └── d.js ├── integer │ ├── a.js │ ├── b.js │ └── c.js └── negative │ ├── a.js │ ├── b.js │ └── c.js ├── resources ├── a.bmp ├── a.eot ├── a.gif ├── a.html ├── a.jpeg ├── a.jpg ├── a.json ├── a.png ├── a.svg ├── a.ttf ├── a.webp ├── a.woff ├── a.woff2 ├── b.md └── other.ext ├── substitute ├── a.js ├── a.json ├── a.scss └── b.js ├── typescript ├── a.ts └── b.js ├── webpack └── a.js └── wrapper └── a.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | end_of_line = lf 8 | indent_size = 2 9 | indent_style = space 10 | insert_final_newline = true 11 | trim_trailing_whitespace = true 12 | 13 | [*.md] 14 | trim_trailing_whitespace = false 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Numerous always-ignore extensions 2 | *.diff 3 | *.err 4 | *.log 5 | *.orig 6 | *.rej 7 | *.swo 8 | *.swp 9 | *.vi 10 | *.zip 11 | *~ 12 | *.sass-cache 13 | *.ruby-version 14 | *.rbenv-version 15 | 16 | # OS or Editor folders 17 | ._* 18 | .cache 19 | .DS_Store 20 | .idea 21 | .project 22 | .settings 23 | .tmproj 24 | *.esproj 25 | *.sublime-project 26 | *.sublime-workspace 27 | nbproject 28 | Thumbs.db 29 | .fseventsd 30 | .DocumentRevisions* 31 | .TemporaryItems 32 | .Trashes 33 | 34 | # Other paths to ignore 35 | bower_components 36 | node_modules 37 | package-lock.json 38 | .temp 39 | dist 40 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "maxerr" : 200, // {int} Maximum error before stopping 3 | 4 | // Enforcing 5 | "bitwise" : true, // true: Prohibit bitwise operators (&, |, ^, etc.) 6 | "curly" : false, // true: Require {} for every new block or scope 7 | "eqeqeq" : true, // true: Require triple equals (===) for comparison 8 | "forin" : true, // true: Require filtering for..in loops with obj.hasOwnProperty() 9 | "freeze" : true, // true: prohibits overwriting prototypes of native objects such as Array, Date etc. 10 | "latedef" : true, // true: Require variables/functions to be defined before being used 11 | "newcap" : true, // true: Require capitalization of all constructor functions e.g. `new F()` 12 | "noarg" : true, // true: Prohibit use of `arguments.caller` and `arguments.callee` 13 | "noempty" : true, // true: Prohibit use of empty blocks 14 | "nonbsp" : true, // true: Prohibit "non-breaking whitespace" characters. 15 | "nonew" : false, // true: Prohibit use of constructors for side-effects (without assignment) 16 | "plusplus" : false, // true: Prohibit use of `++` & `--` 17 | "quotmark" : "single", // Quotation mark consistency: 18 | // false : do nothing (default) 19 | // true : ensure what§ever is used is consistent 20 | // "single" : require single quotes 21 | // "double" : require double quotes 22 | "undef" : true, // true: Require all non-global variables to be declared (prevents global leaks) 23 | "unused" : true, // Unused variables: 24 | // true : all variables, last function parameter 25 | // "vars" : all variables only 26 | // "strict" : all variables, all function parameters 27 | "strict" : false, // true: Requires all functions run in ES5 Strict Mode 28 | "maxparams" : false, // {int} Max number of formal params allowed per function 29 | "maxdepth" : 3, // {int} Max depth of nested blocks (within functions) 30 | "maxstatements" : false, // {int} Max number statements per function 31 | "maxcomplexity" : 10, // {int} Max cyclomatic complexity per function 32 | "maxlen" : false, // {int} Max number of characters per line 33 | "varstmt" : false, // true: Disallow any var statements. Only `let` and `const` are allowed. 34 | 35 | // Relaxing 36 | "asi" : false, // true: Tolerate Automatic Semicolon Insertion (no semicolons) 37 | "boss" : false, // true: Tolerate assignments where comparisons would be expected 38 | "debug" : false, // true: Allow debugger statements e.g. browser breakpoints. 39 | "eqnull" : false, // true: Tolerate use of `== null` 40 | "es5" : false, // true: Allow ES5 syntax (ex: getters and setters) 41 | "esnext" : true, // true: Allow ES.next (ES6) syntax (ex: `const`) 42 | "moz" : false, // true: Allow Mozilla specific syntax (extends and overrides esnext features) 43 | // (ex: `for each`, multiple try/catch, function expression…) 44 | "evil" : false, // true: Tolerate use of `eval` and `new Function()` 45 | "expr" : false, // true: Tolerate `ExpressionStatement` as Programs 46 | "funcscope" : false, // true: Tolerate defining variables inside control statements 47 | "globalstrict" : false, // true: Allow global "use strict" (also enables 'strict') 48 | "iterator" : false, // true: Tolerate using the `__iterator__` property 49 | "lastsemic" : false, // true: Tolerate omitting a semicolon for the last statement of a 1-line block 50 | "laxbreak" : false, // true: Tolerate possibly unsafe line breakings 51 | "laxcomma" : false, // true: Tolerate comma-first style coding 52 | "loopfunc" : false, // true: Tolerate functions being defined in loops 53 | "multistr" : false, // true: Tolerate multi-line strings 54 | "noyield" : false, // true: Tolerate generator functions with no yield statement in them. 55 | "notypeof" : false, // true: Tolerate invalid typeof operator values 56 | "proto" : false, // true: Tolerate using the `__proto__` property 57 | "scripturl" : false, // true: Tolerate script-targeted URLs 58 | "shadow" : false, // true: Allows re-define variables later in code e.g. `var x=1; x=2;` 59 | "sub" : false, // true: Tolerate using `[]` notation when it can still be expressed in dot notation 60 | "supernew" : false, // true: Tolerate `new function () { ... };` and `new Object;` 61 | "validthis" : false, // true: Tolerate using this in a non-constructor function 62 | 63 | // Environments 64 | "browser" : true, // Web Browser (window, document, etc) 65 | "browserify" : false, // Browserify (node.js code in the browser) 66 | "couch" : false, // CouchDB 67 | "devel" : false, // Development/debugging (alert, confirm, etc) 68 | "dojo" : false, // Dojo Toolkit 69 | "jasmine" : false, // Jasmine 70 | "jquery" : true, // jQuery 71 | "mocha" : false, // Mocha 72 | "mootools" : false, // MooTools 73 | "node" : true, // Node.js 74 | "nonstandard" : false, // Widely adopted globals (escape, unescape, etc) 75 | "phantom" : false, // PhantomJS 76 | "prototypejs" : false, // Prototype and Scriptaculous 77 | "qunit" : false, // QUnit 78 | "rhino" : false, // Rhino 79 | "shelljs" : false, // ShellJS 80 | "typed" : false, // Globals for typed array constructions 81 | "worker" : false, // Web Workers 82 | "wsh" : false, // Windows Scripting Host 83 | "yui" : false, // Yahoo User Interface 84 | 85 | // Custom Globals 86 | "globals" : {} // Additional predefined global variables 87 | 88 | } 89 | -------------------------------------------------------------------------------- /.todo: -------------------------------------------------------------------------------- 1 | 2 | Future: 3 | ☐ Migrate code to TypeScript 4 | 5 | Maybe: 6 | ☐ Switch to https://github.com/MatAtBread/fast-async (it's supposed to be faster) 7 | ☐ Support nested suffixes: `*.suffix.suffix.js` 8 | ☐ Publish plugins 9 | ☐ Add patch files that patch single lines, like `foo.patch.js` (quite ugly and not future proof) 10 | ☐ Replace redundant names with index (tab/tab.scss => tab/index.scss) 11 | ☐ allow implicit befores/requires (@require tab/tab.scss => @require tab/index.scss => @require tab) 12 | ☐ should `variables.scss` be inferred too? 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015-2018 Fabio Spampinato 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a 6 | copy of this software and associated documentation files (the "Software"), 7 | to deal in the Software without restriction, including without limitation 8 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | and/or sell copies of the Software, and to permit persons to whom the 10 | Software is furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all 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 20 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | DEALINGS IN THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Pacco 2 | 3 | A bundler for modular and extensible web projects. 4 | 5 | ## Why not WebPack? 6 | 7 | Work on Pacco started before WebPack was even a thing. In most of the cases you'll want to stick with WebPack, but if you're building a modular and extensible web project, like a front-end framework, Pacco will make your life easier: 8 | 9 | - **No configuration**: it just works. But if you need to, you can customize almost everything. 10 | - **Partial builds**: you can compile your project excluding some particular files or folders. You don't have to compile anything that you don't need. 11 | - **Extensibility**: you can build on top of extensible projects, even inject files exactly before or after a particular file, or override some other file. Useful for adding a component to a framework, providing SASS variables or custom configurations in general. 12 | - **Module priority**: you can ensure your most important code stays closer to the beginning of your bundle, ensuring it will be executed as soon as possible, improving percieved performance. 13 | - **Build on top of Gulp**: you may want to add support for LESS, being Pacco built on top of Gulp means it is easy to extend. 14 | 15 | ## Documentation 16 | 17 | //TODO: are you interested in this project? Open an issue and I'll find the time for writing it. 18 | 19 | In the mean time you can take a look at [Svelto](https://github.com/svelto/svelto), the front-end framework this bundler has been created for. 20 | -------------------------------------------------------------------------------- /bin/index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /* REQUIRE */ 4 | 5 | const CLI = require ( '../src/cli' ); 6 | 7 | /* CLI */ 8 | 9 | CLI (); 10 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pacco", 3 | "description": "A bundler for modular and extensible web projects.", 4 | "version": "2.1.18", 5 | "bin": "bin/index.js", 6 | "keywords": [ 7 | "bundler", 8 | "modular", 9 | "extensible", 10 | "web", 11 | "projects", 12 | "js", 13 | "scss", 14 | "gulp" 15 | ], 16 | "bugs": { 17 | "url": "https://github.com/svelto/pacco/issues" 18 | }, 19 | "license": "MIT", 20 | "author": { 21 | "name": "Fabio Spampinato", 22 | "email": "spampinabio@gmail.com" 23 | }, 24 | "repository": { 25 | "type": "git", 26 | "url": "https://github.com/svelto/pacco.git" 27 | }, 28 | "scripts": { 29 | "clean": "rimraf .temp", 30 | "test": "node test/index.js", 31 | "prepublishOnly": "npm run test" 32 | }, 33 | "dependencies": { 34 | "@babel/core": "^7.4.5", 35 | "@babel/preset-env": "^7.4.5", 36 | "async-done": "^1.3.2", 37 | "babel-plugin-lodash-template-compile": "^1.0.0", 38 | "caniuse-db": "^1.0.30001226", 39 | "caniuse-lite": "^1.0.30001228", 40 | "caporal": "git://github.com/fabiospampinato/Caporal.js#cf0f5eeefb2e04cc07798bf4a45d6bda5e2a2f63", 41 | "core-js": "^2.6.0", 42 | "cssnano": "^3.10.0", 43 | "del": "^3.0.0", 44 | "execa": "^1.0.0", 45 | "fancy-log": "^1.3.3", 46 | "find-up": "^3.0.0", 47 | "find-up-json": "^1.0.0", 48 | "google-closure-compiler": "^20220202.0.0", 49 | "gulp": "^4.0.2", 50 | "gulp-autoprefixer": "^6.1.0", 51 | "gulp-babel": "^8.0.0", 52 | "gulp-babili": "^0.1.4", 53 | "gulp-bytediff": "^1.0.0", 54 | "gulp-flatten": "^0.4.0", 55 | "gulp-htmlmin": "^5.0.1", 56 | "gulp-if": "git://github.com/fabiospampinato/gulp-if#17413d9bacd6c7891d93894b0b4a76c4df5177d6", 57 | "gulp-imagemin": "^4.1.0", 58 | "gulp-jsonminify": "^1.1.0", 59 | "gulp-markdown": "^3.0.0", 60 | "gulp-newer": "^1.4.0", 61 | "gulp-plumber": "^1.2.1", 62 | "gulp-postcss": "^7.0.0", 63 | "gulp-rename": "^1.4.0", 64 | "gulp-sass": "^5.0.0", 65 | "gulp-typescript": "^5.0.1", 66 | "gulp-uglify": "^3.0.2", 67 | "is-base64": "^0.1.0", 68 | "lodash": "^4.17.11", 69 | "micromatch": "^3.1.10", 70 | "mkdirp": "^0.5.1", 71 | "node-notifier": "^5.4.0", 72 | "node-sass": "^6.0.1", 73 | "nodejs-fs-utils": "^1.1.2", 74 | "open": "0.0.5", 75 | "pify": "^4.0.1", 76 | "plugin-error": "^1.0.1", 77 | "pretty-bytes": "^5.2.0", 78 | "pretty-time": "^1.1.0", 79 | "sass": "^1.43.4", 80 | "sha1": "^1.1.1", 81 | "specialist": "^0.3.0", 82 | "string-matches": "^1.1.3", 83 | "strip-ansi": "^5.2.0", 84 | "temp": "^0.9.0", 85 | "through2": "^2.0.5", 86 | "typescript": "^3.5.2", 87 | "uglify-js": "^3.6.0", 88 | "vinyl": "^2.2.0", 89 | "webpack-node-externals": "^1.7.2", 90 | "webpack-stream": "^5.2.1", 91 | "yargs": "^6.0.0" 92 | }, 93 | "devDependencies": { 94 | "hard-rejection": "^1.0.0", 95 | "rimraf": "^2.6.3", 96 | "test-diff": "^1.0.0", 97 | "yoctodelay": "^1.1.0" 98 | }, 99 | "optionalDependencies": { 100 | "fsevents": "^1.2.4" 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /resources/icon/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fabiospampinato/pacco/e1d2772892b78739125c3b03be3509f85b355af1/resources/icon/icon.png -------------------------------------------------------------------------------- /resources/icon/icon.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fabiospampinato/pacco/e1d2772892b78739125c3b03be3509f85b355af1/resources/icon/icon.psd -------------------------------------------------------------------------------- /resources/icon/icon_error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fabiospampinato/pacco/e1d2772892b78739125c3b03be3509f85b355af1/resources/icon/icon_error.png -------------------------------------------------------------------------------- /src/cli.js: -------------------------------------------------------------------------------- 1 | 2 | //TODO: Add an option to caporal for hiding an option from the help text (--icon, --icon-error) 3 | 4 | /* REQUIRE */ 5 | 6 | const argv = require ( 'yargs' ).argv, 7 | caporal = require ( 'caporal' ), 8 | {color, updater} = require ( 'specialist' ), 9 | {name, version} = require ( '../package.json' ), 10 | gutil = require ( './utilities/gutil' ); 11 | 12 | /* CLI */ 13 | 14 | async function CLI () { 15 | 16 | /* GULP */ 17 | 18 | gutil.patch (); 19 | 20 | /* APP */ 21 | 22 | updater ({ name, version }); 23 | 24 | const app = caporal.version ( version ); 25 | 26 | /* OPTIONS */ 27 | 28 | app.option ( '--source, --src, -s ', 'Path to the source directory - can be used multiple times' ); 29 | app.option ( '--dist, --dest, --dst, -d ', 'Path to the distribution directory' ); // We actually also support "--distribution, --destination" 30 | app.option ( '--config, -c ', `Your project\'s configuration path or JSON object - can be used multiple times` ); 31 | app.option ( '--target, -t ', 'The compilation target to use' ); 32 | app.option ( '--environment, --env, -e ', 'The environment to use - can be used multiple times' ); // We actually also support "--environments, --envs" 33 | app.option ( '--fresh', 'Clear the cache before building' ); 34 | app.option ( '--dependencies-graph', 'Render the dependencies graph' ); 35 | app.option ( '--no-notification', 'Disable the notification after building' ); 36 | app.option ( '--no-summary', 'Disable the summary after building' ); 37 | // app.option ( '--verbose', 'Enable some extra logging' ); // There's a global option called "verbose" 38 | app.option ( '--icon', 'Icon used for success notifications' ); 39 | app.option ( '--icon-error', 'Icon used for error notifications' ); 40 | 41 | /* TASKS */ 42 | 43 | const taskNames = [ 44 | 'config', 45 | 'clean/html', 'clean/json', 'clean/fonts', 'clean/images', 'clean/javascript', 'clean/typescript', 'clean/scss', 'clean/css', 'clean/style', 'clean', 46 | 'watch/html', 'watch/json', 'watch/fonts', 'watch/images', 'watch/markdown', 'watch/javascript', 'watch/scss/parts/functions', 'watch/scss/parts/keyframes', 'watch/scss/parts/mixins', 'watch/scss/parts/style', 'watch/scss/parts/variables', 'watch/scss/parts', 'watch/scss', 'watch/css/parts/css', 'watch/css/parts/scss', 'watch/css/parts', 'watch/css', 'watch/style', 'watch', 47 | 'build/html', 'build/json', 'build/fonts', 'build/images', 'build/markdown', 'build/javascript', 'build/scss/parts/functions', 'build/scss/parts/keyframes', 'build/scss/parts/mixins', 'build/scss/parts/style', 'build/scss/parts/variables', 'build/scss/parts', 'build/scss', 'build/css/parts/css', 'build/css/parts/scss', 'build/css/parts', 'build/css', 'build/style', 'build' 48 | ]; 49 | const tasks = taskNames.map ( name => require ( `./tasks/${name}` ) ); 50 | tasks.forEach ( task => { 51 | const hidden = ( task.group === 'all' && !argv.all ) || ( task.group === 'more' && !argv.all && !argv.more ); 52 | const command = app.command ( task.displayName, task.description ).action ( task ).visible ( !hidden ); 53 | command._options = app._defaultCommand._options; // Not all commands support all the options, but it's good enough 54 | if ( task.args ) { 55 | task.args.forEach ( args => { 56 | command.argument ( ...args ); 57 | }); 58 | } 59 | }); 60 | 61 | /* DEFAULT TASK */ 62 | 63 | const task = require ( './tasks/default' ); 64 | app.command ( task.displayName, task.description ).action ( task ); 65 | app.action ( task ); 66 | 67 | /* HELP */ 68 | 69 | app.command ( 'help', 'Display help' ) 70 | .option ( '--more', 'Show more available commands' ) 71 | .option ( '--all', 'Show all available commands' ); 72 | 73 | /* DEFAULT COMMAND */ 74 | 75 | const command = app._defaultCommand; 76 | const helpLines = [ 77 | `pacco ${color.green ( '--src' )} ${color.blue ( './source' )} ${color.green ( '--dist' )} ${color.blue ( './bundle' )}`, 78 | `pacco ${color.green ( '--config' )} ${color.blue ( '/path/to/pacco.json' )}`, 79 | `pacco ${color.magenta ( 'help' )} ${color.green ( '--all' )}`, 80 | `pacco ${color.magenta ( 'config' )} ${color.yellow ( 'paths.tokens' )}`, 81 | `pacco ${color.magenta ( 'build' )} ${color.green ( '--config' )} ${color.blue ( '/path/to/pacco.json' )} ${color.green ( '--env' )} ${color.blue ( 'development' )}` 82 | ]; 83 | 84 | command.help ( helpLines.join ( '\n' ), { name: 'USAGE - ADVANCED' } ); 85 | 86 | /* PARSE */ 87 | 88 | caporal.parse ( process.argv ); 89 | 90 | } 91 | 92 | /* EXPORT */ 93 | 94 | module.exports = CLI; 95 | -------------------------------------------------------------------------------- /src/plugins/clear.js: -------------------------------------------------------------------------------- 1 | 2 | //TODO: Publish as `gulp-clear` 3 | 4 | /* REQUIRE */ 5 | 6 | const forAll = require ( './forall' ); 7 | 8 | /* CLEAR */ 9 | 10 | function clear ( files ) { 11 | 12 | return []; 13 | 14 | } 15 | 16 | /* EXPORT */ 17 | 18 | module.exports = forAll ( clear ); 19 | -------------------------------------------------------------------------------- /src/plugins/components.js: -------------------------------------------------------------------------------- 1 | 2 | //TODO: Publish as `gulp-components` 3 | 4 | /* REQUIRE */ 5 | 6 | const _ = require ( 'lodash' ), 7 | through = require ( 'through2' ), 8 | forAll = require ( './forall' ); 9 | 10 | /* UTILITIES */ 11 | 12 | function parseComponents ( components, prefix = '' ) { 13 | 14 | const rules = {}; 15 | 16 | _.forOwn ( components, ( enabled, key ) => { 17 | 18 | key = _.trim ( `${prefix}${key}`, '/' ); 19 | 20 | if ( _.isBoolean ( enabled ) ) { 21 | 22 | rules[key] = enabled; 23 | 24 | } else if ( _.isPlainObject ( enabled ) ) { 25 | 26 | rules[key] = true; 27 | 28 | _.extend ( rules, parseComponents ( enabled, `${key}/` ) ); 29 | 30 | } 31 | 32 | }); 33 | 34 | return rules; 35 | 36 | } 37 | 38 | function isComponentEnabled ( file, config, rules ) { 39 | 40 | const component = config.path2component ( file.path ), 41 | maxPriority = component.split ( '/' ).length; 42 | 43 | let priority = 0, 44 | enabled = true; 45 | 46 | _.forOwn ( rules, ( active, rule ) => { 47 | 48 | if ( !component.startsWith ( rule ) ) return; 49 | 50 | const newPriority = rule.split ( '/' ).length; 51 | 52 | if ( newPriority > priority && newPriority <= maxPriority ) { 53 | 54 | priority = newPriority; 55 | enabled = active; 56 | 57 | } 58 | 59 | }); 60 | 61 | return enabled; 62 | 63 | } 64 | 65 | function partitionComponents ( files, config, rules ) { 66 | 67 | return _.partition ( files, file => isComponentEnabled ( file, config, rules ) ); 68 | 69 | } 70 | 71 | function log ( files ) { 72 | 73 | if ( !files.length ) return; 74 | 75 | const lines = [`Components disabled (${files.length}):`]; 76 | 77 | files.forEach ( file => { 78 | 79 | lines.push ( file.path ); 80 | 81 | }); 82 | 83 | console.log ( lines.join ( '\n' ) ); 84 | 85 | } 86 | 87 | /* COMPONENTS */ 88 | 89 | function components ( files, config ) { 90 | 91 | /* CONFIG */ 92 | 93 | config = _.merge ({ 94 | components: {}, 95 | path2component: _.identity, 96 | log: false 97 | }, config ); 98 | 99 | /* COMPONENTS */ 100 | 101 | const rules = parseComponents ( config.components ); 102 | [enabled, disabled] = partitionComponents ( files, config, rules ); 103 | 104 | if ( config.log ) log ( disabled ); 105 | 106 | return enabled; 107 | 108 | } 109 | 110 | /* EXPORT */ 111 | 112 | module.exports = forAll ( components ); 113 | -------------------------------------------------------------------------------- /src/plugins/concat.js: -------------------------------------------------------------------------------- 1 | 2 | //TODO: Publish as `gulp-concat` 3 | 4 | /* REQUIRE */ 5 | 6 | const _ = require ( 'lodash' ), 7 | PluginError = require ( 'plugin-error' ), 8 | Vinyl = require ( 'vinyl' ), 9 | forAll = require ( './forall' ); 10 | 11 | /* UTILITIES */ 12 | 13 | function getContents ( config, files ) { 14 | 15 | return files.map ( file => { 16 | 17 | const contents = file.contents.toString ( 'utf8' ), 18 | isWrapper = !!contents.match ( config.wrapperContentRe ); 19 | 20 | return { contents, isWrapper }; 21 | 22 | }); 23 | 24 | } 25 | 26 | function partitionContents ( contents ) { 27 | 28 | return _.partition ( contents, content => !content.isWrapper ); 29 | 30 | } 31 | 32 | function getFileContents ( config, normals, wrapper ) { 33 | 34 | const contents = normals.map ( normal => normal.contents ).filter ( _.identity ).join ( config.separator ); 35 | 36 | if ( !wrapper ) return contents; 37 | 38 | return wrapper.contents.replace ( config.wrapperContentRe, match => `${match}\n\n${contents}` ); 39 | 40 | } 41 | 42 | function getFile ( name, contents ) { 43 | 44 | return new Vinyl ({ 45 | path: _.isFunction ( name ) ? name () : name, 46 | contents: Buffer.from ( contents ) 47 | }); 48 | 49 | } 50 | 51 | /* CONCAT */ 52 | 53 | function concat ( files, fileName, config = {} ) { 54 | 55 | if ( !files.length ) return; 56 | 57 | /* CONFIG */ 58 | 59 | config = _.merge ({ 60 | separator: '\n', 61 | wrapperContentRe: /@concat-content/g, 62 | }, config ); 63 | 64 | /* CONCAT */ 65 | 66 | const contents = getContents ( config, files ), 67 | [normals, wrappers] = partitionContents ( contents ); 68 | 69 | if ( wrappers.length > 1 ) return new PluginError ( 'Concat', 'Multiple wrappers are not supported' ); 70 | 71 | const fileContents = getFileContents ( config, normals, wrappers[0] ), 72 | file = getFile ( fileName, fileContents ); 73 | 74 | return file; 75 | 76 | } 77 | 78 | /* EXPORT */ 79 | 80 | module.exports = forAll ( concat ); 81 | -------------------------------------------------------------------------------- /src/plugins/dependencies.js: -------------------------------------------------------------------------------- 1 | 2 | //TODO: Publish as `gulp-dependencies` 3 | 4 | /* REQUIRE */ 5 | 6 | const _ = require ( 'lodash' ), 7 | execa = require ( 'execa' ), 8 | fs = require ( 'fs' ), 9 | open = require ( 'open' ), 10 | path = require ( 'path' ), 11 | pify = require ( 'pify' ), 12 | PluginError = require ( 'plugin-error' ), 13 | {color} = require ( 'specialist' ), 14 | stringMatches = require ( 'string-matches' ).default, 15 | temp = require ( 'temp' ), 16 | forAll = require ( './forall' ); 17 | 18 | /* UTILITIES */ 19 | 20 | function getUniqMatches ( str, regex ) { 21 | 22 | const matches = stringMatches ( str, regex ); 23 | 24 | return _.uniqBy ( matches, match => match[0] ); 25 | 26 | } 27 | 28 | function getFileMatches ( file, regex ) { 29 | 30 | const contents = file.contents.toString ( 'utf8' ); 31 | 32 | return getUniqMatches ( contents, regex ); 33 | 34 | } 35 | 36 | function getFilePriority ( file, regex ) { 37 | 38 | const matches = getFileMatches ( file, regex ); 39 | 40 | return matches.length ? Number ( matches[0][1] ) || false : false; 41 | 42 | } 43 | 44 | function getFilePaths ( file, regex, config ) { 45 | 46 | const matches = getFileMatches ( file, regex ), 47 | targets = matches.map ( match => match[1] ), 48 | dirname = path.dirname ( config.path2component ( file.pathNormalized ) ); 49 | 50 | return targets.map ( target => target.startsWith ( '.' ) ? getPathNormalized ( path.join ( dirname, target ) ) : target ); 51 | 52 | } 53 | 54 | function getPathNormalized ( filepath ) { // Normalizing those stupid Windows paths 55 | 56 | return filepath.replace ( /(\\|\/)+/g, '/' ); 57 | 58 | } 59 | 60 | function getComponentName ( component, regex ) { 61 | 62 | const matches = getUniqMatches ( component, regex ); 63 | 64 | return matches.length ? matches[0][1] : ''; 65 | 66 | } 67 | 68 | function getPathSuffix ( filepath, regex ) { 69 | 70 | const matches = getUniqMatches ( path.basename ( filepath ), regex ); 71 | 72 | return matches.length ? matches[0][1] : ''; 73 | 74 | } 75 | 76 | function getPathWithoutSuffix ( filepath, regex ) { 77 | 78 | const matches = getUniqMatches ( filepath, regex ); 79 | 80 | return matches.length ? `${filepath.substring ( 0, matches[0].index )}${filepath.substring ( matches[0].index + matches[0][1].length + 1 )}` : filepath; 81 | 82 | } 83 | 84 | function getNodesByName ( nodes, name ) { 85 | 86 | return nodes.filter ( node => node.name === name ); 87 | 88 | } 89 | 90 | function groupNodesByNames ( nodes, names ) { // Passing `names` in order to allow non-special names 91 | 92 | const nodesByNames = names.map ( name => getNodesByName ( nodes, name ) ); 93 | 94 | return _.zipObject ( names, nodesByNames ); 95 | 96 | } 97 | 98 | function getNodesBySuffix ( nodes, suffix ) { 99 | 100 | return nodes.filter ( node => node.suffix === suffix ); 101 | 102 | } 103 | 104 | function groupNodesBySuffixes ( nodes, suffixes ) { // Passing `suffixes` in order to allow non-special suffixes 105 | 106 | const nodesBySuffixes = suffixes.map ( suffix => getNodesBySuffix ( nodes, suffix ) ); 107 | 108 | return _.zipObject ( suffixes, nodesBySuffixes ); 109 | 110 | } 111 | 112 | function sortNodes ( nodes, paths ) { 113 | 114 | return _.sortBy ( paths, [path => - nodes[path].priority || 0, path => nodes[path].path] ); 115 | 116 | } 117 | 118 | function bubblePriority ( components, node ) { 119 | 120 | node.dependencies.forEach ( dependency => { 121 | 122 | const parentNode = components[dependency]; 123 | 124 | if ( !parentNode ) return; // It could be an optional dependency 125 | 126 | if ( node.priority <= parentNode.priority ) return; 127 | 128 | parentNode.priority = node.priority; 129 | 130 | bubblePriority ( components, parentNode ); 131 | 132 | }); 133 | 134 | } 135 | 136 | /* GRAPH */ 137 | 138 | async function dotCheck () { 139 | 140 | try { 141 | 142 | await execa ( 'dot', ['-?'] ); // Help command 143 | 144 | return true; 145 | 146 | } catch ( e ) { 147 | 148 | console.error ( color.red ( `"${color.underline ( 'dot' )}" must be installed in order to render the graph` ) ); 149 | 150 | return false; 151 | 152 | } 153 | 154 | } 155 | 156 | function dotGetGraph ( nodes ) { 157 | 158 | const lines = []; 159 | 160 | lines.push ( 'digraph {' ); 161 | lines.push ( 'nodesep=.5' ); 162 | lines.push ( 'node [style="filled",color="gray89"]' ); 163 | lines.push ( 'edge [color="gray43"]' ); 164 | 165 | _.forOwn ( nodes, ( node ) => { 166 | 167 | const {component, dependencies, priority} = node; 168 | 169 | if ( dependencies.length ) { 170 | 171 | dependencies.forEach ( dependency => { 172 | 173 | if ( priority ) lines.push ( `"${dependency}" [color="${priority > 0 ? 'palegreen1' : 'indianred1'}"]` ); 174 | 175 | lines.push ( `"${dependency}" -> "${component}"` ); 176 | 177 | }); 178 | 179 | } else { 180 | 181 | lines.push ( `"${component}" [color="khaki1"]` ); 182 | 183 | } 184 | 185 | }); 186 | 187 | lines.push ( '}' ); 188 | 189 | return lines.length > 5 ? lines.join ( '\n' ) : false; 190 | 191 | } 192 | 193 | async function dotRenderGraph ( src, dst ) { 194 | 195 | return execa ( 'dot', [src, '-Tsvg', '-o', dst] ); 196 | 197 | } 198 | 199 | async function graphNodes ( nodes ) { 200 | 201 | if ( !await dotCheck () ) return; 202 | 203 | const graph = dotGetGraph ( nodes ); 204 | 205 | if ( !graph ) return console.error ( color.red ( 'The dependencies graph can\'t be rendered, there are no nodes to draw' ) ); 206 | 207 | const fileTXT = await pify ( temp.open )({ prefix: 'pacco-dependencies', suffix: '.txt' }); 208 | 209 | fs.writeSync ( fileTXT.fd, graph ); 210 | 211 | const fileSVG = await pify ( temp.open )({ prefix: 'pacco-dependencies', suffix: '.svg' }); 212 | 213 | await dotRenderGraph ( fileTXT.path, fileSVG.path ); 214 | 215 | open ( fileSVG.path ); 216 | 217 | } 218 | 219 | /* RESOLUTION */ 220 | 221 | function getNodes ( files, config ) { 222 | 223 | /* VARIABLES */ 224 | 225 | const nodes = {}, 226 | components = {}; 227 | 228 | /* NORMALIZING PATHS */ 229 | 230 | files.forEach ( file => { 231 | 232 | file.pathNormalized = getPathNormalized ( file.path ); 233 | 234 | }); 235 | 236 | /* POPULATING */ 237 | 238 | files.forEach ( file => { 239 | 240 | const suffix = getPathSuffix ( file.pathNormalized, config.suffixRe ), 241 | component = config.path2component ( file.pathNormalized ), 242 | componentWithoutSuffix = getPathWithoutSuffix ( component, config.suffixRe ), 243 | name = getComponentName ( component, config.nameRe ); 244 | 245 | const node = { 246 | file, 247 | path: file.pathNormalized, 248 | component, 249 | name, 250 | suffix, 251 | priority: config.priority ? getFilePriority ( file, config.priorityRe ) : 0, 252 | optionals: config.optional ? getFilePaths ( file, config.optionalRe, config ) : [], 253 | requires: config.require ? getFilePaths ( file, config.requireRe, config ) : [], 254 | before: ( suffix === config.beforeSuffix ) ? componentWithoutSuffix : false, 255 | beforeAll: ( name === config.beforeSuffix ), 256 | after: ( suffix === config.afterSuffix ) ? componentWithoutSuffix : false, 257 | afterAll: ( name === config.afterSuffix ), 258 | override: ( suffix === config.overrideSuffix ) ? componentWithoutSuffix : false 259 | }; 260 | 261 | if ( !config.before && ( node.before || node.beforeAll ) ) return; 262 | if ( !config.after && ( node.after || node.afterAll ) ) return; 263 | if ( !config.override && node.override ) return; 264 | 265 | nodes[file.pathNormalized] = node; 266 | components[component] = node; 267 | 268 | }); 269 | 270 | /* DEPENDENCIES */ 271 | 272 | files.forEach ( file => { 273 | 274 | const node = nodes[file.pathNormalized], 275 | validOptionals = node.optionals.filter ( optional => components[optional] ); 276 | 277 | node.dependencies = validOptionals.concat ( node.requires ); 278 | 279 | }); 280 | 281 | return { nodes, components }; 282 | 283 | } 284 | 285 | function resolveOverride ( nodes, components, {overrides} ) { 286 | 287 | for ( let node of overrides ) { 288 | 289 | const target = components[node.override]; 290 | 291 | if ( !target ) return getErrorOverride ( node ); 292 | 293 | const originalPath = target.file.pathNormalized; 294 | 295 | _.extend ( target, _.omit ( node, ['path', 'pathNormalized', 'component'] ) ); 296 | 297 | delete nodes[node.path]; 298 | 299 | target.file.originalPath = originalPath; 300 | 301 | } 302 | 303 | } 304 | 305 | function resolveBefore ( nodes, components, {befores} ) { 306 | 307 | for ( let node of befores ) { 308 | 309 | const target = components[node.before]; 310 | 311 | if ( !target ) return getErrorBefore ( node ); 312 | 313 | if ( node.priority !== false ) { 314 | target.priority = node.priority; 315 | } 316 | 317 | target.dependencies = _.uniq ( target.dependencies.concat ( node.dependencies ) ); 318 | 319 | } 320 | 321 | } 322 | 323 | function injectBefores ( nodes, components, files, befores ) { 324 | 325 | befores.forEach ( before => { 326 | 327 | const index = files.findIndex ( file => nodes[file.originalPath || file.pathNormalized].component === before.before ); 328 | 329 | files.splice ( index, 0, before.file ); 330 | 331 | }); 332 | 333 | } 334 | 335 | function injectBeforesAll ( nodes, components, files, beforesAll ) { 336 | 337 | beforesAll.forEach ( beforeAll => { 338 | 339 | files.splice ( 0, 0, beforeAll.file ); 340 | 341 | }); 342 | 343 | } 344 | 345 | function resolveAfter ( nodes, components, {afters} ) { 346 | 347 | for ( let node of afters ) { 348 | 349 | const target = components[node.after]; 350 | 351 | if ( !target ) return getErrorAfter ( node ); 352 | 353 | target.dependencies = _.uniq ( target.dependencies.concat ( node.dependencies ) ); 354 | 355 | } 356 | 357 | } 358 | 359 | function injectAfters ( nodes, components, files, afters ) { 360 | 361 | afters.forEach ( after => { 362 | 363 | const index = files.findIndex ( file => nodes[file.originalPath || file.pathNormalized].component === after.after ); 364 | 365 | files.splice ( index + 1, 0, after.file ); 366 | 367 | }); 368 | 369 | } 370 | 371 | function injectAftersAll ( nodes, components, files, aftersAll ) { 372 | 373 | aftersAll.forEach ( afterAll => { 374 | 375 | files.splice ( files.length, 0, afterAll.file ); 376 | 377 | }); 378 | 379 | } 380 | 381 | function resolvePriority ( nodes, components, {normals} ) { 382 | 383 | for ( let node of normals ) { 384 | 385 | bubblePriority ( components, node ); 386 | 387 | } 388 | 389 | } 390 | 391 | function resolveDependencies ( nodes, components, {normals, befores, beforesAll, afters, aftersAll} ) { 392 | 393 | const paths = sortNodes ( nodes, normals.map ( node => node.path ) ), 394 | files = []; // Resolved files 395 | 396 | let [roots, others] = _.partition ( paths, path => !nodes[path].dependencies.length ); 397 | 398 | function addRoot ( root ) { 399 | 400 | roots.push ( root ); 401 | 402 | roots = sortNodes ( nodes, roots ); // This could be optimized, but the speed gain is not significant 403 | 404 | } 405 | 406 | function resolveRoot ( root ) { 407 | 408 | const node = nodes[root], 409 | component = node.component; 410 | 411 | files.push ( node.file ); 412 | 413 | others = others.filter ( other => { 414 | 415 | const node = nodes[other]; 416 | 417 | _.remove ( node.dependencies, dependency => dependency === component ); 418 | 419 | const isRoot = !node.dependencies.length; 420 | 421 | if ( isRoot ) addRoot ( other ); 422 | 423 | return !isRoot; 424 | 425 | }); 426 | 427 | }; 428 | 429 | function resolveRoots () { 430 | 431 | while ( roots.length ) { // The length will probably change dynamically, can't use forEach 432 | 433 | const root = roots.shift (); 434 | 435 | resolveRoot ( root ); 436 | 437 | } 438 | 439 | } 440 | 441 | resolveRoots (); 442 | injectBefores ( nodes, components, files, befores ); 443 | injectAfters ( nodes, components, files, afters ); 444 | injectBeforesAll ( nodes, components, files, beforesAll ); 445 | injectAftersAll ( nodes, components, files, aftersAll ); 446 | 447 | return getErrorDependencies ( nodes, others ) || files; 448 | 449 | } 450 | 451 | function resolveNodes ( nodes, components, config ) { 452 | 453 | /* VARIABLES */ 454 | 455 | const nodesByNames = groupNodesByNames ( Object.values ( nodes ), ['', config.beforeSuffix, config.afterSuffix] ), 456 | normalsName = nodesByNames[''], 457 | beforesAll = nodesByNames[config.beforeSuffix], 458 | aftersAll = nodesByNames[config.afterSuffix], 459 | nodesBySuffixes = groupNodesBySuffixes ( normalsName, ['', config.beforeSuffix, config.afterSuffix, config.overrideSuffix] ), 460 | normals = nodesBySuffixes[''], 461 | befores = nodesBySuffixes[config.beforeSuffix], 462 | afters = nodesBySuffixes[config.afterSuffix], 463 | overrides = nodesBySuffixes[config.overrideSuffix], 464 | resolvers = [resolveOverride, resolveBefore, resolveAfter, resolvePriority, resolveDependencies]; 465 | 466 | /* RESOLVE */ 467 | 468 | for ( let resolver of resolvers ) { 469 | 470 | const result = resolver ( nodes, components, { normals, befores, beforesAll, afters, aftersAll, overrides } ); 471 | 472 | if ( result ) return result; 473 | 474 | } 475 | 476 | } 477 | 478 | /* LOGGING */ 479 | 480 | function getErrorOverride ( node ) { 481 | 482 | return getErrorMissingFile ( node.path, node.override ); 483 | 484 | } 485 | 486 | function getErrorBefore ( node ) { 487 | 488 | return getErrorMissingFile ( node.path, node.before ); 489 | 490 | } 491 | 492 | function getErrorAfter ( node ) { 493 | 494 | return getErrorMissingFile ( node.path, node.after ); 495 | 496 | } 497 | 498 | function getErrorDependencies ( nodes, leftovers ) { 499 | 500 | if ( !leftovers.length ) return; 501 | 502 | /* MISSING DEPENDENCIES */ 503 | 504 | for ( let leftover of leftovers ) { 505 | 506 | const node = nodes[leftover]; 507 | 508 | if ( !node ) continue; 509 | 510 | for ( let dependency of node.dependencies ) { 511 | 512 | const root = _.find ( nodes, node => node.component === dependency ); 513 | 514 | if ( !root ) return getErrorMissingFile ( node.path, dependency ); 515 | 516 | } 517 | 518 | } 519 | 520 | /* CIRCULAR DEPENDENCIES */ 521 | 522 | return getError ( `Circular dependencies found involving: \n${leftovers.map ( leftover => ` ${color.yellow ( leftover )}` ).join ( '\n' )}` ); 523 | 524 | } 525 | 526 | function getErrorMissingFile ( filepath1, filepath2 ) { 527 | 528 | return getError ( `"${color.yellow ( filepath1 )}" needs "${color.yellow ( filepath2 )}", but it has not been found, is the path correct?` ); 529 | 530 | } 531 | 532 | function getError ( message ) { 533 | 534 | return new PluginError ( 'Dependencies', message ); 535 | 536 | } 537 | 538 | function log ( nodes, files ) { 539 | 540 | if ( !files.length ) return; 541 | 542 | const lines = [`Dependencies (${files.length}):`]; 543 | 544 | files.forEach ( ( file, i ) => { 545 | 546 | const node = nodes[file.originalPath || file.pathNormalized], 547 | isOverride = !!file.originalPath, 548 | isBeforeOrAfter = node.before || node.after, 549 | priority = node.priority; 550 | 551 | let line = file.pathNormalized; 552 | 553 | if ( priority ) { 554 | 555 | const arrow = priority > 0 ? '↑' : '↓', 556 | colorKey = priority > 0 ? 'green' : 'red'; 557 | 558 | line += color[colorKey]( ` ${priority}${arrow}` ); 559 | 560 | } 561 | 562 | const separator = isOverride ? color.yellow ( '!' ) : ( isBeforeOrAfter ? color.yellow ( '<' ) : '-' ); 563 | 564 | line = `${_.padStart ( i + 1, files.length.toString ().length )} ${separator} ${line}`; 565 | 566 | lines.push ( line ); 567 | 568 | }); 569 | 570 | console.log ( lines.join ( '\n' ) ); 571 | 572 | } 573 | 574 | /* DEPENDENCIES */ 575 | 576 | async function dependencies ( files, config ) { 577 | 578 | /* CONFIG */ 579 | 580 | config = _.merge ({ 581 | path2component: _.identity, 582 | log: false, 583 | graph: false, 584 | /* TAG DIRECTIVES */ 585 | priority: true, 586 | priorityRe: /@priority[\s]+(-?(?:(?:\d+)(?:\.\d*)?|(?:\.\d+)+))[\s]*/g, 587 | optional: true, 588 | optionalRe: /@optional[\s]+([\S]+\.[\S]+)[\s]*/g, 589 | require: true, 590 | requireRe: /@require[\s]+([\S]+\.[\S]+)[\s]*/g, 591 | /* NAME/SUFFIX DIRECTIVES */ 592 | nameRe: /^(before|after)\.\S+$/g, 593 | suffixRe: /\.(before|after|override)\.\S+$/g, 594 | before: true, 595 | beforeName: 'before', 596 | beforeSuffix: 'before', 597 | after: true, 598 | afterName: 'after', 599 | afterSuffix: 'after', 600 | override: true, 601 | overrideSuffix: 'override' 602 | }, config ); 603 | 604 | /* DEPENDENCIES */ 605 | 606 | const { nodes, components } = getNodes ( files, config ); 607 | 608 | if ( config.graph ) await graphNodes ( nodes ); 609 | 610 | const result = resolveNodes ( nodes, components, config ); 611 | 612 | if ( result instanceof PluginError ) return result; 613 | 614 | if ( config.log ) log ( nodes, result ); 615 | 616 | return result; 617 | 618 | } 619 | 620 | /* EXPORT */ 621 | 622 | module.exports = forAll ( dependencies ); 623 | -------------------------------------------------------------------------------- /src/plugins/filelog.js: -------------------------------------------------------------------------------- 1 | 2 | //TODO: Publish as `gulp-filelog` 3 | 4 | /* REQUIRE */ 5 | 6 | const _ = require ( 'lodash' ), 7 | {color} = require ( 'specialist' ), 8 | forAll = require ( './forall' ); 9 | 10 | /* FILE LOG */ 11 | 12 | function fileLog ( files, config = {} ) { 13 | 14 | if ( files.length ) { 15 | 16 | const lines = [`Files (${files.length})${config.title ? ` in '${color.cyan ( config.title )}'` : ''}:`]; 17 | 18 | for ( let i = 0, l = files.length; i < l; i++ ) { 19 | 20 | lines.push ( _.padStart ( i + 1, l.toString ().length ) + ' - ' + files[i].path ); 21 | 22 | } 23 | 24 | console.log ( lines.join ( '\n' ) ); 25 | 26 | } else { 27 | 28 | console.log ( `No files in ${config.title ? `'${color.cyan ( config.title )}'` : 'the stream'}` ); 29 | 30 | } 31 | 32 | } 33 | 34 | /* EXPORT */ 35 | 36 | module.exports = forAll ( fileLog ); 37 | -------------------------------------------------------------------------------- /src/plugins/forall.js: -------------------------------------------------------------------------------- 1 | 2 | //TODO: Publish as `gulp-forall` 3 | 4 | /* REQUIRE */ 5 | 6 | const _ = require ( 'lodash' ), 7 | PluginError = require ( 'plugin-error' ), 8 | through = require ( 'through2' ); 9 | 10 | /* FOR ALL */ 11 | 12 | function forAll ( plugin ) { 13 | 14 | return function pluginWrapper ( ...args ) { 15 | 16 | let files = []; 17 | 18 | return through.obj ( function ( file, encoding, callback ) { 19 | 20 | files.push ( file ); 21 | 22 | callback (); 23 | 24 | }, async function ( callback ) { 25 | 26 | files = await plugin ( files, ...args ) || files; 27 | 28 | if ( files instanceof PluginError ) { 29 | 30 | callback ( files ); 31 | 32 | } else { 33 | 34 | if ( files ) _.castArray ( files ).forEach ( this.push.bind ( this ) ); 35 | 36 | callback (); 37 | 38 | } 39 | 40 | }); 41 | 42 | } 43 | 44 | } 45 | 46 | /* EXPORT */ 47 | 48 | module.exports = forAll; 49 | -------------------------------------------------------------------------------- /src/plugins/log.js: -------------------------------------------------------------------------------- 1 | 2 | //TODO: Publish as `gulp-log` 3 | 4 | /* REQUIRE */ 5 | 6 | const _ = require ( 'lodash' ), 7 | forAll = require ( './forall' ); 8 | 9 | /* LOG */ 10 | 11 | function log ( files, txt = _.noop ) { 12 | 13 | txt = _.isFunction ( txt ) ? txt () : txt; 14 | 15 | if ( txt ) console.log ( txt ); 16 | 17 | } 18 | 19 | /* EXPORT */ 20 | 21 | module.exports = forAll ( log ); 22 | -------------------------------------------------------------------------------- /src/plugins/order_pinner.js: -------------------------------------------------------------------------------- 1 | 2 | //TODO: Publish as `gulp-order-pinner` 3 | 4 | /* REQUIRE */ 5 | 6 | const _ = require ( 'lodash' ), 7 | path = require ( 'path' ), 8 | forAll = require ( './forall' ); 9 | 10 | /* ORDER PINNER */ 11 | 12 | function orderPinner ( files ) { 13 | 14 | files.forEach ( ( file, i ) => { 15 | 16 | const dir = path.dirname ( file.path ), 17 | name = path.basename ( file.path ), 18 | namePadded = `${_.padStart ( i + 1, files.length.toString ().length, 0 )}-${name}`; 19 | 20 | file.path = path.join ( dir, namePadded ); 21 | 22 | }); 23 | 24 | } 25 | 26 | /* EXPORT */ 27 | 28 | module.exports = forAll ( orderPinner ); 29 | -------------------------------------------------------------------------------- /src/plugins/picker.js: -------------------------------------------------------------------------------- 1 | 2 | //TODO: Publish as `gulp-picker` or something 3 | 4 | /* REQUIRE */ 5 | 6 | const _ = require ( 'lodash' ), 7 | micromatch = require ( 'micromatch' ), 8 | forAll = require ( './forall' ); 9 | 10 | /* PICKER */ 11 | 12 | function picker () { 13 | 14 | const cache = {}; 15 | 16 | return { 17 | pick: forAll ( ( ...args ) => pick ( cache, ...args ) ), 18 | replace: forAll ( ( ...args ) => replace ( cache, ...args ) ), 19 | reset: forAll ( ( ...args ) => reset ( cache, ...args ) ) 20 | }; 21 | 22 | } 23 | 24 | /* PICK */ 25 | 26 | function pick ( cache, files, filterer ) { // Pick a subset of the cached files 27 | 28 | if ( !cache.files ) cache.files = files; 29 | 30 | if ( _.isFunction ( filterer ) ) { 31 | 32 | return cache.files.filter ( filterer ); 33 | 34 | } else { 35 | 36 | return cache.files.filter ( file => { 37 | 38 | return micromatch ( [file.path], filterer ).length; 39 | 40 | }); 41 | 42 | } 43 | 44 | } 45 | 46 | /* REPLACE */ 47 | 48 | function replace ( cache, files, replacer ) { // Replace all files 49 | 50 | return cache.files = replacer ( cache.files, files ); 51 | 52 | } 53 | 54 | /* RESET */ 55 | 56 | function reset ( cache, files ) { // Reset all files 57 | 58 | return replace ( cache, files, ( cached, files ) => files ); 59 | 60 | } 61 | 62 | /* EXPORT */ 63 | 64 | module.exports = picker; 65 | -------------------------------------------------------------------------------- /src/plugins/substitute.js: -------------------------------------------------------------------------------- 1 | 2 | //TODO: Publish as `gulp-substitute` 3 | 4 | /* REQUIRE */ 5 | 6 | const _ = require ( 'lodash' ), 7 | stringMatches = require ( 'string-matches' ).default, 8 | forAll = require ( './forall' ); 9 | 10 | /* UTILITIES */ 11 | 12 | function getSubstitution ( substitutions, path ) { 13 | 14 | const val = path ? _.get ( substitutions, path ) : substitutions; 15 | 16 | return !_.isObject ( val ) ? val : JSON.stringify ( val ); 17 | 18 | } 19 | 20 | function replaceAll ( string, pattern, replacement ) { 21 | 22 | return string.replace ( new RegExp ( _.escapeRegExp ( pattern ), 'g' ), replacement ); 23 | 24 | } 25 | 26 | function getUniqMatches ( str, regex ) { 27 | 28 | const matches = stringMatches ( str, regex ); 29 | 30 | return _.uniqBy ( matches, match => match[0] ); 31 | 32 | } 33 | 34 | function getMatchesSubstitutions ( matches, substitutions ) { 35 | 36 | return matches.map ( match => { 37 | 38 | return getSubstitution ( substitutions, match[1] ); 39 | 40 | }); 41 | 42 | } 43 | 44 | function fileSubstitute ( file, config ) { 45 | 46 | let contents = file.contents.toString (); 47 | 48 | const matches = getUniqMatches ( contents, config.tokenRe ); 49 | 50 | if ( !matches.length ) return; 51 | 52 | const values = getMatchesSubstitutions ( matches, config.substitutions ); 53 | 54 | matches.forEach ( ( match, i ) => { 55 | 56 | contents = replaceAll ( contents, match[0], values[i] ); 57 | 58 | }); 59 | 60 | file.contents = Buffer.from ( contents ); 61 | 62 | return { file, matches, values }; 63 | 64 | } 65 | 66 | function log ( stats ) { 67 | 68 | if ( !stats.length ) return; 69 | 70 | const matchesNr = _.sum ( stats.map ( ({ matches }) => matches.length ) ), 71 | lines = [`Substitutions (${matchesNr}):`]; 72 | 73 | stats.forEach ( ({ file, matches, values }) => { 74 | 75 | lines.push ( `${file.path}` ); 76 | 77 | matches.forEach ( ( match, i ) => { 78 | 79 | lines.push ( ` '${match[0]}' => '${values[i]}'` ); 80 | 81 | }); 82 | 83 | }); 84 | 85 | console.log ( lines.join ( '\n' ) ); 86 | 87 | } 88 | 89 | /* SUBSTITUTE */ 90 | 91 | function substitute ( files, config ) { 92 | 93 | /* CONFIG */ 94 | 95 | config = _.merge ({ 96 | substitutions: {}, 97 | tokenRe: /\[substitute(?:\.((?:[^\[\]\s]+|\[\d+\]){1,}))?\]/g, 98 | log: false 99 | }, config ); 100 | 101 | /* SUBSTITUTE */ 102 | 103 | const stats = files.map ( file => fileSubstitute ( file, config ) ).filter ( _.identity ); 104 | 105 | if ( config.log ) log ( stats ); 106 | 107 | } 108 | 109 | /* EXPORT */ 110 | 111 | module.exports = forAll ( substitute ); 112 | -------------------------------------------------------------------------------- /src/plugins/tap.js: -------------------------------------------------------------------------------- 1 | 2 | //TODO: Publish as `gulp-tap` or something 3 | 4 | /* REQUIRE */ 5 | 6 | const forAll = require ( './forall' ); 7 | 8 | /* TAP */ 9 | 10 | function tap ( files, handler ) { 11 | 12 | files.forEach ( handler ); 13 | 14 | } 15 | 16 | /* EXPORT */ 17 | 18 | module.exports = forAll ( tap ); 19 | -------------------------------------------------------------------------------- /src/plugins/touch.js: -------------------------------------------------------------------------------- 1 | 2 | //TODO: Publish as `gulp-touch` 3 | 4 | /* REQUIRE */ 5 | 6 | const fs = require ( 'fs' ), 7 | forAll = require ( './forall' ); 8 | 9 | /* TOUCH */ 10 | 11 | function touch ( files ) { 12 | 13 | const now = new Date (); 14 | 15 | files.forEach ( file => { 16 | 17 | fs.utimes ( file.path, now, now, () => {} ) 18 | 19 | }); 20 | 21 | } 22 | 23 | /* EXPORT */ 24 | 25 | module.exports = forAll ( touch ); 26 | -------------------------------------------------------------------------------- /src/plugins/unempty.js: -------------------------------------------------------------------------------- 1 | 2 | //TODO: Publish as `gulp-unempty` 3 | 4 | // It adds an empty file to the stream if it doesn't contain any files 5 | 6 | /* REQUIRE */ 7 | 8 | const fs = require ( 'fs' ), 9 | Vinyl = require ( 'vinyl' ), 10 | forAll = require ( './forall' ); 11 | 12 | /* HELPERS */ 13 | 14 | function getStats () { 15 | 16 | const now = new Date (), 17 | stats = new fs.Stats (); 18 | 19 | stats.atimeMs = stats.mtimeMs = stats.ctimeMs = stats.birthtimeMs = now.getTime (); 20 | stats.atime = stats.mtime = stats.ctime = stats.birthtime = now; 21 | 22 | return stats; 23 | 24 | } 25 | 26 | /* UNEMPTY */ 27 | 28 | function unempty ( files, filePath ) { 29 | 30 | if ( files.length ) return files; 31 | 32 | if ( filePath && ( !fs.existsSync ( filePath ) || !fs.readFileSync ( filePath, { encoding: 'utf8' } ) ) ) return; // Unempty only if this file is present and is not already empty 33 | 34 | return new Vinyl ({ 35 | contents: Buffer.from ( '' ), 36 | path: `/tmp/unempty_${Math.random ()}`, 37 | stat: getStats () 38 | }); 39 | 40 | } 41 | 42 | /* EXPORT */ 43 | 44 | module.exports = forAll ( unempty ); 45 | -------------------------------------------------------------------------------- /src/plugins/wrapper.js: -------------------------------------------------------------------------------- 1 | 2 | //TODO: Publish as `gulp-wrapper` 3 | 4 | /* REQUIRE */ 5 | 6 | const _ = require ( 'lodash' ), 7 | PluginError = require ( 'plugin-error' ), 8 | forAll = require ( './forall' ); 9 | 10 | /* UTILITIES */ 11 | 12 | function fileWrap ( file, template, token ) { 13 | 14 | if ( template && token ) { 15 | 16 | file.contentsUnwrapped = file.contents; 17 | 18 | file.contents = Buffer.from ( template.replace ( token, () => file.contents.toString ( 'utf8' ) ) ); 19 | 20 | } 21 | 22 | return file; 23 | } 24 | 25 | function fileUnwrap ( file ) { 26 | 27 | if ( file.contentsUnwrapped ) { 28 | 29 | file.contents = file.contentsUnwrapped; 30 | 31 | delete file.contentsUnwrapped; 32 | 33 | } 34 | 35 | return file; 36 | 37 | } 38 | 39 | /* WRAPPER */ 40 | 41 | function wrapper ( files, config = {}, wrap = true ) { 42 | 43 | if ( !files.length ) return; 44 | 45 | if ( files.length > 1 ) return new PluginError ( 'Wrapper', 'Only a single file can be wrapped/unwrapped' ); 46 | 47 | /* CONFIG */ 48 | 49 | config = _.merge ({ 50 | token: '[content]', // Token that will be replaced with the actual content inside a template 51 | template: false, // The template to use 52 | templates: { 53 | default: false, 54 | unminified: false, 55 | minified: false 56 | } 57 | }, config ); 58 | 59 | if ( wrap ) { // WRAP 60 | 61 | const template = config.templates[config.template] || config.templates.default; 62 | 63 | return fileWrap ( files[0], template, config.token ); 64 | 65 | } else { // UNWRAP 66 | 67 | return fileUnwrap ( files[0] ); 68 | 69 | } 70 | 71 | } 72 | 73 | /* WRAP */ 74 | 75 | function wrap ( ...args ) { 76 | 77 | return wrapper.call ( this, ...args, true ); 78 | 79 | } 80 | 81 | /* UNWRAP */ 82 | 83 | function unwrap ( ...args ) { 84 | 85 | return wrapper.call ( this, ...args, false ); 86 | 87 | } 88 | 89 | /* EXPORT */ 90 | 91 | module.exports = { 92 | wrap: forAll ( wrap ), 93 | unwrap: forAll ( unwrap ) 94 | }; 95 | -------------------------------------------------------------------------------- /src/project/defaults/components.js: -------------------------------------------------------------------------------- 1 | 2 | // Object used for making partial buildings by filtering out unwanted components 3 | // In the form of `component: enabled`. A component's key can also be divided into sub objects, where each key is a component on its own; in this case the parent component will be assumed to be enabled 4 | // Enabling/disabling is affected by component's key specificity. For instance `'widgets/form': false` will disable `widgets/form/ajax` too, but `'widgets/form/ajax': true` has an higher specificity and will enable it back 5 | 6 | /* COMPONENTS */ 7 | 8 | const components = {}; 9 | 10 | /* EXPORT */ 11 | 12 | module.exports = components; 13 | -------------------------------------------------------------------------------- /src/project/defaults/environments.js: -------------------------------------------------------------------------------- 1 | 2 | // All the properties of the active environment(s) will be merged with the basic object 3 | 4 | /* ENVIRONMENTS */ 5 | 6 | const environments = { 7 | production: {}, 8 | development: { 9 | plugins: { 10 | autoprefixer: { 11 | enabled: false 12 | }, 13 | babel: { 14 | enabled: false 15 | }, 16 | htmlmin: { 17 | enabled: false 18 | }, 19 | imagemin: { 20 | enabled: false 21 | }, 22 | jsonminify: { 23 | enabled: false 24 | }, 25 | postcss: { 26 | enabled: false 27 | }, 28 | uglify: { 29 | enabled: false 30 | } 31 | } 32 | } 33 | }; 34 | 35 | /* EXPORT */ 36 | 37 | module.exports = environments; 38 | -------------------------------------------------------------------------------- /src/project/defaults/index.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const components = require ( './components' ), 5 | environments = require ( './environments' ), 6 | targets = require ( './targets' ), 7 | paths = require ( './paths' ), 8 | plugins = require ( './plugins' ); 9 | 10 | /* DEFAULTS */ 11 | 12 | const defaults = { 13 | 14 | /* ENGINES */ // Target these engine(s) when compiling 15 | 16 | browsers: ['ie >= 10'], 17 | node: 'current', 18 | 19 | /* GENERAL */ 20 | 21 | components, 22 | paths, 23 | plugins, 24 | 25 | /* TARGET */ 26 | 27 | targets, 28 | target: 'web', 29 | 30 | /* ENVIRONMENT */ 31 | 32 | environments, 33 | environment: 'production' // Supports 'env', `[env1[, env2]]` and `env1[,env2[,..]]` 34 | 35 | }; 36 | 37 | /* EXPORT */ 38 | 39 | module.exports = defaults; 40 | -------------------------------------------------------------------------------- /src/project/defaults/paths.js: -------------------------------------------------------------------------------- 1 | 2 | // All paths are relative to `--config` or, if is not a path or is missing, `process.cwd ()` 3 | // `[token]` will be replaced with values defined in `tokens` 4 | // `tokens.src` can also be an array 5 | // In order to extend a source just add another source to `tokens.src` 6 | // Sources may be either relative: `ext`, `../ext` or absolute `/Users/me/ext` 7 | 8 | /* PATHS */ 9 | 10 | const paths = { 11 | tokens: { 12 | src: 'src', 13 | dist: 'dist', 14 | bundle: 'pacco', 15 | target: undefined, // Setted dynamically 16 | temp: undefined, // Setted dynamically 17 | env: undefined, // Setted dynamically 18 | environment: undefined // Setted dynamically 19 | }, 20 | input: { 21 | html: '[src]/**/*.html', 22 | json: '[src]/**/*.json', 23 | fonts: '[src]/**/*.{eot,otf,ttf,woff,woff2}', 24 | images: '[src]/**/*.{bmp,gif,ico,jpg,jpeg,png,svg,webp}', 25 | markdown: '[src]/**/*.md', 26 | javascript: { 27 | all: '[src]/**/*.js' 28 | }, 29 | typescript: { 30 | all: '[src]/**/*.ts' 31 | }, 32 | scss: { 33 | all: '[src]/**/*.scss', 34 | variables: '[src]/**/variables*.scss', 35 | functions: '[src]/**/functions*.scss', 36 | mixins: '[src]/**/mixins*.scss', 37 | keyframes: '[src]/**/keyframes*.scss', 38 | style: ['[src]/**/*.scss', '![src]/**/variables*.scss', '![src]/**/functions*.scss', '![src]/**/mixins*.scss', '![src]/**/keyframes*.scss'] 39 | }, 40 | css: { 41 | all: '[src]/**/*.css' 42 | } 43 | }, 44 | output: { 45 | html: '[dist]/html', 46 | json: '[dist]/json', 47 | fonts: '[dist]/fonts', 48 | images: '[dist]/images', 49 | markdown: '[dist]/html', 50 | javascript: { 51 | unminified: '[dist]/javascript/[bundle].js', 52 | minified: '[dist]/javascript/[bundle].min.js', 53 | partial: '[temp]/partials/javascript/concat.js' 54 | }, 55 | typescript: { 56 | declaration: '[dist]/typescript/[bundle].d.ts', 57 | partial: '[dist]/typescript/[bundle].ts' 58 | }, 59 | scss: { 60 | all: '[dist]/scss/[bundle].scss', 61 | variables: '[dist]/scss/[bundle].variables.scss', 62 | functions: '[dist]/scss/[bundle].functions.scss', 63 | mixins: '[dist]/scss/[bundle].mixins.scss', 64 | keyframes: '[dist]/scss/[bundle].keyframes.scss', 65 | style: '[dist]/scss/[bundle].style.scss', 66 | partial: '[temp]/partials/css/scss.css' 67 | }, 68 | css: { 69 | unminified: '[dist]/css/[bundle].css', 70 | minified: '[dist]/css/[bundle].min.css', 71 | partial: '[temp]/partials/css/css.css' 72 | } 73 | }, 74 | clean: ['[dist]', '[temp]'] 75 | }; 76 | 77 | /* EXPORT */ 78 | 79 | module.exports = paths; 80 | -------------------------------------------------------------------------------- /src/project/defaults/plugins.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const _ = require ( 'lodash' ), 5 | argv = require ( 'yargs' ).argv, 6 | findUp = require ( 'find-up' ), 7 | path = require ( 'path' ), 8 | file = require ( '../../utilities/file' ), 9 | project = require ( '../../utilities/project' ); 10 | 11 | /* PLUGINS */ 12 | 13 | const plugins = { 14 | autoprefixer: { 15 | enabled: true, 16 | options: { 17 | cascade: true 18 | } 19 | }, 20 | babel: { 21 | enabled: true, 22 | options: { 23 | presets: [ 24 | [require.resolve ( '@babel/preset-env' ), { //FIXME: Ugly 25 | modules: 'commonjs', 26 | loose: true, 27 | useBuiltIns: false 28 | }] 29 | ], 30 | plugins: [ 31 | [require.resolve ( 'babel-plugin-lodash-template-compile' ), { //FIXME: Ugly 32 | minify: true, 33 | templateOptions: { 34 | variable: 'o' 35 | } 36 | }] 37 | ], 38 | babelrc: false, 39 | compact: false 40 | } 41 | }, 42 | babili: { 43 | enabled: false, 44 | options: {} 45 | }, 46 | closure: { 47 | enabled: false, 48 | options: { 49 | assume_function_wrapper: true, 50 | compilation_level: 'SIMPLE', 51 | language_in: 'ECMASCRIPT5_STRICT', 52 | language_out: 'ECMASCRIPT5_STRICT', 53 | output_wrapper: '(function(){%output%})();', 54 | warning_level: 'QUIET' 55 | } 56 | }, 57 | concat: { 58 | options: {} 59 | }, 60 | del: { 61 | options: { 62 | force: true 63 | } 64 | }, 65 | components: { 66 | enabled: true, 67 | options: { 68 | path2component: file.file2component, 69 | log: !!argv.verbose 70 | } 71 | }, 72 | dependencies: { 73 | enabled: true, 74 | options: { 75 | path2component: file.file2component, 76 | log: !!argv.verbose, 77 | graph: !!argv.dependenciesGraph 78 | } 79 | }, 80 | htmlmin: { 81 | enabled: true, 82 | options: { 83 | collapseWhitespace: true, 84 | minifyCSS: true, 85 | minifyJS: true, 86 | removeComments: true, 87 | removeRedundantAttributes: true, 88 | removeScriptTypeAttributes: true, 89 | removeStyleLinkTypeAttributes: true 90 | } 91 | }, 92 | imagemin: { 93 | enabled: true, 94 | plugins () { 95 | 96 | const imagemin = require ( 'gulp-imagemin' ); 97 | 98 | return [ 99 | imagemin.gifsicle ({ 100 | interlaced: true, 101 | optimizationLevel: 3 102 | }), 103 | imagemin.jpegtran ({ 104 | progressive: true 105 | }), 106 | imagemin.optipng ({ 107 | optimizationLevel: 7 108 | }), 109 | imagemin.svgo ({ 110 | multipass: true, 111 | plugins: [{ 112 | cleanupIDs: false, 113 | }, { 114 | removeViewBox: false 115 | }] 116 | }) 117 | ]; 118 | 119 | }, 120 | options: {} 121 | }, 122 | jsonminify: { 123 | enabled: true, 124 | options: {} 125 | }, 126 | markdown: { 127 | enabled: true, 128 | options: { 129 | breaks: true, 130 | xhtml: true 131 | } 132 | }, 133 | postcss: { 134 | enabled: true, 135 | plugins () { 136 | 137 | const cssnano = require ( 'cssnano' ); 138 | 139 | return [ 140 | cssnano ({ 141 | autoprefixer: false, 142 | normalizeUrl: false, 143 | svgo: false, 144 | zindex: false 145 | }) 146 | ]; 147 | 148 | }, 149 | options: {} 150 | }, 151 | sass: { 152 | enabled: true, 153 | options: { 154 | outputStyle: 'expanded', 155 | precision: 10 156 | } 157 | }, 158 | substitute: { 159 | enabled: true, 160 | options: { 161 | tokenRe: /\[pacco(?:\.((?:[^\[\]\s]+|\[\d+\]){1,}))?\]/g, 162 | log: !!argv.verbose 163 | } 164 | }, 165 | typescript: { 166 | enabled: true, 167 | options () { 168 | 169 | const config = require ( '..' ), 170 | srcs = project.getSrcPaths ( config ); 171 | 172 | for ( let src of srcs ) { 173 | 174 | const tsconfigPath = findUp.sync ( 'tsconfig.json', { cwd: src } ); 175 | 176 | if ( !tsconfigPath ) continue; 177 | 178 | const tsconfig = file.load ( tsconfigPath, false ); 179 | 180 | if ( !tsconfig || !tsconfig.compilerOptions ) continue; 181 | 182 | return tsconfig.compilerOptions; 183 | 184 | } 185 | 186 | return { 187 | experimentalDecorators: true, 188 | forceConsistentCasingInFileNames: true, 189 | jsx: 'react', 190 | noUnusedParameters: false, 191 | strictNullChecks: true, 192 | target: 'ES5' 193 | }; 194 | 195 | } 196 | }, 197 | uglify: { 198 | enabled: true, 199 | options: {} 200 | }, 201 | webpack: { 202 | enabled: false, 203 | options: {} 204 | }, 205 | wrapper: { 206 | enabled: true, 207 | options: {} 208 | } 209 | }; 210 | 211 | /* EXPORT */ 212 | 213 | module.exports = plugins; 214 | -------------------------------------------------------------------------------- /src/project/defaults/targets.js: -------------------------------------------------------------------------------- 1 | 2 | // All the properties of the active target will be merged with the basic object 3 | 4 | /* REQUIRE */ 5 | 6 | const nodeExternals = require ( 'webpack-node-externals' ); 7 | 8 | /* TARGETS */ 9 | 10 | const targets = { 11 | web: { 12 | plugins: { 13 | webpack: { 14 | options: { 15 | target: 'web' 16 | } 17 | } 18 | } 19 | }, 20 | node: { 21 | plugins: { 22 | webpack: { 23 | options: { 24 | target: 'node', 25 | externals: nodeExternals () 26 | } 27 | } 28 | } 29 | }, 30 | }; 31 | 32 | /* EXPORT */ 33 | 34 | module.exports = targets; 35 | -------------------------------------------------------------------------------- /src/project/index.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const _ = require ( 'lodash' ), 5 | path = require ( 'path' ), 6 | sha1 = require ( 'sha1' ), 7 | defaults = require ( './defaults' ), 8 | config = require ( '../utilities/config' ), 9 | environments = require ( '../utilities/environments' ), 10 | projectU = require ( '../utilities/project' ), 11 | targetU = require ( '../utilities/target' ), 12 | file = require ( '../utilities/file' ), 13 | customJSON = file.loadRecursive ( 'pacco.json', {} ), 14 | customJS = file.loadRecursive ( 'pacco.js', {} ), 15 | arg = config.getObj () || {}, 16 | dynamic = config.getDynamicObj (); 17 | 18 | /* TARGET */ 19 | 20 | const target = dynamic.target || arg.target || customJS.target || customJSON.target || defaults.target, 21 | defaultsTarget = targetU.get ( defaults, target ), 22 | customJSONTarget = targetU.get ( customJSON, target ), 23 | customJSTarget = targetU.get ( customJS, target ), 24 | argTarget = targetU.get ( arg, target ), 25 | dynamicTarget = targetU.get ( dynamic, target ); 26 | 27 | targetU.checkExistence ( target, defaultsTarget, customJSONTarget, customJSTarget, argTarget, dynamicTarget ); 28 | 29 | /* ENVIRONMENT */ 30 | 31 | const envsRaw = dynamic.environment || arg.environment || customJS.environment || customJSON.environment || defaults.environment, 32 | envs = environments.parse ( envsRaw ), 33 | prettyEnvs = environments.pretty ( envs ), 34 | defaultsEnvs = environments.get ( defaults, envs ), 35 | customJSONEnvs = environments.get ( customJSON, envs ), 36 | customJSEnvs = environments.get ( customJS, envs ), 37 | argEnvs = environments.get ( arg, envs ), 38 | dynamicEnvs = environments.get ( dynamic, envs ); 39 | 40 | environments.checkExistence ( envs, defaultsEnvs, customJSONEnvs, customJSEnvs, argEnvs, dynamicEnvs ); 41 | 42 | /* PROJECT */ 43 | 44 | const project = _.merge ( {}, defaults, defaultsTarget, ...defaultsEnvs, customJSON, customJSONTarget, ...customJSONEnvs, customJS, customJSTarget, ...customJSEnvs, arg, argTarget, ...argEnvs, dynamic, dynamicTarget, ...dynamicEnvs ); 45 | 46 | projectU.checkSrcPaths ( project ); 47 | 48 | /* RUNTIME CONFIGURATION */ 49 | 50 | project.target = target; 51 | project.environment = envs; 52 | project.paths.tokens.target = target; 53 | project.paths.tokens.env = prettyEnvs; 54 | project.paths.tokens.environment = prettyEnvs 55 | project.paths.tokens.temp = projectU.getTempPath ( project ); 56 | 57 | projectU.initEngines ( project ); 58 | 59 | /* EXPORT */ 60 | 61 | module.exports = project; 62 | -------------------------------------------------------------------------------- /src/project/previous.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const path = require ( 'path' ), 5 | file = require ( '../utilities/file' ), 6 | projectU = require ( '../utilities/project' ), 7 | project = require ( '.' ); 8 | 9 | /* PREVIOUS */ 10 | 11 | const previousPath = path.join ( projectU.getTempPath ( project ), 'project.previous.json' ), 12 | previous = file.load ( previousPath, {} ); 13 | 14 | /* UPDATE */ 15 | 16 | file.write ( previousPath, project ); 17 | 18 | /* EXPORT */ 19 | 20 | module.exports = previous; 21 | -------------------------------------------------------------------------------- /src/tasks/build/css/index.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const _ = require ( 'lodash' ), 5 | gulp = require ( 'gulp' ), 6 | gulpif = require ( 'gulp-if' ), 7 | newer = require ( 'gulp-newer' ), 8 | plumber = require ( 'gulp-plumber' ), 9 | rename = require ( 'gulp-rename' ), 10 | changed = require ( '../../../utilities/changed' ), 11 | gutil = require ( '../../../utilities/gutil' ), 12 | output = require ( '../../../utilities/paths/output' ), 13 | plumberU = require ( '../../../utilities/plumber' ), 14 | concat = require ( '../../../plugins/concat' ), 15 | touch = require ( '../../../plugins/touch' ), 16 | plugins = require ( '../../../project' ).plugins; 17 | 18 | /* TASK */ 19 | 20 | function task () { 21 | 22 | const needUpdate = changed.environment () || changed.target () || changed.plugins ( 'autoprefixer', 'concat', 'postcss' ), 23 | needOutputUnminified = output.isEnabled ( 'css.unminified' ), 24 | needOutputMinified = output.isEnabled ( 'css.minified' ); 25 | 26 | return gulp.src ( _.filter ([ output.getPath ( 'css.partial' ), output.getPath ( 'scss.partial' ) ]), { allowEmpty: true } ) 27 | .pipe ( plumber ( plumberU.error ) ) 28 | .pipe ( gulpif ( !needUpdate && needOutputMinified, () => newer ( output.getPath ( 'css.minified' ) ) ) ) 29 | .pipe ( concat ( 'unminified.css', plugins.concat.options ) ) 30 | .pipe ( gulpif ( needOutputUnminified, rename ( output.getName ( 'css.unminified' ) ) ) ) 31 | .pipe ( gulpif ( plugins.autoprefixer.enabled, () => require ( 'gulp-autoprefixer' )( plugins.autoprefixer.options ) ) ) 32 | .pipe ( gulpif ( needOutputUnminified, () => gulp.dest ( output.getDir ( 'css.unminified' ) ) ) ) 33 | .pipe ( gulpif ( needOutputUnminified, touch () ) ) 34 | .pipe ( gulpif ( plugins.postcss.enabled, () => require ( 'gulp-postcss' )( plugins.postcss.plugins (), plugins.postcss.options ) ) ) 35 | .pipe ( gulpif ( needOutputMinified, rename ( output.getName ( 'css.minified' ) ) ) ) 36 | .pipe ( gulpif ( needOutputMinified, () => gulp.dest ( output.getDir ( 'css.minified' ) ) ) ) 37 | .pipe ( gulpif ( needOutputMinified, touch () ) ); 38 | 39 | } 40 | 41 | /* EXPORT */ 42 | 43 | module.exports = gutil.task.enhance ( task, 'build-css', 'Build CSS', 'more' ); 44 | -------------------------------------------------------------------------------- /src/tasks/build/css/parts/css.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const _ = require ( 'lodash' ), 5 | gulp = require ( 'gulp' ), 6 | gulpif = require ( 'gulp-if' ), 7 | newer = require ( 'gulp-newer' ), 8 | plumber = require ( 'gulp-plumber' ), 9 | changed = require ( '../../../../utilities/changed' ), 10 | output = require ( '../../../../utilities/paths/output' ), 11 | plumberU = require ( '../../../../utilities/plumber' ), 12 | components = require ( '../../../../plugins/components' ), 13 | concat = require ( '../../../../plugins/concat' ), 14 | dependencies = require ( '../../../../plugins/dependencies' ), 15 | substitute = require ( '../../../../plugins/substitute' ), 16 | touch = require ( '../../../../plugins/touch' ), 17 | unempty = require ( '../../../../plugins/unempty' ), 18 | project = require ( '../../../../project' ), 19 | {plugins} = project; 20 | 21 | /* TASK */ 22 | 23 | function task () { 24 | 25 | const needUpdate = changed.environment () || changed.target () || changed.project ( 'components' ) || changed.plugins ( 'components', 'concat', 'substitute', 'dependencies' ), 26 | needOutput = output.isEnabled ( 'css.partial' ); 27 | 28 | return gulp.src ( input.getPath ( 'css.all' ) ) 29 | .pipe ( plumber ( plumberU.error ) ) 30 | .pipe ( gulpif ( plugins.components.enabled, components ( _.merge ( { components: project.components }, plugins.components.options ) ) ) ) 31 | .pipe ( unempty ( output.getPath ( 'css.partial' ) ) ) 32 | .pipe ( gulpif ( !needUpdate && needOutput, () => newer ( output.getPath ( 'css.partial' ) ) ) ) 33 | .pipe ( gulpif ( plugins.substitute.enabled, substitute ( _.merge ( { substitutions: project }, plugins.substitute.options ) ) ) ) 34 | .pipe ( gulpif ( plugins.dependencies.enabled, dependencies ( plugins.dependencies.options ) ) ) 35 | .pipe ( concat ( output.getName ( 'css.partial' ), plugins.concat.options ) ) 36 | .pipe ( gulpif ( needOutput, () => gulp.dest ( output.getDir ( 'css.partial' ) ) ) ) 37 | .pipe ( gulpif ( needOutput, touch () ) ); 38 | 39 | } 40 | 41 | /* EXPORT */ 42 | 43 | module.exports = gutil.task.enhance ( task, 'build-css-css', 'Build CSS CSS', 'all' ); 44 | -------------------------------------------------------------------------------- /src/tasks/build/css/parts/index.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const gutil = require ( '../../../../utilities/gutil' ), 5 | partCSS = require ( './css' ), 6 | partSCSS = require ( './scss' ); 7 | 8 | /* TASK */ 9 | 10 | const task = gutil.parallel ( partCSS, partSCSS ); 11 | 12 | /* EXPORT */ 13 | 14 | module.exports = gutil.task.enhance ( task, 'build-css-parts', 'Build CSS parts', 'all' ); 15 | -------------------------------------------------------------------------------- /src/tasks/build/css/parts/scss.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const _ = require ( 'lodash' ), 5 | gulp = require ( 'gulp' ), 6 | gulpif = require ( 'gulp-if' ), 7 | newer = require ( 'gulp-newer' ), 8 | plumber = require ( 'gulp-plumber' ), 9 | rename = require ( 'gulp-rename' ), 10 | changed = require ( '../../../../utilities/changed' ), 11 | output = require ( '../../../../utilities/paths/output' ), 12 | plumberU = require ( '../../../../utilities/plumber' ), 13 | touch = require ( '../../../../plugins/touch' ), 14 | plugins = require ( '../../../../project' ).plugins; 15 | 16 | /* TASK */ 17 | 18 | function task () { 19 | 20 | const needUpdate = changed.environment () || changed.target () || changed.plugins ( 'sass' ), 21 | needOutput = output.isEnabled ( 'scss.partial' ); 22 | 23 | return gulp.src ( output.getPath ( 'scss.all' ), { allowEmpty: true } ) 24 | .pipe ( plumber ( plumberU.error ) ) 25 | .pipe ( gulpif ( !needUpdate && needOutput, () => newer ( output.getPath ( 'scss.partial' ) ) ) ) 26 | .pipe ( gulpif ( plugins.sass.enabled, () => require ( 'gulp-sass' )( require ( 'node-sass' ) )( plugins.sass.options ) ) ) 27 | .pipe ( gulpif ( needOutput, rename ( output.getName ( 'scss.partial' ) ) ) ) 28 | .pipe ( gulpif ( needOutput, () => gulp.dest ( output.getDir ( 'scss.partial' ) ) ) ) 29 | .pipe ( gulpif ( needOutput, touch () ) ); 30 | 31 | } 32 | 33 | /* EXPORT */ 34 | 35 | module.exports = gutil.task.enhance ( task, 'build-css-scss', 'Build CSS SCSS', 'all' ); 36 | -------------------------------------------------------------------------------- /src/tasks/build/fonts.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const _ = require ( 'lodash' ), 5 | gulp = require ( 'gulp' ), 6 | gulpif = require ( 'gulp-if' ), 7 | flatten = require ( 'gulp-flatten' ), 8 | newer = require ( 'gulp-newer' ), 9 | plumber = require ( 'gulp-plumber' ) 10 | changed = require ( '../../utilities/changed' ), 11 | gutil = require ( '../../utilities/gutil' ), 12 | input = require ( '../../utilities/paths/input' ), 13 | output = require ( '../../utilities/paths/output' ), 14 | plumberU = require ( '../../utilities/plumber' ), 15 | project = require ( '../../project' ), 16 | {plugins} = project, 17 | components = require ( '../../plugins/components' ), 18 | dependencies = require ( '../../plugins/dependencies' ), 19 | touch = require ( '../../plugins/touch' ); 20 | 21 | /* TASK */ 22 | 23 | function task () { 24 | 25 | const needUpdate = changed.environment () || changed.target () || changed.plugin ( 'dependencies' ), 26 | needOutput = output.isEnabled ( 'fonts' ); 27 | 28 | return gulp.src ( input.getPath ( 'fonts' ) ) 29 | .pipe ( plumber ( plumberU.error ) ) 30 | .pipe ( gulpif ( plugins.components.enabled, components ( _.merge ( { components: project.components }, plugins.components.options ) ) ) ) 31 | .pipe ( gulpif ( plugins.dependencies.enabled, dependencies ( plugins.dependencies.options ) ) ) 32 | .pipe ( flatten () ) 33 | .pipe ( gulpif ( !needUpdate && needOutput, () => newer ( output.getDir ( 'fonts' ) ) ) ) 34 | .pipe ( gulpif ( needOutput, () => gulp.dest ( output.getDir ( 'fonts' ) ) ) ) 35 | .pipe ( gulpif ( needOutput, touch () ) ); 36 | 37 | } 38 | 39 | /* EXPORT */ 40 | 41 | module.exports = gutil.task.enhance ( task, 'build-fonts', 'Build fonts', 'more' ); 42 | -------------------------------------------------------------------------------- /src/tasks/build/html.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const _ = require ( 'lodash' ), 5 | gulp = require ( 'gulp' ), 6 | gulpif = require ( 'gulp-if' ), 7 | flatten = require ( 'gulp-flatten' ), 8 | newer = require ( 'gulp-newer' ), 9 | plumber = require ( 'gulp-plumber' ) 10 | changed = require ( '../../utilities/changed' ), 11 | gutil = require ( '../../utilities/gutil' ), 12 | input = require ( '../../utilities/paths/input' ), 13 | output = require ( '../../utilities/paths/output' ), 14 | plumberU = require ( '../../utilities/plumber' ), 15 | project = require ( '../../project' ), 16 | {plugins} = project, 17 | components = require ( '../../plugins/components' ), 18 | dependencies = require ( '../../plugins/dependencies' ), 19 | touch = require ( '../../plugins/touch' ); 20 | 21 | /* TASK */ 22 | 23 | function task () { 24 | 25 | const needUpdate = changed.environment () || changed.target () || changed.plugin ( 'dependencies', 'htmlmin' ), 26 | needOutput = output.isEnabled ( 'html' ); 27 | 28 | return gulp.src ( input.getPath ( 'html' ) ) 29 | .pipe ( plumber ( plumberU.error ) ) 30 | .pipe ( gulpif ( plugins.components.enabled, components ( _.merge ( { components: project.components }, plugins.components.options ) ) ) ) 31 | .pipe ( gulpif ( plugins.dependencies.enabled, dependencies ( plugins.dependencies.options ) ) ) 32 | .pipe ( flatten () ) 33 | .pipe ( gulpif ( !needUpdate && needOutput, () => newer ( output.getDir ( 'html' ) ) ) ) 34 | .pipe ( gulpif ( plugins.htmlmin.enabled, () => require ( 'gulp-htmlmin' )( plugins.htmlmin.options ) ) ) 35 | .pipe ( gulpif ( needOutput, () => gulp.dest ( output.getDir ( 'html' ) ) ) ) 36 | .pipe ( gulpif ( needOutput, touch () ) ); 37 | 38 | } 39 | 40 | /* EXPORT */ 41 | 42 | module.exports = gutil.task.enhance ( task, 'build-html', 'Build HTML', 'more' ); 43 | -------------------------------------------------------------------------------- /src/tasks/build/images.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const _ = require ( 'lodash' ), 5 | gulp = require ( 'gulp' ), 6 | bytediff = require ( 'gulp-bytediff' ), 7 | flatten = require ( 'gulp-flatten' ), 8 | gulpif = require ( 'gulp-if' ), 9 | newer = require ( 'gulp-newer' ), 10 | plumber = require ( 'gulp-plumber' ), 11 | changed = require ( '../../utilities/changed' ), 12 | gutil = require ( '../../utilities/gutil' ), 13 | input = require ( '../../utilities/paths/input' ), 14 | output = require ( '../../utilities/paths/output' ), 15 | plumberU = require ( '../../utilities/plumber' ), 16 | components = require ( '../../plugins/components' ), 17 | dependencies = require ( '../../plugins/dependencies' ), 18 | touch = require ( '../../plugins/touch' ), 19 | project = require ( '../../project' ), 20 | {plugins} = project; 21 | 22 | /* TASK */ 23 | 24 | function task () { 25 | 26 | const needUpdate = changed.environment () || changed.target () || changed.plugins ( 'dependencies', 'imagemin' ), 27 | needOutput = output.isEnabled ( 'images' ); 28 | 29 | return gulp.src ( input.getPath ( 'images' ) ) 30 | .pipe ( plumber ( plumberU.error ) ) 31 | .pipe ( gulpif ( plugins.components.enabled, components ( _.merge ( { components: project.components }, plugins.components.options ) ) ) ) 32 | .pipe ( gulpif ( plugins.dependencies.enabled, dependencies ( plugins.dependencies.options ) ) ) 33 | .pipe ( flatten () ) 34 | .pipe ( gulpif ( !needUpdate && needOutput, () => newer ( output.getDir ( 'images' ) ) ) ) 35 | .pipe ( gulpif ( plugins.imagemin.enabled, bytediff.start () ) ) 36 | .pipe ( gulpif ( plugins.imagemin.enabled, () => require ( 'gulp-imagemin' )( plugins.imagemin.plugins (), plugins.imagemin.options ) ) ) 37 | .pipe ( gulpif ( plugins.imagemin.enabled, bytediff.stop () ) ) 38 | .pipe ( gulpif ( needOutput, () => gulp.dest ( output.getDir ( 'images' ) ) ) ) 39 | .pipe ( gulpif ( needOutput, touch () ) ); 40 | 41 | } 42 | 43 | /* EXPORT */ 44 | 45 | module.exports = gutil.task.enhance ( task, 'build-images', 'Build images', 'more' ); 46 | -------------------------------------------------------------------------------- /src/tasks/build/index.js: -------------------------------------------------------------------------------- 1 | 2 | //TODO: Ensure the `dist` directory always gets created 3 | 4 | /* REQUIRE */ 5 | 6 | const buildStatus = require ( '../../utilities/build_status' ), 7 | gutil = require ( '../../utilities/gutil' ), 8 | buildHTML = require ( './html' ), 9 | buildJSON = require ( './json' ), 10 | buildFonts = require ( './fonts' ), 11 | buildImages = require ( './images' ), 12 | buildMarkdown = require ( './markdown' ), 13 | buildJavascript = require ( './javascript' ), 14 | buildStyle = require ( './style' ), 15 | notification = require ( './notification' ), 16 | summary = require ( './summary' ); 17 | 18 | /* TASK */ 19 | 20 | const build = gutil.parallel ( buildHTML, buildJSON, buildFonts, buildImages, buildMarkdown, buildJavascript, buildStyle ), 21 | buildEnhanced = gutil.task.enhance ( build, 'build', 'Build your project' ), 22 | buildLogger = gutil.series ( buildStatus.start, buildEnhanced, buildStatus.finish, gutil.parallel ( notification, summary ) ); 23 | buildLoggerEnhanced = gutil.task.withMetadata ( buildLogger, 'build', 'Build your project' ); 24 | 25 | /* EXPORT */ 26 | 27 | module.exports = buildLoggerEnhanced; 28 | -------------------------------------------------------------------------------- /src/tasks/build/javascript.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const _ = require ( 'lodash' ), 5 | gulp = require ( 'gulp' ), 6 | gulpif = require ( 'gulp-if' ), 7 | newer = require ( 'gulp-newer' ), 8 | plumber = require ( 'gulp-plumber' ), 9 | rename = require ( 'gulp-rename' ), 10 | changed = require ( '../../utilities/changed' ), 11 | gutil = require ( '../../utilities/gutil' ), 12 | input = require ( '../../utilities/paths/input' ), 13 | output = require ( '../../utilities/paths/output' ), 14 | plumberU = require ( '../../utilities/plumber' ), 15 | components = require ( '../../plugins/components' ), 16 | concat = require ( '../../plugins/concat' ), 17 | dependencies = require ( '../../plugins/dependencies' ), 18 | pickerFactory = require ( '../../plugins/picker' ), 19 | substitute = require ( '../../plugins/substitute' ), 20 | tap = require ( '../../plugins/tap' ), 21 | touch = require ( '../../plugins/touch' ), 22 | unempty = require ( '../../plugins/unempty' ), 23 | wrapper = require ( '../../plugins/wrapper' ), 24 | project = require ( '../../project' ), 25 | {plugins} = project; 26 | 27 | /* TASK */ 28 | 29 | function task () { 30 | 31 | const picker = pickerFactory (), 32 | needUpdate = changed.environment () || changed.target () || changed.project ( 'components' ) || changed.plugins ( 'components', 'concat', 'substitute', 'dependencies', 'babel', 'babili', 'uglify', 'closure', 'typescript', 'webpack', 'wrapper' ), 33 | needOutputJSPartial = output.isEnabled ( 'javascript.partial' ), 34 | needOutputJSUnminified = output.isEnabled ( 'javascript.unminified' ), 35 | needOutputJSMinified = output.isEnabled ( 'javascript.minified' ), 36 | needOutputTSPartial = output.isEnabled ( 'typescript.partial' ), 37 | needOutputTSDeclaration = output.isEnabled ( 'typescript.declaration' ); 38 | 39 | let isTypeScript = false; 40 | 41 | return gulp.src ( _.flatten ( _.filter ( [input.getPath ( 'javascript.all' ), input.getPath ( 'typescript.all' )] ) ) ) 42 | .pipe ( plumber ( plumberU.error ) ) 43 | .pipe ( gulpif ( plugins.components.enabled, components ( _.merge ( { components: project.components }, plugins.components.options ) ) ) ) 44 | // .pipe ( unempty () ) //TODO 45 | .pipe ( gulpif ( !needUpdate && needOutputJSMinified, () => newer ( output.getPath ( 'javascript.minified' ) ) ) ) 46 | .pipe ( gulpif ( plugins.substitute.enabled, substitute ( _.merge ( { substitutions: project }, plugins.substitute.options ) ) ) ) 47 | .pipe ( gulpif ( plugins.dependencies.enabled, dependencies ( plugins.dependencies.options ) ) ) 48 | .pipe ( tap ( file => isTypeScript = isTypeScript || /\.ts$/.test ( file.path ) ) ) 49 | .pipe ( concat ( () => `partial.${isTypeScript ? 'ts' : 'js'}`, plugins.concat.options ) ) 50 | .pipe ( picker.pick ( () => isTypeScript ) ) 51 | .pipe ( gulpif ( needOutputTSPartial, rename ( output.getName ( 'typescript.partial' ) ) ) ) 52 | .pipe ( gulpif ( needOutputTSPartial, () => gulp.dest ( output.getDir ( 'typescript.partial' ) ) ) ) 53 | .pipe ( gulpif ( needOutputTSPartial, touch () ) ) 54 | .pipe ( gulpif ( plugins.typescript.enabled, () => require ( 'gulp-typescript' )( _.merge ( _.isPlainObject ( plugins.typescript.options ) ? plugins.typescript.options : plugins.typescript.options (), { declaration: true } ) ) ) ) 55 | .pipe ( picker.replace ( ( cached, compiled ) => compiled.length ? compiled : cached ) ) 56 | .pipe ( picker.pick ( '**/*.d.ts' ) ) 57 | .pipe ( gulpif ( needOutputTSDeclaration, rename ( output.getName ( 'typescript.declaration' ) ) ) ) 58 | .pipe ( gulpif ( needOutputTSDeclaration, () => gulp.dest ( output.getDir ( 'typescript.declaration' ) ) ) ) 59 | .pipe ( gulpif ( needOutputTSDeclaration, touch () ) ) 60 | .pipe ( picker.pick ( '**/*.js' ) ) 61 | .pipe ( gulpif ( needOutputJSPartial, rename ( output.getName ( 'javascript.partial' ) ) ) ) 62 | .pipe ( gulpif ( needOutputJSPartial, () => gulp.dest ( output.getDir ( 'javascript.partial' ) ) ) ) 63 | .pipe ( gulpif ( needOutputJSPartial, touch () ) ) 64 | .pipe ( gulpif ( plugins.webpack.enabled, () => require ( 'webpack-stream' )( plugins.webpack.options ) ) ) 65 | .pipe ( gulpif ( plugins.babel.enabled, () => require ( 'gulp-babel' )( plugins.babel.options ) ) ) 66 | .pipe ( gulpif ( needOutputJSUnminified, rename ( output.getName ( 'javascript.unminified' ) ) ) ) 67 | .pipe ( wrapper.wrap ( _.merge ( {}, plugins.wrapper.options, { template: 'unminified' } ) ) ) 68 | .pipe ( gulpif ( needOutputJSUnminified, () => gulp.dest ( output.getDir ( 'javascript.unminified' ) ) ) ) 69 | .pipe ( wrapper.unwrap ( plugins.wrapper.options ) ) 70 | .pipe ( gulpif ( needOutputJSUnminified, touch () ) ) 71 | .pipe ( gulpif ( plugins.babili.enabled, () => require ( 'gulp-babili' )( plugins.babili.options ) ) ) 72 | .pipe ( gulpif ( plugins.uglify.enabled, () => require ( 'gulp-uglify/composer' )( require ( 'uglify-js'), console )( plugins.uglify.options ) ) ) 73 | .pipe ( gulpif ( plugins.closure.enabled, () => require ( 'google-closure-compiler' ).gulp ()( plugins.closure.options ) ) ) 74 | .pipe ( gulpif ( needOutputJSMinified, rename ( output.getName ( 'javascript.minified' ) ) ) ) 75 | .pipe ( wrapper.wrap ( _.merge ( {}, plugins.wrapper.options, { template: 'minified' } ) ) ) 76 | .pipe ( gulpif ( needOutputJSMinified, () => gulp.dest ( output.getDir ( 'javascript.minified' ) ) ) ) 77 | .pipe ( wrapper.unwrap ( plugins.wrapper.options ) ) 78 | .pipe ( gulpif ( needOutputJSMinified, touch () ) ); 79 | 80 | } 81 | 82 | /* EXPORT */ 83 | 84 | module.exports = gutil.task.enhance ( task, 'build-javascript', 'Build JavaScript and TypeScript', 'more' ); 85 | -------------------------------------------------------------------------------- /src/tasks/build/json.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const _ = require ( 'lodash' ), 5 | gulp = require ( 'gulp' ), 6 | flatten = require ( 'gulp-flatten' ), 7 | gulpif = require ( 'gulp-if' ), 8 | newer = require ( 'gulp-newer' ), 9 | plumber = require ( 'gulp-plumber' ), 10 | changed = require ( '../../utilities/changed' ), 11 | gutil = require ( '../../utilities/gutil' ), 12 | input = require ( '../../utilities/paths/input' ), 13 | output = require ( '../../utilities/paths/output' ), 14 | plumberU = require ( '../../utilities/plumber' ), 15 | components = require ( '../../plugins/components' ), 16 | dependencies = require ( '../../plugins/dependencies' ), 17 | substitute = require ( '../../plugins/substitute' ), 18 | touch = require ( '../../plugins/touch' ), 19 | project = require ( '../../project' ), 20 | {plugins} = project; 21 | 22 | /* TASK */ 23 | 24 | function task () { 25 | 26 | const needUpdate = changed.environment () || changed.target () || changed.plugins ( 'dependencies', 'substitute', 'jsonminify' ), 27 | needOutput = output.isEnabled ( 'json' ); 28 | 29 | return gulp.src ( input.getPath ( 'json' ) ) 30 | .pipe ( plumber ( plumberU.error ) ) 31 | .pipe ( gulpif ( plugins.components.enabled, components ( _.merge ( { components: project.components }, plugins.components.options ) ) ) ) 32 | .pipe ( gulpif ( plugins.substitute.enabled, substitute ( _.merge ( { substitutions: project }, plugins.substitute.options ) ) ) ) 33 | .pipe ( gulpif ( plugins.dependencies.enabled, dependencies ( plugins.dependencies.options ) ) ) 34 | .pipe ( flatten () ) 35 | .pipe ( gulpif ( !needUpdate && needOutput, () => newer ( output.getDir ( 'json' ) ) ) ) 36 | .pipe ( gulpif ( plugins.jsonminify.enabled, () => require ( 'gulp-jsonminify' )( plugins.jsonminify.options ) ) ) 37 | .pipe ( gulpif ( needOutput, () => gulp.dest ( output.getDir ( 'json' ) ) ) ) 38 | .pipe ( gulpif ( needOutput, touch () ) ); 39 | 40 | } 41 | 42 | /* EXPORT */ 43 | 44 | module.exports = gutil.task.enhance ( task, 'build-json', 'Build JSON', 'more' ); 45 | -------------------------------------------------------------------------------- /src/tasks/build/markdown.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const _ = require ( 'lodash' ), 5 | gulp = require ( 'gulp' ), 6 | gulpif = require ( 'gulp-if' ), 7 | flatten = require ( 'gulp-flatten' ), 8 | newer = require ( 'gulp-newer' ), 9 | plumber = require ( 'gulp-plumber' ) 10 | changed = require ( '../../utilities/changed' ), 11 | gutil = require ( '../../utilities/gutil' ), 12 | input = require ( '../../utilities/paths/input' ), 13 | output = require ( '../../utilities/paths/output' ), 14 | plumberU = require ( '../../utilities/plumber' ), 15 | project = require ( '../../project' ), 16 | {plugins} = project, 17 | components = require ( '../../plugins/components' ), 18 | dependencies = require ( '../../plugins/dependencies' ), 19 | touch = require ( '../../plugins/touch' ); 20 | 21 | /* TASK */ 22 | 23 | function task () { 24 | 25 | const needUpdate = changed.environment () || changed.target () || changed.plugin ( 'dependencies', 'markdown', 'htmlmin' ), 26 | needOutput = output.isEnabled ( 'markdown' ); 27 | 28 | return gulp.src ( input.getPath ( 'markdown' ) ) 29 | .pipe ( plumber ( plumberU.error ) ) 30 | .pipe ( gulpif ( plugins.components.enabled, components ( _.merge ( { components: project.components }, plugins.components.options ) ) ) ) 31 | .pipe ( gulpif ( plugins.dependencies.enabled, dependencies ( plugins.dependencies.options ) ) ) 32 | .pipe ( flatten () ) 33 | .pipe ( gulpif ( !needUpdate && needOutput, () => newer ( output.getDir ( 'markdown' ) ) ) ) 34 | .pipe ( gulpif ( plugins.markdown.enabled, () => require ( 'gulp-markdown' )( plugins.markdown.options ) ) ) 35 | .pipe ( gulpif ( plugins.htmlmin.enabled, () => require ( 'gulp-htmlmin' )( plugins.htmlmin.options ) ) ) 36 | .pipe ( gulpif ( needOutput, () => gulp.dest ( output.getDir ( 'markdown' ) ) ) ) 37 | .pipe ( gulpif ( needOutput, touch () ) ); 38 | 39 | } 40 | 41 | /* EXPORT */ 42 | 43 | module.exports = gutil.task.enhance ( task, 'build-markdown', 'Build Markdown', 'more' ); 44 | -------------------------------------------------------------------------------- /src/tasks/build/notification.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const stripANSI = require ( 'strip-ansi' ), 5 | project = require ( '../../project' ), 6 | buildStatus = require ( '../../utilities/build_status' ), 7 | notification = require ( '../../utilities/notification' ); 8 | 9 | /* TASK */ 10 | 11 | function task () { 12 | 13 | const {error, pluginError, success, paths, times} = buildStatus.stats (); 14 | 15 | if ( error ) { 16 | 17 | return notification.send ( `Plugin error [${pluginError.plugin}]`, stripANSI ( pluginError.messageFormatted || pluginError.message ), false ); 18 | 19 | } else if ( success ) { 20 | 21 | return notification.send ( `Built [${project.paths.tokens.target}] [${project.paths.tokens.environment}]`, `Bundle generated in ${times.elapsed}` ); 22 | 23 | } 24 | 25 | } 26 | 27 | /* EXPORT */ 28 | 29 | module.exports = task; 30 | -------------------------------------------------------------------------------- /src/tasks/build/scss/index.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const _ = require ( 'lodash' ), 5 | gulp = require ( 'gulp' ), 6 | gulpif = require ( 'gulp-if' ), 7 | newer = require ( 'gulp-newer' ), 8 | rename = require ( 'gulp-rename' ), 9 | plugins = require ( '../../../project' ).plugins, 10 | gutil = require ( '../../../utilities/gutil' ), 11 | output = require ( '../../../utilities/paths/output' ), 12 | concat = require ( '../../../plugins/concat' ), 13 | touch = require ( '../../../plugins/touch' ); 14 | 15 | /* TASK */ 16 | 17 | function task () { 18 | 19 | const parts = ['functions', 'mixins', 'variables', 'keyframes', 'style'], 20 | needOutput = output.isEnabled ( 'scss.all' ); 21 | 22 | return gulp.src ( _.filter ( parts.map ( part => output.getPath ( `scss.${part}` ) ) ), { allowEmpty: true } ) 23 | .pipe ( gulpif ( needOutput, () => newer ( output.getPath ( 'scss.all' ) ) ) ) 24 | .pipe ( concat ( 'all.scss', plugins.concat.options ) ) 25 | .pipe ( gulpif ( needOutput, rename ( output.getName ( 'scss.all' ) ) ) ) 26 | .pipe ( gulpif ( needOutput, () => gulp.dest ( output.getDir ( 'scss.all' ) ) ) ) 27 | .pipe ( gulpif ( needOutput, touch () ) ); 28 | 29 | } 30 | 31 | /* EXPORT */ 32 | 33 | module.exports = gutil.task.enhance ( task, 'build-scss', 'Build SCSS', 'more' ); 34 | -------------------------------------------------------------------------------- /src/tasks/build/scss/parts/functions.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const gutil = require ( '../../../../utilities/gutil' ), 5 | general = require ( './general' ); 6 | 7 | /* TASK */ 8 | 9 | const task = () => general ( 'functions', false ); 10 | 11 | /* EXPORT */ 12 | 13 | module.exports = gutil.task.enhance ( task, 'build-scss-functions', 'Build SCSS functions', 'all' ); 14 | -------------------------------------------------------------------------------- /src/tasks/build/scss/parts/general.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const _ = require ( 'lodash' ), 5 | gulp = require ( 'gulp' ), 6 | gulpif = require ( 'gulp-if' ), 7 | newer = require ( 'gulp-newer' ), 8 | plumber = require ( 'gulp-plumber' ), 9 | rename = require ( 'gulp-rename' ), 10 | project = require ( '../../../../project' ), 11 | {plugins} = project, 12 | changed = require ( '../../../../utilities/changed' ), 13 | input = require ( '../../../../utilities/paths/input' ), 14 | output = require ( '../../../../utilities/paths/output' ), 15 | plumberU = require ( '../../../../utilities/plumber' ), 16 | components = require ( '../../../../plugins/components' ), 17 | concat = require ( '../../../../plugins/concat' ), 18 | dependencies = require ( '../../../../plugins/dependencies' ), 19 | substitute = require ( '../../../../plugins/substitute' ), 20 | touch = require ( '../../../../plugins/touch' ), 21 | unempty = require ( '../../../../plugins/unempty' ); 22 | 23 | /* GENERAL */ 24 | 25 | function general ( name, filterable ) { 26 | 27 | const needUpdate = changed.environment () || changed.target () || changed.project ( 'components' ) || changed.plugins ( 'components', 'concat', 'substitute', 'dependencies' ), 28 | needOutput = output.isEnabled ( `scss.${name}` ); 29 | 30 | return gulp.src ( input.getPath ( `scss.${name}` ) ) 31 | .pipe ( plumber ( plumberU.error ) ) 32 | .pipe ( gulpif ( filterable && plugins.components.enabled, components ( _.merge ( { components: project.components }, plugins.components.options ) ) ) ) 33 | .pipe ( unempty ( output.getPath ( `scss.${name}` ) ) ) 34 | .pipe ( gulpif ( !needUpdate && needOutput, () => newer ( output.getPath ( `scss.${name}` ) ) ) ) 35 | .pipe ( gulpif ( plugins.substitute.enabled, substitute ( _.merge ( { substitutions: project }, plugins.substitute.options ) ) ) ) 36 | .pipe ( gulpif ( plugins.dependencies.enabled, dependencies ( plugins.dependencies.options ) ) ) 37 | .pipe ( concat ( `${name}.scss`, plugins.concat.options ) ) 38 | .pipe ( gulpif ( needOutput, rename ( output.getName ( `scss.${name}` ) ) ) ) 39 | .pipe ( gulpif ( needOutput, () => gulp.dest ( output.getDir ( `scss.${name}` ) ) ) ) 40 | .pipe ( gulpif ( needOutput, touch () ) ); 41 | 42 | } 43 | 44 | /* EXPORT */ 45 | 46 | module.exports = general; 47 | -------------------------------------------------------------------------------- /src/tasks/build/scss/parts/index.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const gutil = require ( '../../../../utilities/gutil' ), 5 | buildFunctions = require ( './functions' ), 6 | buildMixins = require ( './mixins' ), 7 | buildVariables = require ( './variables' ), 8 | buildKeyframes = require ( './keyframes' ), 9 | buildStyle = require ( './style' ); 10 | 11 | /* TASK */ 12 | 13 | const task = gutil.parallel ( buildFunctions, buildMixins, buildVariables, buildKeyframes, buildStyle ); 14 | 15 | /* EXPORT */ 16 | 17 | module.exports = gutil.task.enhance ( task, 'build-scss-parts', 'Build SCSS parts', 'all' ); 18 | -------------------------------------------------------------------------------- /src/tasks/build/scss/parts/keyframes.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const gutil = require ( '../../../../utilities/gutil' ), 5 | general = require ( './general' ); 6 | 7 | /* TASK */ 8 | 9 | const task = () => general ( 'keyframes', true ); 10 | 11 | /* EXPORT */ 12 | 13 | module.exports = gutil.task.enhance ( task, 'build-scss-keyframes', 'Build SCSS keyframes', 'all' ); 14 | -------------------------------------------------------------------------------- /src/tasks/build/scss/parts/mixins.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const gutil = require ( '../../../../utilities/gutil' ), 5 | general = require ( './general' ); 6 | 7 | /* TASK */ 8 | 9 | const task = () => general ( 'mixins', false ); 10 | 11 | /* EXPORT */ 12 | 13 | module.exports = gutil.task.enhance ( task, 'build-scss-mixins', 'Build SCSS mixins', 'all' ); 14 | -------------------------------------------------------------------------------- /src/tasks/build/scss/parts/style.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const gutil = require ( '../../../../utilities/gutil' ), 5 | general = require ( './general' ); 6 | 7 | /* TASK */ 8 | 9 | const task = () => general ( 'style', true ); 10 | 11 | /* EXPORT */ 12 | 13 | module.exports = gutil.task.enhance ( task, 'build-scss-style', 'Build SCSS style', 'all' ); 14 | -------------------------------------------------------------------------------- /src/tasks/build/scss/parts/variables.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const gutil = require ( '../../../../utilities/gutil' ), 5 | general = require ( './general' ); 6 | 7 | /* TASK */ 8 | 9 | const task = () => general ( 'variables', false ); 10 | 11 | /* EXPORT */ 12 | 13 | module.exports = gutil.task.enhance ( task, 'build-scss-variables', 'Build SCSS variables', 'all' ); 14 | -------------------------------------------------------------------------------- /src/tasks/build/style.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const gutil = require ( '../../utilities/gutil' ), 5 | buildSCSSParts = require ( './scss/parts' ), 6 | buildSCSS = require ( './scss' ), 7 | buildCSSParts = require ( './css/parts' ), 8 | buildCSS = require ( './css' ); 9 | 10 | /* TASK */ 11 | 12 | const task = gutil.series ( buildSCSSParts, buildSCSS, buildCSSParts, buildCSS ); 13 | 14 | /* EXPORT */ 15 | 16 | module.exports = gutil.task.enhance ( task, 'build-style', 'Build SCSS and CSS', 'more' ); 17 | -------------------------------------------------------------------------------- /src/tasks/build/summary.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const argv = require ( 'yargs' ).argv, 5 | bytes = require ( 'pretty-bytes' ), 6 | buildStatus = require ( '../../utilities/build_status' ), 7 | log = require ( '../../utilities/log' ); 8 | 9 | /* TASK */ 10 | 11 | async function task () { 12 | 13 | if ( argv.quiet ) return; 14 | 15 | const {error, pluginError, success, paths, times, sizes} = buildStatus.stats (); 16 | 17 | if ( error ) return log.error ( pluginError ); 18 | 19 | if ( !success || argv.summary === false ) return; 20 | 21 | console.log ( `Bundled into "${paths.dist}" (${bytes ( sizes.dist )}) in ${times.elapsed}` ); 22 | 23 | } 24 | 25 | /* EXPORT */ 26 | 27 | module.exports = task; 28 | -------------------------------------------------------------------------------- /src/tasks/clean/css.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const del = require ( 'del' ), 5 | plugins = require ( '../../project' ).plugins, 6 | gutil = require ( '../../utilities/gutil' ), 7 | output = require ( '../../utilities/paths/output' ); 8 | 9 | /* TASK */ 10 | 11 | function task () { 12 | 13 | return del ( output.getDirs ( 'css' ), plugins.del.options ); 14 | 15 | } 16 | 17 | /* EXPORT */ 18 | 19 | module.exports = gutil.task.enhance ( task, 'clean-css', 'Clean generated CSS', 'more' ); 20 | -------------------------------------------------------------------------------- /src/tasks/clean/fonts.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const del = require ( 'del' ), 5 | plugins = require ( '../../project' ).plugins, 6 | gutil = require ( '../../utilities/gutil' ), 7 | output = require ( '../../utilities/paths/output' ); 8 | 9 | /* TASK */ 10 | 11 | function task () { 12 | 13 | return del ( output.getDir ( 'fonts' ), plugins.del.options ); 14 | 15 | } 16 | 17 | /* EXPORT */ 18 | 19 | module.exports = gutil.task.enhance ( task, 'clean-fonts', 'Clean generated fonts', 'more' ); 20 | -------------------------------------------------------------------------------- /src/tasks/clean/html.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const del = require ( 'del' ), 5 | plugins = require ( '../../project' ).plugins, 6 | gutil = require ( '../../utilities/gutil' ), 7 | output = require ( '../../utilities/paths/output' ); 8 | 9 | /* TASK */ 10 | 11 | function task () { 12 | 13 | return del ( output.getDir ( 'html' ), plugins.del.options ); 14 | 15 | } 16 | 17 | /* EXPORT */ 18 | 19 | module.exports = gutil.task.enhance ( task, 'clean-html', 'Clean generated HTML', 'more' ); 20 | -------------------------------------------------------------------------------- /src/tasks/clean/images.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const del = require ( 'del' ), 5 | plugins = require ( '../../project' ).plugins, 6 | gutil = require ( '../../utilities/gutil' ), 7 | output = require ( '../../utilities/paths/output' ); 8 | 9 | /* TASK */ 10 | 11 | function task () { 12 | 13 | return del ( output.getDir ( 'images' ), plugins.del.options ); 14 | 15 | } 16 | 17 | /* EXPORT */ 18 | 19 | module.exports = gutil.task.enhance ( task, 'clean-images', 'Clean generated images', 'more' ); 20 | -------------------------------------------------------------------------------- /src/tasks/clean/index.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const del = require ( 'del' ), 5 | plugins = require ( '../../project' ).plugins, 6 | clean = require ( '../../utilities/paths/clean' ), 7 | gutil = require ( '../../utilities/gutil' ); 8 | 9 | /* TASK */ 10 | 11 | function task () { 12 | 13 | return del ( clean.getPath (), plugins.del.options ); 14 | 15 | } 16 | 17 | /* EXPORT */ 18 | 19 | module.exports = gutil.task.enhance ( task, 'clean', 'Clean generated files' ); 20 | -------------------------------------------------------------------------------- /src/tasks/clean/javascript.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const del = require ( 'del' ), 5 | plugins = require ( '../../project' ).plugins, 6 | gutil = require ( '../../utilities/gutil' ), 7 | output = require ( '../../utilities/paths/output' ); 8 | 9 | /* TASK */ 10 | 11 | function task () { 12 | 13 | return del ( output.getDirs ( 'javascript' ), plugins.del.options ); 14 | 15 | } 16 | 17 | /* EXPORT */ 18 | 19 | module.exports = gutil.task.enhance ( task, 'clean-javascript', 'Clean generated JavaScript', 'more' ); 20 | -------------------------------------------------------------------------------- /src/tasks/clean/json.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const del = require ( 'del' ), 5 | plugins = require ( '../../project' ).plugins, 6 | gutil = require ( '../../utilities/gutil' ), 7 | output = require ( '../../utilities/paths/output' ); 8 | 9 | /* TASK */ 10 | 11 | function task () { 12 | 13 | return del ( output.getDir ( 'json' ), plugins.del.options ); 14 | 15 | } 16 | 17 | /* EXPORT */ 18 | 19 | module.exports = gutil.task.enhance ( task, 'clean-json', 'Clean generated JSON', 'more' ); 20 | -------------------------------------------------------------------------------- /src/tasks/clean/scss.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const del = require ( 'del' ), 5 | plugins = require ( '../../project' ).plugins, 6 | gutil = require ( '../../utilities/gutil' ), 7 | output = require ( '../../utilities/paths/output' ); 8 | 9 | /* TASK */ 10 | 11 | function task () { 12 | 13 | return del ( output.getDirs ( 'scss' ), plugins.del.options ); 14 | 15 | } 16 | 17 | /* EXPORT */ 18 | 19 | module.exports = gutil.task.enhance ( task, 'clean-scss', 'Clean generated SCSS', 'more' ); 20 | -------------------------------------------------------------------------------- /src/tasks/clean/style.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const gutil = require ( '../../utilities/gutil' ), 5 | cleanSCSS = require ( './scss' ), 6 | cleanCSS = require ( './css' ); 7 | 8 | /* TASK */ 9 | 10 | const task = gutil.parallel ( cleanSCSS, cleanCSS ); 11 | 12 | /* EXPORT */ 13 | 14 | module.exports = gutil.task.enhance ( task, 'clean-style', 'Clean generated SCSS and CSS', 'more' ); 15 | -------------------------------------------------------------------------------- /src/tasks/clean/typescript.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const del = require ( 'del' ), 5 | plugins = require ( '../../project' ).plugins, 6 | gutil = require ( '../../utilities/gutil' ), 7 | output = require ( '../../utilities/paths/output' ); 8 | 9 | /* TASK */ 10 | 11 | function task () { 12 | 13 | return del ( output.getDirs ( 'typescript' ), plugins.del.options ); 14 | 15 | } 16 | 17 | /* EXPORT */ 18 | 19 | module.exports = gutil.task.enhance ( task, 'clean-typescript', 'Clean generated TypeScript', 'more' ); 20 | -------------------------------------------------------------------------------- /src/tasks/config.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const _ = require ( 'lodash' ), 5 | argv = require ( 'yargs' ).argv, 6 | project = require ( '../project' ), 7 | gutil = require ( '../utilities/gutil' ); 8 | 9 | /* TASK */ 10 | 11 | async function task () { 12 | 13 | const dotpath = argv._.length >= 2 ? argv._[1] : false, 14 | subproject = dotpath ? _.get ( project, dotpath ) : project, 15 | output = JSON.stringify ( subproject, undefined, 2 ); 16 | 17 | setTimeout ( () => console.log ( output ) ); // In order to print this at the end 18 | 19 | } 20 | 21 | /* EXPORT */ 22 | 23 | module.exports = gutil.task.enhance ( task, 'config', 'Display the current configuration', undefined, [['[dotpath]', 'Display a portion of the whole configuration']] ); 24 | -------------------------------------------------------------------------------- /src/tasks/default.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const gutil = require ( '../utilities/gutil' ), 5 | build = require ( './build' ), 6 | watch = require ( './watch' ); 7 | 8 | /* TASK */ 9 | 10 | const task = gutil.series ( build, watch ); 11 | 12 | /* EXPORT */ 13 | 14 | module.exports = gutil.task.enhance ( task, 'default', 'Build and watch' ); 15 | -------------------------------------------------------------------------------- /src/tasks/watch/css/index.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const _ = require ( 'lodash' ), 5 | gulp = require ( 'gulp' ), 6 | gutil = require ( '../../../utilities/gutil' ), 7 | output = require ( '../../../utilities/paths/output' ), 8 | buildCSS = require ( '../../build/css' ); 9 | 10 | /* TASK */ 11 | 12 | function task () { 13 | 14 | return gulp.watch ( _.filter ([ output.getPath ( 'css.partial' ), output.getPath ( 'scss.partial' ) ]), { interval: 500, usePolling: false }, buildCSS ); 15 | 16 | } 17 | 18 | /* EXPORT */ 19 | 20 | module.exports = gutil.task.enhance ( task, 'watch-css', 'Watch CSS', 'more' ); 21 | -------------------------------------------------------------------------------- /src/tasks/watch/css/parts/css.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const gulp = require ( 'gulp' ), 5 | gutil = require ( '../../../../utilities/gutil' ), 6 | input = require ( '../../../../utilities/paths/input' ), 7 | buildPartCSS = require ( '../../../build/css/parts/css' ); 8 | 9 | /* TASK */ 10 | 11 | function task () { 12 | 13 | return gulp.watch ( input.getPath ( 'css.all' ), { interval: 500, usePolling: false }, buildPartCSS ); 14 | 15 | } 16 | 17 | /* EXPORT */ 18 | 19 | module.exports = gutil.task.enhance ( task, 'watch-css-css', 'Watch CSS CSS', 'all' ); 20 | -------------------------------------------------------------------------------- /src/tasks/watch/css/parts/index.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const gutil = require ( '../../../../utilities/gutil' ), 5 | partCSS = require ( './css' ), 6 | partSCSS = require ( './scss' ); 7 | 8 | /* TASK */ 9 | 10 | const task = gutil.parallel ( partCSS, partSCSS ); 11 | 12 | /* EXPORT */ 13 | 14 | module.exports = gutil.task.enhance ( task, 'watch-css-parts', 'Watch CSS parts', 'all' ); 15 | -------------------------------------------------------------------------------- /src/tasks/watch/css/parts/scss.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const gulp = require ( 'gulp' ), 5 | gutil = require ( '../../../../utilities/gutil' ), 6 | output = require ( '../../../../utilities/paths/output' ), 7 | buildPartSCSS = require ( '../../../build/css/parts/scss' ); 8 | 9 | /* TASK */ 10 | 11 | function task () { 12 | 13 | return gulp.watch ( output.getPath ( 'scss.all' ), { interval: 500, usePolling: false }, buildPartSCSS ); 14 | 15 | } 16 | 17 | /* EXPORT */ 18 | 19 | module.exports = gutil.task.enhance ( task, 'watch-css-scss', 'Watch CSS SCSS', 'all' ); 20 | -------------------------------------------------------------------------------- /src/tasks/watch/fonts.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const gulp = require ( 'gulp' ), 5 | gutil = require ( '../../utilities/gutil' ), 6 | input = require ( '../../utilities/paths/input' ), 7 | buildFonts = require ( '../build/fonts' ); 8 | 9 | /* TASK */ 10 | 11 | function task () { 12 | 13 | return gulp.watch ( input.getPath ( 'fonts' ), { interval: 500, usePolling: false }, buildFonts ); 14 | 15 | } 16 | 17 | /* EXPORT */ 18 | 19 | module.exports = gutil.task.enhance ( task, 'watch-fonts', 'Watch fonts', 'more' ); 20 | -------------------------------------------------------------------------------- /src/tasks/watch/html.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const gulp = require ( 'gulp' ), 5 | gutil = require ( '../../utilities/gutil' ), 6 | input = require ( '../../utilities/paths/input' ), 7 | buildHTML = require ( '../build/html' ); 8 | 9 | /* TASK */ 10 | 11 | function task () { 12 | 13 | return gulp.watch ( input.getPath ( 'html' ), { interval: 500, usePolling: false }, buildHTML ); 14 | 15 | } 16 | 17 | /* EXPORT */ 18 | 19 | module.exports = gutil.task.enhance ( task, 'watch-html', 'Watch HTML', 'more' ); 20 | -------------------------------------------------------------------------------- /src/tasks/watch/images.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const gulp = require ( 'gulp' ), 5 | gutil = require ( '../../utilities/gutil' ), 6 | input = require ( '../../utilities/paths/input' ), 7 | buildImages = require ( '../build/images' ); 8 | 9 | /* TASK */ 10 | 11 | function task () { 12 | 13 | return gulp.watch ( input.getPath ( 'images' ), { interval: 500, usePolling: false }, buildImages ); 14 | 15 | } 16 | 17 | /* EXPORT */ 18 | 19 | module.exports = gutil.task.enhance ( task, 'watch-images', 'Watch images', 'more' ); 20 | -------------------------------------------------------------------------------- /src/tasks/watch/index.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const gutil = require ( '../../utilities/gutil' ), 5 | watchHTML = require ( './html' ), 6 | watchJSON = require ( './json' ), 7 | watchFonts = require ( './fonts' ), 8 | watchImages = require ( './images' ), 9 | watchMarkdown = require ( './markdown' ), 10 | watchJavascript = require ( './javascript' ), 11 | watchStyle = require ( './style' ); 12 | 13 | /* TASK */ 14 | 15 | const task = gutil.parallel ( watchHTML, watchJSON, watchFonts, watchImages, watchMarkdown, watchJavascript, watchStyle ); 16 | 17 | /* EXPORT */ 18 | 19 | module.exports = gutil.task.enhance ( task, 'watch', 'Watch files for changes and rebuild' ); 20 | -------------------------------------------------------------------------------- /src/tasks/watch/javascript.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const _ = require ( 'lodash' ), 5 | gulp = require ( 'gulp' ), 6 | gutil = require ( '../../utilities/gutil' ), 7 | input = require ( '../../utilities/paths/input' ), 8 | buildJavascript = require ( '../build/javascript' ); 9 | 10 | /* TASK */ 11 | 12 | function task () { 13 | 14 | return gulp.watch ( _.flatten ( _.filter ([ input.getPath ( 'javascript.all' ), input.getPath ( 'typescript.all' ) ]) ), { interval: 500, usePolling: false }, buildJavascript ); 15 | 16 | } 17 | 18 | /* EXPORT */ 19 | 20 | module.exports = gutil.task.enhance ( task, 'watch-javascript', 'Watch JavaScript and TypeScript', 'more' ); 21 | -------------------------------------------------------------------------------- /src/tasks/watch/json.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const gulp = require ( 'gulp' ), 5 | gutil = require ( '../../utilities/gutil' ), 6 | input = require ( '../../utilities/paths/input' ), 7 | buildJSON = require ( '../build/json' ); 8 | 9 | /* TASK */ 10 | 11 | function task () { 12 | 13 | return gulp.watch ( input.getPath ( 'json' ), { interval: 500, usePolling: false }, buildJSON ); 14 | 15 | } 16 | 17 | /* EXPORT */ 18 | 19 | module.exports = gutil.task.enhance ( task, 'watch-json', 'Watch JSON', 'more' ); 20 | -------------------------------------------------------------------------------- /src/tasks/watch/markdown.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const gulp = require ( 'gulp' ), 5 | gutil = require ( '../../utilities/gutil' ), 6 | input = require ( '../../utilities/paths/input' ), 7 | buildMarkdown = require ( '../build/markdown' ); 8 | 9 | /* TASK */ 10 | 11 | function task () { 12 | 13 | return gulp.watch ( input.getPath ( 'markdown' ), { interval: 500, usePolling: false }, buildMarkdown ); 14 | 15 | } 16 | 17 | /* EXPORT */ 18 | 19 | module.exports = gutil.task.enhance ( task, 'watch-markdown', 'Watch Markdown', 'more' ); 20 | -------------------------------------------------------------------------------- /src/tasks/watch/scss/index.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const gulp = require ( 'gulp' ), 5 | gutil = require ( '../../../utilities/gutil' ), 6 | output = require ( '../../../utilities/paths/output' ), 7 | buildSCSS = require ( '../../build/scss' ); 8 | 9 | /* TASK */ 10 | 11 | function task () { 12 | 13 | const parts = ['functions', 'mixins', 'variables', 'keyframes', 'style']; 14 | 15 | return gulp.watch ( parts.map ( part => output.getPath ( `scss.${part}` ) ), { interval: 500, usePolling: false }, buildSCSS ); 16 | 17 | } 18 | 19 | /* EXPORT */ 20 | 21 | module.exports = gutil.task.enhance ( task, 'watch-scss', 'Watch SCSS', 'more' ); 22 | -------------------------------------------------------------------------------- /src/tasks/watch/scss/parts/functions.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const gulp = require ( 'gulp' ), 5 | gutil = require ( '../../../../utilities/gutil' ), 6 | input = require ( '../../../../utilities/paths/input' ), 7 | buildFunctions = require ( '../../../build/scss/parts/functions' ); 8 | 9 | /* TASK */ 10 | 11 | function task () { 12 | 13 | return gulp.watch ( input.getPath ( 'scss.functions' ), { interval: 500, usePolling: false }, buildFunctions ); 14 | 15 | } 16 | 17 | /* EXPORT */ 18 | 19 | module.exports = gutil.task.enhance ( task, 'watch-scss-functions', 'Watch SCSS functions', 'all' ); 20 | -------------------------------------------------------------------------------- /src/tasks/watch/scss/parts/index.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const gutil = require ( '../../../../utilities/gutil' ), 5 | watchFunctions = require ( './functions' ), 6 | watchMixins = require ( './mixins' ), 7 | watchVariables = require ( './variables' ), 8 | watchKeyframes = require ( './keyframes' ), 9 | watchStyle = require ( './style' ); 10 | 11 | /* TASK */ 12 | 13 | const task = gutil.parallel ( watchFunctions, watchMixins, watchVariables, watchKeyframes, watchStyle ); 14 | 15 | /* EXPORT */ 16 | 17 | module.exports = gutil.task.enhance ( task, 'watch-scss-parts', 'Watch SCSS parts', 'all' ); 18 | -------------------------------------------------------------------------------- /src/tasks/watch/scss/parts/keyframes.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const gulp = require ( 'gulp' ), 5 | gutil = require ( '../../../../utilities/gutil' ), 6 | input = require ( '../../../../utilities/paths/input' ), 7 | buildKeyframes = require ( '../../../build/scss/parts/keyframes' ); 8 | 9 | /* TASK */ 10 | 11 | function task () { 12 | 13 | return gulp.watch ( input.getPath ( 'scss.keyframes' ), { interval: 500, usePolling: false }, buildKeyframes ); 14 | 15 | } 16 | 17 | /* EXPORT */ 18 | 19 | module.exports = gutil.task.enhance ( task, 'watch-scss-keyframes', 'Watch SCSS keyframes', 'all' ); 20 | -------------------------------------------------------------------------------- /src/tasks/watch/scss/parts/mixins.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const gulp = require ( 'gulp' ), 5 | gutil = require ( '../../../../utilities/gutil' ), 6 | input = require ( '../../../../utilities/paths/input' ), 7 | buildMixins = require ( '../../../build/scss/parts/mixins' ); 8 | 9 | /* TASK */ 10 | 11 | function task () { 12 | 13 | return gulp.watch ( input.getPath ( 'scss.mixins' ), { interval: 500, usePolling: false }, buildMixins ); 14 | 15 | } 16 | 17 | /* EXPORT */ 18 | 19 | module.exports = gutil.task.enhance ( task, 'watch-scss-mixins', 'Watch SCSS mixins', 'all' ); 20 | -------------------------------------------------------------------------------- /src/tasks/watch/scss/parts/style.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const gulp = require ( 'gulp' ), 5 | gutil = require ( '../../../../utilities/gutil' ), 6 | input = require ( '../../../../utilities/paths/input' ), 7 | buildStyle = require ( '../../../build/scss/parts/style' ); 8 | 9 | /* TASK */ 10 | 11 | function task () { 12 | 13 | return gulp.watch ( input.getPath ( 'scss.style' ), { interval: 500, usePolling: false }, buildStyle ); 14 | 15 | } 16 | 17 | /* EXPORT */ 18 | 19 | module.exports = gutil.task.enhance ( task, 'watch-scss-style', 'Watch SCSS style', 'all' ); 20 | -------------------------------------------------------------------------------- /src/tasks/watch/scss/parts/variables.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const gulp = require ( 'gulp' ), 5 | gutil = require ( '../../../../utilities/gutil' ), 6 | input = require ( '../../../../utilities/paths/input' ), 7 | buildVariables = require ( '../../../build/scss/parts/variables' ); 8 | 9 | /* TASK */ 10 | 11 | function task () { 12 | 13 | return gulp.watch ( input.getPath ( 'scss.variables' ), { interval: 500, usePolling: false }, buildVariables ); 14 | 15 | } 16 | 17 | /* EXPORT */ 18 | 19 | module.exports = gutil.task.enhance ( task, 'watch-scss-variables', 'Watch SCSS variables', 'all' ); 20 | -------------------------------------------------------------------------------- /src/tasks/watch/style.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const gutil = require ( '../../utilities/gutil' ), 5 | watchSCSSParts = require ( './scss/parts' ), 6 | watchSCSS = require ( './scss' ), 7 | watchCSSParts = require ( './css/parts' ), 8 | watchCSS = require ( './css' ); 9 | 10 | /* TASK */ 11 | 12 | const task = gutil.parallel ( watchSCSSParts, watchSCSS, watchCSSParts, watchCSS ); 13 | 14 | /* EXPORT */ 15 | 16 | module.exports = gutil.task.enhance ( task, 'watch-style', 'Watch SCSS and CSS', 'more' ); 17 | -------------------------------------------------------------------------------- /src/utilities/build_status.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const _ = require ( 'lodash' ), 5 | PluginError = require ( 'plugin-error' ), 6 | time = require ( 'pretty-time' ), 7 | project = require ( '../project' ), 8 | file = require ( './file' ), 9 | projectU = require ( './project' ); 10 | 11 | /* BUILD STATUS */ 12 | 13 | const buildStatus = { 14 | 15 | status: {}, 16 | 17 | async start () { // Can be used as a Gulp task 18 | 19 | buildStatus.status = { 20 | started: true, 21 | paths: { 22 | src: projectU.getSrcPaths ( project ), 23 | dist: projectU.getDistPath ( project ) 24 | }, 25 | times: { 26 | startTime: Date.now (), 27 | startHRTime: process.hrtime () 28 | } 29 | }; 30 | 31 | }, 32 | 33 | async finish ( pluginError ) { // Can be used as a Gulp task 34 | 35 | if ( buildStatus.status.finished ) return; 36 | 37 | pluginError = pluginError instanceof Error ? pluginError : undefined; 38 | 39 | _.merge ( buildStatus.status, { 40 | finished: true, 41 | success: !pluginError, 42 | error: !!pluginError, 43 | pluginError, 44 | times: { 45 | finishTime: Date.now (), 46 | finishHRTime: process.hrtime () 47 | } 48 | }); 49 | 50 | if ( !buildStatus.status.started ) return; // We won't have the necessary data to proceed further if `buildStatus.start` wasn't called 51 | 52 | _.merge ( buildStatus.status, { 53 | times: { 54 | elapsed: time ( process.hrtime ( buildStatus.status.times.startHRTime ) ) 55 | }, 56 | sizes: { 57 | dist: file.size ( buildStatus.status.paths.dist ) 58 | } 59 | }); 60 | 61 | }, 62 | 63 | stats () { 64 | 65 | return buildStatus.status; 66 | 67 | } 68 | 69 | }; 70 | 71 | /* EXPORT */ 72 | 73 | module.exports = buildStatus; 74 | -------------------------------------------------------------------------------- /src/utilities/changed.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const _ = require ( 'lodash' ), 5 | argv = require ( 'yargs' ).argv, 6 | project = require ( '../project' ), 7 | projectPrev = require ( '../project/previous' ); 8 | 9 | /* CHANGED */ 10 | 11 | const changed = { 12 | 13 | _previous: JSON.parse ( JSON.stringify ( projectPrev ) ), // Using JSON so that all the objects get parsed the same way (basically for supporting functions) 14 | _current : JSON.parse ( JSON.stringify ( project ) ), // Using JSON so that all the objects get parsed the same way (basically for supporting functions) 15 | 16 | project ( key ) { 17 | 18 | if ( argv.fresh ) return true; 19 | 20 | return key ? !_.isEqual ( _.get ( changed._current, key ), _.get ( changed._previous, key ) ) : !_.isEqual ( changed._current, changed._previous ); 21 | 22 | }, 23 | 24 | plugin ( name ) { 25 | 26 | return changed.project ( `plugins.${name}` ); 27 | 28 | }, 29 | 30 | plugins ( ...names ) { 31 | 32 | return names.length ? names.some ( changed.plugin ) : changed.project ( 'plugins' ); 33 | 34 | }, 35 | 36 | environment () { 37 | 38 | return changed.project ( 'environment' ); 39 | 40 | }, 41 | 42 | target () { 43 | 44 | return changed.project ( 'target' ); 45 | 46 | } 47 | 48 | }; 49 | 50 | /* EXPORT */ 51 | 52 | module.exports = changed; 53 | -------------------------------------------------------------------------------- /src/utilities/config.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const _ = require ( 'lodash' ), 5 | isBase64 = require ( 'is-base64' ), 6 | argv = require ( 'yargs' ).argv, 7 | path = require ( 'path' ), 8 | file = require ( './file' ); 9 | 10 | /* CONFIG */ 11 | 12 | const config = { 13 | 14 | /* UTILITIES */ 15 | 16 | _concatArgs ( ...args ) { 17 | 18 | const values = _.compact ( _.concat ( ...args ) ); 19 | 20 | switch ( values.length ) { 21 | case 0: return; 22 | case 1: return values[0]; 23 | default: return values; 24 | } 25 | 26 | }, 27 | 28 | _getRawConfigs () { 29 | 30 | return _.compact ( _.concat ( argv.config, argv.c ) ).map ( config => { 31 | 32 | if ( isBase64 ( config ) ) { 33 | 34 | return JSON.parse ( Buffer.from ( config, 'base64' ).toString () ); 35 | 36 | } else { 37 | 38 | const obj = _.attempt ( JSON.parse, config ); 39 | 40 | return _.isError ( obj ) ? config : obj; 41 | 42 | } 43 | 44 | }); 45 | 46 | }, 47 | 48 | _absPath ( filepath ) { 49 | 50 | return path.isAbsolute ( filepath ) ? filepath : path.resolve ( process.cwd (), filepath ); 51 | 52 | }, 53 | 54 | /* API */ 55 | 56 | getCwd () { 57 | 58 | const configs = config._getRawConfigs (), 59 | lastPath = configs.find ( _.isString ); 60 | 61 | if ( !lastPath ) return; 62 | 63 | return config._absPath ( lastPath ); 64 | 65 | }, 66 | 67 | getObj () { 68 | 69 | const configs = config._getRawConfigs (); 70 | 71 | const objs = configs.map ( conf => { 72 | 73 | return _.isString ( conf ) ? file.load ( config._absPath ( conf ) ) : conf; 74 | 75 | }); 76 | 77 | return _.merge ( ...objs ); 78 | 79 | }, 80 | 81 | getDynamicObj () { 82 | 83 | const src = config._concatArgs ( argv.source, argv.src, argv.s ), 84 | dist = argv.distribution || argv.destination || argv.dist || argv.dest || argv.dst || argv.d, 85 | target = argv.target || argv.t, 86 | environment = config._concatArgs ( argv.environments, argv.environment, argv.envs, argv.env, argv.e ); 87 | 88 | return { 89 | target, 90 | environment, 91 | paths: { 92 | tokens: { src, dist } 93 | } 94 | }; 95 | 96 | } 97 | 98 | }; 99 | 100 | /* EXPORT */ 101 | 102 | module.exports = config; 103 | -------------------------------------------------------------------------------- /src/utilities/environments.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const _ = require ( 'lodash' ), 5 | {color} = require ( 'specialist' ); 6 | 7 | /* ENVIRONMENTS */ 8 | 9 | const environments = { 10 | 11 | parse ( envs ) { 12 | 13 | if ( _.isArray ( envs ) ) { 14 | 15 | return envs.map ( env => _.trim ( env ) ); 16 | 17 | } else { 18 | 19 | return environments.parse ( envs.split ( ',' ) ); 20 | 21 | } 22 | 23 | }, 24 | 25 | pretty ( envs ) { 26 | 27 | if ( _.isString ( envs ) ) return environments.pretty ( envs.split ( ',' ) ); 28 | 29 | return envs.join ( ' - ' ); 30 | 31 | }, 32 | 33 | get ( config, paths ) { 34 | 35 | return paths.map ( path => _.get ( config, `environments.${path}` ) ).filter ( env => env ); 36 | 37 | }, 38 | 39 | checkExistence ( environments, ...objs ) { 40 | 41 | if ( !objs.every ( _.isEmpty ) ) return; 42 | 43 | console.error ( color.red ( `Unknown environment(s) "${environments.map ( env => color.underline ( env ) ).join ( ', ' )}", did you forget to define it?` ) ); 44 | 45 | process.exit ( 1 ); 46 | 47 | } 48 | 49 | }; 50 | 51 | /* EXPORT */ 52 | 53 | module.exports = environments; 54 | -------------------------------------------------------------------------------- /src/utilities/file.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const _ = require ( 'lodash' ), 5 | findUp = require ( 'find-up-json' ), 6 | fs = require ( 'fs' ), 7 | {sync: fsizeSync} = require ( 'nodejs-fs-utils/fs/fsize' ), 8 | gulp = require ( 'gulp' ), 9 | mkdirp = require ( 'mkdirp' ), 10 | path = require ( 'path' ), 11 | {color} = require ( 'specialist' ), 12 | Upath = require ( './path' ); 13 | 14 | /* FILE */ 15 | 16 | const file = { 17 | 18 | exists ( filepath ) { 19 | 20 | try { 21 | 22 | fs.accessSync ( filepath ); 23 | 24 | return true; 25 | 26 | } catch ( e ) { 27 | 28 | return false; 29 | 30 | } 31 | 32 | }, 33 | 34 | size ( filepath ) { 35 | 36 | if ( !file.exists ( filepath ) ) return 0; 37 | 38 | return fsizeSync ( filepath ); 39 | 40 | }, 41 | 42 | load ( filepath, defaultValue ) { 43 | 44 | const file = _.attempt ( require, filepath ); 45 | 46 | if ( _.isError ( file ) ) { 47 | 48 | if ( !_.isUndefined ( defaultValue ) ) return defaultValue; 49 | 50 | console.error ( color.red ( `Failed to load "${color.underline ( filepath )}"` ) ); 51 | 52 | process.exit ( 1 ); 53 | 54 | } 55 | 56 | return file; 57 | 58 | }, 59 | 60 | loadRecursive ( name, defaultValue ) { 61 | 62 | const dotfile = findUp ( name, process.cwd () ); 63 | 64 | return dotfile ? dotfile.content : defaultValue; 65 | 66 | }, 67 | 68 | write ( filepath, content ) { 69 | 70 | mkdirp.sync ( path.dirname ( filepath ) ); 71 | fs.writeFileSync ( filepath, JSON.stringify ( content ) ); 72 | 73 | }, 74 | 75 | file2componentCache: {}, 76 | 77 | file2component ( f ) { 78 | 79 | const filepath = _.isString ( f ) ? f : f.path; 80 | 81 | if ( file.file2componentCache[filepath] ) return file.file2componentCache[filepath]; 82 | 83 | if ( !file._file2componentSrcRe ) { 84 | 85 | const project = require ( '../project' ), // In order to avoid a cyclic dependency 86 | projectU = require ( './project' ), // In order to avoid a cyclic dependency 87 | src = projectU.getSrcPaths ( project ).map ( Upath.normalize ), 88 | srcRe = new RegExp ( `^(${src.map ( _.escapeRegExp ).join ( '|' )})\/` ); 89 | 90 | file._file2componentSrcRe = srcRe; 91 | 92 | } 93 | 94 | const commponent = Upath.normalize ( filepath ).replace ( file._file2componentSrcRe, '' ); 95 | 96 | file.file2componentCache[filepath] = commponent; 97 | 98 | return commponent; 99 | 100 | } 101 | 102 | }; 103 | 104 | /* EXPORT */ 105 | 106 | module.exports = file; 107 | -------------------------------------------------------------------------------- /src/utilities/gutil.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const _ = require ( 'lodash' ), 5 | argv = require ( 'yargs' ).argv, 6 | asyncDone = require ( 'async-done' ), 7 | fancyLog = require ( 'fancy-log' ), 8 | gulp = require ( 'gulp' ), 9 | path = require ( 'path' ), 10 | time = require ( 'pretty-time' ), 11 | {color} = require ( 'specialist' ), 12 | config = require ( './config' ); 13 | 14 | /* GUTIL */ 15 | 16 | const gutil = { 17 | 18 | log: fancyLog, 19 | 20 | cwd () { 21 | 22 | const configCwd = config.getCwd (); 23 | 24 | if ( !configCwd ) return process.cwd (); 25 | 26 | return path.dirname ( configCwd ); 27 | 28 | }, 29 | 30 | abs ( filepath ) { 31 | 32 | if ( path.isAbsolute ( filepath ) ) return filepath; 33 | 34 | return path.resolve ( gutil.cwd (), filepath ); 35 | 36 | }, 37 | 38 | patch () { 39 | 40 | /* SRC & DEST & SYMLINK */ 41 | 42 | // Ensuring Gulp's `cwd` is always `--config` or, if not a path or is missing, `process.cwd ()` 43 | 44 | const cwd = gutil.cwd (), 45 | methods = ['src', 'dest', 'symlink'], 46 | proto = Object.getPrototypeOf ( gulp ); 47 | 48 | methods.forEach ( method => { 49 | 50 | const prev = proto[method]; 51 | 52 | proto[method] = function ( arg0, options, ...otherArgs ) { 53 | 54 | options = _.merge ( { cwd }, options ); 55 | 56 | return prev.call ( gulp, arg0, options, ...otherArgs ); 57 | 58 | }; 59 | 60 | }); 61 | 62 | }, 63 | 64 | sequence ( type, ...tasks ) { // In order to make the invoker return a promise instead of undefined 65 | 66 | return function invoker ( callback ) { 67 | 68 | return new Promise ( resolve => { 69 | 70 | gulp.series ( gulp[type].call ( gulp, ...tasks ), resolve )( callback ); 71 | 72 | }); 73 | 74 | } 75 | 76 | }, 77 | 78 | series ( ...tasks ) { 79 | 80 | return gutil.sequence ( 'series', ...tasks ); 81 | 82 | }, 83 | 84 | parallel ( ...tasks ) { 85 | 86 | return gutil.sequence ( 'parallel', ...tasks ); 87 | 88 | }, 89 | 90 | task: { 91 | 92 | withLogger ( task, name ) { 93 | 94 | function withLogger ( ...args ) { 95 | 96 | let startTime; 97 | 98 | function start () { 99 | 100 | startTime = process.hrtime (); 101 | 102 | gutil.log ( `Starting '${color.cyan ( name )}'...` ); 103 | 104 | } 105 | 106 | function end () { 107 | 108 | const elapsed = process.hrtime ( startTime ); 109 | 110 | gutil.log ( `Finished '${color.cyan ( name )}' after ${color.magenta ( time ( elapsed ) )}` ); 111 | 112 | } 113 | 114 | start (); 115 | 116 | const res = task ( ...args ); 117 | 118 | asyncDone ( () => res, end ); 119 | 120 | return res; 121 | 122 | } 123 | 124 | return withLogger; 125 | 126 | }, 127 | 128 | withMetadata ( task, name, description, group, args ) { 129 | 130 | if ( name ) task.displayName = name; 131 | if ( description ) task.description = description; 132 | if ( group ) task.group = group; 133 | if ( args ) task.args = args; 134 | 135 | return task; 136 | 137 | }, 138 | 139 | enhance ( task, ...metadata ) { 140 | 141 | const withLogger = argv.quiet ? task : gutil.task.withLogger ( task, ...metadata ), 142 | withMetadata = gutil.task.withMetadata ( withLogger, ...metadata ); 143 | 144 | return withMetadata; 145 | 146 | } 147 | 148 | } 149 | 150 | }; 151 | 152 | /* EXPORT */ 153 | 154 | module.exports = gutil; 155 | -------------------------------------------------------------------------------- /src/utilities/log.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const {color} = require ( 'specialist' ); 5 | 6 | /* LOG */ 7 | 8 | const log = { 9 | 10 | line ( type, style, message = '' ) { 11 | 12 | type = color[style]( type ); 13 | 14 | return `[${type}] ${message}`; 15 | 16 | }, 17 | 18 | error ( error ) { 19 | 20 | const lines = []; 21 | 22 | if ( error.plugin ) { 23 | lines.push ( log.line ( 'Error', 'red', 'Plugin `' + color.underline ( error.plugin ) + '` encountered an error' ) ); 24 | } 25 | 26 | if ( error.fileName || error.relativePath || error.file ) { 27 | lines.push ( log.line ( 'File', 'yellow', error.fileName || error.relativePath || error.file ) ); 28 | } 29 | 30 | if ( error.lineNumber || error.line ) { 31 | lines.push ( log.line ( 'Line', 'yellow', error.lineNumber || error.line ) ); 32 | } 33 | 34 | if ( error.columnNumber || error.column ) { 35 | lines.push ( log.line ( 'Column', 'yellow', error.columnNumber || error.column ) ); 36 | } 37 | 38 | lines.push ( log.line ( 'Message', 'yellow', error.messageFormatted || error.message ) ); 39 | 40 | if ( error.codeFrame ) { 41 | lines.push ( log.line ( 'Code', 'yellow', `\n${error.codeFrame}` ) ); 42 | } 43 | 44 | if ( error.stack ) { 45 | lines.push ( log.line ( 'Stack', 'yellow', error.stack ) ); 46 | } 47 | 48 | console.log ( lines.join ( '\n' ) ); 49 | 50 | if ( error.cause ) { 51 | 52 | console.log ( log.line ( 'Cause', 'red' ) ); 53 | 54 | log.error ( error.cause ); 55 | 56 | } 57 | 58 | } 59 | 60 | } 61 | 62 | /* EXPORT */ 63 | 64 | module.exports = log; 65 | -------------------------------------------------------------------------------- /src/utilities/notification.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const _ = require ( 'lodash' ), 5 | argv = require ( 'yargs' ).argv, 6 | notifier = require ( 'node-notifier' ), 7 | path = require ( 'path' ), 8 | pify = require ( 'pify' ); 9 | 10 | /* NOTIFICATION */ 11 | 12 | const notification = { 13 | 14 | defaultOptions: { 15 | wait: false 16 | }, 17 | 18 | defaultSuccessOptions: { 19 | icon: argv.icon || path.join ( process.cwd (), 'resources', 'icon', 'icon.png' ), 20 | sound: 'Glass' 21 | }, 22 | 23 | defaultErrorOptions: { 24 | icon: argv.iconError || path.join ( process.cwd (), 'resources', 'icon', 'icon_error.png' ), 25 | sound: 'Basso' 26 | }, 27 | 28 | async send ( title, message, success = true ) { 29 | 30 | if ( argv.quiet || ( !_.isUndefined ( argv.notification ) && !argv.notification ) ) return; 31 | 32 | const options = _.merge ( {}, notification.defaultOptions, success ? notification.defaultSuccessOptions : notification.defaultErrorOptions, { title, message } ); 33 | 34 | try { 35 | 36 | await pify ( notifier.notify.bind ( notifier ) )( options ); 37 | 38 | } catch ( e ) { 39 | 40 | console.log ( `[${success ? 'SUCCESS' : 'ERROR'}] ${title} - ${message}` ); 41 | 42 | } 43 | 44 | } 45 | 46 | }; 47 | 48 | /* EXPORT */ 49 | 50 | module.exports = notification; 51 | -------------------------------------------------------------------------------- /src/utilities/path.js: -------------------------------------------------------------------------------- 1 | 2 | /* PATH */ 3 | 4 | const path = { 5 | 6 | normalize ( filePath ) { // Normalize those stupid Windows paths 7 | 8 | return filePath.replace ( /(\\|\/)+/g, '/' ); 9 | 10 | } 11 | 12 | }; 13 | 14 | /* EXPORT */ 15 | 16 | module.exports = path; 17 | -------------------------------------------------------------------------------- /src/utilities/paths/clean.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const paths = require ( './paths' ); 5 | 6 | /* CLEAN */ 7 | 8 | const clean = { 9 | 10 | getPath () { 11 | 12 | return paths.getPath ( 'clean' ); 13 | 14 | } 15 | 16 | }; 17 | 18 | /* EXPORT */ 19 | 20 | module.exports = clean; 21 | -------------------------------------------------------------------------------- /src/utilities/paths/input.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const paths = require ( './paths' ); 5 | 6 | /* INPUT */ 7 | 8 | const input = { 9 | 10 | getPath ( key ) { 11 | 12 | return paths.getPath ( `input.${key}` ); 13 | 14 | } 15 | 16 | }; 17 | 18 | /* EXPORT */ 19 | 20 | module.exports = input; 21 | -------------------------------------------------------------------------------- /src/utilities/paths/output.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const paths = require ( './paths' ); 5 | 6 | /* OUTPUT */ 7 | 8 | const output = { 9 | 10 | isEnabled ( key ) { 11 | 12 | return !!output.getPath ( key ); 13 | 14 | }, 15 | 16 | getDir ( key ) { 17 | 18 | return paths.getDir ( `output.${key}` ); 19 | 20 | }, 21 | 22 | getDirs ( key ) { 23 | 24 | return paths.getDirs ( `output.${key}` ); 25 | 26 | }, 27 | 28 | getName ( key ) { 29 | 30 | return paths.getName ( `output.${key}` ); 31 | 32 | }, 33 | 34 | getPath ( key ) { 35 | 36 | return paths.getPath ( `output.${key}` ); 37 | 38 | } 39 | 40 | }; 41 | 42 | /* EXPORT */ 43 | 44 | module.exports = output; 45 | -------------------------------------------------------------------------------- /src/utilities/paths/paths.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const _ = require ( 'lodash' ), 5 | path = require ( 'path' ), 6 | tokens = require ( './tokens' ), 7 | pathU = require ( '../path' ), 8 | project = require ( '../../project' ); 9 | 10 | /* PATHS */ 11 | 12 | const paths = { 13 | 14 | getDir ( key ) { 15 | 16 | const p = paths.getPath ( key ); 17 | 18 | if ( !p ) return p; 19 | 20 | const name = path.parse ( p ).base; 21 | 22 | return name.includes ( '.' ) ? path.parse ( p ).dir : p; 23 | 24 | }, 25 | 26 | getDirs ( key ) { 27 | 28 | const p = paths.getPath ( key ); 29 | 30 | if ( !p || !_.isPlainObject ( p ) ) return p; 31 | 32 | const subkeys = Object.keys ( p ), 33 | dirs = subkeys.map ( subkey => paths.getDir ( `${key}.${subkey}` ) ); 34 | 35 | return _.uniq ( dirs ); 36 | 37 | }, 38 | 39 | getName ( key ) { 40 | 41 | const p = paths.getPath ( key ); 42 | 43 | if ( !p ) return p; 44 | 45 | return path.parse ( p ).base; 46 | 47 | }, 48 | 49 | getPath ( key ) { 50 | 51 | const p = _.get ( project.paths, key ); 52 | 53 | if ( !_.isString ( p ) && !_.isArray ( p ) ) return p; 54 | 55 | const pt = tokens.parse ( p ); 56 | 57 | if ( _.isString ( pt ) ) return pathU.normalize ( pt ); 58 | 59 | if ( _.isArray ( pt ) ) return pt.map ( pathU.normalize ); 60 | 61 | return pt; 62 | 63 | } 64 | 65 | }; 66 | 67 | /* EXPORT */ 68 | 69 | module.exports = paths; 70 | -------------------------------------------------------------------------------- /src/utilities/paths/tokens.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const _ = require ( 'lodash' ), 5 | path = require ( 'path' ), 6 | project = require ( '../../project' ); 7 | 8 | /* TOKENS */ 9 | 10 | const tokens = { 11 | 12 | parse ( paths ) { 13 | 14 | paths = _.castArray ( paths ); 15 | 16 | _.forOwn ( project.paths.tokens, ( replacements, token ) => { 17 | 18 | replacements = _.castArray ( replacements ); 19 | 20 | paths = _.uniq ( _.flatten ( paths.map ( p => { 21 | 22 | return replacements.map ( replacement => p.replace ( `[${token}]`, replacement ) ); 23 | 24 | }))); 25 | 26 | }); 27 | 28 | return paths.length === 1 ? paths[0] : paths; 29 | 30 | } 31 | 32 | }; 33 | 34 | /* EXPORT */ 35 | 36 | module.exports = tokens; 37 | -------------------------------------------------------------------------------- /src/utilities/plumber.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const _ = require ( 'lodash' ), 5 | buildStatus = require ( './build_status' ), 6 | log = require ( './log' ); 7 | 8 | /* PLUMBER */ 9 | 10 | const plumber = { 11 | 12 | error ( pluginError ) { 13 | 14 | /* STATUS */ 15 | 16 | buildStatus.finish ( pluginError ); 17 | 18 | /* LOG ERROR */ // In case there will be no summary 19 | 20 | const {started} = buildStatus.stats (); 21 | 22 | if ( !started ) log.error ( pluginError ); 23 | 24 | /* ENDING */ // Prevents `watch` tasks from crashing 25 | 26 | this.emit ( 'end' ); 27 | 28 | } 29 | 30 | }; 31 | 32 | /* EXPORT */ 33 | 34 | module.exports = plumber; 35 | -------------------------------------------------------------------------------- /src/utilities/project.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const _ = require ( 'lodash' ), 5 | path = require ( 'path' ), 6 | {color} = require ( 'specialist' ), 7 | sha1 = require ( 'sha1' ), 8 | file = require ( './file' ), 9 | gutil = require ( './gutil' ); 10 | 11 | /* PROJECT */ 12 | 13 | const project = { 14 | 15 | getSrcPaths ( config ) { 16 | 17 | const src = _.castArray ( config.paths.tokens.src ); 18 | 19 | return src.map ( gutil.abs ); 20 | 21 | }, 22 | 23 | checkSrcPaths ( config ) { 24 | 25 | const src = project.getSrcPaths ( config ), 26 | missing = src.filter ( _.negate ( file.exists ) ); 27 | 28 | if ( !missing.length ) return; 29 | 30 | console.error ( color.red ( `Source path(s) not found:\n ${missing.map ( m => color.underline ( m ) ).join ( '\n ' )}` ) ); 31 | 32 | process.exit ( 1 ); 33 | 34 | }, 35 | 36 | getDistPath ( config ) { 37 | 38 | return gutil.abs ( config.paths.tokens.dist ); 39 | 40 | }, 41 | 42 | getTempPath ( config ) { // In order to allow for multiple simultaneous compilations 43 | 44 | return path.resolve ( __dirname, '..', '..', '.temp', project.getHash ( config ) ); 45 | 46 | }, 47 | 48 | getHash ( config ) { // Uniquely identifies a `paths.tokens.src`, and `paths.tokens.dist` combination 49 | 50 | const src = project.getSrcPaths ( config ), 51 | dist = project.getDistPath ( config ), 52 | id = `${src.join ( '|' )}|${dist}`, 53 | hash = sha1 ( id ); 54 | 55 | return hash; 56 | 57 | }, 58 | 59 | initEngines ( project ) { 60 | 61 | _.set ( project, 'plugins.autoprefixer.options.overrideBrowserslist', project.browsers ); 62 | 63 | const babelPreset = _.get ( project, 'plugins.babel.options.presets[0][0]' ), 64 | isPresetEnv = babelPreset && babelPreset.match ( /preset-env/g ); 65 | 66 | if ( isPresetEnv ) { 67 | 68 | if ( project.target === 'web' ) { 69 | 70 | _.set ( project, 'plugins.babel.options.presets[0][1].targets.browsers', project.browsers ); 71 | 72 | } else if ( project.target === 'node' ) { 73 | 74 | _.set ( project, 'plugins.babel.options.presets[0][1].targets.node', project.node ); 75 | 76 | } 77 | 78 | } 79 | 80 | } 81 | 82 | }; 83 | 84 | /* EXPORT */ 85 | 86 | module.exports = project; 87 | -------------------------------------------------------------------------------- /src/utilities/target.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const _ = require ( 'lodash' ), 5 | {color} = require ( 'specialist' ); 6 | 7 | /* TARGET */ 8 | 9 | const target = { 10 | 11 | get ( config, target ) { 12 | 13 | return _.get ( config, `targets.${target}` ); 14 | 15 | }, 16 | 17 | checkExistence ( target, ...objs ) { 18 | 19 | if ( !objs.every ( _.isEmpty ) ) return; 20 | 21 | console.error ( color.red ( `Unknown target "${color.underline ( target )}", did you forget to define it?` ) ); 22 | 23 | process.exit ( 1 ); 24 | 25 | } 26 | 27 | }; 28 | 29 | /* EXPORT */ 30 | 31 | module.exports = target; 32 | -------------------------------------------------------------------------------- /test/check/component/css/pacco.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fabiospampinato/pacco/e1d2772892b78739125c3b03be3509f85b355af1/test/check/component/css/pacco.css -------------------------------------------------------------------------------- /test/check/component/css/pacco.min.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fabiospampinato/pacco/e1d2772892b78739125c3b03be3509f85b355af1/test/check/component/css/pacco.min.css -------------------------------------------------------------------------------- /test/check/component/javascript/pacco.js: -------------------------------------------------------------------------------- 1 | 2 | // a/index.js 3 | -------------------------------------------------------------------------------- /test/check/component/javascript/pacco.min.js: -------------------------------------------------------------------------------- 1 | 2 | // a/index.js 3 | -------------------------------------------------------------------------------- /test/check/component/scss/pacco.functions.scss: -------------------------------------------------------------------------------- 1 | 2 | // a/functions.scss 3 | -------------------------------------------------------------------------------- /test/check/component/scss/pacco.keyframes.scss: -------------------------------------------------------------------------------- 1 | 2 | // a/keyframes.scss 3 | -------------------------------------------------------------------------------- /test/check/component/scss/pacco.mixins.scss: -------------------------------------------------------------------------------- 1 | 2 | // a/mixins.scss 3 | -------------------------------------------------------------------------------- /test/check/component/scss/pacco.scss: -------------------------------------------------------------------------------- 1 | 2 | // a/functions.scss 3 | 4 | 5 | // a/mixins.scss 6 | 7 | 8 | // a/variables.scss 9 | 10 | 11 | // a/keyframes.scss 12 | 13 | 14 | // a/index.scss 15 | -------------------------------------------------------------------------------- /test/check/component/scss/pacco.style.scss: -------------------------------------------------------------------------------- 1 | 2 | // a/index.scss 3 | -------------------------------------------------------------------------------- /test/check/component/scss/pacco.variables.scss: -------------------------------------------------------------------------------- 1 | 2 | // a/variables.scss 3 | -------------------------------------------------------------------------------- /test/check/components/css/pacco.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fabiospampinato/pacco/e1d2772892b78739125c3b03be3509f85b355af1/test/check/components/css/pacco.css -------------------------------------------------------------------------------- /test/check/components/css/pacco.min.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fabiospampinato/pacco/e1d2772892b78739125c3b03be3509f85b355af1/test/check/components/css/pacco.min.css -------------------------------------------------------------------------------- /test/check/components/javascript/pacco.js: -------------------------------------------------------------------------------- 1 | 2 | // a/index.js 3 | -------------------------------------------------------------------------------- /test/check/components/javascript/pacco.min.js: -------------------------------------------------------------------------------- 1 | 2 | // a/index.js 3 | -------------------------------------------------------------------------------- /test/check/components/scss/pacco.functions.scss: -------------------------------------------------------------------------------- 1 | 2 | // a/functions.scss 3 | -------------------------------------------------------------------------------- /test/check/components/scss/pacco.mixins.scss: -------------------------------------------------------------------------------- 1 | 2 | // a/mixins.scss 3 | -------------------------------------------------------------------------------- /test/check/components/scss/pacco.scss: -------------------------------------------------------------------------------- 1 | 2 | // a/functions.scss 3 | 4 | 5 | // a/mixins.scss 6 | 7 | 8 | // a/variables.scss 9 | 10 | 11 | // a/index.scss 12 | -------------------------------------------------------------------------------- /test/check/components/scss/pacco.style.scss: -------------------------------------------------------------------------------- 1 | 2 | // a/index.scss 3 | -------------------------------------------------------------------------------- /test/check/components/scss/pacco.variables.scss: -------------------------------------------------------------------------------- 1 | 2 | // a/variables.scss 3 | -------------------------------------------------------------------------------- /test/check/concat_content/javascript/pacco.js: -------------------------------------------------------------------------------- 1 | 2 | function wrapper () { 3 | 4 | // @concat-content 5 | 6 | 7 | // b.js 8 | 9 | 10 | // a.js 11 | // @require b.js 12 | 13 | 14 | } 15 | -------------------------------------------------------------------------------- /test/check/concat_content/javascript/pacco.min.js: -------------------------------------------------------------------------------- 1 | 2 | function wrapper () { 3 | 4 | // @concat-content 5 | 6 | 7 | // b.js 8 | 9 | 10 | // a.js 11 | // @require b.js 12 | 13 | 14 | } 15 | -------------------------------------------------------------------------------- /test/check/css/css/pacco.css: -------------------------------------------------------------------------------- 1 | 2 | /* c.css */ 3 | 4 | 5 | /* b.css */ 6 | /* @require c.css */ 7 | 8 | .a { 9 | visibility: hidden; 10 | } 11 | -------------------------------------------------------------------------------- /test/check/css/css/pacco.min.css: -------------------------------------------------------------------------------- 1 | 2 | /* c.css */ 3 | 4 | 5 | /* b.css */ 6 | /* @require c.css */ 7 | 8 | .a { 9 | visibility: hidden; 10 | } 11 | -------------------------------------------------------------------------------- /test/check/css/scss/pacco.scss: -------------------------------------------------------------------------------- 1 | 2 | // a.scss 3 | 4 | .a { 5 | visibility: hidden; 6 | } 7 | -------------------------------------------------------------------------------- /test/check/css/scss/pacco.style.scss: -------------------------------------------------------------------------------- 1 | 2 | // a.scss 3 | 4 | .a { 5 | visibility: hidden; 6 | } 7 | -------------------------------------------------------------------------------- /test/check/dependencies/javascript/pacco.js: -------------------------------------------------------------------------------- 1 | 2 | // c.js 3 | 4 | 5 | // b.js 6 | // @optional c.js 7 | // @optional undefined.js 8 | 9 | 10 | // a.js 11 | // @require b.js 12 | -------------------------------------------------------------------------------- /test/check/dependencies/javascript/pacco.min.js: -------------------------------------------------------------------------------- 1 | 2 | // c.js 3 | 4 | 5 | // b.js 6 | // @optional c.js 7 | // @optional undefined.js 8 | 9 | 10 | // a.js 11 | // @require b.js 12 | -------------------------------------------------------------------------------- /test/check/extend/css/pacco.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fabiospampinato/pacco/e1d2772892b78739125c3b03be3509f85b355af1/test/check/extend/css/pacco.css -------------------------------------------------------------------------------- /test/check/extend/css/pacco.min.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fabiospampinato/pacco/e1d2772892b78739125c3b03be3509f85b355af1/test/check/extend/css/pacco.min.css -------------------------------------------------------------------------------- /test/check/extend/javascript/pacco.js: -------------------------------------------------------------------------------- 1 | 2 | // before.js 3 | 4 | 5 | // a/after.js 6 | 7 | 8 | // a/before.js 9 | 10 | 11 | // require_a.js 12 | 13 | 14 | // require_b.js 15 | 16 | 17 | // a/index.before.js 18 | // @require require_b.js 19 | 20 | 21 | // a/index.override.js 22 | // @priority 10 23 | // @require ./before.js 24 | // @require ./after.js 25 | 26 | 27 | // a/index.after.js 28 | // @require require_a.js 29 | 30 | 31 | // a.js 32 | 33 | 34 | // z.js 35 | 36 | 37 | // after.js 38 | -------------------------------------------------------------------------------- /test/check/extend/javascript/pacco.min.js: -------------------------------------------------------------------------------- 1 | 2 | // before.js 3 | 4 | 5 | // a/after.js 6 | 7 | 8 | // a/before.js 9 | 10 | 11 | // require_a.js 12 | 13 | 14 | // require_b.js 15 | 16 | 17 | // a/index.before.js 18 | // @require require_b.js 19 | 20 | 21 | // a/index.override.js 22 | // @priority 10 23 | // @require ./before.js 24 | // @require ./after.js 25 | 26 | 27 | // a/index.after.js 28 | // @require require_a.js 29 | 30 | 31 | // a.js 32 | 33 | 34 | // z.js 35 | 36 | 37 | // after.js 38 | -------------------------------------------------------------------------------- /test/check/extend/scss/pacco.functions.scss: -------------------------------------------------------------------------------- 1 | 2 | // a/functions.scss 3 | -------------------------------------------------------------------------------- /test/check/extend/scss/pacco.keyframes.scss: -------------------------------------------------------------------------------- 1 | 2 | // a/keyframes.scss 3 | -------------------------------------------------------------------------------- /test/check/extend/scss/pacco.mixins.scss: -------------------------------------------------------------------------------- 1 | 2 | // a/mixins.scss 3 | -------------------------------------------------------------------------------- /test/check/extend/scss/pacco.scss: -------------------------------------------------------------------------------- 1 | 2 | // a/functions.scss 3 | 4 | 5 | // a/mixins.scss 6 | 7 | 8 | // a/variables.scss 9 | 10 | 11 | // a/keyframes.scss 12 | 13 | 14 | // a/index.scss 15 | -------------------------------------------------------------------------------- /test/check/extend/scss/pacco.style.scss: -------------------------------------------------------------------------------- 1 | 2 | // a/index.scss 3 | -------------------------------------------------------------------------------- /test/check/extend/scss/pacco.variables.scss: -------------------------------------------------------------------------------- 1 | 2 | // a/variables.scss 3 | -------------------------------------------------------------------------------- /test/check/lodash_template/javascript/pacco.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | // a.js 4 | (function (o) { 5 | var __t, 6 | __p = ''; 7 | 8 | __p += '

Hello ' + ((__t = o.name) == null ? '' : __t) + '

'; 9 | return __p; 10 | }); 11 | 12 | (function (o) { 13 | var __t, 14 | __p = ''; 15 | 16 | __p += '

This is just a ' + ((__t = o.what) == null ? '' : __t) + '

'; 17 | return __p; 18 | }); 19 | 20 | (function (o) { 21 | var __t, 22 | __p = ''; 23 | 24 | __p += '

Minified

'; 25 | return __p; 26 | }); -------------------------------------------------------------------------------- /test/check/lodash_template/javascript/pacco.min.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | // a.js 4 | (function (o) { 5 | var __t, 6 | __p = ''; 7 | 8 | __p += '

Hello ' + ((__t = o.name) == null ? '' : __t) + '

'; 9 | return __p; 10 | }); 11 | 12 | (function (o) { 13 | var __t, 14 | __p = ''; 15 | 16 | __p += '

This is just a ' + ((__t = o.what) == null ? '' : __t) + '

'; 17 | return __p; 18 | }); 19 | 20 | (function (o) { 21 | var __t, 22 | __p = ''; 23 | 24 | __p += '

Minified

'; 25 | return __p; 26 | }); -------------------------------------------------------------------------------- /test/check/priority/javascript/pacco.js: -------------------------------------------------------------------------------- 1 | 2 | // integer/c.js 3 | // @priority 100 4 | 5 | 6 | // float/c.js 7 | // @priority 11 8 | 9 | 10 | // float/d.js 11 | // @priority 10.5 12 | 13 | 14 | // float/b.js 15 | // @priority 10 16 | 17 | 18 | // integer/b.js 19 | // @priority 10 20 | 21 | 22 | // float/a.js 23 | 24 | 25 | // integer/a.js 26 | 27 | 28 | // negative/a.js 29 | 30 | 31 | // negative/b.js 32 | // @priority -10 33 | 34 | 35 | // negative/c.js 36 | // @priority -10.5 37 | -------------------------------------------------------------------------------- /test/check/priority/javascript/pacco.min.js: -------------------------------------------------------------------------------- 1 | 2 | // integer/c.js 3 | // @priority 100 4 | 5 | 6 | // float/c.js 7 | // @priority 11 8 | 9 | 10 | // float/d.js 11 | // @priority 10.5 12 | 13 | 14 | // float/b.js 15 | // @priority 10 16 | 17 | 18 | // integer/b.js 19 | // @priority 10 20 | 21 | 22 | // float/a.js 23 | 24 | 25 | // integer/a.js 26 | 27 | 28 | // negative/a.js 29 | 30 | 31 | // negative/b.js 32 | // @priority -10 33 | 34 | 35 | // negative/c.js 36 | // @priority -10.5 37 | -------------------------------------------------------------------------------- /test/check/resources/fonts/a.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fabiospampinato/pacco/e1d2772892b78739125c3b03be3509f85b355af1/test/check/resources/fonts/a.eot -------------------------------------------------------------------------------- /test/check/resources/fonts/a.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fabiospampinato/pacco/e1d2772892b78739125c3b03be3509f85b355af1/test/check/resources/fonts/a.ttf -------------------------------------------------------------------------------- /test/check/resources/fonts/a.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fabiospampinato/pacco/e1d2772892b78739125c3b03be3509f85b355af1/test/check/resources/fonts/a.woff -------------------------------------------------------------------------------- /test/check/resources/fonts/a.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fabiospampinato/pacco/e1d2772892b78739125c3b03be3509f85b355af1/test/check/resources/fonts/a.woff2 -------------------------------------------------------------------------------- /test/check/resources/html/a.html: -------------------------------------------------------------------------------- 1 | 2 | 12 | -------------------------------------------------------------------------------- /test/check/resources/html/b.html: -------------------------------------------------------------------------------- 1 |

Test

2 |

This is just a test

3 | -------------------------------------------------------------------------------- /test/check/resources/images/a.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fabiospampinato/pacco/e1d2772892b78739125c3b03be3509f85b355af1/test/check/resources/images/a.bmp -------------------------------------------------------------------------------- /test/check/resources/images/a.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fabiospampinato/pacco/e1d2772892b78739125c3b03be3509f85b355af1/test/check/resources/images/a.gif -------------------------------------------------------------------------------- /test/check/resources/images/a.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fabiospampinato/pacco/e1d2772892b78739125c3b03be3509f85b355af1/test/check/resources/images/a.jpeg -------------------------------------------------------------------------------- /test/check/resources/images/a.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fabiospampinato/pacco/e1d2772892b78739125c3b03be3509f85b355af1/test/check/resources/images/a.jpg -------------------------------------------------------------------------------- /test/check/resources/images/a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fabiospampinato/pacco/e1d2772892b78739125c3b03be3509f85b355af1/test/check/resources/images/a.png -------------------------------------------------------------------------------- /test/check/resources/images/a.svg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fabiospampinato/pacco/e1d2772892b78739125c3b03be3509f85b355af1/test/check/resources/images/a.svg -------------------------------------------------------------------------------- /test/check/resources/images/a.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fabiospampinato/pacco/e1d2772892b78739125c3b03be3509f85b355af1/test/check/resources/images/a.webp -------------------------------------------------------------------------------- /test/check/resources/json/a.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /test/check/substitute/css/pacco.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fabiospampinato/pacco/e1d2772892b78739125c3b03be3509f85b355af1/test/check/substitute/css/pacco.css -------------------------------------------------------------------------------- /test/check/substitute/css/pacco.min.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fabiospampinato/pacco/e1d2772892b78739125c3b03be3509f85b355af1/test/check/substitute/css/pacco.min.css -------------------------------------------------------------------------------- /test/check/substitute/javascript/pacco.js: -------------------------------------------------------------------------------- 1 | 2 | // b.js 3 | 4 | 5 | // a.js 6 | // @require b.js 7 | 8 | const ENVIRONMENT = 'development'; 9 | -------------------------------------------------------------------------------- /test/check/substitute/javascript/pacco.min.js: -------------------------------------------------------------------------------- 1 | 2 | // b.js 3 | 4 | 5 | // a.js 6 | // @require b.js 7 | 8 | const ENVIRONMENT = 'development'; 9 | -------------------------------------------------------------------------------- /test/check/substitute/json/a.json: -------------------------------------------------------------------------------- 1 | { 2 | "environment": "development" 3 | } 4 | -------------------------------------------------------------------------------- /test/check/substitute/scss/pacco.scss: -------------------------------------------------------------------------------- 1 | 2 | // a.scss 3 | 4 | $environment: 'development'; 5 | -------------------------------------------------------------------------------- /test/check/substitute/scss/pacco.style.scss: -------------------------------------------------------------------------------- 1 | 2 | // a.scss 3 | 4 | $environment: 'development'; 5 | -------------------------------------------------------------------------------- /test/check/typescript/javascript/pacco.js: -------------------------------------------------------------------------------- 1 | // b.js 2 | // a.ts 3 | // @require b.js 4 | function a(arg1, arg2) { 5 | return {}; 6 | } 7 | -------------------------------------------------------------------------------- /test/check/typescript/javascript/pacco.min.js: -------------------------------------------------------------------------------- 1 | // b.js 2 | // a.ts 3 | // @require b.js 4 | function a(arg1, arg2) { 5 | return {}; 6 | } 7 | -------------------------------------------------------------------------------- /test/check/typescript/typescript/pacco.d.ts: -------------------------------------------------------------------------------- 1 | declare function a(arg1: string, arg2?: boolean): {}; 2 | -------------------------------------------------------------------------------- /test/check/typescript/typescript/pacco.ts: -------------------------------------------------------------------------------- 1 | 2 | // b.js 3 | 4 | 5 | // a.ts 6 | // @require b.js 7 | 8 | function a ( arg1: string, arg2?: boolean ) { 9 | return {}; 10 | } 11 | -------------------------------------------------------------------------------- /test/check/webpack/javascript/pacco.js: -------------------------------------------------------------------------------- 1 | !function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){n(1)},function(e,t){e.exports=e=>new Promise(t=>setTimeout(t,e))}]); -------------------------------------------------------------------------------- /test/check/webpack/javascript/pacco.min.js: -------------------------------------------------------------------------------- 1 | !function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){n(1)},function(e,t){e.exports=e=>new Promise(t=>setTimeout(t,e))}]); -------------------------------------------------------------------------------- /test/check/wrapper/javascript/pacco.js: -------------------------------------------------------------------------------- 1 | /* UNMINIFIED - START */ 2 | 3 | // a.js 4 | 5 | /* UNMINIFIED - END */ -------------------------------------------------------------------------------- /test/check/wrapper/javascript/pacco.min.js: -------------------------------------------------------------------------------- 1 | /* MINIFIED - START */ 2 | 3 | // a.js 4 | 5 | /* MINIFIED - END */ -------------------------------------------------------------------------------- /test/config/components.json: -------------------------------------------------------------------------------- 1 | { 2 | "components": { 3 | "a/keyframes.scss": false, 4 | "b": { 5 | "index.js": false 6 | } 7 | }, 8 | "paths": { 9 | "tokens": { 10 | "src": ["test/src/component", "test/src/components"] 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /test/config/extend.json: -------------------------------------------------------------------------------- 1 | { 2 | "paths": { 3 | "tokens": { 4 | "src": ["test/src/component", "test/src/extend"] 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /test/config/general.json: -------------------------------------------------------------------------------- 1 | { 2 | "environment": "development", 3 | "paths": { 4 | "tokens": { 5 | "src": "[src]", 6 | "dist": "[dist]" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /test/config/lodash_template.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": { 3 | "babel": { 4 | "enabled": true 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /test/config/substitute.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": { 3 | "substitute": { 4 | "options": { 5 | "substitutions": { 6 | "my_requirement": "b.js" 7 | } 8 | } 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /test/config/webpack.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": { 3 | "webpack": { 4 | "enabled": true 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /test/config/wrapper.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": { 3 | "wrapper": { 4 | "options": { 5 | "templates": { 6 | "unminified": "/* UNMINIFIED - START */\n[content]\n/* UNMINIFIED - END */", 7 | "minified": "/* MINIFIED - START */\n[content]\n/* MINIFIED - END */" 8 | } 9 | } 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | 2 | /* REQUIRE */ 3 | 4 | const _ = require ( 'lodash' ), 5 | {argv} = require ( 'yargs' ), 6 | diff = require ( 'test-diff' ), 7 | execa = require ( 'execa' ), 8 | path = require ( 'path' ); 9 | 10 | /* VARIABLES */ 11 | 12 | const PACCO = path.resolve ( __dirname, '..', 'bin', 'index.js' ), 13 | CHECK = path.join ( __dirname, 'check' ), 14 | CONFIG = path.join ( __dirname, 'config' ), 15 | OUTPUT = path.join ( __dirname, 'dist' ), 16 | SOURCE = path.join ( __dirname, 'src' ), 17 | GLOB = argv.only ? `${argv.only}{}` : '*'; 18 | 19 | /* TEST */ 20 | 21 | const Test = { 22 | 23 | config: { 24 | 25 | getGeneral ( test ) { 26 | 27 | const escapeBackslash = filePath => filePath.replace ( /\\/g, '\\\\' ), // Required for properly handling Windows paths 28 | {source, output} = Test.paths.get ( test ), 29 | configBase = Test.config.getSpecific ( 'general' ), 30 | config = JSON.parse ( JSON.stringify ( configBase ).replace ( '[src]', escapeBackslash ( source ) ).replace ( '[dist]', escapeBackslash ( output ) ) ); 31 | 32 | return config; 33 | 34 | }, 35 | 36 | getSpecific ( test ) { 37 | 38 | try { 39 | 40 | return require ( Test.paths.get ( test ).config ); 41 | 42 | } catch ( e ) { 43 | 44 | return {}; 45 | 46 | } 47 | 48 | }, 49 | 50 | get ( test ) { 51 | 52 | const general = Test.config.getGeneral ( test ), 53 | specific = Test.config.getSpecific ( test ), 54 | config = _.merge ( general, specific ); 55 | 56 | return config; 57 | 58 | } 59 | 60 | }, 61 | 62 | paths: { 63 | 64 | get ( test ) { 65 | 66 | return { 67 | config: path.join ( CONFIG, `${test}.json` ), 68 | source: path.join ( SOURCE, test ), 69 | output: path.join ( OUTPUT, test ), 70 | check: path.join ( CHECK, test ) 71 | }; 72 | 73 | } 74 | 75 | }, 76 | 77 | make ( test ) { 78 | 79 | const config = Test.config.get ( test ), 80 | result = execa ( PACCO, ['build', '--config', JSON.stringify ( config ), '--no-notification', '--fresh', '--verbose', ...argv._], { reject: false } ); 81 | 82 | return result; 83 | 84 | } 85 | 86 | }; 87 | 88 | /* DIFF */ 89 | 90 | diff ({ 91 | verbose: !!argv.verbose, 92 | source: { 93 | cwd: SOURCE, 94 | glob: GLOB 95 | }, 96 | output: { 97 | cwd: OUTPUT, 98 | make: Test.make 99 | }, 100 | check: { 101 | cwd: CHECK, 102 | glob: GLOB 103 | } 104 | }); 105 | -------------------------------------------------------------------------------- /test/src/component/a/functions.scss: -------------------------------------------------------------------------------- 1 | 2 | // a/functions.scss 3 | -------------------------------------------------------------------------------- /test/src/component/a/index.js: -------------------------------------------------------------------------------- 1 | 2 | // a/index.js 3 | -------------------------------------------------------------------------------- /test/src/component/a/index.scss: -------------------------------------------------------------------------------- 1 | 2 | // a/index.scss 3 | -------------------------------------------------------------------------------- /test/src/component/a/keyframes.scss: -------------------------------------------------------------------------------- 1 | 2 | // a/keyframes.scss 3 | -------------------------------------------------------------------------------- /test/src/component/a/mixins.scss: -------------------------------------------------------------------------------- 1 | 2 | // a/mixins.scss 3 | -------------------------------------------------------------------------------- /test/src/component/a/variables.scss: -------------------------------------------------------------------------------- 1 | 2 | // a/variables.scss 3 | -------------------------------------------------------------------------------- /test/src/components/b/index.js: -------------------------------------------------------------------------------- 1 | 2 | // b/index.js 3 | -------------------------------------------------------------------------------- /test/src/concat_content/a.js: -------------------------------------------------------------------------------- 1 | 2 | // a.js 3 | // @require b.js 4 | -------------------------------------------------------------------------------- /test/src/concat_content/b.js: -------------------------------------------------------------------------------- 1 | 2 | // b.js 3 | -------------------------------------------------------------------------------- /test/src/concat_content/wrapper.js: -------------------------------------------------------------------------------- 1 | 2 | function wrapper () { 3 | 4 | // @concat-content 5 | 6 | } 7 | -------------------------------------------------------------------------------- /test/src/css/a.scss: -------------------------------------------------------------------------------- 1 | 2 | // a.scss 3 | 4 | .a { 5 | visibility: hidden; 6 | } 7 | -------------------------------------------------------------------------------- /test/src/css/b.css: -------------------------------------------------------------------------------- 1 | 2 | /* b.css */ 3 | /* @require c.css */ 4 | -------------------------------------------------------------------------------- /test/src/css/c.css: -------------------------------------------------------------------------------- 1 | 2 | /* c.css */ 3 | -------------------------------------------------------------------------------- /test/src/cyclic/a.js: -------------------------------------------------------------------------------- 1 | 2 | // a.js 3 | // @require b.js 4 | -------------------------------------------------------------------------------- /test/src/cyclic/b.js: -------------------------------------------------------------------------------- 1 | 2 | // b.js 3 | // @require c.js 4 | -------------------------------------------------------------------------------- /test/src/cyclic/c.js: -------------------------------------------------------------------------------- 1 | 2 | // c.js 3 | // @require a.js 4 | -------------------------------------------------------------------------------- /test/src/dependencies/a.js: -------------------------------------------------------------------------------- 1 | 2 | // a.js 3 | // @require b.js 4 | -------------------------------------------------------------------------------- /test/src/dependencies/b.js: -------------------------------------------------------------------------------- 1 | 2 | // b.js 3 | // @optional c.js 4 | // @optional undefined.js 5 | -------------------------------------------------------------------------------- /test/src/dependencies/c.js: -------------------------------------------------------------------------------- 1 | 2 | // c.js 3 | -------------------------------------------------------------------------------- /test/src/extend/a.js: -------------------------------------------------------------------------------- 1 | 2 | // a.js 3 | -------------------------------------------------------------------------------- /test/src/extend/a/after.js: -------------------------------------------------------------------------------- 1 | 2 | // a/after.js 3 | -------------------------------------------------------------------------------- /test/src/extend/a/before.js: -------------------------------------------------------------------------------- 1 | 2 | // a/before.js 3 | -------------------------------------------------------------------------------- /test/src/extend/a/index.after.js: -------------------------------------------------------------------------------- 1 | 2 | // a/index.after.js 3 | // @require require_a.js 4 | -------------------------------------------------------------------------------- /test/src/extend/a/index.before.js: -------------------------------------------------------------------------------- 1 | 2 | // a/index.before.js 3 | // @require require_b.js 4 | -------------------------------------------------------------------------------- /test/src/extend/a/index.override.js: -------------------------------------------------------------------------------- 1 | 2 | // a/index.override.js 3 | // @priority 10 4 | // @require ./before.js 5 | // @require ./after.js 6 | -------------------------------------------------------------------------------- /test/src/extend/after.js: -------------------------------------------------------------------------------- 1 | 2 | // after.js 3 | -------------------------------------------------------------------------------- /test/src/extend/before.js: -------------------------------------------------------------------------------- 1 | 2 | // before.js 3 | -------------------------------------------------------------------------------- /test/src/extend/require_a.js: -------------------------------------------------------------------------------- 1 | 2 | // require_a.js 3 | -------------------------------------------------------------------------------- /test/src/extend/require_b.js: -------------------------------------------------------------------------------- 1 | 2 | // require_b.js 3 | -------------------------------------------------------------------------------- /test/src/extend/z.js: -------------------------------------------------------------------------------- 1 | 2 | // z.js 3 | -------------------------------------------------------------------------------- /test/src/lodash_template/a.js: -------------------------------------------------------------------------------- 1 | 2 | // a.js 3 | 4 | _.template ( '

Hello <%= o.name %>

' ); 5 | lodash.template ( `

This is just a <%= o.what %>

` ); 6 | _.template ( ` 7 |
8 |

Minified

9 |
10 | ` ); 11 | -------------------------------------------------------------------------------- /test/src/priority/float/a.js: -------------------------------------------------------------------------------- 1 | 2 | // float/a.js 3 | -------------------------------------------------------------------------------- /test/src/priority/float/b.js: -------------------------------------------------------------------------------- 1 | 2 | // float/b.js 3 | // @priority 10 4 | -------------------------------------------------------------------------------- /test/src/priority/float/c.js: -------------------------------------------------------------------------------- 1 | 2 | // float/c.js 3 | // @priority 11 4 | -------------------------------------------------------------------------------- /test/src/priority/float/d.js: -------------------------------------------------------------------------------- 1 | 2 | // float/d.js 3 | // @priority 10.5 4 | -------------------------------------------------------------------------------- /test/src/priority/integer/a.js: -------------------------------------------------------------------------------- 1 | 2 | // integer/a.js 3 | -------------------------------------------------------------------------------- /test/src/priority/integer/b.js: -------------------------------------------------------------------------------- 1 | 2 | // integer/b.js 3 | // @priority 10 4 | -------------------------------------------------------------------------------- /test/src/priority/integer/c.js: -------------------------------------------------------------------------------- 1 | 2 | // integer/c.js 3 | // @priority 100 4 | -------------------------------------------------------------------------------- /test/src/priority/negative/a.js: -------------------------------------------------------------------------------- 1 | 2 | // negative/a.js 3 | -------------------------------------------------------------------------------- /test/src/priority/negative/b.js: -------------------------------------------------------------------------------- 1 | 2 | // negative/b.js 3 | // @priority -10 4 | -------------------------------------------------------------------------------- /test/src/priority/negative/c.js: -------------------------------------------------------------------------------- 1 | 2 | // negative/c.js 3 | // @priority -10.5 4 | -------------------------------------------------------------------------------- /test/src/resources/a.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fabiospampinato/pacco/e1d2772892b78739125c3b03be3509f85b355af1/test/src/resources/a.bmp -------------------------------------------------------------------------------- /test/src/resources/a.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fabiospampinato/pacco/e1d2772892b78739125c3b03be3509f85b355af1/test/src/resources/a.eot -------------------------------------------------------------------------------- /test/src/resources/a.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fabiospampinato/pacco/e1d2772892b78739125c3b03be3509f85b355af1/test/src/resources/a.gif -------------------------------------------------------------------------------- /test/src/resources/a.html: -------------------------------------------------------------------------------- 1 | 2 | 12 | -------------------------------------------------------------------------------- /test/src/resources/a.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fabiospampinato/pacco/e1d2772892b78739125c3b03be3509f85b355af1/test/src/resources/a.jpeg -------------------------------------------------------------------------------- /test/src/resources/a.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fabiospampinato/pacco/e1d2772892b78739125c3b03be3509f85b355af1/test/src/resources/a.jpg -------------------------------------------------------------------------------- /test/src/resources/a.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /test/src/resources/a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fabiospampinato/pacco/e1d2772892b78739125c3b03be3509f85b355af1/test/src/resources/a.png -------------------------------------------------------------------------------- /test/src/resources/a.svg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fabiospampinato/pacco/e1d2772892b78739125c3b03be3509f85b355af1/test/src/resources/a.svg -------------------------------------------------------------------------------- /test/src/resources/a.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fabiospampinato/pacco/e1d2772892b78739125c3b03be3509f85b355af1/test/src/resources/a.ttf -------------------------------------------------------------------------------- /test/src/resources/a.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fabiospampinato/pacco/e1d2772892b78739125c3b03be3509f85b355af1/test/src/resources/a.webp -------------------------------------------------------------------------------- /test/src/resources/a.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fabiospampinato/pacco/e1d2772892b78739125c3b03be3509f85b355af1/test/src/resources/a.woff -------------------------------------------------------------------------------- /test/src/resources/a.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fabiospampinato/pacco/e1d2772892b78739125c3b03be3509f85b355af1/test/src/resources/a.woff2 -------------------------------------------------------------------------------- /test/src/resources/b.md: -------------------------------------------------------------------------------- 1 | 2 | ## Test 3 | 4 | This is just a test 5 | -------------------------------------------------------------------------------- /test/src/resources/other.ext: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fabiospampinato/pacco/e1d2772892b78739125c3b03be3509f85b355af1/test/src/resources/other.ext -------------------------------------------------------------------------------- /test/src/substitute/a.js: -------------------------------------------------------------------------------- 1 | 2 | // a.js 3 | // @require [pacco.my_requirement] 4 | 5 | const ENVIRONMENT = '[pacco.environment[0]]'; 6 | -------------------------------------------------------------------------------- /test/src/substitute/a.json: -------------------------------------------------------------------------------- 1 | { 2 | "environment": "[pacco.environment[0]]" 3 | } 4 | -------------------------------------------------------------------------------- /test/src/substitute/a.scss: -------------------------------------------------------------------------------- 1 | 2 | // a.scss 3 | 4 | $environment: '[pacco.environment[0]]'; 5 | -------------------------------------------------------------------------------- /test/src/substitute/b.js: -------------------------------------------------------------------------------- 1 | 2 | // b.js 3 | -------------------------------------------------------------------------------- /test/src/typescript/a.ts: -------------------------------------------------------------------------------- 1 | 2 | // a.ts 3 | // @require b.js 4 | 5 | function a ( arg1: string, arg2?: boolean ) { 6 | return {}; 7 | } 8 | -------------------------------------------------------------------------------- /test/src/typescript/b.js: -------------------------------------------------------------------------------- 1 | 2 | // b.js 3 | -------------------------------------------------------------------------------- /test/src/webpack/a.js: -------------------------------------------------------------------------------- 1 | 2 | // a.js 3 | 4 | const delay = require ( 'yoctodelay' ); 5 | -------------------------------------------------------------------------------- /test/src/wrapper/a.js: -------------------------------------------------------------------------------- 1 | 2 | // a.js 3 | --------------------------------------------------------------------------------