Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
Loading items

Target

Select target project
  • cordeliaze/cesium
  • pfouque06/cesium
  • wellno1/cesium
  • 1000i100/cesium
  • vincentux/cesium
  • calbasi/cesium
  • thomasbromehead/cesium
  • matograine/cesium
  • clients/cesium-grp/cesium
  • cedricmenec/cesium
  • Pamplemousse/cesium
  • etienneleba/cesium
  • tnntwister/cesium
  • scanlegentil/cesium
  • morvanc/cesium
  • yyy/cesium
  • Axce/cesium
  • Bertrandbenj/cesium
  • Lupus/cesium
  • elmau/cesium
  • MartinDelille/cesium
  • tykayn/cesium
  • numeropi/cesium
  • Vivakvo/cesium
  • pokapow/cesium
  • pini-gh/cesium
  • anam/cesium
  • RavanH/cesium
  • bpresles/cesium
  • am97/cesium
  • tuxmain/cesium
  • jytou/cesium
  • oliviermaurice/cesium
  • 666titi999/cesium
  • Yvv/cesium
35 results
Select Git revision
Loading items
Show changes
Showing
with 1482 additions and 1023 deletions
doc/fr/img/70b2ce88a5e7aa5754f6a771cf5efed3c639a27b.png

4.08 KiB

doc/fr/img/a5078db3abdf71c87f245e948ce94a181b0e0f37.png

69.7 KiB

doc/fr/img/b7c419b33a43f6a43c5b756074ee0c199072f7d1.png

3.53 KiB

doc/fr/img/ceb75301172038e75f5c43b328dd7febd7bedc7e.png

95.3 KiB

doc/fr/img/eca671a6d24b8e11566cfcca11b65e6c9c9c370c.png

193 KiB

doc/fr/img/fef4f4dfe7c2168cb27c9e7f5e399fd547ce774a.png

145 KiB

File deleted
# Nouveautés
Nouveautés (depuis les RML9 du Havre).
> ACTU ! **Version 1.0.0** sortie cette semaine !
## Cesium standard
### Architecture
- Nœuds de données de secours (fallback nodes)
* Configuration via `/config.js`
### Connexion
- Connexion != Authentification
- Connexion par pubkey
- Connexion par fichier de trousseau
### Vue réseau
- Compat Duniter v1.6
- Affichage des nœuds WS2P (public)
- Info du nœud connecté (mode expert uniquement)
### Annuaire
- Nombre de résultats (membres, inscription en attente, etc.)
### Mon Compte
- Info sur les fonctionnalités supplémentaires
### Mes opérations
- Affichage des DU créés
- Date cliquable → ouvre le block
### Ergonomique
- Mobile :
* Rafraichissement par glissé "haut → bas"
* Bouton "Partager/Share" utilise les adresses web
* Gestion de bouton "Retour/Back"
### API de paiement
- Accessible via [/api](https://g1.duniter.fr/api)
- Redirection vers la page appellante
- Génération d'un bouton HTML
## Cesium+ (extension optionnelle)
### Architecture
- Nœuds de données de secours (fallback nodes)
* Configuration via `/config.js`
- Visite guidée (fonctionne à nouveau !)
### Vue réseau
- Avatar sur les nœuds mirroir
- Optimisation des perfs d'affichage
- [Cartes des nœuds](https://g1.duniter.fr/#/app/network/map)
* localisation des IP via [freegeoip.net](http://freegeoip.net)
### Annuaire > Toile de conficance
- [Carte des profiles](https://g1.duniter.fr/#/app/wot/map) (membres, inscriptions en attente, simples portefeuilles)
- Fonction de recherche
- Visite guidée
### Annuaire > Pages
- Page = Identification d'un simple portefeuille
- Type de page : association, entreprise (dont commerce local), institution
- Clef associée != Clef du rédacteur de la page
- [Carte des pages](https://g1.duniter.fr/#/app/wot/pagemap) : séparée des profiles
### Profiles
- Localisation
* Cocher la case : `Apparaitre sur les cartes Cesium ?`
* Résolution de l'adresse via un web service OpenStreetMap
* Nécessaire pour apparaitre dans la carte (sans utiliser des services privateurs)
### Invitations
- Désactivé pour les postulants
- Cartes : réseau, membres, pages
- Gestion des « pages », avec recherche spatiale
### Services en ligne
- Notifications par email : plus dans les SPAM ! :)
### Documents stockés (beta)
- Statistiques sur e nombre de documents (maj toutes les heures) : [#/app/data/stats](https://g1.duniter.fr/#/app/data/stats)
- Explorateur : en cliquant sur [un graph de statistique](https://g1.duniter.fr/#/app/data/stats)
- Suivi des synchro P2P : [#/app/data/synchro](https://g1.duniter.fr/#/app/data/synchro)
## Noeud ElasticSearch (ES)
Géré dans le projet [Duniter4j](https://github.com/duniter/duniter4j)
> Version 1.0 sortie cette semaine !
### Architecture
- Meilleure stabilité !
- Nouveau format des documents (JSON)
* `version : 2`
* Signature sur le `hash`, et non plus sur tout le doc (plus rapide)
- Meilleure gestion du `time`
* Nouveaux controles : refus des dates futures ou trop vielles, etc.
### Synchro P2P
- Utilise la couche réseau de Duniter
* Via `endpoints` avec API : `ES_CORE_API`, `ES_USER_API` ou `ES_USER_SUBSCRIPTION`
- Récupération des données :
* par API HTTP
* et/ou par WebSocket (quasi temps réel)
- Configuration :
* `duniter.p2p.discovery.enable`
* `duniter.p2p.includes.endpoints`
Notes :
- Plusieurs nœuds synchronisés, en production !
- Marqueurs `lu` ou `non lu`: lié à chaque noeud ES
### Nouveaux index
- [docstat/record](https://g1.data.duniter.fr/docstat/record/_search?pretty) : Statistiques sur le nombre de docs
* maj toutes les heures
- [docstat/record](https://g1.data.duniter.fr/page/record/_search?pretty) : Pages
### Documentation
- [Site de documentation technique](http://doc.e-is.pro/duniter4j)
## Privacy policy
Cesium Android allow user to upload user profile (avatar, pictures), when the Cesium+ extension has been enable in settings.
### Cesium+ profile
Privacy policy are :
- Profile data and avatar are public data;
- Profile data and avatar on an [Cesium+ node](https://github.com/duniter/cesium-plus-pod); Open Cesium+ settings to know the node address;
- User can remove profile and avatar (open the Settings page, then use the options menu).
\ No newline at end of file
#!/bin/bash
### Control that the script is run on `dev` branch
branch=`git rev-parse --abbrev-ref HEAD`
if [[ ! "$branch" = "master" ]];
then
echo ">> This script must be run under \`master\` branch"
exit
fi
### Releasing
current=`grep -P "version\": \"\d+.\d+.\d+(\w*)" package.json | grep -oP "\d+.\d+.\d+(\w*)"`
echo "Current version: $current"
case "$1" in
del)
if [[ $2 =~ ^[a-zA-Z0-9_]+:[a-zA-Z0-9_]+$ ]]; then
result=`curl -i 'https://api.github.com/repos/duniter/cesium/releases/tags/v'"$current"''`
release_url=`echo "$result" | grep -P "\"url\": \"[^\"]+" | grep -oP "https://api.github.com/repos/duniter/cesium/releases/\d+"`
if [[ $release_url != "" ]]; then
echo "Deleting existing release..."
curl -XDELETE $release_url -u $2
fi
else
echo "Wrong argument"
echo "Usage:"
echo " > ./github.sh del user:password"
exit
fi
;;
pre|rel)
if [[ $2 =~ ^[a-zA-Z0-9_]+:[a-zA-Z0-9_]+$ && $3 != "" ]]; then
if [[ $1 = "pre" ]]; then
prerelease="true"
else
prerelease="false"
fi
result=`curl -i 'https://api.github.com/repos/duniter/cesium/releases/tags/v'"$current"''`
release_url=`echo "$result" | grep -P "\"url\": \"[^\"]+" | grep -oP "https://api.github.com/repos/duniter/cesium/releases/\d+"`
if [[ $release_url != "" ]]; then
echo "Deleting existing release..."
curl -XDELETE $release_url -u $2
fi
echo "Creating new release..."
result=`curl -i https://api.github.com/repos/duniter/cesium/releases -u $2 -d '{"tag_name": "v'"$current"'","target_commitish": "master","name": "'"$current"'","body": "'"$3"'","draft": false,"prerelease": '"$prerelease"'}'`
upload_url=`echo "$result" | grep -P "\"upload_url\": \"[^\"]+" | grep -oP "https://[a-z0-9/.]+"`
### Sending files
echo "Uploading files to GitHub..."
dirname=`pwd`
curl -i -u $2 -H 'Content-Type: application/zip' -T $dirname/platforms/web/build/cesium-web-$current.zip $upload_url?name=cesium-v$current-web.zip
curl -i -u $2 -H 'Content-Type: application/zip' -T $dirname/platforms/firefoxos/build/package.zip $upload_url?name=cesium-v$current-firefoxos.zip
curl -i -u $2 -H 'Content-Type: application/vnd.android.package-archive' -T $dirname/platforms/android/build/outputs/apk/android-release.apk $upload_url?name=cesium-v$current-android.apk
echo "Successfully uploading files"
release_url=`echo "$result" | grep -P "\"url\": \"[^\"]+" | grep -oP "https://api.github.com/repos/[a-z0-9/.]+"`
echo " -> Release url: $release_url"
else
echo "Wrong arguments"
echo "Usage:"
echo " > ./github.sh pre|rel user:password <release_description>"
echo "With:"
echo " - pre: use for pre-release"
echo " - rel: for full release"
exit
fi
;;
*)
echo "No task given"
;;
esac
'use strict'; 'use strict';
var gulp = require('gulp'); const gulp = require('gulp'),
var gutil = require('gulp-util'); path = require("path"),
var bower = require('bower'); sass = require('gulp-sass')(require('node-sass')),
var concat = require('gulp-concat'); cleanCss = require('gulp-clean-css'),
var path = require("path"); base64 = require('gulp-base64-v2'),
var sass = require('gulp-sass'); rename = require('gulp-rename'),
var cleanCss = require('gulp-clean-css'); ngConstant = require('gulp-ng-constant'),
var base64 = require('gulp-base64'); fs = require("fs"),
var rename = require('gulp-rename'); header = require('gulp-header'),
var sh = require('shelljs'); footer = require('gulp-footer'),
var ngConstant = require('gulp-ng-constant'); removeCode = require('gulp-remove-code'),
var fs = require("fs"); removeHtml = require('gulp-html-remove'),
var argv = require('yargs').argv; templateCache = require('gulp-angular-templatecache'),
var header = require('gulp-header'); ngTranslate = require('gulp-angular-translate'),
var removeCode = require('gulp-remove-code'); ngAnnotate = require('gulp-ng-annotate'),
var removeHtml = require('gulp-html-remove'); zip = require('gulp-zip'),
var templateCache = require('gulp-angular-templatecache'); del = require('del'),
var ngTranslate = require('gulp-angular-translate'); debug = require('gulp-debug'),
var ngAnnotate = require('gulp-ng-annotate'); useref = require('gulp-useref'),
var es = require('event-stream'); filter = require('gulp-filter'),
var zip = require('gulp-zip'); uglify = require('gulp-uglify-es').default,
var del = require('del'); sourcemaps = require('gulp-sourcemaps'),
var useref = require('gulp-useref'); lazypipe = require('lazypipe'),
var filter = require('gulp-filter'); csso = require('gulp-csso'),
var uglify = require('gulp-uglify'); replace = require('gulp-replace'),
var csso = require('gulp-csso'); clean = require('gulp-clean'),
var replace = require('gulp-replace'); htmlmin = require('gulp-htmlmin'),
var rev = require('gulp-rev'); jshint = require('gulp-jshint'),
var revReplace = require('gulp-rev-replace'); markdown = require('gulp-markdown'),
var clean = require('gulp-clean'); merge = require('merge2'),
var htmlmin = require('gulp-htmlmin'); log = require('fancy-log'),
var deleteEmpty = require('delete-empty'); colors = require('ansi-colors'),
var jshint = require('gulp-jshint'); {argv} = require('yargs'),
var sourcemaps = require('gulp-sourcemaps'); sriHash = require('gulp-sri-hash'),
sort = require('gulp-sort'),
var paths = { map = require('map-stream');
sass: ['./scss/**/*.scss'],
// 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'], config: ['./app/config.json'],
templates: ['./www/templates/**/*.html'],
templatecache: ['./www/templates/**/*.html'], templatecache: ['./www/templates/**/*.html'],
ng_translate: ['./www/i18n/locale-*.json'], ng_translate: ['./www/i18n/locale-*.json'],
ng_annotate: ['./www/js/**/*.js', '!./www/js/vendor/*.js'], ng_annotate: ['./www/js/**/*.js', '!./www/js/vendor/*.js'],
// plugins: // plugins:
leafletSass: ['./scss/leaflet.app.scss'],
css_plugin: ['./www/plugins/*/css/**/*.css'],
templatecache_plugin: ['./www/plugins/*/templates/**/*.html'], templatecache_plugin: ['./www/plugins/*/templates/**/*.html'],
ng_translate_plugin: ['./www/plugins/*/i18n/locale-*.json'], ng_translate_plugin: ['./www/plugins/*/i18n/locale-*.json'],
ng_annotate_plugin: ['./www/plugins/*/js/**/*.js', '!./www/plugins/*/js/vendor/*.js'], ng_annotate_plugin: ['./www/plugins/*/**/*.js', '!./www/plugins/*/js/vendor/*.js']
css_plugin: ['./www/plugins/*/css/**/*.css'] };
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 cleanCssOptions = {
specialComments: 0 // new name of 'keepSpecialComments', since 4.0
}
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());
gulp.task('default', ['sass', 'config', 'templatecache', 'ng_translate', 'ng_annotate', if (done) done();
'templatecache_plugin', 'ng_translate_plugin', 'ng_annotate_plugin', 'css_plugin' }
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')
gulp.task('sass', function(done) {
gulp.src('./scss/ionic.app.scss')
.pipe(sass()).on('error', sass.logError) .pipe(sass()).on('error', sass.logError)
.pipe(base64({ .pipe(base64({
baseDir: "./www/css", baseDir: "./www/css",
extensions: ['svg', 'png', /\.jpg#datauri$/i], extensions: ['svg', 'png', 'gif', /\.jpg#datauri$/i],
maxSize: 14 * 1024 maxImageSize: 14 * 1024
})) }))
.pipe(gulp.dest('./www/css/')) .pipe(gulp.dest('./www/css/'))
.pipe(cleanCss({ .pipe(cleanCss(cleanCssOptions))
keepSpecialComments: 0
}))
.pipe(sourcemaps.write())
.pipe(rename({ extname: '.min.css' })) .pipe(rename({ extname: '.min.css' }))
.pipe(gulp.dest('./www/css/')) .pipe(gulp.dest('./www/css/'));
.on('end', done);
});
gulp.task('watch', function() {
gulp.watch(paths.sass, ['sass']);
gulp.watch(paths.templatecache, ['templatecache']);
gulp.watch(paths.ng_annotate, ['ng_annotate']);
gulp.watch(paths.ng_translate, ['ng_translate']);
// plugins:
gulp.watch(paths.templatecache_plugin, ['templatecache_plugin']);
gulp.watch(paths.ng_annotate_plugin, ['ng_annotate_plugin']);
gulp.watch(paths.ng_translate_plugin, ['ng_translate_plugin']);
gulp.watch(paths.css_plugin, ['css_plugin']);
});
gulp.task('install', ['git-check'], function() {
return bower.commands.install()
.on('log', function(data) {
gutil.log('bower', gutil.colors.cyan(data.id), data.message);
});
});
gulp.task('git-check', function(done) {
if (!sh.which('git')) {
console.log(
' ' + gutil.colors.red('Git is not installed.'),
'\n Git, the version control system, is required to download Ionic.',
'\n Download git here:', gutil.colors.cyan('http://git-scm.com/downloads') + '.',
'\n Once git is installed, run \'' + gutil.colors.cyan('gulp install') + '\' again.'
);
process.exit(1);
} }
done();
});
gulp.task('config', function (done) { function appConfig() {
var allConfig = JSON.parse(fs.readFileSync('./app/config.json', 'utf8')); const allConfig = JSON.parse(fs.readFileSync('./app/config.json', 'utf8'));
// Determine which environment to use when building config. // Determine which environment to use when building config.
var env = argv.env || 'default'; const env = argv.env || 'default';
var config = allConfig[env]; const config = allConfig[env];
if (!config) { if (!config) {
gutil.log(gutil.colors.red("=> Could not load `" + env + "` environment!")); throw new Error(colors.red("=> Could not load `" + env + "` environment!"));
process.exit(1);
} }
gutil.log(gutil.colors.green("Building `www/js/config.js` for `" + env + "` environment...")); log(colors.green("Building App config at `www/js/config.js` for `" + env + "` environment..."));
var project = JSON.parse(fs.readFileSync('./package.json', 'utf8')); const project = JSON.parse(fs.readFileSync('./package.json', 'utf8'));
config['version'] = project.version; config['version'] = project.version;
config['build'] = (new Date()).toJSON(); config['build'] = (new Date()).toJSON();
config['newIssueUrl'] = project.bugs.new; config['newIssueUrl'] = project.bugs.new;
ngConstant({ return ngConstant({
name: 'cesium.config', name: 'cesium.config',
constants: {"csConfig": config}, constants: {"csConfig": config},
stream: true, stream: true,
...@@ -132,242 +170,411 @@ gulp.task('config', function (done) { ...@@ -132,242 +170,411 @@ gulp.task('config', function (done) {
.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")) .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 // Writes into file www/js/config.js
.pipe(rename('config.js')) .pipe(rename('config.js'))
.pipe(gulp.dest('www/js')) .pipe(gulp.dest('www/js'));
.on('end', done); }
;
}); function appConfigTest() {
const allConfig = JSON.parse(fs.readFileSync('./app/config.json', 'utf8'));
// Determine which environment to use when building config.
const env = 'g1-test';
const config = allConfig[env];
if (!config) {
throw new Error(colors.red("=> Could not load `" + env + "` environment!"));
}
log(colors.green("Building App test config at `www/js/config-test.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;
gulp.task('templatecache', function (done) { return ngConstant({
gulp.src(paths.templatecache) name: 'cesium.config',
constants: {"csConfig": config},
stream: true,
dest: 'config-test.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-test.js
.pipe(rename('config-test.js'))
.pipe(gulp.dest('www/js'));
}
function appAndPluginLint() {
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);
}
cb();
}));
}
function appNgTemplate() {
log(colors.green('Building template file...'));
return gulp.src(paths.templatecache)
.pipe(sort())
.pipe(templateCache({ .pipe(templateCache({
standalone: true, standalone: true,
module: "cesium.templates", module: "cesium.templates",
root: "templates/" root: "templates/"
})) }))
//.pipe(gulp.dest('www/js')) .pipe(gulp.dest('./www/dist/dist_js/app'));
.pipe(gulp.dest('./www/dist/dist_js/app')) }
.on('end', done);
});
gulp.task('ng_annotate', function (done) { function appNgAnnotate(event) {
gulp.src(paths.ng_annotate)
// 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(ngAnnotate({single_quotes: true}))
.pipe(gulp.dest('./www/dist/dist_js/app')) .pipe(gulp.dest('./www/dist/dist_js/app' + path));
.on('end', done); }
});
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...'));
gulp.task('ng_translate', function() {
return gulp.src('www/i18n/locale-*.json') return gulp.src('www/i18n/locale-*.json')
.pipe(jsonlint())
.pipe(jsonlint.reporter())
.pipe(sort())
.pipe(ngTranslate({standalone:true, module: 'cesium.translations'})) .pipe(ngTranslate({standalone:true, module: 'cesium.translations'}))
.pipe(gulp.dest('www/dist/dist_js/app')); .pipe(gulp.dest('www/dist/dist_js/app'));
//.pipe(gulp.dest('www/js')); }
});
function appLicense() {
log(colors.green('Building License files...'));
gulp.task('debug_file', function() {
gutil.log(gutil.colors.green("Building `www/debug.html`...")); return merge(
// Copy license into HTML
return gulp.src(['www/index.html']) gulp.src(paths.license_md)
.pipe(replace('dist/dist_js/app/', 'js/')) .pipe(markdown())
.pipe(replace('dist/dist_js/plugins/', 'plugins/')) .pipe(header('<html><header><meta charset="utf-8"></header><body>'))
// Restore some generate files .pipe(footer('</body></html>'))
.pipe(replace('js/templates.js', 'dist/dist_js/app/templates.js')) .pipe(gulp.dest('www/license')),
.pipe(replace('js/translations.js', 'dist/dist_js/app/translations.js'))
.pipe(replace('plugins/templates.js', 'dist/dist_js/plugins/templates.js')) // Copy license into txt
.pipe(replace('plugins/translations.js', 'dist/dist_js/plugins/translations.js')) gulp.src(paths.license_md)
.pipe(replace('ng-strict-di', '')) .pipe(header('\ufeff')) // Need BOM character for UTF-8 files
.pipe(rename('debug.html')) .pipe(rename({ extname: '.txt' }))
.pipe(gulp.dest('www')); .pipe(gulp.dest('www/license'))
}); );
}
/* -- Plugins -- */ /* -- Plugins -- */
gulp.task('templatecache_plugin', function (done) { function pluginNgTemplate() {
gulp.src(paths.templatecache_plugin) log(colors.green('Building Plugins template file...'));
return gulp.src(paths.templatecache_plugin)
.pipe(sort())
.pipe(templateCache({ .pipe(templateCache({
standalone: true, standalone: true,
module: "cesium.plugins.templates", module: "cesium.plugins.templates",
root: "plugins/" root: "plugins/"
})) }))
.pipe(gulp.dest('./www/dist/dist_js/plugins')) .pipe(gulp.dest('./www/dist/dist_js/plugins'));
//.pipe(gulp.dest('./www/plugins')) }
.on('end', done);
});
gulp.task('ng_annotate_plugin', function (done) { function pluginNgAnnotate(event) {
gulp.src(paths.ng_annotate_plugin)
// 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(ngAnnotate({single_quotes: true}))
.pipe(gulp.dest('./www/dist/dist_js/plugins')) .pipe(gulp.dest('./www/dist/dist_js/app' + path));
.on('end', done); }
});
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...'));
gulp.task('ng_translate_plugin', function() {
return gulp.src(paths.ng_translate_plugin) return gulp.src(paths.ng_translate_plugin)
.pipe(jsonlint())
.pipe(jsonlint.reporter())
.pipe(sort())
.pipe(ngTranslate({standalone:true, module: 'cesium.plugins.translations'})) .pipe(ngTranslate({standalone:true, module: 'cesium.plugins.translations'}))
.pipe(gulp.dest('www/dist/dist_js/plugins')); .pipe(gulp.dest('www/dist/dist_js/plugins'));
//.pipe(gulp.dest('www/plugins')); }
});
gulp.task('css_plugin', function (done) { 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) gulp.src(paths.css_plugin)
.pipe(gulp.dest('./www/dist/dist_css/plugins')) .pipe(gulp.dest('www/dist/dist_css/plugins')),
.on('end', done);
});
/* -- Web dist build -- */ // Leaflet images
gulp.task('clean:tmp', function(done) { pluginLeafletImages('./www/img/'),
return del([
'./tmp'
]);
});
gulp.task('clean:web', function(done) { // 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(cleanCssOptions))
.pipe(rename({ extname: '.min.css' }))
.pipe(gulp.dest('./www/css/'))
);
}
/* --------------------------------------------------------------------------
-- Build the web (ZIP) artifact
--------------------------------------------------------------------------*/
function webClean() {
return del([ return del([
'./platforms/web/www', './dist/web/www'
'./platforms/web/build'
]); ]);
}); }
function webCopyFiles() {
log(colors.green('Preparing dist/web files...'));
let htmlminOptions = {removeComments: true, collapseWhitespace: true};
gulp.task('copy-files:web', ['clean:tmp', 'clean:web', 'sass', 'config'], function(done) { const debugOptions = { ...debugBaseOptions, title: 'Copying' };
var tmpPath = './platforms/web/www';
es.concat( var targetPath = './dist/web/www';
return merge(
// Copy Js (and remove unused code) // Copy Js (and remove unused code)
gulp.src('./www/js/**/*.js') gulp.src('./www/js/**/*.js')
.pipe(debug(debugOptions))
.pipe(removeCode({"no-device": true})) .pipe(removeCode({"no-device": true}))
.pipe(jshint()) .pipe(jshint())
.pipe(gulp.dest(tmpPath + '/js')), .pipe(gulp.dest(targetPath + '/js')),
// Copy HTML templates (and remove unused code) // Copy HTML templates (and remove unused code)
gulp.src('./www/templates/**/*.html') gulp.src('./www/templates/**/*.html')
.pipe(removeCode({"no-device": true})) .pipe(removeCode({"no-device": true}))
.pipe(removeHtml('.hidden-no-device')) .pipe(removeHtml('.hidden-no-device'))
.pipe(removeHtml('[remove-if][remove-if="no-device"]')) .pipe(removeHtml('[remove-if][remove-if="no-device"]'))
.pipe(htmlmin()) .pipe(htmlmin(htmlminOptions))
.pipe(gulp.dest(tmpPath + '/templates')), .pipe(gulp.dest(targetPath + '/templates')),
// Copy index.html (and remove unused code) // Copy index.html (and remove unused code)
gulp.src('./www/index.html') gulp.src('./www/index.html')
.pipe(removeCode({"no-device": true})) .pipe(removeCode({'no-device': true}))
.pipe(removeHtml('.hidden-no-device')) .pipe(removeHtml('.hidden-no-device'))
.pipe(removeHtml('[remove-if][remove-if="no-device"]')) .pipe(removeHtml('[remove-if][remove-if="no-device"]'))
.pipe(htmlmin()) .pipe(htmlmin(/*no options, to keep comments*/))
.pipe(gulp.dest(tmpPath)), .pipe(gulp.dest(targetPath)),
// Copy index.html to debug.html (and remove unused code) // Copy API index.html
gulp.src('./www/index.html') gulp.src('./www/api/index.html')
.pipe(removeCode({"no-device": true})) .pipe(removeCode({'no-device': true}))
.pipe(removeHtml('.hidden-no-device')) .pipe(removeHtml('.hidden-no-device'))
.pipe(removeHtml('[remove-if][remove-if="no-device"]')) .pipe(removeHtml('[remove-if][remove-if="no-device"]'))
.pipe(rename("debug.html")) .pipe(htmlmin())
.pipe(gulp.dest(tmpPath)), .pipe(gulp.dest(targetPath + '/api')),
// Copy config-test.js
gulp.src('./www/js/config*.js')
.pipe(debug(debugOptions))
.pipe(gulp.dest(targetPath)),
// Copy fonts // Copy fonts
gulp.src('./www/fonts/**/*.*') gulp.src('./www/fonts/**/*.*')
.pipe(gulp.dest(tmpPath + '/fonts')), .pipe(debug(debugOptions))
.pipe(gulp.dest(targetPath + '/fonts')),
// Copy CSS // Copy CSS
gulp.src('./www/css/**/*.*') gulp.src('./www/css/**/*.*')
.pipe(gulp.dest(tmpPath + '/css')), .pipe(debug(debugOptions))
.pipe(gulp.dest(targetPath + '/css')),
// Copy i18n // Copy i18n
gulp.src('./www/i18n/locale-*.json') gulp.src('./www/i18n/locale-*.json')
.pipe(jsonlint())
.pipe(jsonlint.reporter())
.pipe(sort())
.pipe(ngTranslate({standalone:true, module: 'cesium.translations'})) .pipe(ngTranslate({standalone:true, module: 'cesium.translations'}))
.pipe(gulp.dest(tmpPath + '/js')), .pipe(debug(debugOptions))
.pipe(gulp.dest(targetPath + '/js')),
// Copy img // Copy img
gulp.src('./www/img/**/*.*') gulp.src('./www/img/**/*.*')
.pipe(gulp.dest(tmpPath + '/img')), .pipe(debug(debugOptions))
.pipe(gulp.dest(targetPath + '/img')),
// Copy manifest // Copy manifest.json
gulp.src('./www/manifest.json') gulp.src('./www/manifest.json')
.pipe(gulp.dest(tmpPath)), .pipe(debug(debugOptions))
.pipe(gulp.dest(targetPath)),
// Copy lib/ionic // Copy lib (JS, CSS and fonts)
gulp.src('./www/lib/ionic/**/*.*') gulp.src(['./www/lib/**/*.js', './www/lib/**/*.css', './www/lib/**/fonts/**/*.*'])
.pipe(gulp.dest(tmpPath + '/lib/ionic')) .pipe(debug(debugOptions))
) .pipe(gulp.dest(targetPath + '/lib')),
.on('end', done);
}); // 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'))
);
}
gulp.task('templatecache:web', ['copy-files:web'], function (done) { function webNgTemplate() {
var tmpPath = './platforms/web/www'; var targetPath = './dist/web/www';
gulp.src(tmpPath + '/templates/**/*.html') return gulp.src(targetPath + '/templates/**/*.html')
.pipe(sort())
.pipe(templateCache({ .pipe(templateCache({
standalone: true, standalone: true,
module: "cesium.templates", module: "cesium.templates",
root: "templates/" root: "templates/"
})) }))
.pipe(gulp.dest(tmpPath + '/js')) .pipe(gulp.dest(targetPath + '/dist/dist_js/app'));
.on('end', done); }
});
gulp.task('ng_annotate:web', ['templatecache:web'], function (done) { function webAppNgAnnotate() {
var tmpPath = './platforms/web/www'; var targetPath = './dist/web/www';
var jsFilter = filter(["**/*.js", "!**/vendor/*"]); var jsFilter = filter(["**/*.js", "!**/vendor/*"]);
gulp.src(tmpPath + '/js/**/*.js') return gulp.src(targetPath + '/js/**/*.js')
.pipe(jsFilter) .pipe(jsFilter)
.pipe(ngAnnotate({single_quotes: true})) .pipe(ngAnnotate({single_quotes: true}))
.pipe(gulp.dest(tmpPath + '/dist/dist_js/app')) .pipe(gulp.dest(targetPath + '/dist/dist_js/app'));
.on('end', done); }
});
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')),
gulp.task('copy-plugin-files:web', ['clean:tmp', 'clean:web', 'sass', 'config'], function(done) {
var tmpPath = './platforms/web/www';
es.concat(
// Transform i18n into JS // Transform i18n into JS
gulp.src(paths.ng_translate_plugin) gulp.src(paths.ng_translate_plugin)
.pipe(jsonlint())
.pipe(jsonlint.reporter())
.pipe(sort())
.pipe(ngTranslate({standalone:true, module: 'cesium.plugins.translations'})) .pipe(ngTranslate({standalone:true, module: 'cesium.plugins.translations'}))
.pipe(gulp.dest(tmpPath + '/dist/dist_js/plugins')), .pipe(gulp.dest(targetPath + '/dist/dist_js/plugins')),
// Copy CSS // Copy plugin CSS
gulp.src(paths.css_plugin) gulp.src(paths.css_plugin)
.pipe(gulp.dest(tmpPath + '/dist/dist_css/plugins')) .pipe(gulp.dest(targetPath + '/dist/dist_css/plugins')),
)
.on('end', done); // Copy Leaflet images
}); pluginLeafletImages(targetPath + '/img'),
// Copy Leaflet CSS
gulp.src('./www/css/**/leaflet.*')
.pipe(gulp.dest(targetPath + '/css'))
gulp.task('templatecache-plugin:web', ['copy-plugin-files:web'], function (done) { );
var tmpPath = './platforms/web/www'; }
gulp.src(paths.templatecache_plugin)
function webPluginNgTemplate() {
var targetPath = './dist/web/www';
return gulp.src(targetPath + '/plugins/**/*.html')
.pipe(sort())
.pipe(templateCache({ .pipe(templateCache({
standalone: true, standalone: true,
module: "cesium.plugins.templates", module: "cesium.plugins.templates",
root: "plugins/" root: "plugins/"
})) }))
.pipe(gulp.dest(tmpPath + '/dist/dist_js/plugins')) .pipe(gulp.dest(targetPath + '/dist/dist_js/plugins'));
.on('end', done); }
});
gulp.task('ng_annotate-plugin:web', ['templatecache-plugin:web'], function (done) { function webPluginNgAnnotate() {
var tmpPath = './platforms/web/www'; var targetPath = './dist/web/www';
gulp.src(paths.ng_annotate_plugin) return gulp.src(targetPath + '/plugins/**/*.js')
.pipe(ngAnnotate({single_quotes: true})) .pipe(ngAnnotate({single_quotes: true}))
.pipe(gulp.dest(tmpPath + '/dist/dist_js/plugins')) .pipe(gulp.dest(targetPath + '/dist/dist_js/plugins'));
.on('end', done); }
});
function webUglify() {
const targetPath = './dist/web/www';
const enableUglify = argv.release || argv.uglify || false;
const version = JSON.parse(fs.readFileSync('./package.json', 'utf8')).version;
gulp.task('debug-files:web', ['ng_annotate:web', 'ng_annotate-plugin:web'], function(done) { if (enableUglify) {
var tmpPath = './platforms/web/www';
gulp.src(tmpPath + '/debug.html') log(colors.green('Minify JS and CSS files...'));
.pipe(useref()) // Concatenate with gulp-useref
.pipe(gulp.dest(tmpPath))
.on('end', done);
});
gulp.task('optimize-files:web', ['debug-files:web'], function(done) { const indexFilter = filter('**/index.html', {restore: true});
var tmpPath = './platforms/web/www'; const jsFilter = filter(["**/*.js", '!**/config.js', '!**/config-test.js'], {restore: true});
var jsFilter = filter(["**/*.js", '!**/config.js'], { restore: true }); const cssFilter = filter("**/*.css", {restore: true});
var cssFilter = filter("**/*.css", { restore: true });
var revFilesFilter = filter(['**/*', '!**/index.html', '!**/config.js'], { restore: true }); // Process index.html
return gulp.src(targetPath + '/index.html')
.pipe(useref({}, lazypipe().pipe(sourcemaps.init, { loadMaps: true }))) // Concatenate with gulp-useref
gulp.src(tmpPath + '/index.html')
.pipe(useref()) // Concatenate with gulp-useref
// Process JS // Process JS
.pipe(jsFilter) .pipe(jsFilter)
.pipe(uglify()) // Minify any javascript sources .pipe(uglify(uglifyBaseOptions)) // Minify javascript files
.pipe(jsFilter.restore) .pipe(jsFilter.restore)
// Process CSS // Process CSS
...@@ -375,93 +582,880 @@ gulp.task('optimize-files:web', ['debug-files:web'], function(done) { ...@@ -375,93 +582,880 @@ gulp.task('optimize-files:web', ['debug-files:web'], function(done) {
.pipe(csso()) // Minify any CSS sources .pipe(csso()) // Minify any CSS sources
.pipe(cssFilter.restore) .pipe(cssFilter.restore)
// Add revision to filename (but not index.html and config.js) // Add version to file path
.pipe(revFilesFilter) .pipe(indexFilter)
.pipe(rev()) // Rename the concatenated files .pipe(replace(/"(dist_js\/[a-zA-Z0-9]+).js"/g, '"$1.js?v=' + version + '"'))
.pipe(revFilesFilter.restore) .pipe(replace(/"(dist_css\/[a-zA-Z0-9]+).css"/g, '"$1.css?v=' + version + '"'))
.pipe(indexFilter.restore)
// Substitute in new filenames .pipe(sourcemaps.write('maps'))
.pipe(revReplace())
.pipe(gulp.dest(tmpPath)) .pipe(gulp.dest(targetPath));
.on('end', done); }
}); else {
return Promise.resolve();
}
}
function webIntegrity() {
const targetPath = './dist/web/www';
const enableIntegrity = argv.release || false;
gulp.task('clean-unused-files:web', ['optimize-files:web'], function(done) { if (enableIntegrity) {
var tmpPath = './platforms/web/www'; log(colors.green('Create index.integrity.html... '));
es.concat( // Process index.html
gulp.src(tmpPath + '/js/**/*.js', {read: false}) 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', '!**/config-test.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(replace("config-test.js", "../config-test.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(replace("config-test.js", "../config-test.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()), .pipe(clean()),
gulp.src(tmpPath + '/css/**/*.css', {read: false}) // 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()),
gulp.src(targetPath + '/maps/config-test.js.map', {read: false, allowEmpty: true})
.pipe(debug(debugOptions))
.pipe(clean()) .pipe(clean())
) )
.on('end', done); .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 });
gulp.task('clean-unused-directories:web', ['clean-unused-files:web'], function(done) { return gulp.src(tmpPath + '/**/*.*')
var tmpPath = './platforms/web/www';
// 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([ return del([
tmpPath + '/css', './dist/web/ext'
tmpPath + '/templates',
tmpPath + '/js',
tmpPath + '/dist',
tmpPath + '/lib/ionic/scss',
tmpPath + '/lib/ionic/css',
tmpPath + '/lib/ionic/js',
tmpPath + '/lib/ionic/version.json'
]); ]);
}); }
gulp.task('zip:web', ['clean-unused-directories:web'], function(done) { function webExtCopyFiles() {
var tmpPath = './platforms/web/www'; const wwwPath = './dist/web/www';
var version = JSON.parse(fs.readFileSync('./package.json', 'utf8')).version; const resourcesPath = './resources/web-ext';
var fileFilter = filter(['**', '!*/templates', '!*/css', '!*/js']); log(colors.green('Copy web extension files...'));
gulp.src(tmpPath + '/**/*.*') const version = JSON.parse(fs.readFileSync('./package.json', 'utf8')).version;
.pipe(zip('cesium-web-'+version+'.zip')) const manifestFilter = filter(["**/manifest.json"], { restore: true });
.pipe(fileFilter) const txtFilter = filter(["**/*.txt"], { restore: true });
.pipe(gulp.dest('./platforms/web/build'))
.on('end', done); // 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));
}
gulp.task('build:web', ['zip:web'], function(done) { function webBuildSuccess(done) {
var version = JSON.parse(fs.readFileSync('./package.json', 'utf8')).version; var version = JSON.parse(fs.readFileSync('./package.json', 'utf8')).version;
gutil.log(gutil.colors.green("Build for web created at: 'plateforms/web/build/cesium-web-" + version + ".zip'")); log(colors.green("Web artifact created at: 'dist/web/build/cesium-v" + version + "-web.zip'"));
return del([ if (done) done();
'./tmp' }
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
]);
}
gulp.task('deploy:android', function (done) { return gulp.src(patterns, {read: false, allowEmpty: true})
var config = require('./hooks/playstore-config.json'); .pipe(debug(debugOptions))
.pipe(clean());
}
if(!config) {
gutil.log(gutil.colors.red("ERROR => Could not load `./hooks/playstore-config.json` file!")); function cdvCopyBuildFiles() {
return done(); 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));
} }
if(!config.client_email || !config.private_key) { else {
gutil.log(gutil.colors.red("ERROR => Could not found 'client_email' or 'private_key' in 'hooks/playstore-config.json' file.")); log(colors.blue(' Directory ' + srcPath + 'not found. Skipping copy to ' + targetPath));
return done(); return Promise.resolve();
} }
}
function cdvAndroidManifest() {
const projectRoot = argv.root || '.';
const platform = argv.platform || 'android';
if (platform !== 'android') return Promise.resolve(); // Skip
var publisher = require('playup')(config); const srcMainPath = path.join(projectRoot, 'platforms', platform, 'app', 'src', 'main');
const androidManifestFile = path.join(srcMainPath, 'AndroidManifest.xml');
var apkFileLocation = path.join('.', 'platforms', 'android', 'build', 'outputs', 'apk', 'android-release.apk'); log(colors.green('Patch Android manifest... ') + colors.grey(androidManifestFile));
console.log('Publishing APK file [' + apkFileLocation + '] to playstore...');
publisher.upload(apkFileLocation, { if (!fs.existsSync(androidManifestFile)) {
track: 'production', throw Error("Missing required file " + androidManifestFile);
recentChanges: {
'fr-FR': 'New stable release'
} }
})
.then(function (data) { return gulp.src(androidManifestFile)
console.log(' > APK has been deployed to playstore !');
done(); // 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">'))
.catch(function(err){
console.log(err); // Use AndroidX
done(); .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 config = gulp.series(appConfig, appConfigTest);
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 = config;
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(config, build);
exports.serveBefore = gulp.series(build, appAndPluginWatch);
exports['ionic:serve:before'] = exports.serveBefore; // Alias need by @ionic/cli
<!--
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
-->
# Cordova Hooks
This directory may contain scripts used to customize cordova commands. This
directory used to exist at `.cordova/hooks`, but has now been moved to the
project root. Any scripts you add to these directories will be executed before
and after the commands corresponding to the directory name. Useful for
integrating your own build systems or integrating with version control systems.
__Remember__: Make your scripts executable.
## Hook Directories
The following subdirectories will be used for hooks:
after_build/
after_compile/
after_docs/
after_emulate/
after_platform_add/
after_platform_rm/
after_platform_ls/
after_plugin_add/
after_plugin_ls/
after_plugin_rm/
after_plugin_search/
after_prepare/
after_run/
after_serve/
before_build/
before_compile/
before_docs/
before_emulate/
before_platform_add/
before_platform_rm/
before_platform_ls/
before_plugin_add/
before_plugin_ls/
before_plugin_rm/
before_plugin_search/
before_prepare/
before_run/
before_serve/
pre_package/ <-- Windows 8 and Windows Phone only.
## Script Interface
All scripts are run from the project's root directory and have the root directory passes as the first argument. All other options are passed to the script using environment variables:
* CORDOVA_VERSION - The version of the Cordova-CLI.
* CORDOVA_PLATFORMS - Comma separated list of platforms that the command applies to (e.g.: android, ios).
* CORDOVA_PLUGINS - Comma separated list of plugin IDs that the command applies to (e.g.: org.apache.cordova.file, org.apache.cordova.file-transfer)
* CORDOVA_HOOK - Path to the hook that is being executed.
* CORDOVA_CMDLINE - The exact command-line arguments passed to cordova (e.g.: cordova run ios --emulate)
If a script returns a non-zero exit code, then the parent cordova command will be aborted.
## Writing hooks
We highly recommend writting your hooks using Node.js so that they are
cross-platform. Some good examples are shown here:
[http://devgirl.org/2013/11/12/three-hooks-your-cordovaphonegap-project-needs/](http://devgirl.org/2013/11/12/three-hooks-your-cordovaphonegap-project-needs/)
#!/usr/bin/env node
"use strict";
var gulp = require('gulp');
var gutil = require('gulp-util');
var path = require("path");
var cmd = process.env.CORDOVA_CMDLINE;
var rootdir = process.argv[2];
var argv = require('yargs').argv;
var skip = true;
if (/*cmd.indexOf("--release") > -1 || */cmd.indexOf("--playstore") > -1) {
skip = false;
}
if (rootdir && !skip) {
// go through each of the platform directories that have been prepared
var platforms = (process.env.CORDOVA_PLATFORMS ? process.env.CORDOVA_PLATFORMS.split(',') : []);
for(var x=0; x<platforms.length; x++) {
var platform = platforms[x].trim().toLowerCase();
var platformRoot = path.join(rootdir, 'platforms', platform);
// Deploy for Android
if(platform == 'android') {
var apkFileLocation = path.join(platformRoot, 'build/outputs/apk/android-release.apk');
console.log('Publishing APK file [' + apkFileLocation + '] to playstore...');
var config = require('../playstore-config.json');
if(!config) {
gutil.log(gutil.colors.red("ERROR => Could not load `hooks/playstore-config.json` file!"));
return;
}
if(!config.client_email || !config.private_key) {
gutil.log(gutil.colors.red("ERROR => Could not found 'client_email' or 'private_key' in 'hooks/playstore-config.json' file."));
return;
}
var publisher = require('playup')(config);
publisher.upload(apkFileLocation,
{
track: 'production',
recentChanges: {
'fr-FR': 'New stable release'
}
})
.then(function (data) {
console.log(' > APK file successfully deployed to Playstore !');
})
.catch(function(err) {
console.log('ERROR while publsihing to playtore: \n' + err);
})
}
else {
// TODO : deploy other for platforms
}
}
}
#!/usr/bin/env node
// Add Platform Class
// v1.0
// Automatically adds the platform class to the body tag
// after the `prepare` command. By placing the platform CSS classes
// directly in the HTML built for the platform, it speeds up
// rendering the correct layout/style for the specific platform
// instead of waiting for the JS to figure out the correct classes.
var fs = require('fs');
var path = require('path');
var rootdir = process.argv[2];
function addPlatformBodyTag(indexPath, platform) {
// add the platform class to the body tag
try {
var platformClass = 'platform-' + platform;
var cordovaClass = 'platform-cordova platform-webview';
var html = fs.readFileSync(indexPath, 'utf8');
var bodyTag = findBodyTag(html);
if(!bodyTag) return; // no opening body tag, something's wrong
if(bodyTag.indexOf(platformClass) > -1) return; // already added
var newBodyTag = bodyTag;
var classAttr = findClassAttr(bodyTag);
if(classAttr) {
// body tag has existing class attribute, add the classname
var endingQuote = classAttr.substring(classAttr.length-1);
var newClassAttr = classAttr.substring(0, classAttr.length-1);
newClassAttr += ' ' + platformClass + ' ' + cordovaClass + endingQuote;
newBodyTag = bodyTag.replace(classAttr, newClassAttr);
} else {
// add class attribute to the body tag
newBodyTag = bodyTag.replace('>', ' class="' + platformClass + ' ' + cordovaClass + '">');
}
html = html.replace(bodyTag, newBodyTag);
fs.writeFileSync(indexPath, html, 'utf8');
process.stdout.write('add to body class: ' + platformClass + '\n');
} catch(e) {
process.stdout.write(e);
}
}
function findBodyTag(html) {
// get the body tag
try{
return html.match(/<body(?=[\s>])(.*?)>/gi)[0];
}catch(e){}
}
function findClassAttr(bodyTag) {
// get the body tag's class attribute
try{
return bodyTag.match(/ class=["|'](.*?)["|']/gi)[0];
}catch(e){}
}
if (rootdir) {
// go through each of the platform directories that have been prepared
var platforms = (process.env.CORDOVA_PLATFORMS ? process.env.CORDOVA_PLATFORMS.split(',') : []);
for(var x=0; x<platforms.length; x++) {
// open up the index.html file at the www root
try {
var platform = platforms[x].trim().toLowerCase();
var indexPath;
if(platform == 'android') {
indexPath = path.join('platforms', platform, 'assets', 'www', 'index.html');
} else {
indexPath = path.join('platforms', platform, 'www', 'index.html');
}
if(fs.existsSync(indexPath)) {
addPlatformBodyTag(indexPath, platform);
}
} catch(e) {
process.stdout.write(e);
}
}
}
#!/usr/bin/env node
"use strict";
var gulp = require('gulp');
var gutil = require('gulp-util');
var path = require("path");
var removeCode = require('gulp-remove-code');
var removeHtml = require('gulp-html-remove');
var es = require('event-stream');
var ngAnnotate = require('gulp-ng-annotate');
var htmlmin = require('gulp-htmlmin');
var cmd = process.env.CORDOVA_CMDLINE;
var rootdir = process.argv[2];
var argv = require('yargs').argv;
if (rootdir) {
// go through each of the platform directories that have been prepared
var platforms = (process.env.CORDOVA_PLATFORMS ? process.env.CORDOVA_PLATFORMS.split(',') : []);
for(var x=0; x<platforms.length; x++) {
var platform = platforms[x].trim().toLowerCase();
var wwwPath;
if(platform == 'android') {
wwwPath = path.join(rootdir, 'platforms', platform, 'assets', 'www');
} else {
wwwPath = path.join(rootdir, 'platforms', platform, 'www');
}
var pluginPath = path.join(wwwPath, 'plugins') + '/es';
// Removing unused code for device...
es.concat(
// Remove unused HTML tags
gulp.src([wwwPath + '/templates/**/*.html', pluginPath + '/templates/**/*.html'])
.pipe(removeCode({device: true}))
.pipe(removeHtml('.hidden-xs.hidden-sm'))
.pipe(removeHtml('.hidden-device'))
.pipe(removeHtml('[remove-if][remove-if="device"]'))
.pipe(htmlmin())
.pipe(gulp.dest(".")),
gulp.src(path.join(wwwPath, 'index.html'))
.pipe(removeCode({device: true}))
.pipe(removeHtml('.hidden-xs.hidden-sm'))
.pipe(removeHtml('.hidden-device'))
.pipe(removeHtml('[remove-if][remove-if="device"]'))
.pipe(htmlmin())
.pipe(gulp.dest(wwwPath)),
// Remove unused JS code
gulp.src([wwwPath + + '/js/**/*.js', pluginPath + + '/js/**/*.js'])
.pipe(removeCode({device: true}))
.pipe(ngAnnotate({single_quotes: true}))
.pipe(gulp.dest("."))
);
}
}
#!/usr/bin/env node
"use strict";
var gulp = require('gulp');
var gutil = require('gulp-util');
var path = require("path");
var templateCache = require('gulp-angular-templatecache');
var es = require('event-stream');
var cmd = process.env.CORDOVA_CMDLINE;
var rootdir = process.argv[2];
var argv = require('yargs').argv;
if (rootdir) {
// go through each of the platform directories that have been prepared
var platforms = (process.env.CORDOVA_PLATFORMS ? process.env.CORDOVA_PLATFORMS.split(',') : []);
for(var x=0; x<platforms.length; x++) {
var platform = platforms[x].trim().toLowerCase();
var wwwPath;
if(platform == 'android') {
wwwPath = path.join(rootdir, 'platforms', platform, 'assets', 'www');
} else {
wwwPath = path.join(rootdir, 'platforms', platform, 'www');
}
var distJsPath = path.join(wwwPath, 'dist', 'dist_js', 'app');
var pluginDistJsPath = path.join(wwwPath, 'dist', 'dist_js', 'plugins');
// Concat templates into a JS
es.concat(
gulp.src(wwwPath + 'templates/**/*.html')
.pipe(templateCache({
standalone:true,
module:"cesium.templates",
root: "templates/"
}))
.pipe(gulp.dest(distJsPath)),
gulp.src(wwwPath + 'plugins/*/templates/**/*.html')
.pipe(templateCache({
standalone:true,
module:"cesium.plugins.templates",
root: "templates/"
}))
.pipe(gulp.dest(pluginDistJsPath))
);
}
}
#!/usr/bin/env node
"use strict";
var gulp = require('gulp');
var gutil = require('gulp-util');
var path = require("path");
var es = require('event-stream');
var cmd = process.env.CORDOVA_CMDLINE;
var rootdir = process.argv[2];
var argv = require('yargs').argv;
var ngTranslate = require('gulp-angular-translate');
if (rootdir) {
// go through each of the platform directories that have been prepared
var platforms = (process.env.CORDOVA_PLATFORMS ? process.env.CORDOVA_PLATFORMS.split(',') : []);
for(var x=0; x<platforms.length; x++) {
var platform = platforms[x].trim().toLowerCase();
var wwwPath;
if(platform == 'android') {
wwwPath = path.join(rootdir, 'platforms', platform, 'assets', 'www');
} else {
wwwPath = path.join(rootdir, 'platforms', platform, 'www');
}
var distJsPath = path.join(wwwPath, 'dist', 'dist_js', 'app');
var pluginDistJsPath = path.join(wwwPath, 'dist', 'dist_js', 'plugins');
// Concat templates into a JS
es.concat(
gulp.src(wwwPath + '/i18n/locale-*.json')
.pipe(ngTranslate({standalone:true, module: 'cesium.translations'}))
.pipe(gulp.dest(distJsPath)),
gulp.src(wwwPath + '/plugins/*/i18n/locale-*.json')
.pipe(ngTranslate({standalone:true, module: 'cesium.plugins.translations'}))
.pipe(gulp.dest(pluginDistJsPath))
);
}
}
#!/usr/bin/env node
"use strict";
var gulp = require('gulp');
var gutil = require('gulp-util');
var path = require("path");
var es = require('event-stream');
var useref = require('gulp-useref');
var filter = require('gulp-filter');
var uglify = require('gulp-uglify');
var csso = require('gulp-csso');
var rev = require('gulp-rev');
var revReplace = require('gulp-rev-replace');
var cmd = process.env.CORDOVA_CMDLINE;
var rootdir = process.argv[2];
var argv = require('yargs').argv;
var skip = true;
if (cmd.indexOf("--release") > -1 || cmd.indexOf("--useref") > -1) {
skip = false;
}
if (rootdir && !skip) {
// go through each of the platform directories that have been prepared
var platforms = (process.env.CORDOVA_PLATFORMS ? process.env.CORDOVA_PLATFORMS.split(',') : []);
for(var x=0; x<platforms.length; x++) {
var platform = platforms[x].trim().toLowerCase();
var wwwPath;
if(platform == 'android') {
wwwPath = path.join(rootdir, 'platforms', platform, 'assets', 'www');
} else {
wwwPath = path.join(rootdir, 'platforms', platform, 'www');
}
var indexPath = path.join(wwwPath, 'index.html');
var jsFilter = filter(["**/*.js", '!**/config.js'], { restore: true });
var cssFilter = filter("**/*.css", { restore: true });
var revFilesFilter = filter(['**/*', '!**/index.html', '!**/config.js'], { restore: true });
// Removing unused code for device...
es.concat(
gulp.src(indexPath)
.pipe(useref()) // Concatenate with gulp-useref
.pipe(jsFilter)
.pipe(uglify()) // Minify any javascript sources
.pipe(jsFilter.restore)
.pipe(cssFilter)
.pipe(csso()) // Minify any CSS sources
.pipe(cssFilter.restore)
.pipe(revFilesFilter)
.pipe(rev()) // Rename the concatenated files (but not index.html)
.pipe(revFilesFilter.restore)
.pipe(revReplace()) // Substitute in new filenames
.pipe(gulp.dest(wwwPath))
);
}
}
#!/usr/bin/env node
"use strict";
var gulp = require('gulp');
var gutil = require('gulp-util');
var allConfig = require('../../app/config.json');
var path = require("path");
var del = require('del');
var cmd = process.env.CORDOVA_CMDLINE;
var rootdir = process.argv[2];
var argv = require('yargs').argv;
var skip = true;
if (cmd.indexOf("--release") > -1 || cmd.indexOf("--useref") > -1) {
skip = false;
}
if (rootdir && !skip) {
// go through each of the platform directories that have been prepared
var platforms = (process.env.CORDOVA_PLATFORMS ? process.env.CORDOVA_PLATFORMS.split(',') : []);
for(var x=0; x<platforms.length; x++) {
var platform = platforms[x].trim().toLowerCase();
var wwwPath;
if(platform == 'android') {
wwwPath = path.join(rootdir, 'platforms', platform, 'assets', 'www');
} else {
wwwPath = path.join(rootdir, 'platforms', platform, 'www');
}
// Clean unused directories
console.log('Cleaning dir ' + path.join(wwwPath, 'lib', '**'));
del([
path.join(wwwPath, 'i18n'),
path.join(wwwPath, 'js'),
path.join(wwwPath, 'templates'),
path.join(wwwPath, 'css'),
path.join(wwwPath, 'dist'),
path.join(wwwPath, 'js'),
path.join(wwwPath, 'cordova-js-src'),
path.join(wwwPath, 'plugins', 'es'),
path.join(wwwPath, 'lib', '**'),
// Keep Ionic lib/ionic/fonts directory
'!'+path.join(wwwPath, 'lib'),
'!'+path.join(wwwPath, 'lib', 'ionic'),
'!'+path.join(wwwPath, 'lib', 'ionic', 'fonts'),
'!'+path.join(wwwPath, 'lib', 'ionic', 'fonts', '*.*')
]);
}
}
#!/usr/bin/env node
var fs = require('fs');
var path = require('path');
var jshint = require('jshint').JSHINT;
var async = require('async');
var foldersToProcess = [
'js',
'js/controllers',
'js/entities',
'js/services',
'plugins/es/js',
'plugins/es/js/controllers',
//'plugins/es/js/entities',
'plugins/es/js/services'
];
foldersToProcess.forEach(function(folder) {
processFiles("www/" + folder);
});
function processFiles(dir, callback) {
var errorCount = 0;
fs.readdir(dir, function(err, list) {
if (err) {
console.log('processFiles err: ' + err);
return;
}
async.eachSeries(list, function(file, innercallback) {
file = dir + '/' + file;
fs.stat(file, function(err, stat) {
if(!stat.isDirectory()) {
if(path.extname(file) === ".js") {
lintFile(file, function(hasError) {
if(hasError) {
errorCount++;
}
innercallback();
});
} else {
innercallback();
}
} else {
innercallback();
}
});
}, function(error) {
if(errorCount > 0) {
process.exit(1);
}
});
});
}
function lintFile(file, callback) {
console.log("Linting " + file);
fs.readFile(file, function(err, data) {
if(err) {
console.log('Error: ' + err);
return;
}
if(jshint(data.toString())) {
console.log('File ' + file + ' has no errors.');
console.log('-----------------------------------------');
callback(false);
} else {
console.log('Errors in file ' + file);
var out = jshint.data(),
errors = out.errors;
for(var j = 0; j < errors.length; j++) {
console.log(errors[j].line + ':' + errors[j].character + ' -> ' + errors[j].reason + ' -> ' +
errors[j].evidence);
}
console.log('-----------------------------------------');
callback(true);
}
});
}