-
Benoit Lavenier authored
[fix] Fix missing i18n (ES) [enh] Market search: use 50km by default
Benoit Lavenier authored[fix] Fix missing i18n (ES) [enh] Market search: use 50km by default
gulpfile.js 43.40 KiB
'use strict';
const gulp = require('gulp'),
path = require("path"),
sass = require('gulp-sass'),
cleanCss = require('gulp-clean-css'),
base64 = require('gulp-base64-v2'),
rename = require('gulp-rename'),
ngConstant = require('gulp-ng-constant'),
fs = require("fs"),
header = require('gulp-header'),
footer = require('gulp-footer'),
removeCode = require('gulp-remove-code'),
removeHtml = require('gulp-html-remove'),
templateCache = require('gulp-angular-templatecache'),
ngTranslate = require('gulp-angular-translate'),
ngAnnotate = require('gulp-ng-annotate'),
zip = require('gulp-zip'),
del = require('del'),
debug = require('gulp-debug'),
useref = require('gulp-useref'),
filter = require('gulp-filter'),
uglify = require('gulp-uglify-es').default,
sourcemaps = require('gulp-sourcemaps'),
lazypipe = require('lazypipe'),
csso = require('gulp-csso'),
replace = require('gulp-replace'),
clean = require('gulp-clean'),
htmlmin = require('gulp-htmlmin'),
jshint = require('gulp-jshint'),
markdown = require('gulp-markdown'),
merge = require('merge2'),
log = require('fancy-log'),
colors = require('ansi-colors'),
{argv} = require('yargs'),
sriHash = require('gulp-sri-hash'),
sort = require('gulp-sort'),
map = require('map-stream');
// Workaround because @ioni/v1-toolkit use gulp v3.9.2 instead of gulp v4
let jsonlint;
try {
jsonlint = require('@prantlf/gulp-jsonlint');
} catch(e) {
log(colors.red("Cannot load 'gulp-jsonlint'. Retrying using project path"), e);
}
const paths = {
license_md: ['./www/license/*.md'],
sass: ['./scss/ionic.app.scss'],
config: ['./app/config.json'],
templatecache: ['./www/templates/**/*.html'],
ng_translate: ['./www/i18n/locale-*.json'],
ng_annotate: ['./www/js/**/*.js', '!./www/js/vendor/*.js'],
// plugins:
leafletSass: ['./scss/leaflet.app.scss'],
css_plugin: ['./www/plugins/*/css/**/*.css'],
templatecache_plugin: ['./www/plugins/*/templates/**/*.html'],
ng_translate_plugin: ['./www/plugins/*/i18n/locale-*.json'],
ng_annotate_plugin: ['./www/plugins/*/**/*.js', '!./www/plugins/*/js/vendor/*.js']
};
const uglifyBaseOptions = {
toplevel: true,
warnings: true,
mangle: {
reserved: ['qrcode', 'Base58']
},
compress: {
global_defs: {
"@console.log": "alert"
},
passes: 2
},
output: {
beautify: false,
preamble: "/* minified */",
max_line_len: 120000
}
};
const debugBaseOptions = {
title: 'Processing',
minimal: true,
showFiles: argv.debug || false,
showCount: argv.debug || false,
logger: m => log(colors.grey(m))
};
function appAndPluginWatch(done) {
log(colors.green('Watching source files...'));
// Licenses
gulp.watch(paths.license_md, () => appLicense());
// App
gulp.watch(paths.sass, () => appSass());
gulp.watch(paths.templatecache, () => appNgTemplate());
gulp.watch(paths.ng_annotate, (event) => appNgAnnotate(event));
gulp.watch(paths.ng_translate, () => appNgTranslate());
// Plugins
gulp.watch(paths.templatecache_plugin, () => pluginNgTemplate());
gulp.watch(paths.ng_annotate_plugin, (event) => pluginNgAnnotate(event));
gulp.watch(paths.ng_translate_plugin, () => pluginNgTranslate());
gulp.watch(paths.css_plugin.concat(paths.leafletSass), () => pluginSass());
if (done) done();
}
function appAndPluginClean() {
return del([
'./www/dist',
'./www/css/ionic.app*.css',
'./www/css/leaflet.app*.css'
]);
}
/**
* Generate App CSS (using SASS)
* @returns {*}
*/
function appSass() {
log(colors.green('Building App Sass...'));
// Default App style
return gulp.src('./scss/ionic.app.scss')
.pipe(sass()).on('error', sass.logError)
.pipe(base64({
baseDir: "./www/css",
extensions: ['svg', 'png', 'gif', /\.jpg#datauri$/i],
maxImageSize: 14 * 1024
}))
.pipe(gulp.dest('./www/css/'))
.pipe(cleanCss({
keepSpecialComments: 0
}))
.pipe(rename({ extname: '.min.css' }))
.pipe(gulp.dest('./www/css/'));
}
function appConfig() {
const allConfig = JSON.parse(fs.readFileSync('./app/config.json', 'utf8'));
// Determine which environment to use when building config.
const env = argv.env || 'default';
const config = allConfig[env];
if (!config) {
throw new Error(colors.red("=> Could not load `" + env + "` environment!"));
}
log(colors.green("Building App config at `www/js/config.js` for `" + env + "` environment..."));
const project = JSON.parse(fs.readFileSync('./package.json', 'utf8'));
config['version'] = project.version;
config['build'] = (new Date()).toJSON();
config['newIssueUrl'] = project.bugs.new;
return ngConstant({
name: 'cesium.config',
constants: {"csConfig": config},
stream: true,
dest: 'config.js'
})
// Add a warning header
.pipe(header("/******\n* !! WARNING: This is a generated file !!\n*\n* PLEASE DO NOT MODIFY DIRECTLY\n*\n* => Changes should be done on file 'app/config.json'.\n******/\n\n"))
// Writes into file www/js/config.js
.pipe(rename('config.js'))
.pipe(gulp.dest('www/js'));
}
function appAndPluginLint(done) {
log(colors.green('Linting JS files...'));
// Copy Js (and remove unused code)
return gulp.src(paths.ng_annotate.concat(paths.ng_annotate_plugin))
.pipe(debug({...debugBaseOptions, title: 'Linting'}))
.pipe(jshint())
.pipe(jshint.reporter(require('jshint-stylish')))
.pipe(map( (file, cb) => {
if (!file.jshint.success) {
console.error('jshint failed');
process.exit(1);
}
}))
.on('end', done);
}
function appNgTemplate() {
log(colors.green('Building template file...'));
return gulp.src(paths.templatecache)
.pipe(sort())
.pipe(templateCache({
standalone: true,
module: "cesium.templates",
root: "templates/"
}))
.pipe(gulp.dest('./www/dist/dist_js/app'));
}
function appNgAnnotate(event) {
// If watch, apply only on changes files
if (event && event.type === 'changed' && event.path && event.path.indexOf('/www/js/') !== -1) {
let path = event.path.substring(event.path.indexOf('/www/js') + 7);
path = path.substring(0, path.lastIndexOf('/'));
return gulp.src(event.path)
.pipe(ngAnnotate({single_quotes: true}))
.pipe(gulp.dest('./www/dist/dist_js/app' + path));
}
log(colors.green('Building JS files...'));
return gulp.src(paths.ng_annotate)
.pipe(ngAnnotate({single_quotes: true}))
.pipe(gulp.dest('./www/dist/dist_js/app'));
}
function appNgTranslate() {
log(colors.green('Building translation file...'));
return gulp.src('www/i18n/locale-*.json')
.pipe(jsonlint())
.pipe(jsonlint.reporter())
.pipe(sort())
.pipe(ngTranslate({standalone:true, module: 'cesium.translations'}))
.pipe(gulp.dest('www/dist/dist_js/app'));
}
function appLicense() {
log(colors.green('Building License files...'));
return merge(
// Copy license into HTML
gulp.src(paths.license_md)
.pipe(markdown())
.pipe(header('<html><header><meta charset="utf-8"></header><body>'))
.pipe(footer('</body></html>'))
.pipe(gulp.dest('www/license')),
// Copy license into txt
gulp.src(paths.license_md)
.pipe(header('\ufeff')) // Need BOM character for UTF-8 files
.pipe(rename({ extname: '.txt' }))
.pipe(gulp.dest('www/license'))
);
}
/* -- Plugins -- */
function pluginNgTemplate() {
log(colors.green('Building Plugins template file...'));
return gulp.src(paths.templatecache_plugin)
.pipe(sort())
.pipe(templateCache({
standalone: true,
module: "cesium.plugins.templates",
root: "plugins/"
}))
.pipe(gulp.dest('./www/dist/dist_js/plugins'));
}
function pluginNgAnnotate(event) {
// If watch, apply only on changes files
if (event && event.type === 'changed' && event.path && event.path.indexOf('/www/js/') !== -1) {
let path = event.path.substring(event.path.indexOf('/www/js') + 7);
path = path.substring(0, path.lastIndexOf('/'));
return gulp.src(event.path)
.pipe(ngAnnotate({single_quotes: true}))
.pipe(gulp.dest('./www/dist/dist_js/app' + path));
}
log(colors.green('Building Plugins JS file...'));
return gulp.src(paths.ng_annotate_plugin)
.pipe(ngAnnotate({single_quotes: true}))
.pipe(gulp.dest('./www/dist/dist_js/plugins'));
}
function pluginNgTranslate() {
log(colors.green('Building Plugins translation file...'));
return gulp.src(paths.ng_translate_plugin)
.pipe(jsonlint())
.pipe(jsonlint.reporter())
.pipe(sort())
.pipe(ngTranslate({standalone:true, module: 'cesium.plugins.translations'}))
.pipe(gulp.dest('www/dist/dist_js/plugins'));
}
function pluginLeafletImages(dest) {
dest = dest || './www/img/';
// Leaflet images
return gulp.src(['scss/leaflet/images/*.*',
'www/lib/leaflet/dist/images/*.*',
'www/lib/leaflet-search/images/*.*',
'!www/lib/leaflet-search/images/back.png',
'!www/lib/leaflet-search/images/leaflet-search.jpg',
'www/lib/leaflet.awesome-markers/dist/images/*.*'],
{read: false, allowEmpty: true}
)
.pipe(gulp.dest(dest));
}
function pluginSass() {
log(colors.green('Building Plugins Sass...'));
return merge(
// Copy plugins CSS
gulp.src(paths.css_plugin)
.pipe(gulp.dest('www/dist/dist_css/plugins')),
// Leaflet images
pluginLeafletImages('./www/img/'),
// Leaflet App style
gulp.src('./scss/leaflet.app.scss')
.pipe(sass()).on('error', sass.logError)
// Fix bad images path
.pipe(replace("url('../images/", "url('../img/"))
.pipe(replace("url(\"../images/", "url(\"../img/"))
.pipe(replace("url('images/", "url('../img/"))
.pipe(replace("url(\"images/", "url(\"../img/"))
.pipe(replace("url(images/", "url(../img/"))
.pipe(base64({
baseDir: "./www/css/",
extensions: ['png', 'gif', /\.jpg#datauri$/i],
maxImageSize: 14 * 1024,
deleteAfterEncoding: false
}))
.pipe(gulp.dest('./www/css/'))
.pipe(cleanCss({
keepSpecialComments: 0
}))
.pipe(rename({ extname: '.min.css' }))
.pipe(gulp.dest('./www/css/'))
);
}
/* --------------------------------------------------------------------------
-- Build the web (ZIP) artifact
--------------------------------------------------------------------------*/
function webClean() {
return del([
'./dist/web/www'
]);
}
function webCopyFiles() {
log(colors.green('Preparing dist/web files...'));
let htmlminOptions = {removeComments: true, collapseWhitespace: true};
const debugOptions = { ...debugBaseOptions, title: 'Copying' };
var targetPath = './dist/web/www';
return merge(
// Copy Js (and remove unused code)
gulp.src('./www/js/**/*.js')
.pipe(debug(debugOptions))
.pipe(removeCode({"no-device": true}))
.pipe(jshint())
.pipe(gulp.dest(targetPath + '/js')),
// Copy HTML templates (and remove unused code)
gulp.src('./www/templates/**/*.html')
.pipe(removeCode({"no-device": true}))
.pipe(removeHtml('.hidden-no-device'))
.pipe(removeHtml('[remove-if][remove-if="no-device"]'))
.pipe(htmlmin(htmlminOptions))
.pipe(gulp.dest(targetPath + '/templates')),
// Copy index.html (and remove unused code)
gulp.src('./www/index.html')
.pipe(removeCode({'no-device': true}))
.pipe(removeHtml('.hidden-no-device'))
.pipe(removeHtml('[remove-if][remove-if="no-device"]'))
.pipe(htmlmin(/*no options, to keep comments*/))
.pipe(gulp.dest(targetPath)),
// Copy API index.html
gulp.src('./www/api/index.html')
.pipe(removeCode({'no-device': true}))
.pipe(removeHtml('.hidden-no-device'))
.pipe(removeHtml('[remove-if][remove-if="no-device"]'))
.pipe(htmlmin())
.pipe(gulp.dest(targetPath + '/api')),
// Copy fonts
gulp.src('./www/fonts/**/*.*')
.pipe(debug(debugOptions))
.pipe(gulp.dest(targetPath + '/fonts')),
// Copy CSS
gulp.src('./www/css/**/*.*')
.pipe(debug(debugOptions))
.pipe(gulp.dest(targetPath + '/css')),
// Copy i18n
gulp.src('./www/i18n/locale-*.json')
.pipe(jsonlint())
.pipe(jsonlint.reporter())
.pipe(sort())
.pipe(ngTranslate({standalone:true, module: 'cesium.translations'}))
.pipe(debug(debugOptions))
.pipe(gulp.dest(targetPath + '/js')),
// Copy img
gulp.src('./www/img/**/*.*')
.pipe(debug(debugOptions))
.pipe(gulp.dest(targetPath + '/img')),
// Copy manifest.json
gulp.src('./www/manifest.json')
.pipe(debug(debugOptions))
.pipe(gulp.dest(targetPath)),
// Copy lib (JS, CSS and fonts)
gulp.src(['./www/lib/**/*.js', './www/lib/**/*.css', './www/lib/**/fonts/**/*.*'])
.pipe(debug(debugOptions))
.pipe(gulp.dest(targetPath + '/lib')),
// Copy license into HTML
gulp.src('./www/license/*.md')
.pipe(markdown())
.pipe(header('<html><header><meta charset="utf-8"></header><body>'))
.pipe(footer('</body></html>'))
.pipe(gulp.dest(targetPath + '/license')),
// Copy license into txt
gulp.src('./www/license/*.md')
.pipe(header('\ufeff')) // Need BOM character for UTF-8 files
.pipe(rename({ extname: '.txt' }))
.pipe(gulp.dest(targetPath + '/license'))
);
}
function webNgTemplate() {
var targetPath = './dist/web/www';
return gulp.src(targetPath + '/templates/**/*.html')
.pipe(sort())
.pipe(templateCache({
standalone: true,
module: "cesium.templates",
root: "templates/"
}))
.pipe(gulp.dest(targetPath + '/dist/dist_js/app'));
}
function webAppNgAnnotate() {
var targetPath = './dist/web/www';
var jsFilter = filter(["**/*.js", "!**/vendor/*"]);
return gulp.src(targetPath + '/js/**/*.js')
.pipe(jsFilter)
.pipe(ngAnnotate({single_quotes: true}))
.pipe(gulp.dest(targetPath + '/dist/dist_js/app'));
}
function webPluginCopyFiles() {
const targetPath = './dist/web/www';
return merge(
// Copy Js (and remove unused code)
gulp.src('./www/plugins/**/*.js')
.pipe(removeCode({"no-device": true}))
.pipe(jshint())
.pipe(gulp.dest(targetPath + '/plugins')),
// Copy HTML templates (and remove unused code)
gulp.src('./www/plugins/**/*.html')
.pipe(removeCode({"no-device": true}))
.pipe(removeHtml('.hidden-no-device'))
.pipe(removeHtml('[remove-if][remove-if="no-device"]'))
.pipe(htmlmin())
.pipe(gulp.dest(targetPath + '/plugins')),
// Transform i18n into JS
gulp.src(paths.ng_translate_plugin)
.pipe(jsonlint())
.pipe(jsonlint.reporter())
.pipe(sort())
.pipe(ngTranslate({standalone:true, module: 'cesium.plugins.translations'}))
.pipe(gulp.dest(targetPath + '/dist/dist_js/plugins')),
// Copy plugin CSS
gulp.src(paths.css_plugin)
.pipe(gulp.dest(targetPath + '/dist/dist_css/plugins')),
// Copy Leaflet images
pluginLeafletImages(targetPath + '/img'),
// Copy Leaflet CSS
gulp.src('./www/css/**/leaflet.*')
.pipe(gulp.dest(targetPath + '/css'))
);
}
function webPluginNgTemplate() {
var targetPath = './dist/web/www';
return gulp.src(targetPath + '/plugins/**/*.html')
.pipe(sort())
.pipe(templateCache({
standalone: true,
module: "cesium.plugins.templates",
root: "plugins/"
}))
.pipe(gulp.dest(targetPath + '/dist/dist_js/plugins'));
}
function webPluginNgAnnotate() {
var targetPath = './dist/web/www';
return gulp.src(targetPath + '/plugins/**/*.js')
.pipe(ngAnnotate({single_quotes: true}))
.pipe(gulp.dest(targetPath + '/dist/dist_js/plugins'));
}
function webUglify() {
const targetPath = './dist/web/www';
const enableUglify = argv.release || argv.uglify || false;
const version = JSON.parse(fs.readFileSync('./package.json', 'utf8')).version;
if (enableUglify) {
log(colors.green('Minify JS and CSS files...'));
const indexFilter = filter('**/index.html', {restore: true});
const jsFilter = filter(["**/*.js", '!**/config.js'], {restore: true});
const cssFilter = filter("**/*.css", {restore: true});
// Process index.html
return gulp.src(targetPath + '/index.html')
.pipe(useref({}, lazypipe().pipe(sourcemaps.init, { loadMaps: true }))) // Concatenate with gulp-useref
// Process JS
.pipe(jsFilter)
.pipe(uglify(uglifyBaseOptions)) // Minify javascript files
.pipe(jsFilter.restore)
// Process CSS
.pipe(cssFilter)
.pipe(csso()) // Minify any CSS sources
.pipe(cssFilter.restore)
// Add version to file path
.pipe(indexFilter)
.pipe(replace(/"(dist_js\/[a-zA-Z0-9]+).js"/g, '"$1.js?v=' + version + '"'))
.pipe(replace(/"(dist_css\/[a-zA-Z0-9]+).css"/g, '"$1.css?v=' + version + '"'))
.pipe(indexFilter.restore)
.pipe(sourcemaps.write('maps'))
.pipe(gulp.dest(targetPath));
}
else {
return Promise.resolve();
}
}
function webIntegrity() {
const targetPath = './dist/web/www';
const enableIntegrity = argv.release || false;
if (enableIntegrity) {
log(colors.green('Create index.integrity.html... '));
// Process index.html
return gulp.src(targetPath + '/index.html', {base: targetPath})
// Add an integrity hash
.pipe(sriHash())
.pipe(rename({ extname: '.integrity.html' }))
.pipe(gulp.dest(targetPath));
}
else {
return Promise.resolve();
}
}
function webApiUglify() {
const targetPath = './dist/web/www';
const version = JSON.parse(fs.readFileSync('./package.json', 'utf8')).version;
const jsFilter = filter(["**/*.js", '!**/config.js'], {restore: true});
const cssFilter = filter("**/*.css", {restore: true});
const indexFilter = filter('**/index.html', {restore: true});
// Skip if not required
const enableUglify = argv.release || argv.uglify || false;
if (enableUglify) {
log(colors.green('API: Minify JS and CSS files...'));
// Process api/index.html
return gulp.src(targetPath + '/*/index.html')
.pipe(useref({}, lazypipe().pipe(sourcemaps.init, { loadMaps: true }))) // Concatenate with gulp-useref
// Process JS
.pipe(jsFilter)
.pipe(uglify(uglifyBaseOptions)) // Minify any javascript sources
.pipe(jsFilter.restore)
// Process CSS
.pipe(cssFilter)
.pipe(csso()) // Minify any CSS sources
.pipe(cssFilter.restore)
.pipe(indexFilter)
// Add version to files path
.pipe(replace(/"(dist_js\/[a-zA-Z0-9-.]+).js"/g, '"$1.js?v=' + version + '"'))
.pipe(replace(/"(dist_css\/[a-zA-Z0-9-.]+).css"/g, '"$1.css?v=' + version + '"'))
.pipe(replace("dist_js", "../dist_js"))
.pipe(replace("dist_css", "../dist_css"))
.pipe(replace("config.js", "../config.js"))
.pipe(indexFilter.restore)
.pipe(sourcemaps.write('maps'))
.pipe(gulp.dest(targetPath));
}
else {
log(colors.red('API: Skipping minify JS and CSS files') + colors.grey(' (missing options --release or --uglify)'));
return gulp.src(targetPath + '/*/index.html')
.pipe(useref()) // Concatenate with gulp-useref
.pipe(indexFilter)
.pipe(replace("dist_js", "../dist_js"))
.pipe(replace("dist_css", "../dist_css"))
.pipe(replace("config.js", "../config.js"))
.pipe(indexFilter.restore)
.pipe(gulp.dest(targetPath));
}
}
function webCleanUnusedFiles(done) {
log(colors.green('Clean unused files...'));
const targetPath = './dist/web/www';
const enableUglify = argv.release || argv.uglify || false;
const cleanSources = enableUglify;
const debugOptions = {...debugBaseOptions,
title: 'Deleting',
showCount: !argv.debug
};
if (cleanSources) {
return merge(
// Clean core JS
gulp.src(targetPath + '/js/**/*.js', {read: false})
.pipe(debug(debugOptions))
.pipe(clean()),
// Clean core CSS
gulp.src(targetPath + '/css/**/*.css', {read: false})
.pipe(debug(debugOptions))
.pipe(clean()),
// Clean plugins JS + CSS
gulp.src(targetPath + '/plugins/**/*.js', {read: false})
.pipe(debug(debugOptions))
.pipe(clean()),
gulp.src(targetPath + '/plugins/**/*.css', {read: false})
.pipe(debug(debugOptions))
.pipe(clean()),
// Unused maps/config.js.map
gulp.src(targetPath + '/maps/config.js.map', {read: false, allowEmpty: true})
.pipe(debug(debugOptions))
.pipe(clean())
)
.on('end', done);
}
if (done) done();
}
function webCleanUnusedDirectories() {
log(colors.green('Clean unused directories...'));
const enableUglify = argv.release || argv.uglify || false;
const debugOptions = { ...debugBaseOptions,
title: 'Deleting',
showCount: !argv.debug
};
// Clean dir
const wwwPath = './dist/web/www';
let patterns = [
wwwPath + '/templates',
wwwPath + '/plugins'
];
if (enableUglify) {
patterns = patterns.concat([
wwwPath + '/js',
wwwPath + '/css',
wwwPath + '/dist',
wwwPath + '/lib/*',
// Keep IonIcons font
'!' + wwwPath + '/lib/ionic',
wwwPath + '/lib/ionic/*',
'!' + wwwPath + '/lib/ionic/fonts',
// Keep RobotoDraft font
'!' + wwwPath + '/lib/robotodraft',
wwwPath + '/lib/robotodraft/*',
'!' + wwwPath + '/lib/robotodraft/fonts'
]);
}
else {
patterns = patterns.concat([
wwwPath + '/js/*',
'!' + wwwPath + '/js/vendor',
wwwPath + '/dist_css',
wwwPath + '/dist_js'
]);
}
return gulp.src(patterns, {read: false, allowEmpty: true})
.pipe(debug(debugOptions))
.pipe(clean());
}
function webZip() {
const tmpPath = './dist/web/www';
const version = JSON.parse(fs.readFileSync('./package.json', 'utf8')).version;
const txtFilter = filter(["**/*.txt"], { restore: true });
return gulp.src(tmpPath + '/**/*.*')
// Process TXT files: Add the UTF-8 BOM character
.pipe(txtFilter)
.pipe(header('\ufeff'))
.pipe(txtFilter.restore)
.pipe(zip('cesium-v'+version+'-web.zip'))
.pipe(gulp.dest('./dist/web/build'));
}
function webExtClean() {
return del([
'./dist/web/ext'
]);
}
function webExtCopyFiles() {
const wwwPath = './dist/web/www';
const resourcesPath = './resources/web-ext';
log(colors.green('Copy web extension files...'));
const version = JSON.parse(fs.readFileSync('./package.json', 'utf8')).version;
const manifestFilter = filter(["**/manifest.json"], { restore: true });
const txtFilter = filter(["**/*.txt"], { restore: true });
// Copy files
return gulp.src([
wwwPath + '/**/*',
// Skip API files
'!' + wwwPath + '/api',
'!' + wwwPath + '/dist_js/*-api.js',
'!' + wwwPath + '/dist_css/*-api.css',
'!' + wwwPath + '/maps/dist_js/*-api.js.map',
'!' + wwwPath + '/maps/dist_css/*-api.css.map',
// Skip web manifest
'!' + wwwPath + '/manifest.json',
// Add specific resource (and overwrite the default 'manifest.json')
resourcesPath + '/**/*.*'
])
// Process TXT files: Add the UTF-8 BOM character
.pipe(txtFilter)
.pipe(header('\ufeff'))
.pipe(txtFilter.restore)
// Replace version in 'manifest.json' file
.pipe(manifestFilter)
.pipe(replace(/\"version\": \"[^\"]*\"/, '"version": "' + version + '"'))
.pipe(manifestFilter.restore)
.pipe(gulp.dest('./dist/web/ext'));
}
function webExtensionZip() {
const srcPath = './dist/web/ext';
const distPath = './dist/web/build';
const version = JSON.parse(fs.readFileSync('./package.json', 'utf8')).version;
return gulp.src(srcPath + '/**/*.*')
.pipe(zip('cesium-v'+version+'-extension.zip'))
.pipe(gulp.dest(distPath));
}
function webBuildSuccess(done) {
var version = JSON.parse(fs.readFileSync('./package.json', 'utf8')).version;
log(colors.green("Web artifact created at: 'dist/web/build/cesium-v" + version + "-web.zip'"));
if (done) done();
}
function webExtBuildSuccess(done) {
var version = JSON.parse(fs.readFileSync('./package.json', 'utf8')).version;
log(colors.green("Web extension artifact created at: 'dist/web/build/cesium-v" + version + "-extension.zip'"));
if (done) done();
}
function cdvAddPlatformToBodyTag() {
log(colors.green('Add platform CSS class to <body>... '));
const projectRoot = argv.root || '.';
const platform = argv.platform || 'android';
let wwwPath;
if (platform === 'android') {
wwwPath = path.join(projectRoot, 'platforms', platform, 'app','src','main','assets','www');
} else {
wwwPath = path.join(projectRoot, 'platforms', platform, 'www');
}
const indexPath = path.join(wwwPath, 'index.html');
// no opening body tag, something's wrong
if (!fs.existsSync(indexPath)) throw new Error('Unable to find the file ' + indexPath +'!');
// add the platform class to the body tag
try {
const platformClass = 'platform-' + platform;
const cordovaClass = 'platform-cordova platform-webview';
let html = fs.readFileSync(indexPath, 'utf8');
// get the body tag
let matches = html && html.match(/<body[^>/]+>/gi)
const bodyTag = matches && matches[0];
// no opening body tag, something's wrong
if (!bodyTag) throw new Error('No <body> element found in file ' + indexPath);
if (bodyTag.indexOf(platformClass) > -1) return; // already added
let newBodyTag = '' + bodyTag;
matches = bodyTag.match(/ class=["|'](.*?)["|']/gi);
const classAttr = matches && matches[0];
if (classAttr) {
// body tag has existing class attribute, add the classname
let endingQuote = classAttr.substring(classAttr.length - 1);
let newClassAttr = classAttr.substring(0, classAttr.length - 1);
newClassAttr += ' ' + platformClass + ' ' + cordovaClass + endingQuote;
newBodyTag = newBodyTag.replace(classAttr, newClassAttr);
} else {
// add class attribute to the body tag
newBodyTag = newBodyTag.replace('>', ' class="' + platformClass + ' ' + cordovaClass + '">');
}
html = html.replace(bodyTag, newBodyTag);
fs.writeFileSync(indexPath, html, 'utf8');
return Promise.resolve();
} catch (e) {
return Promise.reject(e);
}
}
function cdvNgAnnotate() {
log(colors.green('Building JS files... '));
const projectRoot = argv.root || '.';
const platform = argv.platform || 'android';
let wwwPath;
if (platform === 'android') {
wwwPath = path.join(projectRoot, 'platforms', platform, 'app','src','main','assets','www');
} else {
wwwPath = path.join(projectRoot, 'platforms', platform, 'www');
}
const jsFilter = filter(["**/*.js", "!**/vendor/*"]);
return merge(
// Ng annotate app JS file
gulp.src(wwwPath + '/js/**/*.js')
.pipe(jsFilter)
.pipe(ngAnnotate({single_quotes: true}))
.pipe(gulp.dest(wwwPath + '/dist/dist_js/app')),
// Ng annotate app JS file
gulp.src(wwwPath + '/plugins/**/*.js')
.pipe(ngAnnotate({single_quotes: true}))
.pipe(gulp.dest(wwwPath + '/dist/dist_js/plugins'))
);
}
function cdvRemoveCode() {
log(colors.green('Removing code... '));
const projectRoot = argv.root || '.';
const platform = argv.platform || 'android';
let wwwPath;
if (platform === 'android') {
wwwPath = path.join(projectRoot, 'platforms', platform, 'app','src','main','assets','www');
} else {
wwwPath = path.join(projectRoot, 'platforms', platform, 'www');
}
const appJsPath = [path.join(wwwPath, 'js', '**', '*.js'),
// Exclude vendor libs
"!" + path.join(wwwPath, 'js', 'vendor', '**', '*.js')];
const pluginPath = path.join(wwwPath, 'plugins', '*');
const pluginJsPath = path.join(pluginPath, '**', '*.js');
// Compute options {device-<platform>: true}
let removeCodeOptions = {};
removeCodeOptions[platform] = true; // = {<platform>: true}
const htmlminOptions = {removeComments: true, collapseWhitespace: true};
const debugOptions = {...debugBaseOptions,
showCount: false
};
// Do not remove desktop code for iOS and macOS (support for tablets and desktop macs)
if (platform !== 'ios' && platform !== 'osx') {
// Removing unused code for device...
return merge(
// Remove unused HTML tags
gulp.src(path.join(wwwPath, 'templates', '**', '*.html'))
.pipe(debug(debugOptions))
.pipe(removeCode({device: true}))
.pipe(removeCode(removeCodeOptions))
.pipe(removeHtml('.hidden-xs.hidden-sm'))
.pipe(removeHtml('.hidden-device'))
.pipe(removeHtml('[remove-if][remove-if="device"]'))
.pipe(htmlmin(htmlminOptions))
.pipe(gulp.dest(wwwPath + '/templates')),
gulp.src(path.join(pluginPath, '**', '*.html'))
.pipe(debug(debugOptions))
.pipe(removeCode({device: true}))
.pipe(removeCode(removeCodeOptions))
.pipe(removeHtml('.hidden-xs.hidden-sm'))
.pipe(removeHtml('.hidden-device'))
.pipe(removeHtml('[remove-if][remove-if="device"]'))
.pipe(htmlmin(htmlminOptions))
.pipe(gulp.dest(pluginPath)),
gulp.src(path.join(wwwPath, 'index.html'))
.pipe(debug(debugOptions))
.pipe(removeCode({device: true}))
.pipe(removeCode(removeCodeOptions))
.pipe(removeHtml('.hidden-xs.hidden-sm'))
.pipe(removeHtml('.hidden-device'))
.pipe(removeHtml('[remove-if][remove-if="device"]'))
.pipe(htmlmin(/*no options, to keep comments*/))
.pipe(gulp.dest(wwwPath)),
// Remove unused JS code + add ng annotations
gulp.src(appJsPath)
.pipe(debug(debugOptions))
.pipe(removeCode({device: true}))
.pipe(removeCode(removeCodeOptions))
.pipe(ngAnnotate({single_quotes: true}))
.pipe(gulp.dest(wwwPath + '/dist/dist_js/app')),
gulp.src(pluginJsPath)
.pipe(debug(debugOptions))
.pipe(removeCode({device: true}))
.pipe(removeCode(removeCodeOptions))
.pipe(ngAnnotate({single_quotes: true}))
.pipe(gulp.dest(wwwPath + '/dist/dist_js/plugins'))
);
} else {
return merge(
gulp.src(path.join(wwwPath, 'templates', '**', '*.html'))
.pipe(debug(debugOptions))
.pipe(htmlmin(htmlminOptions))
.pipe(gulp.dest(wwwPath + '/templates')),
gulp.src(path.join(pluginPath, '**', '*.html'))
.pipe(debug(debugOptions))
.pipe(htmlmin(htmlminOptions))
.pipe(gulp.dest(pluginPath)),
gulp.src(path.join(wwwPath, 'index.html'))
.pipe(gulp.dest(wwwPath)),
gulp.src(appJsPath)
.pipe(debug(debugOptions))
.pipe(ngAnnotate({single_quotes: true}))
.pipe(gulp.dest(wwwPath + '/dist/dist_js/app')),
gulp.src(pluginJsPath)
.pipe(debug(debugOptions))
.pipe(gulp.dest(wwwPath + '/dist/dist_js/plugins'))
);
}
}
function cdvNgTemplate() {
log(colors.green('Building template files...'));
const projectRoot = argv.root || '.';
const platform = argv.platform || 'android';
let wwwPath;
if (platform === 'android') {
wwwPath = path.join(projectRoot, 'platforms', platform, 'app','src','main','assets','www');
} else {
wwwPath = path.join(projectRoot, 'platforms', platform, 'www');
}
let distJsPath = path.join(wwwPath, 'dist', 'dist_js', 'app');
let pluginDistJsPath = path.join(wwwPath, 'dist', 'dist_js', 'plugins');
const debugOptions = { ...debugBaseOptions,
showCount: false
};
// Concat templates into a JS
return merge(
gulp.src(path.join(wwwPath, 'templates', '**', '*.html'))
.pipe(debug(debugOptions))
.pipe(templateCache({
standalone: true,
module: "cesium.templates",
root: "templates/"
}))
.pipe(gulp.dest(distJsPath)),
gulp.src(path.join(wwwPath, 'plugins', '*', 'templates', '**', '*.html'))
.pipe(debug(debugOptions))
.pipe(templateCache({
standalone: true,
module: "cesium.plugins.templates",
root: "plugins/"
}))
.pipe(gulp.dest(pluginDistJsPath))
);
}
function cdvNgTranslate() {
log(colors.green('Building translation files...'));
const projectRoot = argv.root || '.';
const platform = argv.platform || 'android';
let wwwPath;
if (platform === 'android') {
wwwPath = path.join(projectRoot, 'platforms', platform, 'app', 'src', 'main', 'assets', 'www');
} else {
wwwPath = path.join(projectRoot, 'platforms', platform, 'www');
}
let distJsPath = path.join(wwwPath, 'dist', 'dist_js', 'app');
let pluginDistJsPath = path.join(wwwPath, 'dist', 'dist_js', 'plugins');
const debugOptions = {
title: 'Processing',
minimal: true,
showFiles: argv.debug || false,
showCount: false,
logger: m => log(colors.grey(m))
};
// Concat templates into a JS
return merge(
gulp.src(wwwPath + '/i18n/locale-*.json')
.pipe(debug(debugOptions))
.pipe(ngTranslate({standalone: true, module: 'cesium.translations'}))
.pipe(gulp.dest(distJsPath)),
gulp.src(wwwPath + '/plugins/*/i18n/locale-*.json')
.pipe(debug(debugOptions))
.pipe(ngTranslate({standalone: true, module: 'cesium.plugins.translations'}))
.pipe(gulp.dest(pluginDistJsPath))
);
}
function cdvUglify() {
const projectRoot = argv.root || '.';
const platform = argv.platform || 'android';
let wwwPath;
if (platform === 'android') {
wwwPath = path.join(projectRoot, 'platforms', platform, 'app', 'src', 'main', 'assets', 'www');
} else {
wwwPath = path.join(projectRoot, 'platforms', platform, 'www');
}
let indexPath = path.join(wwwPath, 'index.html');
// Skip if not required
const enableUglify = argv.release || argv.uglify || false;
if (enableUglify) {
log(colors.green('Minify JS and CSS files...'));
// WARN: uglify only libs, to keep sources readable (need by free repo)
const jsLibFilter = filter(['*/lib/**/*.js', '*/js/vendor/**/*.js'], {restore: true}); // External libs only
const cssFilter = filter("**/*.css", {restore: true});
const cdvUglifyOptions = {
...uglifyBaseOptions,
ecma: '5'
};
const debugOptions = { ...debugBaseOptions,
title: 'Minifying',
showCount: false
};
return gulp.src(indexPath)
.pipe(useref()) // Concatenate with gulp-useref
// Process JS
.pipe(jsLibFilter)
.pipe(debug(debugOptions))
.pipe(uglify(cdvUglifyOptions))// Minify javascript sources
.pipe(jsLibFilter.restore)
// Process CSS
.pipe(cssFilter)
.pipe(debug(debugOptions))
.pipe(csso()) // Minify any CSS sources
.pipe(cssFilter.restore)
.pipe(gulp.dest(wwwPath));
}
else {
log(colors.red('Skipping minify JS and CSS files') + colors.grey(' (missing options --release or --uglify)'));
return Promise.resolve();
}
}
function cdvCleanUnusedDirectories() {
log(colors.green('Clean unused directories...'));
const projectRoot = argv.root || '.';
const platform = argv.platform || 'android';
let wwwPath;
if (platform === 'android') {
wwwPath = path.join(projectRoot, 'platforms', platform, 'app', 'src', 'main', 'assets', 'www');
} else {
wwwPath = path.join(projectRoot, 'platforms', platform, 'www');
}
const enableUglify = argv.release || argv.uglify || false;
const debugOptions = {
title: 'Deleting',
minimal: true,
showFiles: argv.debug || false,
showCount: !argv.debug,
logger: m => log(colors.grey(m))
};
let patterns = [
wwwPath + '/api',
// Remove HTML templates - replaced by ngTemplate()
wwwPath + '/templates',
// Remove Cesium plugins
// (WARN: remove one by one, to keep Cordova plugins)
wwwPath + '/plugins/es',
wwwPath + '/plugins/graph',
wwwPath + '/plugins/map',
wwwPath + '/plugins/rml9',
// Remove translations - replaced by ngTranslate()
wwwPath + '/**/i18n',
];
if (enableUglify) {
patterns = patterns.concat([
wwwPath + '/js',
wwwPath + '/css', // Have been replaced by useref(), into 'dist_css'
wwwPath + '/dist', // Have been replaced by useref(), into 'dist_js'
wwwPath + '/cordova-js-src',
// Clean lib directory...
wwwPath + '/lib/*',
// ...but Keep IonIcons font
'!' + wwwPath + '/lib/ionic',
wwwPath + '/lib/ionic/*',
'!' + wwwPath + '/lib/ionic/fonts',
// ...but Keep RobotoDraft font
'!' + wwwPath + '/lib/robotodraft',
wwwPath + '/lib/robotodraft/*',
'!' + wwwPath + '/lib/robotodraft/fonts'
]);
}
else {
patterns = patterns.concat([
wwwPath + '/js/*', // Have been replace into dist/dist_js
'!' + wwwPath + '/js/vendor', // BUT keep vendor lib
]);
}
return gulp.src(patterns, {read: false, allowEmpty: true})
.pipe(debug(debugOptions))
.pipe(clean());
}
function cdvCopyBuildFiles() {
log(colors.green('Copy build files... '));
const projectRoot = argv.root || '.';
const platform = argv.platform || 'android';
const srcPath = path.join(projectRoot, 'resources', platform, 'build');
const targetPath = path.join(projectRoot, 'platforms', platform);
const debugOptions = { ...debugBaseOptions, title: 'Copying',
showFiles: argv.debug || false,
showCount: !argv.debug
};
if (fs.existsSync(srcPath)) {
return gulp.src(srcPath + '/**/*.*')
.pipe(debug(debugOptions))
.pipe(gulp.dest(targetPath));
}
else {
log(colors.blue(' Directory ' + srcPath + 'not found. Skipping copy to ' + targetPath));
return Promise.resolve();
}
}
function cdvAndroidManifest() {
const projectRoot = argv.root || '.';
const platform = argv.platform || 'android';
if (platform !== 'android') return Promise.resolve(); // Skip
const srcMainPath = path.join(projectRoot, 'platforms', platform, 'app', 'src', 'main');
const androidManifestFile = path.join(srcMainPath, 'AndroidManifest.xml');
log(colors.green('Patch Android manifest... ') + colors.grey(androidManifestFile));
if (!fs.existsSync(androidManifestFile)) {
throw Error("Missing required file " + androidManifestFile);
}
return gulp.src(androidManifestFile)
// Add 'tools' namespace to root tag
.pipe(replace(/(xmlns:android="http:\/\/schemas.android.com\/apk\/res\/android")\s*>/g, '$1 xmlns:tools="http://schemas.android.com/tools">'))
// Use AndroidX
.pipe(replace(/\s+tools:replace="android:appComponentFactory"/, ''))
.pipe(replace(/\s+android:appComponentFactory="[^"]+"/, ''))
.pipe(replace(/(\s*<application)\s*/, '$1 tools:replace="android:appComponentFactory" android:appComponentFactory="androidx.core.app.CoreComponentFactory" '))
// remove all <uses-sdk>
.pipe(replace(/<uses-sdk [^>]+\/>/g, ''))
// add <uses-sdk> (tools:overrideLibrary)
.pipe(replace(/(<\/manifest>)/, ' <uses-sdk tools:overrideLibrary="org.kaliumjni.lib,org.apache.cordova" />\n$1'))
// Add URI scheme web+june
// Patch invalid intent-filter (should be a bug of cordova-plugin-customurlschema)
// FIXME : this cause too many intent-filter are appended, on each build
//.pipe(replace('<data android:host=" " android:pathPrefix="/" android:scheme=" " />', '<data android:scheme="web+june" />'))
.pipe(gulp.dest(srcMainPath));
}
function cdvAndroidCheckSigning() {
const projectRoot = argv.root || '.';
const platform = argv.platform || 'android';
if (platform !== 'android') return Promise.resolve(); // Skip
const targetPath = path.join(projectRoot, 'platforms', platform);
const signingFile = path.join(targetPath, 'release-signing.properties');
// Check signing file exists
if (fs.existsSync(targetPath) && !fs.existsSync(signingFile)) {
log(colors.blue('WARNING: Missing file ' + signingFile));
log(colors.blue(' Please create it manually, otherwise release APK files will NOT be signed! '));
}
return Promise.resolve();
}
function cdvAsHook(wrapper) {
return (done, projectRoot, platform) => {
projectRoot = (typeof projectRoot === 'string' && projectRoot) || argv.root || '.';
platform = ((typeof platform === 'string' && platform) || argv.platform || 'android').toLowerCase();
// Override arguments, to pass it to other tasks
argv.root = projectRoot;
argv.platform = platform;
wrapper(done);
}
}
function help() {
log(colors.green("Usage: gulp {config|webBuild|webExtBuild} OPTIONS"));
log(colors.green(""));
log(colors.green("NAME"));
log(colors.green(""));
log(colors.green(" config --env <config_name> Configure environment (create file `www/config.js`). "));
log(colors.green(" build Build from sources (CSS and JS)"));
log(colors.green(" webBuild Build ZIP artifact"));
log(colors.green(" webExtBuild Build web extension artifact (browser module)"));
log(colors.green(""));
log(colors.green("OPTIONS"));
log(colors.green(""));
log(colors.green(" --release Release build (with uglify and sourcemaps)"));
log(colors.green(" --uglify Build using uglify plugin"));
}
/* --------------------------------------------------------------------------
-- Combine task
--------------------------------------------------------------------------*/
const translate = gulp.series(appNgTranslate, pluginNgTranslate);
const template = gulp.series(appNgTemplate, pluginNgTemplate);
const appAndPluginSass = gulp.series(appSass, pluginSass);
const app = gulp.series(appSass, appNgTemplate, appNgAnnotate, appNgTranslate);
const plugin = gulp.series(pluginSass, pluginNgTemplate, pluginNgAnnotate, pluginNgTranslate);
const build = gulp.series(appLicense, app, plugin);
const webApp = gulp.series(appSass, webCopyFiles, webNgTemplate, webAppNgAnnotate);
const webPlugin = gulp.series(pluginSass, webPluginCopyFiles, webPluginNgTemplate, webPluginNgAnnotate);
const webCompile = gulp.series(
webClean,
webApp,
webPlugin,
webUglify,
webIntegrity,
webApiUglify,
webCleanUnusedFiles,
webCleanUnusedDirectories
);
// note : Do not call config, to keep same config between web and webExt artifacts
const webBuild = gulp.series(
webClean,
webCompile,
webZip,
webBuildSuccess
);
const webExtCompile = gulp.series(
webExtClean,
webCompile,
webExtCopyFiles
);
// note : Do not call config, to keep same config between web and webExt artifacts
const webExtBuild = gulp.series(
webExtCompile,
webExtensionZip,
webExtBuildSuccess
);
/* --------------------------------------------------------------------------
-- Define public tasks
--------------------------------------------------------------------------*/
exports.help = help;
exports.config = appConfig;
exports.license = appLicense;
exports.sass = appAndPluginSass;
exports.translate = translate;
exports.template = template;
exports.clean = appAndPluginClean;
exports.lint = appAndPluginLint;
exports.annotate = gulp.series(appNgAnnotate, pluginNgAnnotate);
exports.watch = appAndPluginWatch;
exports.build = build;
// Web
exports.webClean = webClean;
exports.webCompile = webCompile;
exports.webBuild = webBuild;
exports['build:web'] = exports.webBuild; // Alias
// Web extension
exports.webExtClean = webExtClean;
exports.webExtCompile = webExtCompile;
exports.webExtBuild = webExtBuild;
exports.webExtCopyFiles = webExtCopyFiles;
exports['build:webExt'] = exports.webExtBuild; // Alias
// Cordova (hooks)
const cdvAfterPrepare = gulp.series(
gulp.parallel(cdvNgAnnotate, cdvAddPlatformToBodyTag),
cdvRemoveCode,
gulp.parallel(cdvNgTemplate, cdvNgTranslate),
cdvUglify,
gulp.parallel(cdvCleanUnusedDirectories, cdvCopyBuildFiles),
// Android tasks
gulp.parallel(cdvAndroidManifest, cdvAndroidCheckSigning),
);
exports.cdvAfterPrepare = cdvAsHook(cdvAfterPrepare);
const cdvBeforeCompile = gulp.series(
cdvCleanUnusedDirectories,
cdvCopyBuildFiles,
cdvAndroidManifest,
cdvAndroidCheckSigning
);
exports.cdvBeforeCompile = cdvAsHook(cdvBeforeCompile);
exports.default = gulp.series(appConfig, build);
exports.serveBefore = gulp.series(build, appAndPluginWatch);
exports['ionic:serve:before'] = exports.serveBefore; // Alias need need by @ionic/cli