From 100314dfd7e301d4c7fb5cd8892b5eae2baab1be Mon Sep 17 00:00:00 2001 From: printempw Date: Thu, 19 Jan 2017 22:54:47 +0800 Subject: [PATCH] use babel to compile ES6 scripts to ES5 --- app/helpers.php | 1 - gulpfile.js | 120 +++++++++----- package.json | 2 + resources/assets/src/js/general.js | 250 ++++++++++++++++++++++++----- resources/assets/src/js/utils.js | 176 -------------------- resources/lang/en/locale.js | 4 +- resources/lang/zh_CN/locale.js | 4 +- 7 files changed, 294 insertions(+), 263 deletions(-) delete mode 100644 resources/assets/src/js/utils.js diff --git a/app/helpers.php b/app/helpers.php index d3f7e07b..5fa040f4 100644 --- a/app/helpers.php +++ b/app/helpers.php @@ -99,7 +99,6 @@ if (! function_exists('bs_footer')) { $scripts = [ assets('js/app.min.js'), assets('lang/'.config('app.locale').'/locale.js'), - assets('js/general.js') ]; if ($page_identification !== "") { diff --git a/gulpfile.js b/gulpfile.js index 1c098792..4e509a14 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -2,24 +2,26 @@ * @Author: printempw * @Date: 2016-07-21 13:38:26 * @Last Modified by: printempw -* @Last Modified time: 2017-01-18 23:04:20 +* @Last Modified time: 2017-01-19 23:07:05 */ 'use strict'; -let gulp = require('gulp'), +var gulp = require('gulp'), + babel = require('gulp-babel'), elixir = require('laravel-elixir'), uglify = require('gulp-uglify'), sass = require('gulp-sass'), cleanCss = require('gulp-clean-css'), del = require('del'), - zip = require('gulp-zip'); + zip = require('gulp-zip'), + notify = require('gulp-notify'); require('laravel-elixir-replace'); let version = require('./package.json').version; -let vendor_js = [ +let vendorJs = [ 'jquery/dist/jquery.min.js', 'bootstrap/dist/js/bootstrap.min.js', 'AdminLTE/dist/js/app.min.js', @@ -28,11 +30,11 @@ let vendor_js = [ 'AdminLTE/plugins/datatables/dataTables.bootstrap.min.js', 'iCheck/icheck.min.js', 'toastr/toastr.min.js', + 'es6-promise/es6-promise.auto.min.js', 'sweetalert2/dist/sweetalert2.min.js', - 'es6-promise/es6-promise.min.js' ]; -let vendor_css = [ +let vendorCss = [ 'bootstrap/dist/css/bootstrap.min.css', 'AdminLTE/dist/css/AdminLTE.min.css', 'AdminLTE/plugins/datatables/dataTables.bootstrap.css', @@ -40,72 +42,67 @@ let vendor_css = [ 'font-awesome/css/font-awesome.min.css', 'iCheck/skins/square/blue.css', 'toastr/toastr.min.css', - 'sweetalert2/dist/sweetalert2.min.css' + 'sweetalert2/dist/sweetalert2.min.css', ]; let replacements = [ - ['@import url(https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,300italic,400italic,600italic);', ''], - ['../fonts/glyphicons', '../fonts/glyphicons'], - ['../fonts/fontawesome', '../fonts/fontawesome'], ['blue.png', '"../images/blue.png"'], ['blue@2x.png', '"../images/blue@2x.png"'], + ['../fonts/glyphicons', '../fonts/glyphicons'], + ['../fonts/fontawesome', '../fonts/fontawesome'], ['../img/loading.gif', '"../images/loading.gif"'], - ['../img/loading-sm.gif', '"../images/loading-sm.gif"'] + ['../img/loading-sm.gif', '"../images/loading-sm.gif"'], + ['@import url(https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,300italic,400italic,600italic);', ''], +]; + +let fonts = [ + 'font-awesome/fonts/**', + 'bootstrap/dist/fonts/**', +]; + +let images = [ + 'iCheck/skins/square/blue.png', + 'iCheck/skins/square/blue@2x.png', + 'bootstrap-fileinput/img/loading.gif', + 'bootstrap-fileinput/img/loading-sm.gif', ]; elixir.config.sourcemaps = false; elixir((mix) => { - mix - .scripts(vendor_js.map((js) => 'resources/assets/src/bower_components/' + js).concat([ - 'resources/assets/src/js/utils.js' + mix // compile sass files & ES6 scripts first + .task('compile-sass') + .task('compile-es6') + + .scripts(convertRelativePath(vendorJs).concat([ + 'resources/assets/dist/js/general.js' ]), 'resources/assets/dist/js/app.min.js', './') - .styles(vendor_css.map((css) => 'resources/assets/src/bower_components/' + css), 'resources/assets/dist/css/app.min.css', './') + .styles(convertRelativePath(vendorCss), 'resources/assets/dist/css/app.min.css', './') .replace('resources/assets/dist/css/app.min.css', replacements) // copy fonts & images - .copy([ - 'resources/assets/src/bower_components/bootstrap/dist/fonts/**', - 'resources/assets/src/bower_components/font-awesome/fonts/**' - ], 'resources/assets/dist/fonts/') - .copy([ - 'resources/assets/src/bower_components/iCheck/skins/square/blue.png', - 'resources/assets/src/bower_components/iCheck/skins/square/blue@2x.png', - 'resources/assets/src/bower_components/bootstrap-fileinput/img/loading.gif', - 'resources/assets/src/bower_components/bootstrap-fileinput/img/loading-sm.gif' - ], 'resources/assets/dist/images/') - - .task('sass') - .task('uglify'); + .copy(convertRelativePath(fonts), 'resources/assets/dist/fonts/') + .copy(convertRelativePath(images), 'resources/assets/dist/images/'); }); // compile sass -gulp.task('sass', () => { +gulp.task('compile-sass', () => { gulp.src('resources/assets/src/sass/*.scss') .pipe(sass().on('error', sass.logError)) .pipe(cleanCss()) .pipe(gulp.dest('./resources/assets/dist/css')); }); -gulp.task('uglify', () => { +gulp.task('compile-es6', () => { gulp.src('resources/assets/src/js/*.js') + .pipe(babel({ + presets: ['es2015'] + })) .pipe(uglify()) .pipe(gulp.dest('./resources/assets/dist/js')); }); -function clearCache() { - return del([ - 'storage/logs/*', - 'storage/debugbar/*', - 'storage/update_cache/*', - 'storage/yaml-translation/*', - 'storage/framework/cache/*', - 'storage/framework/sessions/*', - 'storage/framework/views/*' - ]); -} - // delete cache files gulp.task('clear', () => { clearCache(); @@ -115,6 +112,14 @@ gulp.task('clear', () => { gulp.task('zip', () => { clearCache(); + console.info("============================================================================") + console.info("= Don't forget to compile Sass & ES2015 files before publishing a release! ="); + console.info("============================================================================") + + let zipPath = `blessing-skin-server-v${version}.zip`; + + console.log(`Zip archive will be saved to ${zipPath}.`); + return gulp.src([ '**/*.*', 'LICENSE', @@ -144,6 +149,33 @@ gulp.task('zip', () => { '!vendor/symfony/css-selector/**/*.*', '!vendor/symfony/dom-crawler/**/*.*' ], { dot: true }) - .pipe(zip('blessing-skin-server-v'+version+'.zip')) - .pipe(gulp.dest('../')); + .pipe(zip(zipPath)) + .pipe(gulp.dest('../')) + .pipe(notify({ message: `Zip archive saved to ${zipPath}!` })); }); + +gulp.task('notify') + +gulp.task('watch', () => { + // Watch .scss files + gulp.watch('resources/assets/src/sass/*.scss', ['compile-sass'], () => notify({ message: 'Sass files compiled!' })); + // Watch .js files + gulp.watch('resources/assets/src/js/*.js', ['compile-es6'], () => notify({ message: 'ES6 scripts compiled!' })); + gulp.watch('resources/assets/src/js/general.js', ['scripts']); +}); + +function convertRelativePath(paths) { + return paths.map(relativePath => 'resources/assets/src/bower_components/' + relativePath); +} + +function clearCache() { + return del([ + 'storage/logs/*', + 'storage/debugbar/*', + 'storage/update_cache/*', + 'storage/yaml-translation/*', + 'storage/framework/cache/*', + 'storage/framework/sessions/*', + 'storage/framework/views/*' + ]); +} diff --git a/package.json b/package.json index f433c147..74dbe3cc 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,9 @@ "dev": "gulp watch" }, "devDependencies": { + "babel-preset-es2015": "^6.18.0", "gulp": "^3.9.1", + "gulp-babel": "^6.1.2", "gulp-clean-css": "^2.0.11", "gulp-concat": "^2.6.0", "gulp-jshint": "^2.0.1", diff --git a/resources/assets/src/js/general.js b/resources/assets/src/js/general.js index bd30d654..09c5c21f 100644 --- a/resources/assets/src/js/general.js +++ b/resources/assets/src/js/general.js @@ -2,49 +2,227 @@ * @Author: printempw * @Date: 2016-09-15 10:39:41 * @Last Modified by: printempw -* @Last Modified time: 2017-01-18 21:35:01 +* @Last Modified time: 2017-01-19 22:42:44 */ 'use strict'; -function logout(with_out_confirm, callback) { - if (!with_out_confirm) { - swal({ - text: trans('general.confirmLogout'), - type: 'warning', - showCancelButton: true, - confirmButtonText: trans('general.confirm'), - cancelButtonText: trans('general.cancel') - }).then(function() { - do_logout(function(json) { - swal({ - type: 'success', - html: json.msg - }); - window.setTimeout(function() { - window.location = url(); - }, 1000); - }); - }); - } else { - do_logout(function(json) { - if (callback) callback(json); - }); +$.locales = {}; +$.currentLocale = {}; + +/** + * Check if given value is empty. + * + * @param {any} obj + * @return {Boolean} + */ +function isEmpty(obj) { + + // null and undefined are "empty" + if (obj == null) return true; + + // Assume if it has a length property with a non-zero value + // that that property is correct. + if (obj.length > 0) return false; + if (obj.length === 0) return true; + + // If it isn't an object at this point + // it is empty, but it can't be anything *but* empty + // Is it empty? Depends on your application. + if (typeof obj !== "object") return true; + + // Otherwise, does it have any properties of its own? + // Note that this doesn't handle + // toString and valueOf enumeration bugs in IE < 9 + for (var key in obj) { + if (hasOwnProperty.call(obj, key)) return false; + } + + return true; +} + +/** + * Load current selected language. + * + * @return void + */ +function loadLocales() { + for (lang in $.locales) { + if (!isEmpty($.locales[lang])) { + $.currentLocale = $.locales[lang] || {}; + } } } -function do_logout(callback) { - $.ajax({ - type: "POST", - url: url('auth/logout'), - dataType: "json", - success: function(json) { - if (callback) callback(json); - }, - error: showAjaxError +/** + * Translate according to given key. + * + * @param {string} key + * @param {dict} parameters + * @return {string} + */ +function trans(key, parameters = {}) { + if (isEmpty($.currentLocale)) { + loadLocales(); + } + + let segments = key.split('.'); + let temp = $.currentLocale || {}; + + for (i in segments) { + if (isEmpty(temp[segments[i]])) { + return key; + } else { + temp = temp[segments[i]]; + } + } + + for (i in parameters) { + if (!isEmpty(parameters[i])) { + temp = temp.replace(':'+i, parameters[i]); + } + } + + return temp; +} + +function showModal(msg, title = 'Messgae', type = 'default', callback) { + let btnType = (type != "default") ? "btn-outline" : "btn-primary"; + + let dom = ` + `; + + $(dom).modal(); +} + +/** + * Show message to div#msg with level + * + * @param {string} msg + * @param {string} type + * @return {void} + */ +function showMsg(msg, type = 'info') { + $("[id=msg]").removeClass().addClass("callout").addClass('callout-'+type).html(msg); +} + +/** + * Show modal if error occured when sending an ajax request. + * + * @param {object} json + * @return {void} + */ +function showAjaxError(json) { + if (!json.responseText) { + console.warn('Empty Ajax response body.'); + return; + } + + showModal(json.responseText.replace(/\n/g, '
'), trans('general.fatalError'), 'danger'); +} + +/** + * Check if current environment is mobile. + * + * @return {Boolean} + */ +function isMobile() { + if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) { + return true; + } + return false; +} + +/** + * Get parameters in query string with key. + * + * @param {string} key + * @return {string} + */ +function getQueryString(key) { + result = location.search.match(new RegExp('[\?\&]'+key+'=([^\&]+)','i')); + + if (result == null || result.length < 1){ + return ""; + } else { + return result[1]; + } +} + +// quick fix for compatibility of String.prototype.endsWith +if (!String.prototype.endsWith) { + String.prototype.endsWith = function (searchString, position) { + var subjectString = this.toString(); + if (typeof position !== 'number' || !isFinite(position) || Math.floor(position) !== position || position > subjectString.length) { + position = subjectString.length; + } + position -= searchString.length; + var lastIndex = subjectString.lastIndexOf(searchString, position); + return lastIndex !== -1 && lastIndex === position; + }; +} + +function url(relativeUri) { + relativeUri = relativeUri || ""; + blessing.base_url = blessing.base_url || ""; + + if (relativeUri[0] != "/") { + relativeUri = "/" + relativeUri; + } + + return blessing.base_url + relativeUri; +} + +function confirmLogout() { + swal({ + text: trans('general.confirmLogout'), + type: 'warning', + showCancelButton: true, + confirmButtonText: trans('general.confirm'), + cancelButtonText: trans('general.cancel') + }).then(() => { + logout().then((json) => { + swal({ + type: 'success', + html: json.msg + }); + window.setTimeout(() => window.location = url(), 1000); + }); }); } -$(document).ready(function() { - $('li.active > ul').show(); -}); +function logout() { + return new Promise((resolve, reject) => { + $.ajax({ + type: "POST", + url: url('auth/logout'), + dataType: "json", + success: (json) => resolve(json), + error: (json) => { + showAjaxError(json); + reject(json); + } + }); + }); +} + +$('#logout-button').click(() => confirmLogout()); + +$(document).ready(() => $('li.active > ul').show()); diff --git a/resources/assets/src/js/utils.js b/resources/assets/src/js/utils.js deleted file mode 100644 index 1b579cc6..00000000 --- a/resources/assets/src/js/utils.js +++ /dev/null @@ -1,176 +0,0 @@ -/* - * @Author: printempw - * @Date: 2016-07-16 09:02:32 - * @Last Modified by: printempw - * @Last Modified time: 2017-01-18 21:36:24 - */ - -$.locales = {}; - -var locale = {}; - -/** - * Check if given value is empty. - * - * @param {any} obj - * @return {Boolean} - */ -function isEmpty(obj) { - - // null and undefined are "empty" - if (obj == null) return true; - - // Assume if it has a length property with a non-zero value - // that that property is correct. - if (obj.length > 0) return false; - if (obj.length === 0) return true; - - // If it isn't an object at this point - // it is empty, but it can't be anything *but* empty - // Is it empty? Depends on your application. - if (typeof obj !== "object") return true; - - // Otherwise, does it have any properties of its own? - // Note that this doesn't handle - // toString and valueOf enumeration bugs in IE < 9 - for (var key in obj) { - if (hasOwnProperty.call(obj, key)) return false; - } - - return true; -} - -/** - * Load current selected language. - * - * @return void - */ -function loadLocales() { - for (lang in $.locales) { - if (!isEmpty($.locales[lang])) { - locale = $.locales[lang] || {}; - } - } -} - -/** - * Translate according to given key. - * - * @param {string} key - * @param {dict} parameters - * @return {string} - */ -function trans(key, parameters) { - if (isEmpty(locale)) { - loadLocales(); - } - - parameters = parameters || {}; - - var segments = key.split('.'); - var temp = locale || {}; - - for (i in segments) { - if (isEmpty(temp[segments[i]])) { - return key; - } else { - temp = temp[segments[i]]; - } - } - - for (i in parameters) { - if (!isEmpty(parameters[i])) { - temp = temp.replace(':'+i, parameters[i]); - } - } - - return temp; -} - -function showModal(msg, title, type, callback) { - title = title === undefined ? "Messgae" : title; - type = type === undefined ? "default" : type; - callback = callback === undefined ? 'data-dismiss="modal"' : 'onclick="'+callback+'"'; - var btn_type = (type != "default") ? "btn-outline" : "btn-primary"; - var dom = ''; - $(dom).modal(); -} - -/** - * Show message to div#msg with level - * - * @param {string} msg - * @param {string} type - * @return {void} - */ -function showMsg(msg, type) { - type = (type === undefined) ? "info" : type; - $("[id=msg]").removeClass().addClass("callout").addClass('callout-'+type).html(msg); -} - -/** - * Show modal if error occured when sending an ajax request. - * - * @param {object} json - * @return {void} - */ -function showAjaxError(json) { - if (!json.responseText) { - console.warn('Empty Ajax response body.'); - return; - } - - showModal(json.responseText.replace(/\n/g, '
'), trans('utils.fatalError'), 'danger'); -} - -/** - * Check if current environment is mobile. - * - * @return {Boolean} - */ -function isMobile() { - if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) { - return true; - } - return false; -} - -/** - * Get parameters in query string with key. - * - * @param {string} key - * @return {string} - */ -function getQueryString(key) { - result = location.search.match(new RegExp('[\?\&]'+key+'=([^\&]+)','i')); - - if (result == null || result.length < 1){ - return ""; - } else { - return result[1]; - } -} - -// quick fix for compatibility of String.prototype.endsWith -if (!String.prototype.endsWith) { - String.prototype.endsWith = function(searchString, position) { - var subjectString = this.toString(); - if (typeof position !== 'number' || !isFinite(position) || Math.floor(position) !== position || position > subjectString.length) { - position = subjectString.length; - } - position -= searchString.length; - var lastIndex = subjectString.lastIndexOf(searchString, position); - return lastIndex !== -1 && lastIndex === position; - }; -} - -function url(relativeUri) { - relativeUri = relativeUri || ""; - blessing.base_url = blessing.base_url || ""; - - if (relativeUri[0] != "/") { - relativeUri = "/" + relativeUri; - } - - return blessing.base_url + relativeUri; -} diff --git a/resources/lang/en/locale.js b/resources/lang/en/locale.js index 426f0d59..19c44730 100644 --- a/resources/lang/en/locale.js +++ b/resources/lang/en/locale.js @@ -138,10 +138,8 @@ downloadCompleted: 'Update package download completed.', extracting: 'Extracting update package..' }, - utils: { - fatalError: 'Fatal Error (Please contact the author)' - }, general: { + fatalError: 'Fatal Error (Please contact the author)', confirmLogout: 'Sure to log out?', confirm: 'OK', cancel: 'Cancel' diff --git a/resources/lang/zh_CN/locale.js b/resources/lang/zh_CN/locale.js index 0482e0da..334d212d 100644 --- a/resources/lang/zh_CN/locale.js +++ b/resources/lang/zh_CN/locale.js @@ -138,10 +138,8 @@ downloadCompleted: '更新包下载完成', extracting: '正在解压更新包' }, - utils: { - fatalError: '严重错误(请联系作者)' - }, general: { + fatalError: '严重错误(请联系作者)', confirmLogout: '确定要登出吗?', confirm: '确定', cancel: '取消'