Merge pull request #4120 from umbraco/temp8-gulp-refactoring

V8 Client Gulp factoring
This commit is contained in:
Warren Buckley
2019-01-17 15:47:22 +00:00
committed by GitHub
18 changed files with 680 additions and 3 deletions

3
.gitignore vendored
View File

@@ -13,6 +13,7 @@
*.suo
*.vs10x
*.ndproj
*.ignorer.*
# common directories
.DS_Store
@@ -156,4 +157,4 @@ build/temp/
# eof
# eof

View File

@@ -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/"
}
};

View File

@@ -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);
});

View File

@@ -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);
});

View File

@@ -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;
});

View File

@@ -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);
});

View File

@@ -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();
});

View File

@@ -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);
});

View File

@@ -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;
});

View File

@@ -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;
});

View File

@@ -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();
});

View File

@@ -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;
});

View File

@@ -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;
});

View File

@@ -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');
};

View File

@@ -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");
};

View File

@@ -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");
}

View File

@@ -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));
};

View File

@@ -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"
}
}