From 736e7ef72a4862afa033f28fcae0c7e7ac34e874 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Wed, 14 Oct 2020 22:47:32 +0200 Subject: [PATCH 1/6] MOBILE-3565 core: Fix init delegate properties --- src/app/services/init.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/services/init.ts b/src/app/services/init.ts index 8e06292fc..26bb797e5 100644 --- a/src/app/services/init.ts +++ b/src/app/services/init.ts @@ -81,7 +81,7 @@ export class CoreInitDelegate { ordered.sort((a, b) => b.priority - a.priority); ordered = ordered.map((data: CoreInitHandler) => ({ - func: this.prepareProcess.bind(this, data), + function: this.prepareProcess.bind(this, data), blocking: !!data.blocking, })); From 0b40fd0baa512b4fbe5a6ecc3fa6298e378e868e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Thu, 15 Oct 2020 10:10:00 +0200 Subject: [PATCH 2/6] MOBILE-3565 core: Component icon fixes --- src/app/components/icon/icon.ts | 48 +++++++++++---------------------- 1 file changed, 15 insertions(+), 33 deletions(-) diff --git a/src/app/components/icon/icon.ts b/src/app/components/icon/icon.ts index ff70d868e..7ae4328cf 100644 --- a/src/app/components/icon/icon.ts +++ b/src/app/components/icon/icon.ts @@ -26,20 +26,21 @@ import { Component, Input, OnChanges, OnDestroy, ElementRef, SimpleChange } from styleUrls: ['icon.scss'], }) export class CoreIconComponent implements OnChanges, OnDestroy { + // Common params. @Input() name: string; - @Input('color') color?: string; - @Input('slash') slash?: boolean; // Display a red slash over the icon. + @Input() color?: string; + @Input() slash?: boolean; // Display a red slash over the icon. // Ionicons params. - @Input('isActive') isActive?: boolean; - @Input('md') md?: string; - @Input('ios') ios?: string; + @Input() isActive?: boolean; + @Input() md?: string; + @Input() ios?: string; // FontAwesome params. - @Input('fixed-width') fixedWidth: string; + @Input('fixed-width') fixedWidth: boolean; - @Input('label') ariaLabel?: string; + @Input() label?: string; @Input() flipRtl?: boolean; // Whether to flip the icon in RTL. Defaults to false. protected element: HTMLElement; @@ -66,18 +67,15 @@ export class CoreIconComponent implements OnChanges, OnDestroy { if (this.name.startsWith('fa-')) { this.newElement.classList.add('fa'); this.newElement.classList.add(this.name); - if (this.isTrueProperty(this.fixedWidth)) { + if (this.fixedWidth) { this.newElement.classList.add('fa-fw'); } - if (this.color) { - this.newElement.classList.add('fa-' + this.color); - } } - !this.ariaLabel && this.newElement.setAttribute('aria-hidden', 'true'); - !this.ariaLabel && this.newElement.setAttribute('role', 'presentation'); - this.ariaLabel && this.newElement.setAttribute('aria-label', this.ariaLabel); - this.ariaLabel && this.newElement.setAttribute('title', this.ariaLabel); + !this.label && this.newElement.setAttribute('aria-hidden', 'true'); + !this.label && this.newElement.setAttribute('role', 'presentation'); + this.label && this.newElement.setAttribute('aria-label', this.label); + this.label && this.newElement.setAttribute('title', this.label); const attrs = this.element.attributes; for (let i = attrs.length - 1; i >= 0; i--) { @@ -91,8 +89,7 @@ export class CoreIconComponent implements OnChanges, OnDestroy { } } } - - } else { + } else if (attrs[i].name != 'name') { this.newElement.setAttribute(attrs[i].name, attrs[i].value); } } @@ -108,22 +105,6 @@ export class CoreIconComponent implements OnChanges, OnDestroy { oldElement.parentElement.replaceChild(this.newElement, oldElement); } - /** - * Check if the value is true or on. - * - * @param val value to be checked. - * @return If has a value equivalent to true. - */ - isTrueProperty(val: any): boolean { - if (typeof val === 'string') { - val = val.toLowerCase().trim(); - - return (val === 'true' || val === 'on' || val === ''); - } - - return !!val; - } - /** * Component destroyed. */ @@ -132,4 +113,5 @@ export class CoreIconComponent implements OnChanges, OnDestroy { this.newElement.remove(); } } + } From dd636e61fd5034ab88c9df287729118b3f29728e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Wed, 14 Oct 2020 23:30:15 +0200 Subject: [PATCH 3/6] MOBILE-3565 core: Remove globalization service from lang service --- package-lock.json | 13 --- package.json | 2 - src/app/core/emulator/emulator.module.ts | 2 - src/app/services/lang.ts | 106 +++++++++++++---------- src/app/singletons/core.singletons.ts | 2 - 5 files changed, 60 insertions(+), 65 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4c2bf21f4..60cadcaa4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2193,14 +2193,6 @@ "@types/cordova": "^0.0.34" } }, - "@ionic-native/globalization": { - "version": "5.28.0", - "resolved": "https://registry.npmjs.org/@ionic-native/globalization/-/globalization-5.28.0.tgz", - "integrity": "sha512-+L/svbUNnJgbeUs70G7vdRUjqWPIB2gOtUiCo7jr6BWsPqfw7iNjBF15ZjGLcbkzRIRd3wezTgPInbpqHDIWow==", - "requires": { - "@types/cordova": "^0.0.34" - } - }, "@ionic-native/http": { "version": "5.28.0", "resolved": "https://registry.npmjs.org/@ionic-native/http/-/http-5.28.0.tgz", @@ -6119,11 +6111,6 @@ "version": "git+https://github.com/apache/cordova-plugin-geolocation.git#89cf51d222e8f225bdfb661965b3007d669c40ff", "from": "git+https://github.com/apache/cordova-plugin-geolocation.git#89cf51d222e8f225bdfb661965b3007d669c40ff" }, - "cordova-plugin-globalization": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/cordova-plugin-globalization/-/cordova-plugin-globalization-1.11.0.tgz", - "integrity": "sha1-6sMVgQAphJOvowvolA5pj2HvvP4=" - }, "cordova-plugin-inappbrowser": { "version": "git+https://github.com/moodlemobile/cordova-plugin-inappbrowser.git#715c858975cc1cb5d140afaa7973938511d38509", "from": "git+https://github.com/moodlemobile/cordova-plugin-inappbrowser.git#moodle" diff --git a/package.json b/package.json index 14fd1b867..e42b50605 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,6 @@ "@ionic-native/file-opener": "^5.28.0", "@ionic-native/file-transfer": "^5.28.0", "@ionic-native/geolocation": "^5.28.0", - "@ionic-native/globalization": "^5.28.0", "@ionic-native/http": "^5.28.0", "@ionic-native/in-app-browser": "^5.28.0", "@ionic-native/ionic-webview": "^5.28.0", @@ -79,7 +78,6 @@ "cordova-plugin-file-opener2": "^3.0.5", "cordova-plugin-file-transfer": "1.7.1", "cordova-plugin-geolocation": "git+https://github.com/apache/cordova-plugin-geolocation.git#89cf51d222e8f225bdfb661965b3007d669c40ff", - "cordova-plugin-globalization": "1.11.0", "cordova-plugin-inappbrowser": "git+https://github.com/moodlemobile/cordova-plugin-inappbrowser.git#moodle", "cordova-plugin-ionic-keyboard": "2.1.3", "cordova-plugin-ionic-webview": "git+https://github.com/moodlemobile/cordova-plugin-ionic-webview.git#500-moodle", diff --git a/src/app/core/emulator/emulator.module.ts b/src/app/core/emulator/emulator.module.ts index 2b73dbc3f..dc81075e1 100644 --- a/src/app/core/emulator/emulator.module.ts +++ b/src/app/core/emulator/emulator.module.ts @@ -22,7 +22,6 @@ import { File } from '@ionic-native/file/ngx'; import { FileOpener } from '@ionic-native/file-opener/ngx'; import { FileTransfer } from '@ionic-native/file-transfer/ngx'; import { Geolocation } from '@ionic-native/geolocation/ngx'; -import { Globalization } from '@ionic-native/globalization/ngx'; import { HTTP } from '@ionic-native/http/ngx'; import { InAppBrowser } from '@ionic-native/in-app-browser/ngx'; import { WebView } from '@ionic-native/ionic-webview/ngx'; @@ -59,7 +58,6 @@ import { Zip } from '@ionic-native/zip/ngx'; FileOpener, FileTransfer, Geolocation, - Globalization, HTTP, InAppBrowser, Keyboard, diff --git a/src/app/services/lang.ts b/src/app/services/lang.ts index 2b89a0fd1..5a763614d 100644 --- a/src/app/services/lang.ts +++ b/src/app/services/lang.ts @@ -15,9 +15,10 @@ import { Injectable } from '@angular/core'; import CoreConfigConstants from '@app/config.json'; +import { LangChangeEvent } from '@ngx-translate/core'; import { CoreAppProvider } from '@services/app'; import { CoreConfig } from '@services/config'; -import { makeSingleton, Translate, Platform, Globalization } from '@singletons/core.singletons'; +import { makeSingleton, Translate, Platform } from '@singletons/core.singletons'; import * as moment from 'moment'; @@ -39,22 +40,33 @@ export class CoreLangProvider { Translate.instance.setDefaultLang(this.fallbackLanguage); Translate.instance.use(this.defaultLanguage); - Platform.instance.ready().then(() => { - if (CoreAppProvider.isAutomated()) { - // Force current language to English when Behat is running. - this.changeCurrentLanguage('en'); + this.initLanguage(); - return; - } + Translate.instance.onLangChange.subscribe((event: LangChangeEvent) => { + document.documentElement.setAttribute('lang', event.lang); - this.getCurrentLanguage().then((language) => { - this.changeCurrentLanguage(language); - }); + let dir = Translate.instance.instant('core.thisdirection'); + dir = dir.indexOf('rtl') != -1 ? 'rtl' : 'ltr'; + document.documentElement.setAttribute('dir', dir); }); + } - Translate.instance.onLangChange.subscribe(() => { - // @todo: Set platform lang and dir. - }); + /** + * Init language. + */ + protected async initLanguage(): Promise { + await Platform.instance.ready(); + + let language: string; + + if (CoreAppProvider.isAutomated()) { + // Force current language to English when Behat is running. + language = 'en'; + } else { + language = await this.getCurrentLanguage(); + } + + return this.changeCurrentLanguage(language); } /** @@ -221,43 +233,45 @@ export class CoreLangProvider { return this.currentLanguage; } + this.currentLanguage = await this.detectLanguage(); + + return this.currentLanguage; + } + + /** + * Get the current language from settings, or detect the browser one. + * + * @return Promise resolved with the selected language. + */ + protected async detectLanguage(): Promise { // Get current language from config (user might have changed it). - return CoreConfig.instance.get('current_language').then((language) => language).catch(() => { - // User hasn't defined a language. If default language is forced, use it. - if (CoreConfigConstants.default_lang && CoreConfigConstants.forcedefaultlanguage) { - return CoreConfigConstants.default_lang; + try { + return CoreConfig.instance.get('current_language'); + } catch (e) { + // Try will return, ignore errors here to avoid nesting. + } + + // User hasn't defined a language. If default language is forced, use it. + if (CoreConfigConstants.default_lang && CoreConfigConstants.forcedefaultlanguage) { + return CoreConfigConstants.default_lang; + } + + // No forced language, try to get current language from browser. + let preferredLanguage = navigator.language.toLowerCase(); + if (preferredLanguage.indexOf('-') > -1) { + // Language code defined by locale has a dash, like en-US or es-ES. Check if it's supported. + if (CoreConfigConstants.languages && typeof CoreConfigConstants.languages[preferredLanguage] == 'undefined') { + // Code is NOT supported. Fallback to language without dash. E.g. 'en-US' would fallback to 'en'. + preferredLanguage = preferredLanguage.substr(0, preferredLanguage.indexOf('-')); } + } - try { - // No forced language, try to get current language from cordova globalization. - return Globalization.instance.getPreferredLanguage().then((result) => { - let language = result.value.toLowerCase(); - if (language.indexOf('-') > -1) { - // Language code defined by locale has a dash, like en-US or es-ES. Check if it's supported. - if (CoreConfigConstants.languages && typeof CoreConfigConstants.languages[language] == 'undefined') { - // Code is NOT supported. Fallback to language without dash. E.g. 'en-US' would fallback to 'en'. - language = language.substr(0, language.indexOf('-')); - } - } + if (typeof CoreConfigConstants.languages[preferredLanguage] == 'undefined') { + // Language not supported, use default language. + return this.defaultLanguage; + } - if (typeof CoreConfigConstants.languages[language] == 'undefined') { - // Language not supported, use default language. - return this.defaultLanguage; - } - - return language; - }).catch(() => - // Error getting locale. Use default language. - this.defaultLanguage); - } catch (err) { - // Error getting locale. Use default language. - return Promise.resolve(this.defaultLanguage); - } - }).then((language) => { - this.currentLanguage = language; // Save it for later. - - return language; - }); + return preferredLanguage; } /** diff --git a/src/app/singletons/core.singletons.ts b/src/app/singletons/core.singletons.ts index 441573fa5..45fcba1a6 100644 --- a/src/app/singletons/core.singletons.ts +++ b/src/app/singletons/core.singletons.ts @@ -30,7 +30,6 @@ import { File as FileService } from '@ionic-native/file/ngx'; import { FileOpener as FileOpenerService } from '@ionic-native/file-opener/ngx'; import { FileTransfer as FileTransferService } from '@ionic-native/file-transfer/ngx'; import { Geolocation as GeolocationService } from '@ionic-native/geolocation/ngx'; -import { Globalization as GlobalizationService } from '@ionic-native/globalization/ngx'; import { HTTP } from '@ionic-native/http/ngx'; import { InAppBrowser as InAppBrowserService } from '@ionic-native/in-app-browser/ngx'; import { WebView as WebViewService } from '@ionic-native/ionic-webview/ngx'; @@ -78,7 +77,6 @@ export class File extends makeSingleton(FileService) {} export class FileOpener extends makeSingleton(FileOpenerService) {} export class FileTransfer extends makeSingleton(FileTransferService) {} export class Geolocation extends makeSingleton(GeolocationService) {} -export class Globalization extends makeSingleton(GlobalizationService) {} export class InAppBrowser extends makeSingleton(InAppBrowserService) {} export class Keyboard extends makeSingleton(KeyboardService) {} export class LocalNotifications extends makeSingleton(LocalNotificationsService) {} From 8fef21ff554cee6721ab2ca9f6557632ed8be721 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Thu, 15 Oct 2020 10:09:23 +0200 Subject: [PATCH 4/6] MOBILE-3565 core: Fix SQL params --- src/app/classes/sqlitedb.ts | 133 ++++++++++++++++++++++++++---------- 1 file changed, 97 insertions(+), 36 deletions(-) diff --git a/src/app/classes/sqlitedb.ts b/src/app/classes/sqlitedb.ts index ff0acb7da..6cd1e7b68 100644 --- a/src/app/classes/sqlitedb.ts +++ b/src/app/classes/sqlitedb.ts @@ -156,8 +156,14 @@ export class SQLiteDB { * @param tableCheck Check constraint for the table. * @return SQL query. */ - buildCreateTableSql(name: string, columns: SQLiteDBColumnSchema[], primaryKeys?: string[], uniqueKeys?: string[][], - foreignKeys?: SQLiteDBForeignKeySchema[], tableCheck?: string): string { + buildCreateTableSql( + name: string, + columns: SQLiteDBColumnSchema[], + primaryKeys?: string[], + uniqueKeys?: string[][], + foreignKeys?: SQLiteDBForeignKeySchema[], + tableCheck?: string, + ): string { const columnsSql = []; let sql = `CREATE TABLE IF NOT EXISTS ${name} (`; @@ -258,7 +264,7 @@ export class SQLiteDB { async countRecords(table: string, conditions?: SQLiteDBRecordValues): Promise { const selectAndParams = this.whereClause(conditions); - return this.countRecordsSelect(table, selectAndParams[0], selectAndParams[1]); + return this.countRecordsSelect(table, selectAndParams.sql, selectAndParams.params); } /** @@ -270,8 +276,12 @@ export class SQLiteDB { * @param countItem The count string to be used in the SQL call. Default is COUNT('x'). * @return Promise resolved with the count of records returned from the specified criteria. */ - async countRecordsSelect(table: string, select: string = '', params?: SQLiteDBRecordValue[], - countItem: string = 'COUNT(\'x\')'): Promise { + async countRecordsSelect( + table: string, + select: string = '', + params?: SQLiteDBRecordValue[], + countItem: string = 'COUNT(\'x\')', + ): Promise { if (select) { select = 'WHERE ' + select; } @@ -308,8 +318,14 @@ export class SQLiteDB { * @param tableCheck Check constraint for the table. * @return Promise resolved when success. */ - async createTable(name: string, columns: SQLiteDBColumnSchema[], primaryKeys?: string[], uniqueKeys?: string[][], - foreignKeys?: SQLiteDBForeignKeySchema[], tableCheck?: string): Promise { + async createTable( + name: string, + columns: SQLiteDBColumnSchema[], + primaryKeys?: string[], + uniqueKeys?: string[][], + foreignKeys?: SQLiteDBForeignKeySchema[], + tableCheck?: string, + ): Promise { const sql = this.buildCreateTableSql(name, columns, primaryKeys, uniqueKeys, foreignKeys, tableCheck); await this.execute(sql); @@ -358,7 +374,7 @@ export class SQLiteDB { const selectAndParams = this.whereClause(conditions); - return this.deleteRecordsSelect(table, selectAndParams[0], selectAndParams[1]); + return this.deleteRecordsSelect(table, selectAndParams.sql, selectAndParams.params); } /** @@ -372,7 +388,7 @@ export class SQLiteDB { async deleteRecordsList(table: string, field: string, values: SQLiteDBRecordValue[]): Promise { const selectAndParams = this.whereClauseList(field, values); - return this.deleteRecordsSelect(table, selectAndParams[0], selectAndParams[1]); + return this.deleteRecordsSelect(table, selectAndParams.sql, selectAndParams.params); } /** @@ -483,7 +499,7 @@ export class SQLiteDB { async getField(table: string, field: string, conditions?: SQLiteDBRecordValues): Promise { const selectAndParams = this.whereClause(conditions); - return this.getFieldSelect(table, field, selectAndParams[0], selectAndParams[1]); + return this.getFieldSelect(table, field, selectAndParams.sql, selectAndParams.params); } /** @@ -495,8 +511,12 @@ export class SQLiteDB { * @param params Array of sql parameters. * @return Promise resolved with the field's value. */ - async getFieldSelect(table: string, field: string, select: string = '', params?: SQLiteDBRecordValue[]): - Promise { + async getFieldSelect( + table: string, + field: string, + select: string = '', + params?: SQLiteDBRecordValue[], + ): Promise { if (select) { select = 'WHERE ' + select; } @@ -529,8 +549,11 @@ export class SQLiteDB { * meaning return empty. Other values will become part of the returned SQL fragment. * @return A list containing the constructed sql fragment and an array of parameters. */ - getInOrEqual(items: SQLiteDBRecordValue | SQLiteDBRecordValue[], equal: boolean = true, onEmptyItems?: SQLiteDBRecordValue): - SQLiteDBQueryParams { + getInOrEqual( + items: SQLiteDBRecordValue | SQLiteDBRecordValue[], + equal: boolean = true, + onEmptyItems?: SQLiteDBRecordValue, + ): SQLiteDBQueryParams { let sql = ''; let params: SQLiteDBRecordValue[]; @@ -581,7 +604,7 @@ export class SQLiteDB { getRecord(table: string, conditions?: SQLiteDBRecordValues, fields: string = '*'): Promise { const selectAndParams = this.whereClause(conditions); - return this.getRecordSelect(table, selectAndParams[0], selectAndParams[1], fields); + return this.getRecordSelect(table, selectAndParams.sql, selectAndParams.params, fields); } /** @@ -593,8 +616,12 @@ export class SQLiteDB { * @param fields A comma separated list of fields to return. * @return Promise resolved with the record, rejected if not found. */ - getRecordSelect(table: string, select: string = '', params: SQLiteDBRecordValue[] = [], fields: string = '*'): - Promise { + getRecordSelect( + table: string, + select: string = '', + params: SQLiteDBRecordValue[] = [], + fields: string = '*', + ): Promise { if (select) { select = ' WHERE ' + select; } @@ -633,11 +660,17 @@ export class SQLiteDB { * @param limitNum Return a subset comprising this many records in total. * @return Promise resolved with the records. */ - getRecords(table: string, conditions?: SQLiteDBRecordValues, sort: string = '', fields: string = '*', - limitFrom: number = 0, limitNum: number = 0): Promise { + getRecords( + table: string, + conditions?: SQLiteDBRecordValues, + sort: string = '', + fields: string = '*', + limitFrom: number = 0, + limitNum: number = 0, + ): Promise { const selectAndParams = this.whereClause(conditions); - return this.getRecordsSelect(table, selectAndParams[0], selectAndParams[1], sort, fields, limitFrom, limitNum); + return this.getRecordsSelect(table, selectAndParams.sql, selectAndParams.params, sort, fields, limitFrom, limitNum); } /** @@ -652,11 +685,18 @@ export class SQLiteDB { * @param limitNum Return a subset comprising this many records in total. * @return Promise resolved with the records. */ - getRecordsList(table: string, field: string, values: SQLiteDBRecordValue[], sort: string = '', - fields: string = '*', limitFrom: number = 0, limitNum: number = 0): Promise { + getRecordsList( + table: string, + field: string, + values: SQLiteDBRecordValue[], + sort: string = '', + fields: string = '*', + limitFrom: number = 0, + limitNum: number = 0, + ): Promise { const selectAndParams = this.whereClauseList(field, values); - return this.getRecordsSelect(table, selectAndParams[0], selectAndParams[1], sort, fields, limitFrom, limitNum); + return this.getRecordsSelect(table, selectAndParams.sql, selectAndParams.params, sort, fields, limitFrom, limitNum); } /** @@ -671,8 +711,15 @@ export class SQLiteDB { * @param limitNum Return a subset comprising this many records in total. * @return Promise resolved with the records. */ - getRecordsSelect(table: string, select: string = '', params: SQLiteDBRecordValue[] = [], sort: string = '', - fields: string = '*', limitFrom: number = 0, limitNum: number = 0): Promise { + getRecordsSelect( + table: string, + select: string = '', + params: SQLiteDBRecordValue[] = [], + sort: string = '', + fields: string = '*', + limitFrom: number = 0, + limitNum: number = 0, + ): Promise { if (select) { select = ' WHERE ' + select; } @@ -694,8 +741,12 @@ export class SQLiteDB { * @param limitNum Return a subset comprising this many records. * @return Promise resolved with the records. */ - async getRecordsSql(sql: string, params?: SQLiteDBRecordValue[], limitFrom?: number, limitNum?: number): - Promise { + async getRecordsSql( + sql: string, + params?: SQLiteDBRecordValue[], + limitFrom?: number, + limitNum?: number, + ): Promise { const limits = this.normaliseLimitFromNum(limitFrom, limitNum); if (limits[0] || limits[1]) { @@ -746,6 +797,8 @@ export class SQLiteDB { })) .then((db: SQLiteObject) => { this.db = db; + + return; }); } @@ -758,7 +811,7 @@ export class SQLiteDB { */ async insertRecord(table: string, data: SQLiteDBRecordValues): Promise { const sqlAndParams = this.getSqlInsertQuery(table, data); - const result = await this.execute(sqlAndParams[0], sqlAndParams[1]); + const result = await this.execute(sqlAndParams.sql, sqlAndParams.params); return result.insertId; } @@ -772,7 +825,7 @@ export class SQLiteDB { */ async insertRecords(table: string, dataObjects: SQLiteDBRecordValues[]): Promise { if (!Array.isArray(dataObjects)) { - throw new CoreError('Invalid parameter supplied to insertRecords, it should be an array.'); + throw new CoreError('Invalid parameter supplied to insertRecords, it should be an array.'); } const statements = dataObjects.map((dataObject) => { @@ -793,11 +846,15 @@ export class SQLiteDB { * @param fields A comma separated list of fields to return. * @return Promise resolved when done. */ - async insertRecordsFrom(table: string, source: string, conditions?: SQLiteDBRecordValues, fields: string = '*'): - Promise { + async insertRecordsFrom( + table: string, + source: string, + conditions?: SQLiteDBRecordValues, + fields: string = '*', + ): Promise { const selectAndParams = this.whereClause(conditions); - const select = selectAndParams[0] ? 'WHERE ' + selectAndParams[0] : ''; - const params = selectAndParams[1]; + const select = selectAndParams.sql ? 'WHERE ' + selectAndParams.sql : ''; + const params = selectAndParams.params; await this.execute(`INSERT INTO ${table} SELECT ${fields} FROM ${source} ${select}`, params); } @@ -913,7 +970,7 @@ export class SQLiteDB { async updateRecords(table: string, data: SQLiteDBRecordValues, conditions?: SQLiteDBRecordValues): Promise { const whereAndParams = this.whereClause(conditions); - return this.updateRecordsWhere(table, data, whereAndParams[0], whereAndParams[1]); + return this.updateRecordsWhere(table, data, whereAndParams.sql, whereAndParams.params); } /** @@ -925,8 +982,12 @@ export class SQLiteDB { * @param whereParams Params for the where clause. * @return Promise resolved with the number of affected rows. */ - async updateRecordsWhere(table: string, data: SQLiteDBRecordValues, where?: string, whereParams?: SQLiteDBRecordValue[]): - Promise { + async updateRecordsWhere( + table: string, + data: SQLiteDBRecordValues, + where?: string, + whereParams?: SQLiteDBRecordValue[], + ): Promise { this.formatDataToInsert(data); if (!data || !Object.keys(data).length) { // No fields to update, consider it's done. From 21de5fc66a8f9ca64232ddf372405474c6757f93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Thu, 15 Oct 2020 10:21:27 +0200 Subject: [PATCH 5/6] MOBILE-3565 gulp: Install gulp --- package-lock.json | 2023 +++++++++++++++++++++++++++++++++++++++++++++ package.json | 7 + 2 files changed, 2030 insertions(+) diff --git a/package-lock.json b/package-lock.json index 60cadcaa4..db4ec28a4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3827,17 +3827,44 @@ "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==", "dev": true }, + "ansi-cyan": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-cyan/-/ansi-cyan-0.1.1.tgz", + "integrity": "sha1-U4rlKK+JgvKK4w2G8vF0VtJgmHM=", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, "ansi-escapes": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==" }, + "ansi-gray": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", + "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, "ansi-html": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=", "dev": true }, + "ansi-red": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-red/-/ansi-red-0.1.1.tgz", + "integrity": "sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw=", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, "ansi-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", @@ -3851,6 +3878,12 @@ "color-convert": "^2.0.1" } }, + "ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", + "dev": true + }, "anymatch": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", @@ -3861,12 +3894,27 @@ "picomatch": "^2.0.4" } }, + "append-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", + "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", + "dev": true, + "requires": { + "buffer-equal": "^1.0.0" + } + }, "aproba": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "dev": true }, + "archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "dev": true + }, "arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", @@ -3894,18 +3942,42 @@ "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", "dev": true }, + "arr-filter": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", + "integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=", + "dev": true, + "requires": { + "make-iterator": "^1.0.0" + } + }, "arr-flatten": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", "dev": true }, + "arr-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", + "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=", + "dev": true, + "requires": { + "make-iterator": "^1.0.0" + } + }, "arr-union": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", "dev": true }, + "array-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", + "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", + "dev": true + }, "array-find-index": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", @@ -3953,6 +4025,66 @@ } } }, + "array-initial": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", + "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=", + "dev": true, + "requires": { + "array-slice": "^1.0.0", + "is-number": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + } + } + }, + "array-last": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", + "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", + "dev": true, + "requires": { + "is-number": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + } + } + }, + "array-slice": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", + "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", + "dev": true + }, + "array-sort": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", + "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", + "dev": true, + "requires": { + "default-compare": "^1.0.0", + "get-value": "^2.0.6", + "kind-of": "^5.0.2" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, "array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", @@ -4069,6 +4201,18 @@ "lodash": "^4.17.14" } }, + "async-done": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", + "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.2", + "process-nextick-args": "^2.0.0", + "stream-exhaust": "^1.0.1" + } + }, "async-each": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", @@ -4081,6 +4225,15 @@ "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", "dev": true }, + "async-settle": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", + "integrity": "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=", + "dev": true, + "requires": { + "async-done": "^1.2.2" + } + }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -4332,6 +4485,23 @@ "babel-preset-current-node-syntax": "^0.1.3" } }, + "bach": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", + "integrity": "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=", + "dev": true, + "requires": { + "arr-filter": "^1.1.1", + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "array-each": "^1.0.0", + "array-initial": "^1.0.0", + "array-last": "^1.1.1", + "async-done": "^1.2.2", + "async-settle": "^1.0.0", + "now-and-later": "^2.0.0" + } + }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -4744,6 +4914,12 @@ "isarray": "^1.0.0" } }, + "buffer-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", + "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", + "dev": true + }, "buffer-from": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", @@ -4903,6 +5079,16 @@ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" }, + "camel-case": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", + "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=", + "dev": true, + "requires": { + "no-case": "^2.2.0", + "upper-case": "^1.1.1" + } + }, "camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", @@ -5124,6 +5310,23 @@ } } }, + "clean-css": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz", + "integrity": "sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==", + "dev": true, + "requires": { + "source-map": "~0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, "clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", @@ -5184,6 +5387,12 @@ "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", "dev": true }, + "clone-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", + "dev": true + }, "clone-deep": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", @@ -5203,6 +5412,23 @@ "mimic-response": "^1.0.0" } }, + "clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", + "dev": true + }, + "cloneable-readable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", + "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "process-nextick-args": "^2.0.0", + "readable-stream": "^2.3.5" + } + }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -5272,12 +5498,29 @@ } } }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, "collect-v8-coverage": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", "dev": true }, + "collection-map": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", + "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", + "dev": true, + "requires": { + "arr-map": "^2.0.2", + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } + }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", @@ -5338,6 +5581,12 @@ "simple-swizzle": "^0.2.2" } }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true + }, "colorette": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.1.0.tgz", @@ -5458,6 +5707,23 @@ "typedarray": "^0.0.6" } }, + "concat-with-sourcemaps": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz", + "integrity": "sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==", + "dev": true, + "requires": { + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, "conf": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/conf/-/conf-1.4.0.tgz", @@ -5608,6 +5874,16 @@ "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", "dev": true }, + "copy-props": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.4.tgz", + "integrity": "sha512-7cjuUME+p+S3HZlbllgsn2CDwS+5eCCX16qBgNC4jgSTf49qR1VKy/Zhl400m0IQXl/bPGEVqncgUUMjrr4s8A==", + "dev": true, + "requires": { + "each-props": "^1.3.0", + "is-plain-object": "^2.0.1" + } + }, "copy-webpack-plugin": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-6.0.3.tgz", @@ -6763,6 +7039,23 @@ "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", "dev": true }, + "default-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", + "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", + "dev": true, + "requires": { + "kind-of": "^5.0.2" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, "default-gateway": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-4.2.0.tgz", @@ -6863,6 +7156,12 @@ } } }, + "default-resolution": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz", + "integrity": "sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=", + "dev": true + }, "defaults": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", @@ -7049,6 +7348,12 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" }, + "detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", + "dev": true + }, "detect-indent": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.0.0.tgz", @@ -7239,6 +7544,16 @@ "stream-shift": "^1.0.0" } }, + "each-props": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", + "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.1", + "object.defaults": "^1.1.0" + } + }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -7501,6 +7816,18 @@ "ext": "^1.1.2" } }, + "es6-weak-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } + }, "escalade": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.0.tgz", @@ -8048,6 +8375,15 @@ } } }, + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, "expect": { "version": "26.5.2", "resolved": "https://registry.npmjs.org/expect/-/expect-26.5.2.tgz", @@ -8238,6 +8574,18 @@ "integrity": "sha512-RrWKFSSA/aNLP0g3o2WW1Zez7/MnMr7xkiZmoCfAGZmdkDQZ6l2KtuXHN5XjdvpRjDl8+3vf+Rrtl06Z352+Mw==", "dev": true }, + "fancy-log": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", + "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", + "dev": true, + "requires": { + "ansi-gray": "^0.1.1", + "color-support": "^1.1.3", + "parse-node-version": "^1.0.0", + "time-stamp": "^1.0.0" + } + }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -8433,6 +8781,148 @@ "locate-path": "^2.0.0" } }, + "findup-sync": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", + "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + }, + "dependencies": { + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + } + } + }, + "fined": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", + "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "is-plain-object": "^2.0.3", + "object.defaults": "^1.1.0", + "object.pick": "^1.2.0", + "parse-filepath": "^1.0.1" + } + }, + "flagged-respawn": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", + "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", + "dev": true + }, "flat-cache": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", @@ -8488,6 +8978,15 @@ "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", "dev": true }, + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "dev": true, + "requires": { + "for-in": "^1.0.1" + } + }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -8552,6 +9051,16 @@ "minipass": "^3.0.0" } }, + "fs-mkdirp-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", + "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "through2": "^2.0.3" + } + }, "fs-write-stream-atomic": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", @@ -8661,6 +9170,270 @@ "is-glob": "^4.0.1" } }, + "glob-stream": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", + "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", + "dev": true, + "requires": { + "extend": "^3.0.0", + "glob": "^7.1.1", + "glob-parent": "^3.1.0", + "is-negated-glob": "^1.0.0", + "ordered-read-streams": "^1.0.0", + "pumpify": "^1.3.5", + "readable-stream": "^2.1.5", + "remove-trailing-separator": "^1.0.1", + "to-absolute-glob": "^2.0.0", + "unique-stream": "^2.0.2" + }, + "dependencies": { + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + } + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "glob-watcher": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.5.tgz", + "integrity": "sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-done": "^1.2.0", + "chokidar": "^2.0.0", + "is-negated-glob": "^1.0.0", + "just-debounce": "^1.0.0", + "normalize-path": "^3.0.0", + "object.defaults": "^1.1.0" + }, + "dependencies": { + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "dev": true, + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + } + } + }, "global-dirs": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.0.1.tgz", @@ -8669,6 +9442,41 @@ "ini": "^1.3.5" } }, + "global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dev": true, + "requires": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + } + }, + "global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + }, + "dependencies": { + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, "globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", @@ -8688,6 +9496,15 @@ "slash": "^3.0.0" } }, + "glogg": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", + "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", + "dev": true, + "requires": { + "sparkles": "^1.0.0" + } + }, "got": { "version": "9.6.0", "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", @@ -8728,6 +9545,403 @@ "dev": true, "optional": true }, + "gulp": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", + "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", + "dev": true, + "requires": { + "glob-watcher": "^5.0.3", + "gulp-cli": "^2.2.0", + "undertaker": "^1.2.1", + "vinyl-fs": "^3.0.0" + }, + "dependencies": { + "ansi-colors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", + "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", + "dev": true, + "requires": { + "ansi-wrap": "^0.1.0" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true + }, + "gulp-cli": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.3.0.tgz", + "integrity": "sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A==", + "dev": true, + "requires": { + "ansi-colors": "^1.0.1", + "archy": "^1.0.0", + "array-sort": "^1.0.0", + "color-support": "^1.1.3", + "concat-stream": "^1.6.0", + "copy-props": "^2.0.1", + "fancy-log": "^1.3.2", + "gulplog": "^1.0.0", + "interpret": "^1.4.0", + "isobject": "^3.0.1", + "liftoff": "^3.1.0", + "matchdep": "^2.0.0", + "mute-stdout": "^1.0.0", + "pretty-hrtime": "^1.0.0", + "replace-homedir": "^1.0.0", + "semver-greatest-satisfied-range": "^1.1.0", + "v8flags": "^3.2.0", + "yargs": "^7.1.0" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + } + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", + "dev": true + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + } + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yargs": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.1.tgz", + "integrity": "sha512-huO4Fr1f9PmiJJdll5kwoS2e4GqzGSsMT3PPMpOwoVkOK8ckqAewMTZyA6LXVQWflleb/Z8oPBEvNsMft0XE+g==", + "dev": true, + "requires": { + "camelcase": "^3.0.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.2", + "which-module": "^1.0.0", + "y18n": "^3.2.1", + "yargs-parser": "5.0.0-security.0" + } + }, + "yargs-parser": { + "version": "5.0.0-security.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0-security.0.tgz", + "integrity": "sha512-T69y4Ps64LNesYxeYGYPvfoMTt/7y1XtfpIslUeK4um+9Hu7hlGoRtaDLvdXb7+/tfq4opVa2HRY5xGip022rQ==", + "dev": true, + "requires": { + "camelcase": "^3.0.0", + "object.assign": "^4.1.0" + } + } + } + }, + "gulp-clip-empty-files": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/gulp-clip-empty-files/-/gulp-clip-empty-files-0.1.2.tgz", + "integrity": "sha1-vumATiU7vaVc+8Em6NuuZDPtzMg=", + "dev": true, + "requires": { + "through2": "~2.0.1" + } + }, + "gulp-concat": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.6.1.tgz", + "integrity": "sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M=", + "dev": true, + "requires": { + "concat-with-sourcemaps": "^1.0.0", + "through2": "^2.0.0", + "vinyl": "^2.0.0" + } + }, + "gulp-flatten": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/gulp-flatten/-/gulp-flatten-0.4.0.tgz", + "integrity": "sha512-eg4spVTAiv1xXmugyaCxWne1oPtNG0UHEtABx5W8ScLiqAYceyYm6GYA36x0Qh8KOIXmAZV97L2aYGnKREG3Sg==", + "dev": true, + "requires": { + "plugin-error": "^0.1.2", + "through2": "^2.0.0" + } + }, + "gulp-htmlmin": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/gulp-htmlmin/-/gulp-htmlmin-5.0.1.tgz", + "integrity": "sha512-ASlyDPZOSKjHYUifYV0rf9JPDflN9IRIb8lw2vRqtYMC4ljU3zAmnnaVXwFQ3H+CfXxZSUesZ2x7jrnPJu93jA==", + "dev": true, + "requires": { + "html-minifier": "^3.5.20", + "plugin-error": "^1.0.1", + "through2": "^2.0.3" + }, + "dependencies": { + "ansi-colors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", + "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", + "dev": true, + "requires": { + "ansi-wrap": "^0.1.0" + } + }, + "plugin-error": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", + "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", + "dev": true, + "requires": { + "ansi-colors": "^1.0.1", + "arr-diff": "^4.0.0", + "arr-union": "^3.1.0", + "extend-shallow": "^3.0.2" + } + } + } + }, + "gulp-rename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-2.0.0.tgz", + "integrity": "sha512-97Vba4KBzbYmR5VBs9mWmK+HwIf5mj+/zioxfZhOKeXtx5ZjBk57KFlePf5nxq9QsTtFl0ejnHE3zTC9MHXqyQ==", + "dev": true + }, + "gulp-slash": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/gulp-slash/-/gulp-slash-1.1.3.tgz", + "integrity": "sha1-8VUhrCOxeNtE5VHjDi/Lykv2/h0=", + "dev": true, + "requires": { + "slash": "~0.1.3", + "through2": "~0.5.1" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "slash": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/slash/-/slash-0.1.3.tgz", + "integrity": "sha1-qnEMjvULjh0YetbP9G84xla6Dlc=", + "dev": true + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "through2": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", + "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", + "dev": true, + "requires": { + "readable-stream": "~1.0.17", + "xtend": "~3.0.0" + } + }, + "xtend": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz", + "integrity": "sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=", + "dev": true + } + } + }, + "gulplog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", + "dev": true, + "requires": { + "glogg": "^1.0.0" + } + }, "handle-thing": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", @@ -8873,6 +10087,12 @@ "minimalistic-assert": "^1.0.1" } }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true + }, "hex-color-regex": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz", @@ -8890,6 +10110,15 @@ "minimalistic-crypto-utils": "^1.0.1" } }, + "homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dev": true, + "requires": { + "parse-passwd": "^1.0.0" + } + }, "hosted-git-info": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.5.tgz", @@ -8949,6 +10178,29 @@ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, + "html-minifier": { + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.21.tgz", + "integrity": "sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA==", + "dev": true, + "requires": { + "camel-case": "3.0.x", + "clean-css": "4.2.x", + "commander": "2.17.x", + "he": "1.2.x", + "param-case": "2.1.x", + "relateurl": "0.2.x", + "uglify-js": "3.4.x" + }, + "dependencies": { + "commander": { + "version": "2.17.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", + "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", + "dev": true + } + } + }, "htmlparser2": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", @@ -9552,6 +10804,12 @@ "ipaddr.js": "^1.9.0" } }, + "interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "dev": true + }, "invariant": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", @@ -9561,6 +10819,12 @@ "loose-envify": "^1.0.0" } }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true + }, "ionicons": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/ionicons/-/ionicons-5.1.2.tgz", @@ -9608,6 +10872,16 @@ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" }, + "is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "dev": true, + "requires": { + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" + } + }, "is-absolute-url": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz", @@ -9790,6 +11064,12 @@ "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", "dev": true }, + "is-negated-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", + "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=", + "dev": true + }, "is-negative-zero": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", @@ -9880,6 +11160,15 @@ "has-symbols": "^1.0.1" } }, + "is-relative": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "dev": true, + "requires": { + "is-unc-path": "^1.0.0" + } + }, "is-resolvable": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", @@ -9920,6 +11209,27 @@ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" }, + "is-unc-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "dev": true, + "requires": { + "unc-path-regex": "^0.1.2" + } + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is-valid-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", + "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=", + "dev": true + }, "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", @@ -11242,6 +12552,12 @@ } } }, + "just-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.0.0.tgz", + "integrity": "sha1-h/zPrv/AtozRnVX2cilD+SnqNeo=", + "dev": true + }, "karma-source-map-support": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/karma-source-map-support/-/karma-source-map-support-1.4.0.tgz", @@ -11277,6 +12593,16 @@ "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", "dev": true }, + "last-run": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", + "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", + "dev": true, + "requires": { + "default-resolution": "^2.0.0", + "es6-weak-map": "^2.0.1" + } + }, "latest-version": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", @@ -11285,6 +12611,33 @@ "package-json": "^6.3.0" } }, + "lazystream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "dev": true, + "requires": { + "readable-stream": "^2.0.5" + } + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "^1.0.0" + } + }, + "lead": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", + "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", + "dev": true, + "requires": { + "flush-write-stream": "^1.0.2" + } + }, "less": { "version": "3.12.2", "resolved": "https://registry.npmjs.org/less/-/less-3.12.2.tgz", @@ -11381,6 +12734,22 @@ "webpack-sources": "^1.2.0" } }, + "liftoff": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", + "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", + "dev": true, + "requires": { + "extend": "^3.0.0", + "findup-sync": "^3.0.0", + "fined": "^1.0.1", + "flagged-respawn": "^1.0.0", + "is-plain-object": "^2.0.4", + "object.map": "^1.0.0", + "rechoir": "^0.6.2", + "resolve": "^1.1.7" + } + }, "lines-and-columns": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", @@ -11567,6 +12936,12 @@ "signal-exit": "^3.0.2" } }, + "lower-case": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", + "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=", + "dev": true + }, "lowercase-keys": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", @@ -11704,6 +13079,15 @@ } } }, + "make-iterator": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", + "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", + "dev": true, + "requires": { + "kind-of": "^6.0.2" + } + }, "makeerror": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz", @@ -11728,6 +13112,150 @@ "object-visit": "^1.0.0" } }, + "matchdep": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", + "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", + "dev": true, + "requires": { + "findup-sync": "^2.0.0", + "micromatch": "^3.0.4", + "resolve": "^1.4.0", + "stack-trace": "0.0.10" + }, + "dependencies": { + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "findup-sync": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", + "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^3.1.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + } + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + } + } + }, "md5-file": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/md5-file/-/md5-file-5.0.0.tgz", @@ -12107,6 +13635,12 @@ "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=", "dev": true }, + "mute-stdout": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", + "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==", + "dev": true + }, "mute-stream": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", @@ -12178,6 +13712,15 @@ "resolved": "https://registry.npmjs.org/nl.kingsquare.cordova.background-audio/-/nl.kingsquare.cordova.background-audio-1.0.1.tgz", "integrity": "sha1-Gx1NzaijXAx/x5UzN7FzsUtPmGA=" }, + "no-case": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", + "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", + "dev": true, + "requires": { + "lower-case": "^1.1.1" + } + }, "node-fetch-npm": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/node-fetch-npm/-/node-fetch-npm-2.0.4.tgz", @@ -12340,6 +13883,15 @@ "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==" }, + "now-and-later": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", + "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", + "dev": true, + "requires": { + "once": "^1.3.2" + } + }, "npm-bundled": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz", @@ -12480,6 +14032,12 @@ "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", "dev": true }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, "nwsapi": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", @@ -12585,6 +14143,26 @@ "object-keys": "^1.1.1" } }, + "object.defaults": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", + "dev": true, + "requires": { + "array-each": "^1.0.1", + "array-slice": "^1.0.0", + "for-own": "^1.0.0", + "isobject": "^3.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, "object.getownpropertydescriptors": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", @@ -12616,6 +14194,16 @@ } } }, + "object.map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", + "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", + "dev": true, + "requires": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } + }, "object.pick": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", @@ -12633,6 +14221,16 @@ } } }, + "object.reduce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.reduce/-/object.reduce-1.0.1.tgz", + "integrity": "sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60=", + "dev": true, + "requires": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } + }, "object.values": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", @@ -12798,6 +14396,15 @@ } } }, + "ordered-read-streams": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", + "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", + "dev": true, + "requires": { + "readable-stream": "^2.0.1" + } + }, "original": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz", @@ -12818,6 +14425,15 @@ "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, + "requires": { + "lcid": "^1.0.0" + } + }, "os-name": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/os-name/-/os-name-3.1.0.tgz", @@ -13136,6 +14752,15 @@ "readable-stream": "^2.1.5" } }, + "param-case": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", + "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=", + "dev": true, + "requires": { + "no-case": "^2.2.0" + } + }, "parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -13157,6 +14782,17 @@ "safe-buffer": "^5.1.1" } }, + "parse-filepath": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", + "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", + "dev": true, + "requires": { + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" + } + }, "parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", @@ -13167,6 +14803,18 @@ "json-parse-better-errors": "^1.0.1" } }, + "parse-node-version": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", + "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", + "dev": true + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true + }, "parse5": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", @@ -13221,6 +14869,21 @@ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" }, + "path-root": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", + "dev": true, + "requires": { + "path-root-regex": "^0.1.0" + } + }, + "path-root-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", + "dev": true + }, "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", @@ -13362,6 +15025,58 @@ "xmldom": "0.1.x" } }, + "plugin-error": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz", + "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=", + "dev": true, + "requires": { + "ansi-cyan": "^0.1.1", + "ansi-red": "^0.1.1", + "arr-diff": "^1.0.1", + "arr-union": "^2.0.1", + "extend-shallow": "^1.1.2" + }, + "dependencies": { + "arr-diff": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz", + "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=", + "dev": true, + "requires": { + "arr-flatten": "^1.0.1", + "array-slice": "^0.2.3" + } + }, + "arr-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-2.1.0.tgz", + "integrity": "sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0=", + "dev": true + }, + "array-slice": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", + "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", + "dev": true + }, + "extend-shallow": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-1.1.4.tgz", + "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=", + "dev": true, + "requires": { + "kind-of": "^1.1.0" + } + }, + "kind-of": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz", + "integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=", + "dev": true + } + } + }, "pnp-webpack-plugin": { "version": "1.6.4", "resolved": "https://registry.npmjs.org/pnp-webpack-plugin/-/pnp-webpack-plugin-1.6.4.tgz", @@ -14199,6 +15914,12 @@ } } }, + "pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", + "dev": true + }, "process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -14605,6 +16326,15 @@ "picomatch": "^2.2.1" } }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "requires": { + "resolve": "^1.1.6" + } + }, "reflect-metadata": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", @@ -14753,6 +16483,33 @@ } } }, + "relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", + "dev": true + }, + "remove-bom-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", + "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5", + "is-utf8": "^0.2.1" + } + }, + "remove-bom-stream": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", + "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", + "dev": true, + "requires": { + "remove-bom-buffer": "^3.0.0", + "safe-buffer": "^5.1.0", + "through2": "^2.0.3" + } + }, "remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", @@ -14771,6 +16528,23 @@ "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", "dev": true }, + "replace-ext": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", + "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", + "dev": true + }, + "replace-homedir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", + "integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1", + "is-absolute": "^1.0.0", + "remove-trailing-separator": "^1.1.0" + } + }, "request": { "version": "2.88.2", "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", @@ -14889,11 +16663,30 @@ } } }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + } + }, "resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" }, + "resolve-options": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", + "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", + "dev": true, + "requires": { + "value-or-function": "^3.0.0" + } + }, "resolve-url": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", @@ -15545,6 +17338,15 @@ } } }, + "semver-greatest-satisfied-range": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", + "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=", + "dev": true, + "requires": { + "sver-compat": "^1.5.0" + } + }, "semver-intersect": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/semver-intersect/-/semver-intersect-1.4.0.tgz", @@ -16131,6 +17933,12 @@ "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", "dev": true }, + "sparkles": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", + "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", + "dev": true + }, "spdx-correct": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", @@ -16338,6 +18146,12 @@ "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", "dev": true }, + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", + "dev": true + }, "stack-utils": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.2.tgz", @@ -16412,6 +18226,12 @@ "stream-shift": "^1.0.0" } }, + "stream-exhaust": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", + "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==", + "dev": true + }, "stream-http": { "version": "2.8.3", "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", @@ -16723,6 +18543,16 @@ "supports-color": "^7.0.0" } }, + "sver-compat": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", + "integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=", + "dev": true, + "requires": { + "es6-iterator": "^2.0.1", + "es6-symbol": "^3.1.1" + } + }, "svgo": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz", @@ -17009,12 +18839,28 @@ "xtend": "~4.0.1" } }, + "through2-filter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", + "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", + "dev": true, + "requires": { + "through2": "~2.0.0", + "xtend": "~4.0.0" + } + }, "thunky": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", "dev": true }, + "time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", + "dev": true + }, "timers-browserify": { "version": "2.0.11", "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.11.tgz", @@ -17044,6 +18890,16 @@ "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=", "dev": true }, + "to-absolute-glob": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", + "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", + "dev": true, + "requires": { + "is-absolute": "^1.0.0", + "is-negated-glob": "^1.0.0" + } + }, "to-arraybuffer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", @@ -17101,6 +18957,15 @@ "is-number": "^7.0.0" } }, + "to-through": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", + "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", + "dev": true, + "requires": { + "through2": "^2.0.3" + } + }, "toidentifier": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", @@ -17313,11 +19178,73 @@ "integrity": "sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==", "dev": true }, + "uglify-js": { + "version": "3.4.10", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.10.tgz", + "integrity": "sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw==", + "dev": true, + "requires": { + "commander": "~2.19.0", + "source-map": "~0.6.1" + }, + "dependencies": { + "commander": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", + "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", + "dev": true + }, "underscore": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.11.0.tgz", "integrity": "sha512-xY96SsN3NA461qIRKZ/+qox37YXPtSBswMGfiNptr+wrt6ds4HaMw23TP612fEyGekRE6LNRiLYr/aqbHXNedw==" }, + "undertaker": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.3.0.tgz", + "integrity": "sha512-/RXwi5m/Mu3H6IHQGww3GNt1PNXlbeCuclF2QYR14L/2CHPz3DFZkvB5hZ0N/QUkiXWCACML2jXViIQEQc2MLg==", + "dev": true, + "requires": { + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "bach": "^1.0.0", + "collection-map": "^1.0.0", + "es6-weak-map": "^2.0.1", + "fast-levenshtein": "^1.0.0", + "last-run": "^1.1.0", + "object.defaults": "^1.0.0", + "object.reduce": "^1.0.0", + "undertaker-registry": "^1.0.0" + }, + "dependencies": { + "fast-levenshtein": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.1.4.tgz", + "integrity": "sha1-5qdUzI8V5YmHqpy9J69m/W9OWvk=", + "dev": true + } + } + }, + "undertaker-registry": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", + "integrity": "sha1-XkvaMI5KiirlhPm5pDWaSZglzFA=", + "dev": true + }, "unicode-canonical-property-names-ecmascript": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", @@ -17388,6 +19315,16 @@ "imurmurhash": "^0.1.4" } }, + "unique-stream": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", + "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", + "dev": true, + "requires": { + "json-stable-stringify-without-jsonify": "^1.0.1", + "through2-filter": "^3.0.0" + } + }, "unique-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", @@ -17517,6 +19454,12 @@ "xdg-basedir": "^4.0.0" } }, + "upper-case": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", + "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=", + "dev": true + }, "uri-js": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", @@ -17665,6 +19608,15 @@ "source-map": "^0.7.3" } }, + "v8flags": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", + "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, "valid-identifier": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/valid-identifier/-/valid-identifier-0.0.2.tgz", @@ -17687,6 +19639,12 @@ "builtins": "^1.0.3" } }, + "value-or-function": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", + "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", + "dev": true + }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -17708,6 +19666,71 @@ "extsprintf": "^1.2.0" } }, + "vinyl": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", + "integrity": "sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==", + "dev": true, + "requires": { + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" + } + }, + "vinyl-fs": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", + "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", + "dev": true, + "requires": { + "fs-mkdirp-stream": "^1.0.0", + "glob-stream": "^6.1.0", + "graceful-fs": "^4.0.0", + "is-valid-glob": "^1.0.0", + "lazystream": "^1.0.0", + "lead": "^1.0.0", + "object.assign": "^4.0.4", + "pumpify": "^1.3.5", + "readable-stream": "^2.3.3", + "remove-bom-buffer": "^3.0.0", + "remove-bom-stream": "^1.2.0", + "resolve-options": "^1.1.0", + "through2": "^2.0.0", + "to-through": "^2.0.0", + "value-or-function": "^3.0.0", + "vinyl": "^2.0.0", + "vinyl-sourcemap": "^1.1.0" + } + }, + "vinyl-sourcemap": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", + "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=", + "dev": true, + "requires": { + "append-buffer": "^1.0.2", + "convert-source-map": "^1.5.0", + "graceful-fs": "^4.1.6", + "normalize-path": "^2.1.1", + "now-and-later": "^2.0.0", + "remove-bom-buffer": "^3.0.0", + "vinyl": "^2.0.0" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, "vm-browserify": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", diff --git a/package.json b/package.json index e42b50605..80b676724 100644 --- a/package.json +++ b/package.json @@ -132,6 +132,13 @@ "eslint-plugin-prefer-arrow": "^1.2.2", "eslint-plugin-promise": "^4.2.1", "faker": "^5.1.0", + "gulp": "4.0.2", + "gulp-clip-empty-files": "^0.1.2", + "gulp-concat": "^2.6.1", + "gulp-flatten": "^0.4.0", + "gulp-htmlmin": "^5.0.1", + "gulp-rename": "^2.0.0", + "gulp-slash": "^1.1.3", "jest": "^26.5.0", "jest-preset-angular": "^8.3.1", "ts-jest": "^26.4.1", From d4f11a99d44d9291297202598ea013bb9ae9de25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Thu, 15 Oct 2020 11:41:42 +0200 Subject: [PATCH 6/6] MOBILE-3565 gulp: Add language and jira gulp tasks --- gulp/dev-config.js | 69 ++++ gulp/git.js | 237 ++++++++++++ gulp/jira.js | 475 ++++++++++++++++++++++++ gulp/task-build-lang.js | 190 ++++++++++ gulp/task-push.js | 280 ++++++++++++++ gulp/url.js | 79 ++++ gulp/utils.js | 119 ++++++ gulpfile.js | 48 +++ package.json | 3 +- src/app/app.component.ts | 33 +- src/app/core/login/lang/en.json | 3 + src/app/core/login/login.module.ts | 3 +- src/app/core/login/pages/site/site.html | 2 +- src/app/services/lang.ts | 2 +- src/assets/countries/en.json | 251 +++++++++++++ src/assets/lang/en.json | 304 +++++++++++++++ src/assets/mimetypes/en.json | 54 +++ 17 files changed, 2146 insertions(+), 6 deletions(-) create mode 100644 gulp/dev-config.js create mode 100644 gulp/git.js create mode 100644 gulp/jira.js create mode 100644 gulp/task-build-lang.js create mode 100644 gulp/task-push.js create mode 100644 gulp/url.js create mode 100644 gulp/utils.js create mode 100644 gulpfile.js create mode 100644 src/app/core/login/lang/en.json create mode 100644 src/assets/countries/en.json create mode 100644 src/assets/lang/en.json create mode 100644 src/assets/mimetypes/en.json diff --git a/gulp/dev-config.js b/gulp/dev-config.js new file mode 100644 index 000000000..b270bf51f --- /dev/null +++ b/gulp/dev-config.js @@ -0,0 +1,69 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// Licensed 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. + +const fs = require('fs'); + +const DEV_CONFIG_FILE = '.moodleapp-dev-config'; + +/** + * Class to read and write dev-config data from a file. + */ +class DevConfig { + + constructor() { + this.loadFileData(); + } + + /** + * Get a setting. + * + * @param name Name of the setting to get. + * @param defaultValue Value to use if not found. + */ + get(name, defaultValue) { + return typeof this.config[name] != 'undefined' ? this.config[name] : defaultValue; + } + + /** + * Load file data to memory. + */ + loadFileData() { + if (!fs.existsSync(DEV_CONFIG_FILE)) { + this.config = {}; + + return; + } + + try { + this.config = JSON.parse(fs.readFileSync(DEV_CONFIG_FILE)); + } catch (error) { + console.error('Error reading dev config file.', error); + this.config = {}; + } + } + + /** + * Save some settings. + * + * @param settings Object with the settings to save. + */ + save(settings) { + this.config = Object.assign(this.config, settings); + + // Save the data in the dev file. + fs.writeFileSync(DEV_CONFIG_FILE, JSON.stringify(this.config, null, 4)); + } +} + +module.exports = new DevConfig(); diff --git a/gulp/git.js b/gulp/git.js new file mode 100644 index 000000000..f3f66298a --- /dev/null +++ b/gulp/git.js @@ -0,0 +1,237 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// Licensed 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. + +const exec = require('child_process').exec; +const fs = require('fs'); +const DevConfig = require('./dev-config'); +const Utils = require('./utils'); + +/** + * Class to run git commands. + */ +class Git { + + /** + * Create a patch. + * + * @param range Show only commits in the specified revision range. + * @param saveTo Path to the file to save the patch to. If not defined, the patch contents will be returned. + * @return Promise resolved when done. If saveTo not provided, it will return the patch contents. + */ + createPatch(range, saveTo) { + return new Promise((resolve, reject) => { + exec(`git format-patch ${range} --stdout`, (err, result) => { + if (err) { + reject(err || 'Cannot create patch.'); + return; + } + + if (!saveTo) { + resolve(result); + return; + } + + // Save it to a file. + const directory = saveTo.substring(0, saveTo.lastIndexOf('/')); + if (directory && directory != '.' && directory != '..' && !fs.existsSync(directory)) { + fs.mkdirSync(directory); + } + fs.writeFileSync(saveTo, result); + + resolve(); + }); + }); + } + + /** + * Get current branch. + * + * @return Promise resolved with the branch name. + */ + getCurrentBranch() { + return new Promise((resolve, reject) => { + exec('git branch --show-current', (err, branch) => { + if (branch) { + resolve(branch.replace('\n', '')); + } else { + reject (err || 'Current branch not found.'); + } + }); + }); + } + + /** + * Get the HEAD commit for a certain branch. + * + * @param branch Name of the branch. + * @param branchData Parsed branch data. If not provided it will be calculated. + * @return HEAD commit. + */ + async getHeadCommit(branch, branchData) { + if (!branchData) { + // Parse the branch to get the project and issue number. + branchData = Utils.parseBranch(branch); + } + + // Loop over the last commits to find the first commit messages that doesn't belong to the issue. + const commitsString = await this.log(50, branch, '%s_____%H'); + const commits = commitsString.split('\n'); + commits.pop(); // Remove last element, it's an empty string. + + for (let i = 0; i < commits.length; i++) { + const commit = commits[i]; + const match = Utils.getIssueFromCommitMessage(commit) == branchData.issue; + + if (i === 0 && !match) { + // Most recent commit doesn't belong to the issue. Stop looking. + break; + } + + if (!match) { + // The commit does not match any more, we found it! + return commit.split('_____')[1]; + } + } + + // Couldn't find the commit using the commit names, get the last commit in the integration branch. + const remote = DevConfig.get('upstreamRemote', 'origin'); + console.log(`Head commit not found using commit messages. Get last commit from ${remote}/integration`); + const hashes = await this.hashes(1, `${remote}/integration`); + + return hashes[0]; + } + + /** + * Get the URL of a certain remote. + * + * @param remote Remote name. + * @return Promise resolved with the remote URL. + */ + getRemoteUrl(remote) { + return new Promise((resolve, reject) => { + exec(`git remote get-url ${remote}`, (err, url) => { + if (url) { + resolve(url.replace('\n', '')); + } else { + reject (err || 'Remote not found.'); + } + }); + }); + } + + /** + * Return the latest hashes from git log. + * + * @param count Number of commits to display. + * @param range Show only commits in the specified revision range. + * @param format Pretty-print the contents of the commit logs in a given format. + * @return Promise resolved with the list of hashes. + */ + async hashes(count, range, format) { + format = format || '%H'; + + const hashList = await this.log(count, range, format); + + const hashes = hashList.split('\n'); + hashes.pop(); // Remove last element, it's an empty string. + + return hashes; + } + + /** + * Calls the log command and returns the raw output. + * + * @param count Number of commits to display. + * @param range Show only commits in the specified revision range. + * @param format Pretty-print the contents of the commit logs in a given format. + * @param path Show only commits that are enough to explain how the files that match the specified paths came to be. + * @return Promise resolved with the result. + */ + log(count, range, format, path) { + if (typeof count == 'undefined') { + count = 10; + } + + let command = 'git log'; + + if (count > 0) { + command += ` -n ${count} `; + } + if (format) { + command += ` --format=${format} `; + } + if (range){ + command += ` ${range} `; + } + if (path) { + command += ` -- ${path}`; + } + + return new Promise((resolve, reject) => { + exec(command, (err, result, stderr) => { + if (err) { + reject(err); + } else { + resolve(result); + } + }); + }); + } + + /** + * Return the latest titles of the commit messages. + * + * @param count Number of commits to display. + * @param range Show only commits in the specified revision range. + * @param path Show only commits that are enough to explain how the files that match the specified paths came to be. + * @return Promise resolved with the list of titles. + */ + async messages(count, range, path) { + count = typeof count != 'undefined' ? count : 10; + + const messageList = await this.log(count, range, '%s', path); + + const messages = messageList.split('\n'); + messages.pop(); // Remove last element, it's an empty string. + + return messages; + } + + /** + * Push a branch. + * + * @param remote Remote to use. + * @param branch Branch to push. + * @param force Whether to force the push. + * @return Promise resolved when done. + */ + push(remote, branch, force) { + return new Promise((resolve, reject) => { + let command = `git push ${remote} ${branch}`; + if (force) { + command += ' -f'; + } + + exec(command, (err, result, stderr) => { + if (err) { + reject(err); + } else { + resolve(); + } + }); + }); + } +} + +module.exports = new Git(); diff --git a/gulp/jira.js b/gulp/jira.js new file mode 100644 index 000000000..90aeaa1c7 --- /dev/null +++ b/gulp/jira.js @@ -0,0 +1,475 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// Licensed 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. + +const exec = require('child_process').exec; +const https = require('https'); +const inquirer = require('inquirer'); +const fs = require('fs'); +const request = require('request'); // This lib is deprecated, but it was the only way I found to make upload files work. +const DevConfig = require('./dev-config'); +const Git = require('./git'); +const Url = require('./url'); +const Utils = require('./utils'); + +const apiVersion = 2; + +/** + * Class to interact with Jira. + */ +class Jira { + + /** + * Ask the password to the user. + * + * @return Promise resolved with the password. + */ + async askPassword() { + const data = await inquirer.prompt([ + { + type: 'password', + name: 'password', + message: `Please enter the password for the username ${this.username}.`, + }, + ]); + + return data.password; + } + + /** + * Ask the user the tracker data. + * + * @return Promise resolved with the data, rejected if cannot get. + */ + async askTrackerData() { + const data = await inquirer.prompt([ + { + type: 'input', + name: 'url', + message: 'Please enter the tracker URL.', + default: 'https://tracker.moodle.org/', + }, + { + type: 'input', + name: 'username', + message: 'Please enter your tracker username.', + }, + ]); + + DevConfig.save({ + 'tracker.url': data.url, + 'tracker.username': data.username, + }); + + return data; + } + + /** + * Build URL to perform requests to Jira. + * + * @param uri URI to add the the Jira URL. + * @return URL. + */ + buildRequestUrl(uri) { + return Utils.concatenatePaths([this.url, this.uri, '/rest/api/', apiVersion, uri]); + } + + /** + * Delete an attachment. + * + * @param attachmentId Attachment ID. + * @return Promise resolved when done. + */ + async deleteAttachment(attachmentId) { + const response = await this.request(`attachment/${attachmentId}`, 'DELETE'); + + if (response.status != 204) { + throw new Error('Could not delete the attachment'); + } + } + + /** + * Load the issue info from jira server using a REST API call. + * + * @param key Key to identify the issue. E.g. MOBILE-1234. + * @param fields Fields to get. + * @return Promise resolved with the issue data. + */ + async getIssue(key, fields) { + fields = fields || '*all,-comment'; + + await this.init(); // Initialize data if needed. + + const response = await this.request(`issue/${key}`, 'GET', {'fields': fields, 'expand': 'names'}); + + if (response.status == 404) { + throw new Error('Issue could not be found.'); + } else if (response.status != 200) { + throw new Error('The tracker is not available.') + } + + const issue = response.data; + issue.named = {}; + + // Populate the named fields in a separate key. Allows us to easily find them without knowing the field ID. + const nameList = issue.names || {}; + for (const fieldKey in issue.fields) { + if (nameList[fieldKey]) { + issue.named[nameList[fieldKey]] = issue.fields[fieldKey]; + } + } + + return issue + } + + /** + * Load the version info from the jira server using a rest api call. + * + * @return Promise resolved when done. + */ + async getServerInfo() { + const response = await this.request('serverInfo'); + + if (response.status != 200) { + throw new Error(`Unexpected response code: ${response.status}`, response); + } + + this.version = response.data; + } + + /** + * Get tracker data to push an issue. + * + * @return Promise resolved with the data. + */ + async getTrackerData() { + // Check dev-config file first. + let data = this.getTrackerDataFromDevConfig(); + + if (data) { + console.log('Using tracker data from dev-config file'); + return data; + } + + // Try to use mdk now. + try { + data = await this.getTrackerDataFromMdk(); + + console.log('Using tracker data from mdk'); + + return data; + } catch (error) { + // MDK not available or not configured. Ask for the data. + const data = await this.askTrackerData(); + + data.fromInput = true; + + return data; + } + } + + /** + * Get tracker data from dev config file. + * + * @return Data, undefined if cannot get. + */ + getTrackerDataFromDevConfig() { + const url = DevConfig.get('tracker.url'); + const username = DevConfig.get('tracker.username'); + + if (url && username) { + return { + url, + username, + }; + } + } + + /** + * Get tracker URL and username from mdk. + * + * @return Promise resolved with the data, rejected if cannot get. + */ + getTrackerDataFromMdk() { + return new Promise((resolve, reject) => { + exec('mdk config show tracker.url', (err, url) => { + if (!url) { + reject(err || 'URL not found.'); + return; + } + + exec('mdk config show tracker.username', (err, username) => { + if (username) { + resolve({ + url: url.replace('\n', ''), + username: username.replace('\n', ''), + }); + } else { + reject(err | 'Username not found.'); + } + }); + }); + }); + } + + /** + * Initialize some data. + * + * @return Promise resolved when done. + */ + async init() { + if (this.initialized) { + // Already initialized. + return; + } + + // Get tracker URL and username. + const trackerData = await this.getTrackerData(); + + this.url = trackerData.url; + this.username = trackerData.username; + + const parsed = Url.parse(this.url); + this.ssl = parsed.protocol == 'https'; + this.host = parsed.domain; + this.uri = parsed.path; + + // Get the password. + const keytar = require('keytar'); + + this.password = await keytar.getPassword('mdk-jira-password', this.username); // Use same service name as mdk. + + if (!this.password) { + // Ask the user. + this.password = await this.askPassword(); + } + + while (!this.initialized) { + try { + await this.getServerInfo(); + + this.initialized = true; + keytar.setPassword('mdk-jira-password', this.username, this.password); + } catch (error) { + console.log('Error connecting to the server. Please make sure you entered the data correctly.', error); + if (trackerData.fromInput) { + // User entered the data manually, ask him again. + trackerData = await this.askTrackerData(); + + this.url = trackerData.url; + this.username = trackerData.username; + } + + this.password = await this.askPassword(); + } + } + } + + /** + * Check if a certain issue could be a security issue. + * + * @param key Key to identify the issue. E.g. MOBILE-1234. + * @return Promise resolved with boolean: whether it's a security issue. + */ + async isSecurityIssue(key) { + const issue = await this.getIssue(key, 'security'); + + return issue.fields && !!issue.fields.security; + } + + /** + * Sends a request to the server and returns the data. + * + * @param uri URI to add the the Jira URL. + * @param method Method to use. Defaults to 'GET'. + * @param params Params to send as GET params (in the URL). + * @param data JSON string with the data to send as POST/PUT params. + * @param headers Headers to send. + * @return Promise resolved with the result. + */ + request(uri, method, params, data, headers) { + uri = uri || ''; + method = (method || 'GET').toUpperCase(); + data = data || ''; + params = params || {}; + headers = headers || {}; + headers['Content-Type'] = 'application/json'; + + return new Promise((resolve, reject) => { + + // Build the request URL. + const url = Url.addParamsToUrl(this.buildRequestUrl(uri), params); + + // Initialize the request. + const options = { + method: method, + auth: `${this.username}:${this.password}`, + headers: headers, + }; + const request = https.request(url, options); + + // Add data. + if (data) { + request.write(data); + } + + // Treat response. + request.on('response', (response) => { + // Read the result. + let result = ''; + response.on('data', (chunk) => { + result += chunk; + }); + response.on('end', () => { + try { + result = JSON.parse(result); + } catch (error) { + // Leave it as text. + } + + resolve({ + status: response.statusCode, + data: result, + }); + }); + }); + + request.on('error', (e) => { + reject(e); + }); + + // Send the request. + request.end(); + }); + } + + /** + * Sets a set of fields for a certain issue in Jira. + * + * @param key Key to identify the issue. E.g. MOBILE-1234. + * @param updates Object with the fields to update. + * @return Promise resolved when done. + */ + async setCustomFields(key, updates) { + const issue = await this.getIssue(key); + const update = {'fields': {}}; + + // Detect which fields have changed. + for (const updateName in updates) { + const updateValue = updates[updateName]; + const remoteValue = issue.named[updateName]; + + if (!remoteValue || remoteValue != updateValue) { + // Map the label of the field with the field code. + let fieldKey; + for (const key in issue.names) { + if (issue.names[key] == updateName) { + fieldKey = key; + break; + } + } + + if (!fieldKey) { + throw new Error(`Could not find the field named ${updateName}.`); + } + + update.fields[fieldKey] = updateValue; + } + } + + if (!Object.keys(update.fields).length) { + // No fields to update. + console.log('No updates required.') + return; + } + + const response = await this.request(`issue/${key}`, 'PUT', null, JSON.stringify(update)); + + if (response.status != 204) { + throw new Error(`Issue was not updated: ${response.status}`, response.data); + } + + console.log('Issue updated successfully.'); + } + + /** + * Upload a new attachment to an issue. + * + * @param key Key to identify the issue. E.g. MOBILE-1234. + * @param filePath Path to the file to upload. + * @return Promise resolved when done. + */ + async upload(key, filePath) { + + const uri = `issue/${key}/attachments`; + const headers = { + 'X-Atlassian-Token': 'nocheck', + } + + const response = await this.uploadFile(uri, 'file', filePath, headers); + + if (response.status != 200) { + throw new Error('Could not upload file to Jira issue'); + } + + console.log('File successfully uploaded.') + } + + /** + * Upload a file to Jira. + * + * @param uri URI to add the the Jira URL. + * @param fieldName Name of the form field where to put the file. + * @param filePath Path to the file. + * @param headers Headers. + * @return Promise resolved with the result. + */ + async uploadFile(uri, fieldName, filePath, headers) { + uri = uri || ''; + headers = headers || {}; + headers['Content-Type'] = 'multipart/form-data'; + + return new Promise((resolve, reject) => { + // Add the file to the form data. + const formData = {}; + formData[fieldName] = { + value: fs.createReadStream(filePath), + options: { + filename: filePath.substr(filePath.lastIndexOf('/') + 1), + contentType: 'multipart/form-data', + }, + }; + + // Perform the request. + const options = { + url: this.buildRequestUrl(uri), + method: 'POST', + headers: headers, + auth: { + user: this.username, + pass: this.password, + }, + formData: formData, + }; + + request(options, (err, httpResponse, body) => { + resolve({ + status: httpResponse.statusCode, + data: body, + }); + }); + }); + } +} + +module.exports = new Jira(); diff --git a/gulp/task-build-lang.js b/gulp/task-build-lang.js new file mode 100644 index 000000000..980bf52a4 --- /dev/null +++ b/gulp/task-build-lang.js @@ -0,0 +1,190 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// Licensed 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. + +const gulp = require('gulp'); +const slash = require('gulp-slash'); +const clipEmptyFiles = require('gulp-clip-empty-files'); +const through = require('through'); +const bufferFrom = require('buffer-from'); +const File = require('vinyl'); +const pathLib = require('path'); + +/** + * Task to build the language files into a single file per language. + */ +class BuildLangTask { + + /** + * Copy a property from one object to another, adding a prefix to the key if needed. + * + * @param target Object to copy the properties to. + * @param source Object to copy the properties from. + * @param prefix Prefix to add to the keys. + */ + addProperties(target, source, prefix) { + for (let property in source) { + target[prefix + property] = source[property]; + } + } + + /** + * Run the task. + * + * @param language Language to treat. + * @param langPaths Paths to the possible language files. + * @param done Function to call when done. + */ + run(language, langPaths, done) { + const filename = language + '.json'; + const data = {}; + let firstFile = null; + const self = this; + + const paths = langPaths.map((path) => { + if (path.slice(-1) != '/') { + path = path + '/'; + } + + return path + language + '.json'; + }); + + gulp.src(paths, { allowEmpty: true }) + .pipe(slash()) + .pipe(clipEmptyFiles()) + .pipe(through(function(file) { + if (!firstFile) { + firstFile = file; + } + + return self.treatFile(file, data); + }, function() { + /* This implementation is based on gulp-jsoncombine module. + * https://github.com/reflog/gulp-jsoncombine */ + if (firstFile) { + const joinedPath = pathLib.join(firstFile.base, language + '.json'); + + const joinedFile = new File({ + cwd: firstFile.cwd, + base: firstFile.base, + path: joinedPath, + contents: self.treatMergedData(data), + }); + + this.emit('data', joinedFile); + } + + this.emit('end'); + })) + .pipe(gulp.dest(pathLib.join('./src/assets', 'lang'))) + .on('end', done); + } + + /** + * Treats a file to merge JSONs. This function is based on gulp-jsoncombine module. + * https://github.com/reflog/gulp-jsoncombine + * + * @param file File treated. + * @param data Object where to store the data. + */ + treatFile(file, data) { + if (file.isNull() || file.isStream()) { + return; // ignore + } + + try { + let path = file.path; + let length = 9; + + let srcPos = path.lastIndexOf('/src/app/'); + if (srcPos < 0) { + // It's probably a Windows environment. + srcPos = path.lastIndexOf('\\src\\app\\'); + } + if (srcPos < 0) { + length = 5; + srcPos = path.lastIndexOf('/src/'); + if (srcPos < 0) { + // It's probably a Windows environment. + srcPos = path.lastIndexOf('\\src\\'); + } + } + path = path.substr(srcPos + length); + + data[path] = JSON.parse(file.contents.toString()); + } catch (err) { + console.log('Error parsing JSON: ' + err); + } + } + + /** + * Treats the merged JSON data, adding prefixes depending on the component. + * + * @param data Merged data. + * @return Buffer with the treated data. + */ + treatMergedData(data) { + const merged = {}; + const mergedOrdered = {}; + + for (let filepath in data) { + + const pathSplit = filepath.split(/[\/\\]/); + let prefix; + + pathSplit.pop(); + + switch (pathSplit[0]) { + case 'lang': + prefix = 'core'; + break; + case 'core': + if (pathSplit[1] == 'lang') { + // Not used right now. + prefix = 'core'; + } else { + prefix = 'core.' + pathSplit[1]; + } + break; + case 'addon': + // Remove final item 'lang'. + pathSplit.pop(); + // Remove first item 'addon'. + pathSplit.shift(); + + // For subplugins. We'll use plugin_subfolder_subfolder2_... + // E.g. 'mod_assign_feedback_comments'. + prefix = 'addon.' + pathSplit.join('_'); + break; + case 'assets': + prefix = 'assets.' + pathSplit[1]; + break; + } + + if (prefix) { + this.addProperties(merged, data[filepath], prefix + '.'); + } + } + + + + // Force ordering by string key. + Object.keys(merged).sort().forEach((key) => { + mergedOrdered[key] = merged[key]; + }); + + return bufferFrom(JSON.stringify(mergedOrdered, null, 4)); + } +} + +module.exports = BuildLangTask; diff --git a/gulp/task-push.js b/gulp/task-push.js new file mode 100644 index 000000000..54d151dde --- /dev/null +++ b/gulp/task-push.js @@ -0,0 +1,280 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// Licensed 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. + +const gulp = require('gulp'); +const inquirer = require('inquirer'); +const DevConfig = require('./dev-config'); +const Git = require('./git'); +const Jira = require('./jira'); +const Utils = require('./utils'); + +/** + * Task to push a git branch and update tracker issue. + */ +class PushTask { + + /** + * Ask the user whether he wants to continue. + * + * @return Promise resolved with boolean: true if he wants to continue. + */ + async askConfirmContinue() { + const answer = await inquirer.prompt([ + { + type: 'input', + name: 'confirm', + message: 'Are you sure you want to continue?', + default: 'n', + }, + ]); + + return answer.confirm == 'y'; + } + + /** + * Push a patch to the tracker and remove the previous one. + * + * @param branch Branch name. + * @param branchData Parsed branch data. + * @param remote Remote used. + * @return Promise resolved when done. + */ + async pushPatch(branch, branchData, remote) { + const headCommit = await Git.getHeadCommit(branch, branchData); + + if (!headCommit) { + throw new Error('Head commit not resolved, abort pushing patch.'); + } + + // Create the patch file. + const fileName = branch + '.patch'; + const tmpPatchPath = `./tmp/${fileName}`; + + await Git.createPatch(`${headCommit}...${branch}`, tmpPatchPath); + console.log('Git patch created'); + + // Check if there is an attachment with same name in the issue. + const issue = await Jira.getIssue(branchData.issue, 'attachment'); + + let existingAttachmentId; + const attachments = (issue.fields && issue.fields.attachment) || []; + for (const i in attachments) { + if (attachments[i].filename == fileName) { + // Found an existing attachment with the same name, we keep track of it. + existingAttachmentId = attachments[i].id; + break + } + } + + // Push the patch to the tracker. + console.log(`Uploading patch ${fileName} to the tracker...`); + await Jira.upload(branchData.issue, tmpPatchPath); + + if (existingAttachmentId) { + // On success, deleting file that was there before. + try { + console.log('Deleting older patch...') + await Jira.deleteAttachment(existingAttachmentId); + } catch (error) { + console.log('Could not delete older attachment.'); + } + } + } + + /** + * Run the task. + * + * @param args Command line arguments. + * @param done Function to call when done. + */ + async run(args, done) { + try { + const remote = args.remote || DevConfig.get('upstreamRemote', 'origin'); + let branch = args.branch; + const force = !!args.force; + + if (!branch) { + branch = await Git.getCurrentBranch(); + } + + if (!branch) { + throw new Error('Cannot determine the current branch. Please make sure youu aren\'t in detached HEAD state'); + } else if (branch == 'HEAD') { + throw new Error('Cannot push HEAD branch'); + } + + // Parse the branch to get the project and issue number. + const branchData = Utils.parseBranch(branch); + const keepRunning = await this.validateCommitMessages(branchData); + + if (!keepRunning) { + // Last commit not valid, stop. + console.log('Exiting...'); + done(); + return; + } + + if (!args.patch) { + // Check if it's a security issue to force patch mode. + try { + args.patch = await Jira.isSecurityIssue(branchData.issue); + + if (args.patch) { + console.log(`${branchData.issue} appears to be a security issue, switching to patch mode...`); + } + } catch (error) { + console.log(`Could not check if ${branchData.issue} is a security issue.`); + } + } + + if (args.patch) { + // Create and upload a patch file. + await this.pushPatch(branch, branchData, remote); + } else { + // Push the branch. + console.log(`Pushing branch ${branch} to remote ${remote}...`); + await Git.push(remote, branch, force); + + // Update tracker info. + console.log(`Branch pushed, update tracker info...`); + await this.updateTrackerGitInfo(branch, branchData, remote); + } + } catch (error) { + console.error(error); + } + + done(); + } + + /** + * Update git info in the tracker issue. + * + * @param branch Branch name. + * @param branchData Parsed branch data. + * @param remote Remote used. + * @return Promise resolved when done. + */ + async updateTrackerGitInfo(branch, branchData, remote) { + // Get the repository data for the project. + let repositoryUrl = DevConfig.get(branchData.project + '.repositoryUrl'); + let diffUrlTemplate = DevConfig.get(branchData.project + '.diffUrlTemplate', ''); + + if (!repositoryUrl) { + // Calculate the repositoryUrl based on the remote URL. + repositoryUrl = await Git.getRemoteUrl(remote); + } + + // Make sure the repository URL uses the regular format. + repositoryUrl = repositoryUrl.replace(/^(git@|git:\/\/)/, 'https://') + .replace(/\.git$/, '') + .replace('github.com:', 'github.com/'); + + if (!diffUrlTemplate) { + diffUrlTemplate = Utils.concatenatePaths([repositoryUrl, 'compare/%headcommit%...%branch%']); + } + + // Now create the git URL for the repository. + const repositoryGitUrl = repositoryUrl.replace(/^https?:\/\//, 'git://') + '.git'; + + // Search HEAD commit to put in the diff URL. + console.log ('Searching for head commit...'); + let headCommit = await Git.getHeadCommit(branch, branchData); + + if (!headCommit) { + throw new Error('Head commit not resolved, aborting update of tracker fields'); + } + + headCommit = headCommit.substr(0, 10); + console.log(`Head commit resolved to ${headCommit}`); + + // Calculate last properties needed. + const diffUrl = diffUrlTemplate.replace('%branch%', branch).replace('%headcommit%', headCommit); + const fieldRepositoryUrl = DevConfig.get('tracker.fieldnames.repositoryurl', 'Pull from Repository'); + const fieldBranch = DevConfig.get('tracker.fieldnames.branch', 'Pull Master Branch'); + const fieldDiffUrl = DevConfig.get('tracker.fieldnames.diffurl', 'Pull Master Diff URL'); + + // Update tracker fields. + const updates = {}; + updates[fieldRepositoryUrl] = repositoryGitUrl; + updates[fieldBranch] = branch; + updates[fieldDiffUrl] = diffUrl; + + console.log('Setting tracker fields...'); + await Jira.setCustomFields(branchData.issue, updates); + } + + /** + * Validate commit messages comparing them with the branch name. + * + * @param branchData Parsed branch data. + * @return True if value is ok or the user wants to continue anyway, false to stop. + */ + async validateCommitMessages(branchData) { + const messages = await Git.messages(30); + + let numConsecutive = 0; + let wrongCommitCandidate = null; + + for (let i = 0; i < messages.length; i++) { + const message = messages[i]; + const issue = Utils.getIssueFromCommitMessage(message); + + if (!issue || issue != branchData.issue) { + if (i === 0) { + // Last commit is wrong, it shouldn't happen. Ask the user if he wants to continue. + if (!issue) { + console.log('The issue number could not be found in the last commit message.'); + console.log(`Commit: ${message}`); + } else if (issue != branchData.issue) { + console.log('The issue number in the last commit does not match the branch being pushed to.'); + console.log(`Branch: ${branchData.issue} vs. commit: ${issue}`); + } + + return this.askConfirmContinue(); + } + + numConsecutive++; + if (numConsecutive > 2) { + // 3 consecutive commits with different branch, probably the branch commits are over. Everything OK. + return true; + + // Don't treat a merge pull request commit as a wrong commit between right commits. + // The current push could be a quick fix after a merge. + } else if (!wrongCommitCandidate && message.indexOf('Merge pull request') == -1) { + wrongCommitCandidate = { + message: message, + issue: issue, + index: i, + }; + } + } else if (wrongCommitCandidate) { + // We've found a commit with the branch name after a commit with a different branch. Probably wrong commit. + if (!wrongCommitCandidate.issue) { + console.log('The issue number could not be found in one of the commit messages.'); + console.log(`Commit: ${wrongCommitCandidate.message}`); + } else { + console.log('The issue number in a certain commit does not match the branch being pushed to.'); + console.log(`Branch: ${branchData.issue} vs. commit: ${wrongCommitCandidate.issue}`); + console.log(`Commit message: ${wrongCommitCandidate.message}`); + } + + return this.askConfirmContinue(); + } + } + + return true; + } +} + +module.exports = PushTask; diff --git a/gulp/url.js b/gulp/url.js new file mode 100644 index 000000000..8b46409f6 --- /dev/null +++ b/gulp/url.js @@ -0,0 +1,79 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// Licensed 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. + +/** + * Class with helper functions for urls. + */ +class Url { + + /** + * Add params to a URL. + * + * @param url URL to add the params to. + * @param params Object with the params to add. + * @return URL with params. + */ + static addParamsToUrl(url, params) { + let separator = url.indexOf('?') != -1 ? '&' : '?'; + + for (const key in params) { + let value = params[key]; + + // Ignore objects. + if (typeof value != 'object') { + url += separator + key + '=' + value; + separator = '&'; + } + } + + return url; + } + + /** + * Parse parts of a url, using an implicit protocol if it is missing from the url. + * + * @param url Url. + * @return Url parts. + */ + static parse(url) { + // Parse url with regular expression taken from RFC 3986: https://tools.ietf.org/html/rfc3986#appendix-B. + const match = url.trim().match(/^(([^:/?#]+):)?(\/\/([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/); + + if (!match) { + return null; + } + + const host = match[4] || ''; + + // Get the credentials and the port from the host. + const [domainAndPort, credentials] = host.split('@').reverse(); + const [domain, port] = domainAndPort.split(':'); + const [username, password] = credentials ? credentials.split(':') : []; + + // Prepare parts replacing empty strings with undefined. + return { + protocol: match[2] || undefined, + domain: domain || undefined, + port: port || undefined, + credentials: credentials || undefined, + username: username || undefined, + password: password || undefined, + path: match[5] || undefined, + query: match[7] || undefined, + fragment: match[9] || undefined, + }; + } +} + +module.exports = Url; diff --git a/gulp/utils.js b/gulp/utils.js new file mode 100644 index 000000000..0ca11fa74 --- /dev/null +++ b/gulp/utils.js @@ -0,0 +1,119 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// Licensed 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. + +const DevConfig = require('./dev-config'); +const DEFAULT_ISSUE_REGEX = '^(MOBILE)[-_]([0-9]+)'; + +/** + * Class with some utility functions. + */ +class Utils { + /** + * Concatenate several paths, adding a slash between them if needed. + * + * @param paths List of paths. + * @return Concatenated path. + */ + static concatenatePaths(paths) { + if (!paths.length) { + return ''; + } + + // Remove all slashes between paths. + for (let i = 0; i < paths.length; i++) { + if (!paths[i]) { + continue; + } + + if (i === 0) { + paths[i] = String(paths[i]).replace(/\/+$/g, ''); + } else if (i === paths.length - 1) { + paths[i] = String(paths[i]).replace(/^\/+/g, ''); + } else { + paths[i] = String(paths[i]).replace(/^\/+|\/+$/g, ''); + } + } + + // Remove empty paths. + paths = paths.filter(path => !!path); + + return paths.join('/'); + } + + /** + * Get command line arguments. + * + * @return Object with command line arguments. + */ + static getCommandLineArguments() { + + let args = {}, opt, thisOpt, curOpt; + for (let a = 0; a < process.argv.length; a++) { + + thisOpt = process.argv[a].trim(); + opt = thisOpt.replace(/^\-+/, ''); + + if (opt === thisOpt) { + // argument value + if (curOpt) { + args[curOpt] = opt; + } + curOpt = null; + } + else { + // Argument name. + curOpt = opt; + args[curOpt] = true; + } + } + + return args; + } + + /** + * Given a commit message, return the issue name (e.g. MOBILE-1234). + * + * @param commit Commit message. + * @return Issue name. + */ + static getIssueFromCommitMessage(commit) { + const regex = new RegExp(DevConfig.get('wording.branchRegex', DEFAULT_ISSUE_REGEX), 'i'); + const matches = commit.match(regex); + + return matches && matches[0]; + } + + /** + * Parse a branch name to extract some data. + * + * @param branch Branch name to parse. + * @return Data. + */ + static parseBranch(branch) { + const regex = new RegExp(DevConfig.get('wording.branchRegex', DEFAULT_ISSUE_REGEX), 'i'); + + const matches = branch.match(regex); + if (!matches || matches.length < 3) { + throw new Error(`Error parsing branch ${branch}`); + } + + return { + issue: matches[0], + project: matches[1], + issueNumber: matches[2], + }; + } +} + +module.exports = Utils; diff --git a/gulpfile.js b/gulpfile.js new file mode 100644 index 000000000..7a08d6c88 --- /dev/null +++ b/gulpfile.js @@ -0,0 +1,48 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// Licensed 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. + +const BuildLangTask = require('./gulp/task-build-lang'); +const PushTask = require('./gulp/task-push'); +const Utils = require('./gulp/utils'); +const gulp = require('gulp'); + +const paths = { + lang: [ + './src/app/lang/', + './src/app/core/**/lang/', + './src/app/addon/**/lang/', + './src/app/**/**/lang/', + './src/assets/countries/', + './src/assets/mimetypes/' + ] +}; + +const args = Utils.getCommandLineArguments(); + +// Build the language files into a single file per language. +gulp.task('lang', (done) => { + new BuildLangTask().run('en', paths.lang, done); +}); + +gulp.task('push', (done) => { + new PushTask().run(args, done); +}); + +gulp.task('default', gulp.parallel('lang')); + +gulp.task('watch', () => { + const langsPaths = paths.lang.map(path => path + 'en.json'); + + gulp.watch(langsPaths, { interval: 500 }, gulp.parallel('lang')); +}); diff --git a/package.json b/package.json index 80b676724..72bd72e26 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,8 @@ "test:ci": "jest -ci --runInBand --verbose", "test:watch": "jest --watch", "test:coverage": "jest --coverage", - "lint": "ng lint" + "lint": "ng lint", + "ionic:serve:before": "npx gulp" }, "dependencies": { "@angular/common": "~10.0.0", diff --git a/src/app/app.component.ts b/src/app/app.component.ts index dde487788..48afedd0e 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -12,11 +12,40 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Component } from '@angular/core'; +import { Component, OnInit } from '@angular/core'; +import { CoreLangProvider } from '@services/lang'; +import { CoreEvents, CoreEventsProvider } from '@services/events'; @Component({ selector: 'app-root', templateUrl: 'app.component.html', styleUrls: ['app.component.scss'], }) -export class AppComponent { } +export class AppComponent implements OnInit { + + constructor( + private langProvider: CoreLangProvider, + ) { + } + + /** + * Component being initialized. + */ + ngOnInit(): void { + CoreEvents.instance.on(CoreEventsProvider.LOGOUT, () => { + // Go to sites page when user is logged out. + // Due to DeepLinker, we need to use the ViewCtrl instead of name. + // Otherwise some pages are re-created when they shouldn't. + // TODO + // CoreApp.instance.getRootNavController().setRoot(CoreLoginSitesPage); + + // Unload lang custom strings. + this.langProvider.clearCustomStrings(); + + // Remove version classes from body. + // TODO + // this.removeVersionClass(); + }); + } + +} diff --git a/src/app/core/login/lang/en.json b/src/app/core/login/lang/en.json new file mode 100644 index 000000000..e776074e5 --- /dev/null +++ b/src/app/core/login/lang/en.json @@ -0,0 +1,3 @@ +{ + "yourenteredsite": "Connect to your site" +} diff --git a/src/app/core/login/login.module.ts b/src/app/core/login/login.module.ts index 74707b4fb..39ba3ce72 100644 --- a/src/app/core/login/login.module.ts +++ b/src/app/core/login/login.module.ts @@ -16,17 +16,18 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { IonicModule } from '@ionic/angular'; +import { TranslateModule } from '@ngx-translate/core'; import { CoreLoginRoutingModule } from './login-routing.module'; import { CoreLoginInitPage } from './pages/init/init.page'; import { CoreLoginSitePage } from './pages/site/site.page'; - @NgModule({ imports: [ CommonModule, IonicModule, CoreLoginRoutingModule, + TranslateModule.forChild(), ], declarations: [ CoreLoginInitPage, diff --git a/src/app/core/login/pages/site/site.html b/src/app/core/login/pages/site/site.html index 49d7a9823..e2beae84f 100644 --- a/src/app/core/login/pages/site/site.html +++ b/src/app/core/login/pages/site/site.html @@ -1,3 +1,3 @@ - Site page. + {{ 'core.login.yourenteredsite' | translate }} diff --git a/src/app/services/lang.ts b/src/app/services/lang.ts index 5a763614d..dc405bd31 100644 --- a/src/app/services/lang.ts +++ b/src/app/services/lang.ts @@ -246,7 +246,7 @@ export class CoreLangProvider { protected async detectLanguage(): Promise { // Get current language from config (user might have changed it). try { - return CoreConfig.instance.get('current_language'); + return await CoreConfig.instance.get('current_language'); } catch (e) { // Try will return, ignore errors here to avoid nesting. } diff --git a/src/assets/countries/en.json b/src/assets/countries/en.json new file mode 100644 index 000000000..777763e84 --- /dev/null +++ b/src/assets/countries/en.json @@ -0,0 +1,251 @@ +{ + "AD": "Andorra", + "AE": "United Arab Emirates", + "AF": "Afghanistan", + "AG": "Antigua and Barbuda", + "AI": "Anguilla", + "AL": "Albania", + "AM": "Armenia", + "AO": "Angola", + "AQ": "Antarctica", + "AR": "Argentina", + "AS": "American Samoa", + "AT": "Austria", + "AU": "Australia", + "AW": "Aruba", + "AX": "Åland Islands", + "AZ": "Azerbaijan", + "BA": "Bosnia and Herzegovina", + "BB": "Barbados", + "BD": "Bangladesh", + "BE": "Belgium", + "BF": "Burkina Faso", + "BG": "Bulgaria", + "BH": "Bahrain", + "BI": "Burundi", + "BJ": "Benin", + "BL": "Saint Barthélemy", + "BM": "Bermuda", + "BN": "Brunei Darussalam", + "BO": "Bolivia (Plurinational State of)", + "BQ": "Bonaire, Sint Eustatius and Saba", + "BR": "Brazil", + "BS": "Bahamas", + "BT": "Bhutan", + "BV": "Bouvet Island", + "BW": "Botswana", + "BY": "Belarus", + "BZ": "Belize", + "CA": "Canada", + "CC": "Cocos (Keeling) Islands", + "CD": "Congo (the Democratic Republic of the)", + "CF": "Central African Republic", + "CG": "Congo", + "CH": "Switzerland", + "CI": "Côte d'Ivoire", + "CK": "Cook Islands", + "CL": "Chile", + "CM": "Cameroon", + "CN": "China", + "CO": "Colombia", + "CR": "Costa Rica", + "CU": "Cuba", + "CV": "Cabo Verde", + "CW": "Curaçao", + "CX": "Christmas Island", + "CY": "Cyprus", + "CZ": "Czechia", + "DE": "Germany", + "DJ": "Djibouti", + "DK": "Denmark", + "DM": "Dominica", + "DO": "Dominican Republic", + "DZ": "Algeria", + "EC": "Ecuador", + "EE": "Estonia", + "EG": "Egypt", + "EH": "Western Sahara", + "ER": "Eritrea", + "ES": "Spain", + "ET": "Ethiopia", + "FI": "Finland", + "FJ": "Fiji", + "FK": "Falkland Islands (Malvinas)", + "FM": "Micronesia (Federated States of)", + "FO": "Faroe Islands", + "FR": "France", + "GA": "Gabon", + "GB": "United Kingdom", + "GD": "Grenada", + "GE": "Georgia", + "GF": "French Guiana", + "GG": "Guernsey", + "GH": "Ghana", + "GI": "Gibraltar", + "GL": "Greenland", + "GM": "Gambia", + "GN": "Guinea", + "GP": "Guadeloupe", + "GQ": "Equatorial Guinea", + "GR": "Greece", + "GS": "South Georgia and the South Sandwich Islands", + "GT": "Guatemala", + "GU": "Guam", + "GW": "Guinea-Bissau", + "GY": "Guyana", + "HK": "Hong Kong", + "HM": "Heard Island and McDonald Islands", + "HN": "Honduras", + "HR": "Croatia", + "HT": "Haiti", + "HU": "Hungary", + "ID": "Indonesia", + "IE": "Ireland", + "IL": "Israel", + "IM": "Isle of Man", + "IN": "India", + "IO": "British Indian Ocean Territory", + "IQ": "Iraq", + "IR": "Iran (Islamic Republic of)", + "IS": "Iceland", + "IT": "Italy", + "JE": "Jersey", + "JM": "Jamaica", + "JO": "Jordan", + "JP": "Japan", + "KE": "Kenya", + "KG": "Kyrgyzstan", + "KH": "Cambodia", + "KI": "Kiribati", + "KM": "Comoros", + "KN": "Saint Kitts and Nevis", + "KP": "Korea (the Democratic People's Republic of)", + "KR": "Korea (the Republic of)", + "KW": "Kuwait", + "KY": "Cayman Islands", + "KZ": "Kazakhstan", + "LA": "Lao People's Democratic Republic", + "LB": "Lebanon", + "LC": "Saint Lucia", + "LI": "Liechtenstein", + "LK": "Sri Lanka", + "LR": "Liberia", + "LS": "Lesotho", + "LT": "Lithuania", + "LU": "Luxembourg", + "LV": "Latvia", + "LY": "Libya", + "MA": "Morocco", + "MC": "Monaco", + "MD": "Moldova (the Republic of)", + "ME": "Montenegro", + "MF": "Saint Martin (French part)", + "MG": "Madagascar", + "MH": "Marshall Islands", + "MK": "North Macedonia", + "ML": "Mali", + "MM": "Myanmar", + "MN": "Mongolia", + "MO": "Macao", + "MP": "Northern Mariana Islands", + "MQ": "Martinique", + "MR": "Mauritania", + "MS": "Montserrat", + "MT": "Malta", + "MU": "Mauritius", + "MV": "Maldives", + "MW": "Malawi", + "MX": "Mexico", + "MY": "Malaysia", + "MZ": "Mozambique", + "NA": "Namibia", + "NC": "New Caledonia", + "NE": "Niger", + "NF": "Norfolk Island", + "NG": "Nigeria", + "NI": "Nicaragua", + "NL": "Netherlands", + "NO": "Norway", + "NP": "Nepal", + "NR": "Nauru", + "NU": "Niue", + "NZ": "New Zealand", + "OM": "Oman", + "PA": "Panama", + "PE": "Peru", + "PF": "French Polynesia", + "PG": "Papua New Guinea", + "PH": "Philippines", + "PK": "Pakistan", + "PL": "Poland", + "PM": "Saint Pierre and Miquelon", + "PN": "Pitcairn", + "PR": "Puerto Rico", + "PS": "Palestine, State of", + "PT": "Portugal", + "PW": "Palau", + "PY": "Paraguay", + "QA": "Qatar", + "RE": "Réunion", + "RO": "Romania", + "RS": "Serbia", + "RU": "Russian Federation", + "RW": "Rwanda", + "SA": "Saudi Arabia", + "SB": "Solomon Islands", + "SC": "Seychelles", + "SD": "Sudan", + "SE": "Sweden", + "SG": "Singapore", + "SH": "Saint Helena, Ascension and Tristan da Cunha", + "SI": "Slovenia", + "SJ": "Svalbard and Jan Mayen", + "SK": "Slovakia", + "SL": "Sierra Leone", + "SM": "San Marino", + "SN": "Senegal", + "SO": "Somalia", + "SR": "Suriname", + "SS": "South Sudan", + "ST": "Sao Tome and Principe", + "SV": "El Salvador", + "SX": "Sint Maarten (Dutch part)", + "SY": "Syrian Arab Republic", + "SZ": "Eswatini", + "TC": "Turks and Caicos Islands", + "TD": "Chad", + "TF": "French Southern Territories", + "TG": "Togo", + "TH": "Thailand", + "TJ": "Tajikistan", + "TK": "Tokelau", + "TL": "Timor-Leste", + "TM": "Turkmenistan", + "TN": "Tunisia", + "TO": "Tonga", + "TR": "Turkey", + "TT": "Trinidad and Tobago", + "TV": "Tuvalu", + "TW": "Taiwan", + "TZ": "Tanzania, the United Republic of", + "UA": "Ukraine", + "UG": "Uganda", + "UM": "United States Minor Outlying Islands", + "US": "United States", + "UY": "Uruguay", + "UZ": "Uzbekistan", + "VA": "Holy See", + "VC": "Saint Vincent and the Grenadines", + "VE": "Venezuela (Bolivarian Republic of)", + "VG": "Virgin Islands (British)", + "VI": "Virgin Islands (U.S.)", + "VN": "Viet Nam", + "VU": "Vanuatu", + "WF": "Wallis and Futuna", + "WS": "Samoa", + "YE": "Yemen", + "YT": "Mayotte", + "ZA": "South Africa", + "ZM": "Zambia", + "ZW": "Zimbabwe" +} \ No newline at end of file diff --git a/src/assets/lang/en.json b/src/assets/lang/en.json new file mode 100644 index 000000000..5ada0eb7d --- /dev/null +++ b/src/assets/lang/en.json @@ -0,0 +1,304 @@ +{ + "assets.countries.AD": "Andorra", + "assets.countries.AE": "United Arab Emirates", + "assets.countries.AF": "Afghanistan", + "assets.countries.AG": "Antigua and Barbuda", + "assets.countries.AI": "Anguilla", + "assets.countries.AL": "Albania", + "assets.countries.AM": "Armenia", + "assets.countries.AO": "Angola", + "assets.countries.AQ": "Antarctica", + "assets.countries.AR": "Argentina", + "assets.countries.AS": "American Samoa", + "assets.countries.AT": "Austria", + "assets.countries.AU": "Australia", + "assets.countries.AW": "Aruba", + "assets.countries.AX": "Åland Islands", + "assets.countries.AZ": "Azerbaijan", + "assets.countries.BA": "Bosnia and Herzegovina", + "assets.countries.BB": "Barbados", + "assets.countries.BD": "Bangladesh", + "assets.countries.BE": "Belgium", + "assets.countries.BF": "Burkina Faso", + "assets.countries.BG": "Bulgaria", + "assets.countries.BH": "Bahrain", + "assets.countries.BI": "Burundi", + "assets.countries.BJ": "Benin", + "assets.countries.BL": "Saint Barthélemy", + "assets.countries.BM": "Bermuda", + "assets.countries.BN": "Brunei Darussalam", + "assets.countries.BO": "Bolivia (Plurinational State of)", + "assets.countries.BQ": "Bonaire, Sint Eustatius and Saba", + "assets.countries.BR": "Brazil", + "assets.countries.BS": "Bahamas", + "assets.countries.BT": "Bhutan", + "assets.countries.BV": "Bouvet Island", + "assets.countries.BW": "Botswana", + "assets.countries.BY": "Belarus", + "assets.countries.BZ": "Belize", + "assets.countries.CA": "Canada", + "assets.countries.CC": "Cocos (Keeling) Islands", + "assets.countries.CD": "Congo (the Democratic Republic of the)", + "assets.countries.CF": "Central African Republic", + "assets.countries.CG": "Congo", + "assets.countries.CH": "Switzerland", + "assets.countries.CI": "Côte d'Ivoire", + "assets.countries.CK": "Cook Islands", + "assets.countries.CL": "Chile", + "assets.countries.CM": "Cameroon", + "assets.countries.CN": "China", + "assets.countries.CO": "Colombia", + "assets.countries.CR": "Costa Rica", + "assets.countries.CU": "Cuba", + "assets.countries.CV": "Cabo Verde", + "assets.countries.CW": "Curaçao", + "assets.countries.CX": "Christmas Island", + "assets.countries.CY": "Cyprus", + "assets.countries.CZ": "Czechia", + "assets.countries.DE": "Germany", + "assets.countries.DJ": "Djibouti", + "assets.countries.DK": "Denmark", + "assets.countries.DM": "Dominica", + "assets.countries.DO": "Dominican Republic", + "assets.countries.DZ": "Algeria", + "assets.countries.EC": "Ecuador", + "assets.countries.EE": "Estonia", + "assets.countries.EG": "Egypt", + "assets.countries.EH": "Western Sahara", + "assets.countries.ER": "Eritrea", + "assets.countries.ES": "Spain", + "assets.countries.ET": "Ethiopia", + "assets.countries.FI": "Finland", + "assets.countries.FJ": "Fiji", + "assets.countries.FK": "Falkland Islands (Malvinas)", + "assets.countries.FM": "Micronesia (Federated States of)", + "assets.countries.FO": "Faroe Islands", + "assets.countries.FR": "France", + "assets.countries.GA": "Gabon", + "assets.countries.GB": "United Kingdom", + "assets.countries.GD": "Grenada", + "assets.countries.GE": "Georgia", + "assets.countries.GF": "French Guiana", + "assets.countries.GG": "Guernsey", + "assets.countries.GH": "Ghana", + "assets.countries.GI": "Gibraltar", + "assets.countries.GL": "Greenland", + "assets.countries.GM": "Gambia", + "assets.countries.GN": "Guinea", + "assets.countries.GP": "Guadeloupe", + "assets.countries.GQ": "Equatorial Guinea", + "assets.countries.GR": "Greece", + "assets.countries.GS": "South Georgia and the South Sandwich Islands", + "assets.countries.GT": "Guatemala", + "assets.countries.GU": "Guam", + "assets.countries.GW": "Guinea-Bissau", + "assets.countries.GY": "Guyana", + "assets.countries.HK": "Hong Kong", + "assets.countries.HM": "Heard Island and McDonald Islands", + "assets.countries.HN": "Honduras", + "assets.countries.HR": "Croatia", + "assets.countries.HT": "Haiti", + "assets.countries.HU": "Hungary", + "assets.countries.ID": "Indonesia", + "assets.countries.IE": "Ireland", + "assets.countries.IL": "Israel", + "assets.countries.IM": "Isle of Man", + "assets.countries.IN": "India", + "assets.countries.IO": "British Indian Ocean Territory", + "assets.countries.IQ": "Iraq", + "assets.countries.IR": "Iran (Islamic Republic of)", + "assets.countries.IS": "Iceland", + "assets.countries.IT": "Italy", + "assets.countries.JE": "Jersey", + "assets.countries.JM": "Jamaica", + "assets.countries.JO": "Jordan", + "assets.countries.JP": "Japan", + "assets.countries.KE": "Kenya", + "assets.countries.KG": "Kyrgyzstan", + "assets.countries.KH": "Cambodia", + "assets.countries.KI": "Kiribati", + "assets.countries.KM": "Comoros", + "assets.countries.KN": "Saint Kitts and Nevis", + "assets.countries.KP": "Korea (the Democratic People's Republic of)", + "assets.countries.KR": "Korea (the Republic of)", + "assets.countries.KW": "Kuwait", + "assets.countries.KY": "Cayman Islands", + "assets.countries.KZ": "Kazakhstan", + "assets.countries.LA": "Lao People's Democratic Republic", + "assets.countries.LB": "Lebanon", + "assets.countries.LC": "Saint Lucia", + "assets.countries.LI": "Liechtenstein", + "assets.countries.LK": "Sri Lanka", + "assets.countries.LR": "Liberia", + "assets.countries.LS": "Lesotho", + "assets.countries.LT": "Lithuania", + "assets.countries.LU": "Luxembourg", + "assets.countries.LV": "Latvia", + "assets.countries.LY": "Libya", + "assets.countries.MA": "Morocco", + "assets.countries.MC": "Monaco", + "assets.countries.MD": "Moldova (the Republic of)", + "assets.countries.ME": "Montenegro", + "assets.countries.MF": "Saint Martin (French part)", + "assets.countries.MG": "Madagascar", + "assets.countries.MH": "Marshall Islands", + "assets.countries.MK": "North Macedonia", + "assets.countries.ML": "Mali", + "assets.countries.MM": "Myanmar", + "assets.countries.MN": "Mongolia", + "assets.countries.MO": "Macao", + "assets.countries.MP": "Northern Mariana Islands", + "assets.countries.MQ": "Martinique", + "assets.countries.MR": "Mauritania", + "assets.countries.MS": "Montserrat", + "assets.countries.MT": "Malta", + "assets.countries.MU": "Mauritius", + "assets.countries.MV": "Maldives", + "assets.countries.MW": "Malawi", + "assets.countries.MX": "Mexico", + "assets.countries.MY": "Malaysia", + "assets.countries.MZ": "Mozambique", + "assets.countries.NA": "Namibia", + "assets.countries.NC": "New Caledonia", + "assets.countries.NE": "Niger", + "assets.countries.NF": "Norfolk Island", + "assets.countries.NG": "Nigeria", + "assets.countries.NI": "Nicaragua", + "assets.countries.NL": "Netherlands", + "assets.countries.NO": "Norway", + "assets.countries.NP": "Nepal", + "assets.countries.NR": "Nauru", + "assets.countries.NU": "Niue", + "assets.countries.NZ": "New Zealand", + "assets.countries.OM": "Oman", + "assets.countries.PA": "Panama", + "assets.countries.PE": "Peru", + "assets.countries.PF": "French Polynesia", + "assets.countries.PG": "Papua New Guinea", + "assets.countries.PH": "Philippines", + "assets.countries.PK": "Pakistan", + "assets.countries.PL": "Poland", + "assets.countries.PM": "Saint Pierre and Miquelon", + "assets.countries.PN": "Pitcairn", + "assets.countries.PR": "Puerto Rico", + "assets.countries.PS": "Palestine, State of", + "assets.countries.PT": "Portugal", + "assets.countries.PW": "Palau", + "assets.countries.PY": "Paraguay", + "assets.countries.QA": "Qatar", + "assets.countries.RE": "Réunion", + "assets.countries.RO": "Romania", + "assets.countries.RS": "Serbia", + "assets.countries.RU": "Russian Federation", + "assets.countries.RW": "Rwanda", + "assets.countries.SA": "Saudi Arabia", + "assets.countries.SB": "Solomon Islands", + "assets.countries.SC": "Seychelles", + "assets.countries.SD": "Sudan", + "assets.countries.SE": "Sweden", + "assets.countries.SG": "Singapore", + "assets.countries.SH": "Saint Helena, Ascension and Tristan da Cunha", + "assets.countries.SI": "Slovenia", + "assets.countries.SJ": "Svalbard and Jan Mayen", + "assets.countries.SK": "Slovakia", + "assets.countries.SL": "Sierra Leone", + "assets.countries.SM": "San Marino", + "assets.countries.SN": "Senegal", + "assets.countries.SO": "Somalia", + "assets.countries.SR": "Suriname", + "assets.countries.SS": "South Sudan", + "assets.countries.ST": "Sao Tome and Principe", + "assets.countries.SV": "El Salvador", + "assets.countries.SX": "Sint Maarten (Dutch part)", + "assets.countries.SY": "Syrian Arab Republic", + "assets.countries.SZ": "Eswatini", + "assets.countries.TC": "Turks and Caicos Islands", + "assets.countries.TD": "Chad", + "assets.countries.TF": "French Southern Territories", + "assets.countries.TG": "Togo", + "assets.countries.TH": "Thailand", + "assets.countries.TJ": "Tajikistan", + "assets.countries.TK": "Tokelau", + "assets.countries.TL": "Timor-Leste", + "assets.countries.TM": "Turkmenistan", + "assets.countries.TN": "Tunisia", + "assets.countries.TO": "Tonga", + "assets.countries.TR": "Turkey", + "assets.countries.TT": "Trinidad and Tobago", + "assets.countries.TV": "Tuvalu", + "assets.countries.TW": "Taiwan", + "assets.countries.TZ": "Tanzania, the United Republic of", + "assets.countries.UA": "Ukraine", + "assets.countries.UG": "Uganda", + "assets.countries.UM": "United States Minor Outlying Islands", + "assets.countries.US": "United States", + "assets.countries.UY": "Uruguay", + "assets.countries.UZ": "Uzbekistan", + "assets.countries.VA": "Holy See", + "assets.countries.VC": "Saint Vincent and the Grenadines", + "assets.countries.VE": "Venezuela (Bolivarian Republic of)", + "assets.countries.VG": "Virgin Islands (British)", + "assets.countries.VI": "Virgin Islands (U.S.)", + "assets.countries.VN": "Viet Nam", + "assets.countries.VU": "Vanuatu", + "assets.countries.WF": "Wallis and Futuna", + "assets.countries.WS": "Samoa", + "assets.countries.YE": "Yemen", + "assets.countries.YT": "Mayotte", + "assets.countries.ZA": "South Africa", + "assets.countries.ZM": "Zambia", + "assets.countries.ZW": "Zimbabwe", + "assets.mimetypes.application/epub_zip": "EPUB ebook", + "assets.mimetypes.application/msword": "Word document", + "assets.mimetypes.application/pdf": "PDF document", + "assets.mimetypes.application/vnd.moodle.backup": "Moodle backup", + "assets.mimetypes.application/vnd.ms-excel": "Excel spreadsheet", + "assets.mimetypes.application/vnd.ms-excel.sheet.macroEnabled.12": "Excel 2007 macro-enabled workbook", + "assets.mimetypes.application/vnd.ms-powerpoint": "Powerpoint presentation", + "assets.mimetypes.application/vnd.oasis.opendocument.spreadsheet": "OpenDocument Spreadsheet", + "assets.mimetypes.application/vnd.oasis.opendocument.spreadsheet-template": "OpenDocument Spreadsheet template", + "assets.mimetypes.application/vnd.oasis.opendocument.text": "OpenDocument Text document", + "assets.mimetypes.application/vnd.oasis.opendocument.text-template": "OpenDocument Text template", + "assets.mimetypes.application/vnd.oasis.opendocument.text-web": "OpenDocument Web page template", + "assets.mimetypes.application/vnd.openxmlformats-officedocument.presentationml.presentation": "Powerpoint 2007 presentation", + "assets.mimetypes.application/vnd.openxmlformats-officedocument.presentationml.slideshow": "Powerpoint 2007 slideshow", + "assets.mimetypes.application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "Excel 2007 spreadsheet", + "assets.mimetypes.application/vnd.openxmlformats-officedocument.spreadsheetml.template": "Excel 2007 template", + "assets.mimetypes.application/vnd.openxmlformats-officedocument.wordprocessingml.document": "Word 2007 document", + "assets.mimetypes.application/x-iwork-keynote-sffkey": "iWork Keynote presentation", + "assets.mimetypes.application/x-iwork-numbers-sffnumbers": "iWork Numbers spreadsheet", + "assets.mimetypes.application/x-iwork-pages-sffpages": "iWork Pages document", + "assets.mimetypes.application/x-javascript": "JavaScript source", + "assets.mimetypes.application/x-mspublisher": "Publisher document", + "assets.mimetypes.application/x-shockwave-flash": "Flash animation", + "assets.mimetypes.application/xhtml_xml": "XHTML document", + "assets.mimetypes.archive": "Archive ({{$a.EXT}})", + "assets.mimetypes.audio": "Audio file ({{$a.EXT}})", + "assets.mimetypes.default": "{{$a.mimetype}}", + "assets.mimetypes.document/unknown": "File", + "assets.mimetypes.group:archive": "Archive files", + "assets.mimetypes.group:audio": "Audio files", + "assets.mimetypes.group:document": "Document files", + "assets.mimetypes.group:html_audio": "Audio files natively supported by browsers", + "assets.mimetypes.group:html_track": "HTML track files", + "assets.mimetypes.group:html_video": "Video files natively supported by browsers", + "assets.mimetypes.group:image": "Image files", + "assets.mimetypes.group:presentation": "Presentation files", + "assets.mimetypes.group:sourcecode": "Source code", + "assets.mimetypes.group:spreadsheet": "Spreadsheet files", + "assets.mimetypes.group:video": "Video files", + "assets.mimetypes.group:web_audio": "Audio files used on the web", + "assets.mimetypes.group:web_file": "Web files", + "assets.mimetypes.group:web_image": "Image files used on the web", + "assets.mimetypes.group:web_video": "Video files used on the web", + "assets.mimetypes.image": "Image ({{$a.MIMETYPE2}})", + "assets.mimetypes.image/vnd.microsoft.icon": "Windows icon", + "assets.mimetypes.text/css": "Cascading Style-Sheet", + "assets.mimetypes.text/csv": "Comma-separated values", + "assets.mimetypes.text/html": "HTML document", + "assets.mimetypes.text/plain": "Text file", + "assets.mimetypes.text/rtf": "RTF document", + "assets.mimetypes.text/vtt": "Web Video Text Track", + "assets.mimetypes.video": "Video file ({{$a.EXT}})", + "core.login.yourenteredsite": "Connect to your site" +} \ No newline at end of file diff --git a/src/assets/mimetypes/en.json b/src/assets/mimetypes/en.json new file mode 100644 index 000000000..f94347be4 --- /dev/null +++ b/src/assets/mimetypes/en.json @@ -0,0 +1,54 @@ +{ + "application/epub_zip": "EPUB ebook", + "application/msword": "Word document", + "application/pdf": "PDF document", + "application/vnd.moodle.backup": "Moodle backup", + "application/vnd.ms-excel": "Excel spreadsheet", + "application/vnd.ms-excel.sheet.macroEnabled.12": "Excel 2007 macro-enabled workbook", + "application/vnd.ms-powerpoint": "Powerpoint presentation", + "application/vnd.oasis.opendocument.spreadsheet": "OpenDocument Spreadsheet", + "application/vnd.oasis.opendocument.spreadsheet-template": "OpenDocument Spreadsheet template", + "application/vnd.oasis.opendocument.text": "OpenDocument Text document", + "application/vnd.oasis.opendocument.text-template": "OpenDocument Text template", + "application/vnd.oasis.opendocument.text-web": "OpenDocument Web page template", + "application/vnd.openxmlformats-officedocument.presentationml.presentation": "Powerpoint 2007 presentation", + "application/vnd.openxmlformats-officedocument.presentationml.slideshow": "Powerpoint 2007 slideshow", + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "Excel 2007 spreadsheet", + "application/vnd.openxmlformats-officedocument.spreadsheetml.template": "Excel 2007 template", + "application/vnd.openxmlformats-officedocument.wordprocessingml.document": "Word 2007 document", + "application/x-iwork-keynote-sffkey": "iWork Keynote presentation", + "application/x-iwork-numbers-sffnumbers": "iWork Numbers spreadsheet", + "application/x-iwork-pages-sffpages": "iWork Pages document", + "application/x-javascript": "JavaScript source", + "application/x-mspublisher": "Publisher document", + "application/x-shockwave-flash": "Flash animation", + "application/xhtml_xml": "XHTML document", + "archive": "Archive ({{$a.EXT}})", + "audio": "Audio file ({{$a.EXT}})", + "default": "{{$a.mimetype}}", + "document/unknown": "File", + "group:archive": "Archive files", + "group:audio": "Audio files", + "group:document": "Document files", + "group:html_audio": "Audio files natively supported by browsers", + "group:html_track": "HTML track files", + "group:html_video": "Video files natively supported by browsers", + "group:image": "Image files", + "group:presentation": "Presentation files", + "group:sourcecode": "Source code", + "group:spreadsheet": "Spreadsheet files", + "group:video": "Video files", + "group:web_audio": "Audio files used on the web", + "group:web_file": "Web files", + "group:web_image": "Image files used on the web", + "group:web_video": "Video files used on the web", + "image": "Image ({{$a.MIMETYPE2}})", + "image/vnd.microsoft.icon": "Windows icon", + "text/css": "Cascading Style-Sheet", + "text/csv": "Comma-separated values", + "text/html": "HTML document", + "text/plain": "Text file", + "text/rtf": "RTF document", + "text/vtt": "Web Video Text Track", + "video": "Video file ({{$a.EXT}})" +} \ No newline at end of file