diff --git a/.gitignore b/.gitignore index 279bdb39dd..57b4e18aaa 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ *.suo *.vs10x *.ndproj +*.ignorer.* # common directories .DS_Store @@ -156,4 +157,4 @@ build/temp/ -# eof \ No newline at end of file +# eof diff --git a/src/Umbraco.Web.UI.Client/gulp/config.js b/src/Umbraco.Web.UI.Client/gulp/config.js new file mode 100755 index 0000000000..c27a2c5f53 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/gulp/config.js @@ -0,0 +1,52 @@ +'use strict'; + +module.exports = { + sources: { + + //less files used by backoffice and preview + //processed in the less task + less: { + installer: { files: ["./src/less/installer.less"], out: "installer.css" }, + nonodes: { files: ["./src/less/pages/nonodes.less"], out: "nonodes.style.min.css"}, + preview: { files: ["./src/less/canvas-designer.less"], out: "canvasdesigner.css" }, + umbraco: { files: ["./src/less/belle.less"], out: "umbraco.css" } + }, + + //js files for backoffie + //processed in the js task + js: { + preview: { files: ["./src/preview/**/*.js"], out: "umbraco.preview.js" }, + installer: { files: ["./src/installer/**/*.js"], out: "umbraco.installer.js" }, + controllers: { files: ["./src/{views,controllers}/**/*.controller.js"], out: "umbraco.controllers.js" }, + directives: { files: ["./src/common/directives/**/*.js"], out: "umbraco.directives.js" }, + filters: { files: ["./src/common/filters/**/*.js"], out: "umbraco.filters.js" }, + resources: { files: ["./src/common/resources/**/*.js"], out: "umbraco.resources.js" }, + services: { files: ["./src/common/services/**/*.js"], out: "umbraco.services.js" }, + security: { files: ["./src/common/interceptors/**/*.js"], out: "umbraco.interceptors.js" } + }, + + //selectors for copying all views into the build + //processed in the views task + views:{ + umbraco: {files: ["./src/views/**/*.html"], folder: ""}, + installer: {files: ["./src/installer/steps/*.html"], folder: "install/"} + }, + + //globs for file-watching + globs:{ + views: "./src/views/**/*.html", + less: "./src/less/**/*.less", + js: "./src/*.js", + lib: "./lib/**/*", + assets: "./src/assets/**" + } + }, + root: "../Umbraco.Web.UI/Umbraco/", + targets: { + js: "js/", + lib: "lib/", + views: "views/", + css: "assets/css/", + assets: "assets/" + } +}; diff --git a/src/Umbraco.Web.UI.Client/gulp/index.js b/src/Umbraco.Web.UI.Client/gulp/index.js new file mode 100755 index 0000000000..9dd80598af --- /dev/null +++ b/src/Umbraco.Web.UI.Client/gulp/index.js @@ -0,0 +1,10 @@ +'use strict'; + +var fs = require('fs'); + +var onlyScripts = require('./util/scriptFilter'); +var tasks = fs.readdirSync('./gulp/tasks/').filter(onlyScripts); + +tasks.forEach(function(task) { + require('./tasks/' + task); +}); diff --git a/src/Umbraco.Web.UI.Client/gulp/tasks/build.js b/src/Umbraco.Web.UI.Client/gulp/tasks/build.js new file mode 100644 index 0000000000..4e519c58e9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/gulp/tasks/build.js @@ -0,0 +1,10 @@ +'use strict'; + +var config = require('../config'); +var gulp = require('gulp'); +var runSequence = require('run-sequence'); + +// Build - build the files ready for production +gulp.task('build', function(cb) { + runSequence(["dependencies", "js", "less", "views"], cb); +}); diff --git a/src/Umbraco.Web.UI.Client/gulp/tasks/dependencies.js b/src/Umbraco.Web.UI.Client/gulp/tasks/dependencies.js new file mode 100644 index 0000000000..8032274ee7 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/gulp/tasks/dependencies.js @@ -0,0 +1,288 @@ +'use strict'; + +var config = require('../config'); +var gulp = require('gulp'); + +var MergeStream = require('merge-stream'); + +var imagemin = require('gulp-imagemin'); + +/************************** + * Task processes and copies all dependencies, either installed by npm or stored locally in the project + **************************/ +gulp.task('dependencies', function () { + + //as we do multiple things in this task, we merge the multiple streams + var stream = new MergeStream(); + + // Pick the dependencies we need from each package + // so we don't just ship with a lot of files that aren't needed + const nodeModules = [ + { + "name": "ace-builds", + "src": [ + "./node_modules/ace-builds/src-min-noconflict/ace.js", + "./node_modules/ace-builds/src-min-noconflict/ext-language_tools.js", + "./node_modules/ace-builds/src-min-noconflict/ext-searchbox.js", + "./node_modules/ace-builds/src-min-noconflict/ext-settings_menu.js", + "./node_modules/ace-builds/src-min-noconflict/snippets/text.js", + "./node_modules/ace-builds/src-min-noconflict/snippets/javascript.js", + "./node_modules/ace-builds/src-min-noconflict/snippets/css.js", + "./node_modules/ace-builds/src-min-noconflict/theme-chrome.js", + "./node_modules/ace-builds/src-min-noconflict/mode-razor.js", + "./node_modules/ace-builds/src-min-noconflict/mode-javascript.js", + "./node_modules/ace-builds/src-min-noconflict/mode-css.js", + "./node_modules/ace-builds/src-min-noconflict/worker-javascript.js", + "./node_modules/ace-builds/src-min-noconflict/worker-css.js" + ], + "base": "./node_modules/ace-builds" + }, + { + "name": "angular", + "src": ["./node_modules/angular/angular.js"], + "base": "./node_modules/angular" + }, + { + "name": "angular-cookies", + "src": ["./node_modules/angular-cookies/angular-cookies.js"], + "base": "./node_modules/angular-cookies" + }, + { + "name": "angular-dynamic-locale", + "src": [ + "./node_modules/angular-dynamic-locale/dist/tmhDynamicLocale.min.js", + "./node_modules/angular-dynamic-locale/dist/tmhDynamicLocale.min.js.map" + ], + "base": "./node_modules/angular-dynamic-locale/dist" + }, + { + "name": "angular-sanitize", + "src": ["./node_modules/angular-sanitize/angular-sanitize.js"], + "base": "./node_modules/angular-sanitize" + }, + { + "name": "angular-touch", + "src": ["./node_modules/angular-touch/angular-touch.js"], + "base": "./node_modules/angular-touch" + }, + { + "name": "angular-ui-sortable", + "src": ["./node_modules/angular-ui-sortable/dist/sortable.js"], + "base": "./node_modules/angular-ui-sortable/dist" + }, + { + "name": "angular-route", + "src": ["./node_modules/angular-route/angular-route.js"], + "base": "./node_modules/angular-route" + }, + { + "name": "angular-animate", + "src": ["./node_modules/angular-animate/angular-animate.js"], + "base": "./node_modules/angular-animate" + }, + { + "name": "angular-i18n", + "src": [ + "./node_modules/angular-i18n/angular-i18n.js", + "./node_modules/angular-i18n/angular-locale_*.js" + ], + "base": "./node_modules/angular-i18n" + }, + { + "name": "angular-local-storage", + "src": [ + "./node_modules/angular-local-storage/dist/angular-local-storage.min.js", + "./node_modules/angular-local-storage/dist/angular-local-storage.min.js.map" + ], + "base": "./node_modules/angular-local-storage/dist" + }, + { + "name": "angular-messages", + "src": ["./node_modules/angular-messages/angular-messages.js"], + "base": "./node_modules/angular-messages" + }, + { + "name": "angular-mocks", + "src": ["./node_modules/angular-mocks/angular-mocks.js"], + "base": "./node_modules/angular-mocks" + }, + { + "name": "animejs", + "src": ["./node_modules/animejs/anime.min.js"], + "base": "./node_modules/animejs" + }, + { + "name": "bootstrap-social", + "src": ["./node_modules/bootstrap-social/bootstrap-social.css"], + "base": "./node_modules/bootstrap-social" + }, + + { + "name": "angular-chart.js", + "src": ["./node_modules/angular-chart.js/dist/angular-chart.min.js"], + "base": "./node_modules/angular-chart.js/dist" + }, + { + "name": "chart.js", + "src": ["./node_modules/chart.js/dist/chart.min.js"], + "base": "./node_modules/chart.js/dist" + }, + { + "name": "clipboard", + "src": ["./node_modules/clipboard/dist/clipboard.min.js"], + "base": "./node_modules/clipboard/dist" + }, + { + "name": "jsdiff", + "src": ["./node_modules/diff/dist/diff.min.js"], + "base": "./node_modules/diff/dist" + }, + { + "name": "flatpickr", + "src": [ + "./node_modules/flatpickr/dist/flatpickr.js", + "./node_modules/flatpickr/dist/flatpickr.css" + ], + "base": "./node_modules/flatpickr/dist" + }, + { + "name": "font-awesome", + "src": [ + "./node_modules/font-awesome/fonts/*", + "./node_modules/font-awesome/css/font-awesome.min.css" + ], + "base": "./node_modules/font-awesome" + }, + { + "name": "jquery", + "src": [ + "./node_modules/jquery/dist/jquery.min.js", + "./node_modules/jquery/dist/jquery.min.map" + ], + "base": "./node_modules/jquery/dist" + }, + { + "name": "jquery-ui", + "src": ["./node_modules/jquery-ui-dist/jquery-ui.min.js"], + "base": "./node_modules/jquery-ui-dist" + }, + { + "name": "jquery-ui-touch-punch", + "src": ["./node_modules/jquery-ui-touch-punch/jquery.ui.touch-punch.min.js"], + "base": "./node_modules/jquery-ui-touch-punch" + }, + { + "name": "lazyload-js", + "src": ["./node_modules/lazyload-js/lazyload.min.js"], + "base": "./node_modules/lazyload-js" + }, + { + "name": "moment", + "src": ["./node_modules/moment/min/moment.min.js"], + "base": "./node_modules/moment/min" + }, + { + "name": "moment", + "src": ["./node_modules/moment/locale/*.js"], + "base": "./node_modules/moment/locale" + }, + { + "name": "ng-file-upload", + "src": ["./node_modules/ng-file-upload/dist/ng-file-upload.min.js"], + "base": "./node_modules/ng-file-upload/dist" + }, + { + "name": "nouislider", + "src": [ + "./node_modules/nouislider/distribute/nouislider.min.js", + "./node_modules/nouislider/distribute/nouislider.min.css" + ], + "base": "./node_modules/nouislider/distribute" + }, + { + "name": "signalr", + "src": ["./node_modules/signalr/jquery.signalR.js"], + "base": "./node_modules/signalr" + }, + { + "name": "spectrum", + "src": [ + "./node_modules/spectrum-colorpicker/spectrum.js", + "./node_modules/spectrum-colorpicker/spectrum.css" + ], + "base": "./node_modules/spectrum-colorpicker" + }, + { + "name": "tinymce", + "src": [ + "./node_modules/tinymce/tinymce.min.js", + "./node_modules/tinymce/plugins/**", + "./node_modules/tinymce/skins/**", + "./node_modules/tinymce/themes/**" + ], + "base": "./node_modules/tinymce" + }, + { + "name": "typeahead.js", + "src": ["./node_modules/typeahead.js/dist/typeahead.bundle.min.js"], + "base": "./node_modules/typeahead.js/dist" + }, + { + "name": "underscore", + "src": ["node_modules/underscore/underscore-min.js"], + "base": "./node_modules/underscore" + } + ]; + + // add streams for node modules + nodeModules.forEach(module => { + stream.add( + gulp.src(module.src, + { base: module.base }) + .pipe(gulp.dest(config.root + config.targets.lib + "/" + module.name)) + ); + }); + + //copy over libs which are not on npm (/lib) + stream.add( + gulp.src(config.sources.globs.lib) + .pipe(gulp.dest(config.root + config.targets.lib)) + ); + + //Copies all static assets into /root / assets folder + //css, fonts and image files + stream.add( + gulp.src(config.sources.globs.assets) + .pipe(imagemin([ + imagemin.gifsicle({interlaced: true}), + imagemin.jpegtran({progressive: true}), + imagemin.optipng({optimizationLevel: 5}), + imagemin.svgo({ + plugins: [ + {removeViewBox: true}, + {cleanupIDs: false} + ] + }) + ])) + .pipe(gulp.dest(config.root + config.targets.assets)) + ); + + // Copies all the less files related to the preview into their folder + //these are not pre-processed as preview has its own less combiler client side + stream.add( + gulp.src("src/canvasdesigner/editors/*.less") + .pipe(gulp.dest(config.root + config.targets.assets + "/less")) + ); + + // Todo: check if we need these fileSize + stream.add( + gulp.src("src/views/propertyeditors/grid/config/*.*") + .pipe(gulp.dest(config.root + config.targets.views + "/propertyeditors/grid/config")) + ); + stream.add( + gulp.src("src/views/dashboard/default/*.jpg") + .pipe(gulp.dest(config.root + config.targets.views + "/dashboard/default")) + ); + + return stream; +}); diff --git a/src/Umbraco.Web.UI.Client/gulp/tasks/dev.js b/src/Umbraco.Web.UI.Client/gulp/tasks/dev.js new file mode 100644 index 0000000000..bca4da8c43 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/gulp/tasks/dev.js @@ -0,0 +1,10 @@ +'use strict'; + +var config = require('../config'); +var gulp = require('gulp'); +var runSequence = require('run-sequence'); + +// Dev - build the files ready for development and start watchers +gulp.task('dev', function(cb) { + runSequence(["dependencies", "js", "less", "views"], "watch", cb); +}); diff --git a/src/Umbraco.Web.UI.Client/gulp/tasks/docs.js b/src/Umbraco.Web.UI.Client/gulp/tasks/docs.js new file mode 100644 index 0000000000..34271a018c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/gulp/tasks/docs.js @@ -0,0 +1,55 @@ +'use strict'; + +var config = require('../config'); +var gulp = require('gulp'); + +var connect = require('gulp-connect'); +var open = require('gulp-open'); +var gulpDocs = require('gulp-ngdocs'); + +/************************** + * Build Backoffice UI API documentation + **************************/ +gulp.task('docs', [], function (cb) { + + var options = { + html5Mode: false, + startPage: '/api', + title: "Umbraco Backoffice UI API Documentation", + dest: 'docs/api', + styles: ['docs/umb-docs.css'], + image: "https://our.umbraco.com/assets/images/logo.svg" + } + + return gulpDocs.sections({ + api: { + glob: ['src/common/**/*.js', 'docs/src/api/**/*.ngdoc'], + api: true, + title: 'API Documentation' + } + }) + .pipe(gulpDocs.process(options)) + .pipe(gulp.dest('docs/api')); + cb(); +}); + +gulp.task('connect:docs', function (cb) { + connect.server({ + root: 'docs/api', + livereload: true, + fallback: 'docs/api/index.html', + port: 8880 + }); + cb(); +}); + +gulp.task('open:docs', function (cb) { + + var options = { + uri: 'http://localhost:8880/index.html' + }; + + gulp.src(__filename) + .pipe(open(options)); + cb(); +}); diff --git a/src/Umbraco.Web.UI.Client/gulp/tasks/docserve.js b/src/Umbraco.Web.UI.Client/gulp/tasks/docserve.js new file mode 100644 index 0000000000..a402003383 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/gulp/tasks/docserve.js @@ -0,0 +1,10 @@ +'use strict'; + +var config = require('../config'); +var gulp = require('gulp'); +var runSequence = require('run-sequence'); + +// Docserve - build and open the back office documentation +gulp.task('docserve', function(cb) { + runSequence('docs', 'connect:docs', 'open:docs', cb); +}); diff --git a/src/Umbraco.Web.UI.Client/gulp/tasks/js.js b/src/Umbraco.Web.UI.Client/gulp/tasks/js.js new file mode 100644 index 0000000000..e3ea0cc9d8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/gulp/tasks/js.js @@ -0,0 +1,29 @@ +'use strict'; + +var config = require('../config'); +var gulp = require('gulp'); + +var _ = require('lodash'); +var MergeStream = require('merge-stream'); + +var processJs = require('../util/processJs'); + +/************************** + * Copies all angular JS files into their seperate umbraco.*.js file + **************************/ +gulp.task('js', function () { + + //we run multiple streams, so merge them all together + var stream = new MergeStream(); + + stream.add( + gulp.src(config.sources.globs.js) + .pipe(gulp.dest(config.root + config.targets.js)) + ); + + _.forEach(config.sources.js, function (group) { + stream.add (processJs(group.files, group.out) ); + }); + + return stream; +}); diff --git a/src/Umbraco.Web.UI.Client/gulp/tasks/less.js b/src/Umbraco.Web.UI.Client/gulp/tasks/less.js new file mode 100644 index 0000000000..3d19716b67 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/gulp/tasks/less.js @@ -0,0 +1,20 @@ +'use strict'; + +var config = require('../config'); +var gulp = require('gulp'); + +var _ = require('lodash'); +var MergeStream = require('merge-stream'); + +var processLess = require('../util/processLess'); + +gulp.task('less', function () { + + var stream = new MergeStream(); + + _.forEach(config.sources.less, function (group) { + stream.add( processLess(group.files, group.out) ); + }); + + return stream; +}); diff --git a/src/Umbraco.Web.UI.Client/gulp/tasks/test.js b/src/Umbraco.Web.UI.Client/gulp/tasks/test.js new file mode 100644 index 0000000000..e40d4c436a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/gulp/tasks/test.js @@ -0,0 +1,26 @@ +'use strict'; + +var config = require('../config'); +var gulp = require('gulp'); +var karmaServer = require('karma').Server; + +/************************** + * Build tests + **************************/ + + // Karma test +gulp.task('test:unit', function() { + new karmaServer({ + configFile: __dirname + "/test/config/karma.conf.js", + keepalive: true + }) + .start(); +}); + +gulp.task('test:e2e', function() { + new karmaServer({ + configFile: __dirname + "/test/config/e2e.js", + keepalive: true + }) + .start(); +}); diff --git a/src/Umbraco.Web.UI.Client/gulp/tasks/views.js b/src/Umbraco.Web.UI.Client/gulp/tasks/views.js new file mode 100644 index 0000000000..05246370c2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/gulp/tasks/views.js @@ -0,0 +1,25 @@ +'use strict'; + +var config = require('../config'); +var gulp = require('gulp'); + +var _ = require('lodash'); +var MergeStream = require('merge-stream'); + +gulp.task('views', function () { + + var stream = new MergeStream(); + + _.forEach(config.sources.views, function (group) { + + console.log("copying " + group.files + " to " + config.root + config.targets.views + group.folder) + + stream.add ( + gulp.src(group.files) + .pipe( gulp.dest(config.root + config.targets.views + group.folder) ) + ); + + }); + + return stream; +}); diff --git a/src/Umbraco.Web.UI.Client/gulp/tasks/watch.js b/src/Umbraco.Web.UI.Client/gulp/tasks/watch.js new file mode 100644 index 0000000000..a5c476f7d2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/gulp/tasks/watch.js @@ -0,0 +1,58 @@ +'use strict'; + +var config = require('../config'); +var gulp = require('gulp'); + +var _ = require('lodash'); +var MergeStream = require('merge-stream'); + +var processJs = require('../util/processJs'); + +var watch = require('gulp-watch'); + +gulp.task('watch', function () { + + var stream = new MergeStream(); + var watchInterval = 500; + + //Setup a watcher for all groups of javascript files + _.forEach(config.sources.js, function (group) { + + if(group.watch !== false){ + + stream.add( + + watch(group.files, { ignoreInitial: true, interval: watchInterval }, function (file) { + + console.info(file.path + " has changed, added to: " + group.out); + processJs(group.files, group.out); + + }) + + ); + + } + + }); + + stream.add( + //watch all less files and trigger the less task + watch(config.sources.globs.less, { ignoreInitial: true, interval: watchInterval }, function () { + gulp.run(['less']); + }) + ); + + //watch all views - copy single file changes + stream.add( + watch(config.sources.globs.views, { interval: watchInterval }) + .pipe(gulp.dest(config.root + config.targets.views)) + ); + + //watch all app js files that will not be merged - copy single file changes + stream.add( + watch(config.sources.globs.js, { interval: watchInterval }) + .pipe(gulp.dest(config.root + config.targets.js)) + ); + + return stream; +}); diff --git a/src/Umbraco.Web.UI.Client/gulp/util/handleErrors.js b/src/Umbraco.Web.UI.Client/gulp/util/handleErrors.js new file mode 100755 index 0000000000..3c32a928dd --- /dev/null +++ b/src/Umbraco.Web.UI.Client/gulp/util/handleErrors.js @@ -0,0 +1,18 @@ +'use strict'; + +var notify = require('gulp-notify'); + +module.exports = function(error) { + + var args = Array.prototype.slice.call(arguments); + + // Send error to notification center with gulp-notify + notify.onError({ + title: 'Compile Error', + message: '<%= error.message %>' + }).apply(this, args); + + // Keep gulp from hanging on this task + this.emit('end'); + +}; diff --git a/src/Umbraco.Web.UI.Client/gulp/util/processJs.js b/src/Umbraco.Web.UI.Client/gulp/util/processJs.js new file mode 100644 index 0000000000..c110fa9cae --- /dev/null +++ b/src/Umbraco.Web.UI.Client/gulp/util/processJs.js @@ -0,0 +1,26 @@ + +var config = require('../config'); +var gulp = require('gulp'); + +var eslint = require('gulp-eslint'); +var babel = require("gulp-babel"); +var sort = require('gulp-sort'); +var concat = require('gulp-concat'); +var wrap = require("gulp-wrap-js"); + +module.exports = function(files, out) { + + return gulp.src(files) + // check for js errors + .pipe(eslint()) + // outputs the lint results to the console + .pipe(eslint.format()) + // sort files in stream by path or any custom sort comparator + .pipe(babel()) + .pipe(sort()) + .pipe(concat(out)) + .pipe(wrap('(function(){\n%= body %\n})();')) + .pipe(gulp.dest(config.root + config.targets.js)); + + console.log(out + " compiled"); +}; diff --git a/src/Umbraco.Web.UI.Client/gulp/util/processLess.js b/src/Umbraco.Web.UI.Client/gulp/util/processLess.js new file mode 100644 index 0000000000..e2bb758499 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/gulp/util/processLess.js @@ -0,0 +1,26 @@ + +var config = require('../config'); +var gulp = require('gulp'); + +var postcss = require('gulp-postcss'); +var less = require('gulp-less'); +var autoprefixer = require('autoprefixer'); +var cssnano = require('cssnano'); +var cleanCss = require("gulp-clean-css"); +var rename = require('gulp-rename'); + +module.exports = function(files, out) { + var processors = [ + autoprefixer, + cssnano({zindex: false}) + ]; + + return gulp.src(files) + .pipe(less()) + .pipe(cleanCss()) + .pipe(postcss(processors)) + .pipe(rename(out)) + .pipe(gulp.dest(config.root + config.targets.css)); + + console.log(out + " compiled"); +} diff --git a/src/Umbraco.Web.UI.Client/gulp/util/scriptFilter.js b/src/Umbraco.Web.UI.Client/gulp/util/scriptFilter.js new file mode 100755 index 0000000000..7d8ce45f82 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/gulp/util/scriptFilter.js @@ -0,0 +1,9 @@ +'use strict'; + +var path = require('path'); + +// Filters out non .js files. Prevents +// accidental inclusion of possible hidden files +module.exports = function(name) { + return /(\.(js)$)/i.test(path.extname(name)); +}; diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index e35fdc3442..6e8159a940 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -2,7 +2,9 @@ "private": true, "scripts": { "test": "karma start test/config/karma.conf.js --singlerun", - "build": "gulp" + "build": "gulp build", + "dev": "gulp dev", + "docs": "gulp docs" }, "dependencies": { "ace-builds": "1.4.2", @@ -62,6 +64,7 @@ "gulp-watch": "5.0.1", "gulp-wrap": "0.14.0", "gulp-wrap-js": "0.4.1", + "gulp-notify": "^3.0.0", "jasmine-core": "3.3.0", "karma": "3.1.1", "karma-jasmine": "2.0.1", @@ -70,6 +73,7 @@ "lodash": "4.17.11", "marked": "^0.5.2", "merge-stream": "1.0.1", - "run-sequence": "2.2.1" + "run-sequence": "2.2.1", + "fs": "0.0.2" } }