mirror of
https://github.com/zulip/zulip-desktop.git
synced 2025-10-30 11:33:36 +00:00
xo: Lint *.js too.
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
This commit is contained in:
30
gulpfile.js
30
gulpfile.js
@@ -5,14 +5,14 @@ const electron = require('electron-connect').server.create({
|
|||||||
});
|
});
|
||||||
const tape = require('gulp-tape');
|
const tape = require('gulp-tape');
|
||||||
const tapColorize = require('tap-colorize');
|
const tapColorize = require('tap-colorize');
|
||||||
const ts = require("gulp-typescript");
|
const ts = require('gulp-typescript');
|
||||||
const tsProject = ts.createProject("tsconfig.json");
|
const tsProject = ts.createProject('tsconfig.json');
|
||||||
|
|
||||||
const glob = require('glob');
|
const glob = require('glob');
|
||||||
const { execSync } = require('child_process');
|
const {execSync} = require('child_process');
|
||||||
|
|
||||||
const baseFilePattern = 'app/+(main|renderer)/**/*';
|
const baseFilePattern = 'app/+(main|renderer)/**/*';
|
||||||
const globOptions = { cwd: __dirname };
|
const globOptions = {cwd: __dirname};
|
||||||
const jsFiles = glob.sync(baseFilePattern + '.js', globOptions);
|
const jsFiles = glob.sync(baseFilePattern + '.js', globOptions);
|
||||||
const tsFiles = glob.sync(baseFilePattern + '.ts', globOptions);
|
const tsFiles = glob.sync(baseFilePattern + '.ts', globOptions);
|
||||||
if (jsFiles.length !== tsFiles.length) {
|
if (jsFiles.length !== tsFiles.length) {
|
||||||
@@ -21,18 +21,18 @@ if (jsFiles.length !== tsFiles.length) {
|
|||||||
execSync(`${npx} tsc`);
|
execSync(`${npx} tsc`);
|
||||||
}
|
}
|
||||||
|
|
||||||
gulp.task("compile", function () {
|
gulp.task('compile', () => {
|
||||||
return tsProject.src()
|
return tsProject.src()
|
||||||
.pipe(tsProject())
|
.pipe(tsProject())
|
||||||
.js.pipe(gulp.dest("app"));
|
.js.pipe(gulp.dest('app'));
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('dev', () => {
|
gulp.task('dev', () => {
|
||||||
// Start browser process
|
// Start browser process
|
||||||
electron.start();
|
electron.start();
|
||||||
// Restart browser process
|
// Restart browser process
|
||||||
gulp.watch('app/main/*.ts', gulp.series('compile', 'restart:browser'));
|
gulp.watch('app/main/*.ts', gulp.series('compile', 'restart:browser'));
|
||||||
// Reload renderer process
|
// Reload renderer process
|
||||||
gulp.watch('app/renderer/css/*.css', gulp.series('reload:renderer'));
|
gulp.watch('app/renderer/css/*.css', gulp.series('reload:renderer'));
|
||||||
gulp.watch('app/renderer/*.html', gulp.series('reload:renderer'));
|
gulp.watch('app/renderer/*.html', gulp.series('reload:renderer'));
|
||||||
gulp.watch('app/renderer/js/**/*.ts', gulp.series('compile', 'reload:renderer'));
|
gulp.watch('app/renderer/js/**/*.ts', gulp.series('compile', 'reload:renderer'));
|
||||||
@@ -45,16 +45,16 @@ gulp.task('restart:browser', done => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('reload:renderer', done => {
|
gulp.task('reload:renderer', done => {
|
||||||
// Reload renderer process
|
// Reload renderer process
|
||||||
electron.reload();
|
electron.reload();
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('test-e2e', () => {
|
gulp.task('test-e2e', () => {
|
||||||
return gulp.src('tests/*.js')
|
return gulp.src('tests/*.js')
|
||||||
.pipe(tape({
|
.pipe(tape({
|
||||||
reporter: tapColorize()
|
reporter: tapColorize()
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('default', gulp.parallel('dev', 'test-e2e'));
|
gulp.task('default', gulp.parallel('dev', 'test-e2e'));
|
||||||
|
|||||||
24
package.json
24
package.json
@@ -195,12 +195,14 @@
|
|||||||
"electron-notarize": "^0.2.1",
|
"electron-notarize": "^0.2.1",
|
||||||
"eslint-config-xo-typescript": "^0.26.0",
|
"eslint-config-xo-typescript": "^0.26.0",
|
||||||
"fs-extra": "^8.1.0",
|
"fs-extra": "^8.1.0",
|
||||||
|
"glob": "^5.0.15",
|
||||||
"gulp": "^4.0.2",
|
"gulp": "^4.0.2",
|
||||||
"gulp-tape": "^1.0.0",
|
"gulp-tape": "^1.0.0",
|
||||||
"gulp-typescript": "^6.0.0-alpha.1",
|
"gulp-typescript": "^6.0.0-alpha.1",
|
||||||
"htmlhint": "^0.11.0",
|
"htmlhint": "^0.11.0",
|
||||||
"nodemon": "^2.0.2",
|
"nodemon": "^2.0.2",
|
||||||
"pre-commit": "^1.2.2",
|
"pre-commit": "^1.2.2",
|
||||||
|
"rimraf": "^2.7.1",
|
||||||
"spectron": "^10.0.1",
|
"spectron": "^10.0.1",
|
||||||
"stylelint": "^13.2.0",
|
"stylelint": "^13.2.0",
|
||||||
"tap-colorize": "^1.2.0",
|
"tap-colorize": "^1.2.0",
|
||||||
@@ -209,22 +211,16 @@
|
|||||||
"xo": "^0.27.2"
|
"xo": "^0.27.2"
|
||||||
},
|
},
|
||||||
"xo": {
|
"xo": {
|
||||||
"extends": "xo-typescript",
|
|
||||||
"extensions": [
|
"extensions": [
|
||||||
"ts"
|
"ts"
|
||||||
],
|
],
|
||||||
"parserOptions": {
|
"parserOptions": {
|
||||||
"ecmaVersion": 6,
|
"ecmaVersion": 2019
|
||||||
"sourceType": "module",
|
|
||||||
"ecmaFeatures": {
|
|
||||||
"globalReturn": true,
|
|
||||||
"modules": true
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"esnext": true,
|
|
||||||
"overrides": [
|
"overrides": [
|
||||||
{
|
{
|
||||||
"files": "app/**/*.ts",
|
"files": "**/*.ts",
|
||||||
|
"extends": "xo-typescript",
|
||||||
"rules": {
|
"rules": {
|
||||||
"@typescript-eslint/member-ordering": "off",
|
"@typescript-eslint/member-ordering": "off",
|
||||||
"@typescript-eslint/no-dynamic-delete": "off",
|
"@typescript-eslint/no-dynamic-delete": "off",
|
||||||
@@ -250,17 +246,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"ignore": [
|
|
||||||
"tests/*.js",
|
|
||||||
"tools/locale-helper/*.js",
|
|
||||||
"*/**/*.js",
|
|
||||||
"*.js",
|
|
||||||
"typings.d.ts"
|
|
||||||
],
|
|
||||||
"envs": [
|
"envs": [
|
||||||
"node",
|
"node",
|
||||||
"browser",
|
"browser"
|
||||||
"mocha"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
const dotenv = require('dotenv');
|
const dotenv = require('dotenv');
|
||||||
|
|
||||||
dotenv.config({ path: path.join(__dirname, '/../.env') });
|
dotenv.config({path: path.join(__dirname, '/../.env')});
|
||||||
|
|
||||||
const { notarize } = require('electron-notarize');
|
const {notarize} = require('electron-notarize');
|
||||||
|
|
||||||
exports.default = async function notarizing(context) {
|
exports.default = async function (context) {
|
||||||
const { electronPlatformName, appOutDir } = context;
|
const {electronPlatformName, appOutDir} = context;
|
||||||
if (electronPlatformName !== 'darwin') {
|
if (electronPlatformName !== 'darwin') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const appName = context.packager.appInfo.productFilename;
|
const appName = context.packager.appInfo.productFilename;
|
||||||
|
|
||||||
return await notarize({
|
return notarize({
|
||||||
appBundleId: 'org.zulip.zulip-electron',
|
appBundleId: 'org.zulip.zulip-electron',
|
||||||
appPath: `${appOutDir}/${appName}.app`,
|
appPath: `${appOutDir}/${appName}.app`,
|
||||||
appleId: process.env.APPLE_ID,
|
appleId: process.env.APPLE_ID,
|
||||||
appleIdPassword: process.env.APPLE_ID_PASS,
|
appleIdPassword: process.env.APPLE_ID_PASS
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
const path = require('path')
|
const TEST_APP_PRODUCT_NAME = 'ZulipTest';
|
||||||
|
|
||||||
const TEST_APP_PRODUCT_NAME = 'ZulipTest'
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
TEST_APP_PRODUCT_NAME
|
TEST_APP_PRODUCT_NAME
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -1,13 +1,16 @@
|
|||||||
const test = require('tape')
|
const test = require('tape');
|
||||||
const setup = require('./setup')
|
const setup = require('./setup');
|
||||||
|
|
||||||
test('app runs', function (t) {
|
test('app runs', async t => {
|
||||||
t.timeoutAfter(10e3)
|
t.timeoutAfter(10e3);
|
||||||
setup.resetTestDataDir()
|
setup.resetTestDataDir();
|
||||||
const app = setup.createApp()
|
const app = setup.createApp();
|
||||||
setup.waitForLoad(app, t)
|
try {
|
||||||
.then(() => app.client.windowByIndex(1)) // focus on webview
|
await setup.waitForLoad(app, t);
|
||||||
.then(() => app.client.waitForExist('//*[@id="connect"]')) // id of the connect button
|
await app.client.windowByIndex(1); // Focus on webview
|
||||||
.then(() => setup.endTest(app, t),
|
await app.client.waitForExist('//*[@id="connect"]'); // Id of the connect button
|
||||||
(err) => setup.endTest(app, t, err || 'error'))
|
await setup.endTest(app, t);
|
||||||
})
|
} catch (error) {
|
||||||
|
await setup.endTest(app, t, error || 'error');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|||||||
136
tests/setup.js
136
tests/setup.js
@@ -1,97 +1,95 @@
|
|||||||
const Application = require('spectron').Application
|
const {Application} = require('spectron');
|
||||||
const fs = require('fs')
|
const fs = require('fs');
|
||||||
const mkdirp = require('mkdirp')
|
const path = require('path');
|
||||||
const path = require('path')
|
const rimraf = require('rimraf');
|
||||||
const rimraf = require('rimraf')
|
|
||||||
|
|
||||||
const config = require('./config')
|
const config = require('./config');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
createApp,
|
createApp,
|
||||||
endTest,
|
endTest,
|
||||||
waitForLoad,
|
waitForLoad,
|
||||||
wait,
|
wait,
|
||||||
resetTestDataDir
|
resetTestDataDir
|
||||||
}
|
};
|
||||||
|
|
||||||
// Runs Zulip Desktop.
|
// Runs Zulip Desktop.
|
||||||
// Returns a promise that resolves to a Spectron Application once the app has loaded.
|
// Returns a promise that resolves to a Spectron Application once the app has loaded.
|
||||||
// Takes a Tape test. Makes some basic assertions to verify that the app loaded correctly.
|
// Takes a Tape test. Makes some basic assertions to verify that the app loaded correctly.
|
||||||
function createApp (t) {
|
function createApp() {
|
||||||
generateTestAppPackageJson()
|
generateTestAppPackageJson();
|
||||||
return new Application({
|
return new Application({
|
||||||
path: path.join(__dirname, '..', 'node_modules', '.bin',
|
path: path.join(__dirname, '..', 'node_modules', '.bin',
|
||||||
'electron' + (process.platform === 'win32' ? '.cmd' : '')),
|
'electron' + (process.platform === 'win32' ? '.cmd' : '')),
|
||||||
args: [path.join(__dirname)], // Ensure this dir has a package.json file with a 'main' entry piont
|
args: [path.join(__dirname)], // Ensure this dir has a package.json file with a 'main' entry piont
|
||||||
env: {NODE_ENV: 'test'},
|
env: {NODE_ENV: 'test'},
|
||||||
waitTimeout: 10e3
|
waitTimeout: 10e3
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generates package.json for test app
|
// Generates package.json for test app
|
||||||
// Reads app package.json and updates the productName to config.TEST_APP_PRODUCT_NAME
|
// Reads app package.json and updates the productName to config.TEST_APP_PRODUCT_NAME
|
||||||
// We do this so that the app integration doesn't doesn't share the same appDataDir as the dev application
|
// We do this so that the app integration doesn't doesn't share the same appDataDir as the dev application
|
||||||
function generateTestAppPackageJson () {
|
function generateTestAppPackageJson() {
|
||||||
let packageJson = require(path.join(__dirname, '../package.json'))
|
const packageJson = require(path.join(__dirname, '../package.json'));
|
||||||
packageJson.productName = config.TEST_APP_PRODUCT_NAME
|
packageJson.productName = config.TEST_APP_PRODUCT_NAME;
|
||||||
packageJson.main = '../app/main'
|
packageJson.main = '../app/main';
|
||||||
|
|
||||||
const testPackageJsonPath = path.join(__dirname, 'package.json')
|
const testPackageJsonPath = path.join(__dirname, 'package.json');
|
||||||
fs.writeFileSync(testPackageJsonPath, JSON.stringify(packageJson, null, ' '), 'utf-8')
|
fs.writeFileSync(testPackageJsonPath, JSON.stringify(packageJson, null, ' '), 'utf-8');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Starts the app, waits for it to load, returns a promise
|
// Starts the app, waits for it to load, returns a promise
|
||||||
function waitForLoad (app, t, opts) {
|
async function waitForLoad(app, t, opts) {
|
||||||
if (!opts) opts = {}
|
if (!opts) {
|
||||||
return app.start().then(function () {
|
opts = {};
|
||||||
return app.client.waitUntilWindowLoaded()
|
}
|
||||||
})
|
|
||||||
.then(function() {
|
await app.start();
|
||||||
return app.client.pause(2000);
|
await app.client.waitUntilWindowLoaded();
|
||||||
})
|
await app.client.pause(2000);
|
||||||
.then(function () {
|
const title = await app.webContents.getTitle();
|
||||||
return app.webContents.getTitle()
|
t.equal(title, 'Zulip', 'html title');
|
||||||
}).then(function (title) {
|
|
||||||
t.equal(title, 'Zulip', 'html title')
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a promise that resolves after 'ms' milliseconds. Default: 1 second
|
// Returns a promise that resolves after 'ms' milliseconds. Default: 1 second
|
||||||
function wait (ms) {
|
async function wait(ms) {
|
||||||
if (ms === undefined) ms = 1000 // Default: wait long enough for the UI to update
|
if (ms === undefined) {
|
||||||
return new Promise(function (resolve, reject) {
|
ms = 1000;
|
||||||
setTimeout(resolve, ms)
|
} // Default: wait long enough for the UI to update
|
||||||
})
|
|
||||||
|
return new Promise((resolve => {
|
||||||
|
setTimeout(resolve, ms);
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Quit the app, end the test, either in success (!err) or failure (err)
|
// Quit the app, end the test, either in success (!err) or failure (err)
|
||||||
function endTest (app, t, err) {
|
async function endTest(app, t, err) {
|
||||||
return app.stop().then(function () {
|
await app.stop();
|
||||||
t.end(err)
|
t.end(err);
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAppDataDir () {
|
function getAppDataDir() {
|
||||||
let base
|
let base;
|
||||||
|
|
||||||
if (process.platform === 'darwin') {
|
if (process.platform === 'darwin') {
|
||||||
base = path.join(process.env.HOME, 'Library', 'Application Support')
|
base = path.join(process.env.HOME, 'Library', 'Application Support');
|
||||||
} else if (process.platform === 'linux') {
|
} else if (process.platform === 'linux') {
|
||||||
base = process.env.XDG_CONFIG_HOME ?
|
base = process.env.XDG_CONFIG_HOME ?
|
||||||
process.env.XDG_CONFIG_HOME : path.join(process.env.HOME, '.config')
|
process.env.XDG_CONFIG_HOME : path.join(process.env.HOME, '.config');
|
||||||
} else if (process.platform === 'win32') {
|
} else if (process.platform === 'win32') {
|
||||||
base = process.env.APPDATA
|
base = process.env.APPDATA;
|
||||||
} else {
|
} else {
|
||||||
console.log('Could not detect app data dir base. Exiting...')
|
throw new Error('Could not detect app data dir base.');
|
||||||
process.exit(1)
|
}
|
||||||
}
|
|
||||||
console.log('Detected App Data Dir base:', base)
|
console.log('Detected App Data Dir base:', base);
|
||||||
return path.join(base, config.TEST_APP_PRODUCT_NAME)
|
return path.join(base, config.TEST_APP_PRODUCT_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resets the test directory, containing domain.json, window-state.json, etc
|
// Resets the test directory, containing domain.json, window-state.json, etc
|
||||||
function resetTestDataDir () {
|
function resetTestDataDir() {
|
||||||
appDataDir = getAppDataDir()
|
const appDataDir = getAppDataDir();
|
||||||
rimraf.sync(appDataDir)
|
rimraf.sync(appDataDir);
|
||||||
rimraf.sync(path.join(__dirname, 'package.json'))
|
rimraf.sync(path.join(__dirname, 'package.json'));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,21 @@
|
|||||||
const test = require('tape')
|
const test = require('tape');
|
||||||
const setup = require('./setup')
|
const setup = require('./setup');
|
||||||
|
|
||||||
test('add-organization', function (t) {
|
|
||||||
t.timeoutAfter(50e3)
|
|
||||||
setup.resetTestDataDir()
|
|
||||||
const app = setup.createApp()
|
|
||||||
setup.waitForLoad(app, t)
|
|
||||||
.then(() => app.client.windowByIndex(1)) // focus on webview
|
|
||||||
.then(() => app.client.setValue('.setting-input-value', 'chat.zulip.org'))
|
|
||||||
.then(() => app.client.click('#connect'))
|
|
||||||
.then(() => setup.wait(5000))
|
|
||||||
.then(() => app.client.windowByIndex(0)) // Switch focus back to main win
|
|
||||||
.then(() => app.client.windowByIndex(1)) // Switch focus back to org webview
|
|
||||||
.then(() => app.client.waitForExist('//*[@id="id_username"]'))
|
|
||||||
.then(() => setup.endTest(app, t),
|
|
||||||
(err) => setup.endTest(app, t, err || 'error'))
|
|
||||||
})
|
|
||||||
|
|
||||||
|
test('add-organization', async t => {
|
||||||
|
t.timeoutAfter(50e3);
|
||||||
|
setup.resetTestDataDir();
|
||||||
|
const app = setup.createApp();
|
||||||
|
try {
|
||||||
|
await setup.waitForLoad(app, t);
|
||||||
|
await app.client.windowByIndex(1); // Focus on webview
|
||||||
|
await app.client.setValue('.setting-input-value', 'chat.zulip.org');
|
||||||
|
await app.client.click('#connect');
|
||||||
|
await setup.wait(5000);
|
||||||
|
await app.client.windowByIndex(0); // Switch focus back to main win
|
||||||
|
await app.client.windowByIndex(1); // Switch focus back to org webview
|
||||||
|
await app.client.waitForExist('//*[@id="id_username"]');
|
||||||
|
await setup.endTest(app, t);
|
||||||
|
} catch (error) {
|
||||||
|
await setup.endTest(app, t, error || 'error');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,17 +1,19 @@
|
|||||||
const test = require('tape')
|
const test = require('tape');
|
||||||
const setup = require('./setup')
|
const setup = require('./setup');
|
||||||
|
|
||||||
// Create new org link should open in the default browser [WIP]
|
// Create new org link should open in the default browser [WIP]
|
||||||
|
|
||||||
test('new-org-link', function (t) {
|
test('new-org-link', async t => {
|
||||||
t.timeoutAfter(50e3)
|
t.timeoutAfter(50e3);
|
||||||
setup.resetTestDataDir()
|
setup.resetTestDataDir();
|
||||||
const app = setup.createApp()
|
const app = setup.createApp();
|
||||||
setup.waitForLoad(app, t)
|
try {
|
||||||
.then(() => app.client.windowByIndex(1)) // focus on webview
|
await setup.waitForLoad(app, t);
|
||||||
.then(() => app.client.click('#open-create-org-link')) // Click on new org link button
|
await app.client.windowByIndex(1); // Focus on webview
|
||||||
.then(() => setup.wait(5000))
|
await app.client.click('#open-create-org-link'); // Click on new org link button
|
||||||
.then(() => setup.endTest(app, t),
|
await setup.wait(5000);
|
||||||
(err) => setup.endTest(app, t, err || 'error'))
|
await setup.endTest(app, t);
|
||||||
})
|
} catch (error) {
|
||||||
|
await setup.endTest(app, t, error || 'error');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|||||||
@@ -5,28 +5,30 @@ const fs = require('fs');
|
|||||||
const translationDir = path.resolve(__dirname, '../../app/translations');
|
const translationDir = path.resolve(__dirname, '../../app/translations');
|
||||||
|
|
||||||
function writeJSON(file, data) {
|
function writeJSON(file, data) {
|
||||||
const filePath = path.resolve(translationDir, file);
|
const filePath = path.resolve(translationDir, file);
|
||||||
fs.writeFileSync(filePath, `${JSON.stringify(data, null, '\t')}\n`, 'utf8');
|
fs.writeFileSync(filePath, `${JSON.stringify(data, null, '\t')}\n`, 'utf8');
|
||||||
}
|
}
|
||||||
|
|
||||||
const { phrases } = require('./locale-template');
|
const {phrases} = require('./locale-template');
|
||||||
const supportedLocales = require('./supported-locales.json');
|
const supportedLocales = require('./supported-locales.json');
|
||||||
|
|
||||||
phrases.sort();
|
phrases.sort();
|
||||||
for (let locale in supportedLocales) {
|
for (const [locale, name] of Object.entries(supportedLocales)) {
|
||||||
console.log(`fetching translation for: ${supportedLocales[locale]} - ${locale}..`);
|
console.log(`fetching translation for: ${name} - ${locale}..`);
|
||||||
translate(phrases.join('\n'), { to: locale })
|
(async () => {
|
||||||
.then(res => {
|
try {
|
||||||
const localeFile = `${locale}.json`;
|
const res = await translate(phrases.join('\n'), {to: locale});
|
||||||
const translatedText = res.text.split('\n');
|
const localeFile = `${locale}.json`;
|
||||||
const translationJSON = {};
|
const translatedText = res.text.split('\n');
|
||||||
phrases.forEach((phrase, index) => {
|
const translationJSON = {};
|
||||||
translationJSON[phrase] = translatedText[index];
|
phrases.forEach((phrase, index) => {
|
||||||
});
|
translationJSON[phrase] = translatedText[index];
|
||||||
|
});
|
||||||
|
|
||||||
writeJSON(localeFile, translationJSON);
|
writeJSON(localeFile, translationJSON);
|
||||||
console.log(`create: ${localeFile}`);
|
console.log(`create: ${localeFile}`);
|
||||||
}).catch(err => {
|
} catch (error) {
|
||||||
console.error(err);
|
console.error(error);
|
||||||
});
|
}
|
||||||
|
})();
|
||||||
}
|
}
|
||||||
|
|||||||
18
typings.d.ts
vendored
18
typings.d.ts
vendored
@@ -3,20 +3,20 @@ declare module 'node-mac-notifier';
|
|||||||
declare module 'wurl';
|
declare module 'wurl';
|
||||||
|
|
||||||
interface PageParamsObject {
|
interface PageParamsObject {
|
||||||
realm_uri: string;
|
realm_uri: string;
|
||||||
default_language: string;
|
default_language: string;
|
||||||
external_authentication_methods: any;
|
external_authentication_methods: any;
|
||||||
}
|
}
|
||||||
declare var page_params: PageParamsObject;
|
declare let page_params: PageParamsObject;
|
||||||
|
|
||||||
// This is mostly zulip side of code we access from window
|
// This is mostly zulip side of code we access from window
|
||||||
interface Window {
|
interface Window {
|
||||||
$: any;
|
$: any;
|
||||||
narrow: any
|
narrow: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ZulipWebWindow extends Window {
|
interface ZulipWebWindow extends Window {
|
||||||
electron_bridge: any;
|
electron_bridge: any;
|
||||||
tray: any;
|
tray: any;
|
||||||
lightbox: any;
|
lightbox: any;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user