501 lines
15 KiB
JavaScript
501 lines
15 KiB
JavaScript
'use strict';
|
|
|
|
const gulp = require('gulp');
|
|
const fs = require('fs');
|
|
const pkg = require('./package.json');
|
|
const iopackage = require('./io-package.json');
|
|
const version = (pkg && pkg.version) ? pkg.version : iopackage.common.version;
|
|
const uglify = require('gulp-uglify');
|
|
const concat = require('gulp-concat');
|
|
const sourcemaps = require('gulp-sourcemaps');
|
|
const gutil = require('gulp-util');
|
|
const htmlmin = require('gulp-htmlmin');
|
|
const del = require('del');
|
|
|
|
/*var appName = getAppName();
|
|
|
|
function getAppName() {
|
|
var parts = __dirname.replace(/\\/g, '/').split('/');
|
|
return parts[parts.length - 1].split('.')[0].toLowerCase();
|
|
}
|
|
*/
|
|
const fileName = 'words.js';
|
|
let languages = {
|
|
en: {},
|
|
de: {},
|
|
ru: {},
|
|
pt: {},
|
|
nl: {},
|
|
fr: {},
|
|
it: {},
|
|
es: {},
|
|
pl: {}
|
|
};
|
|
|
|
function lang2data(lang, isFlat) {
|
|
let str = isFlat ? '' : '{\n';
|
|
let count = 0;
|
|
for (const w in lang) {
|
|
if (lang.hasOwnProperty(w)) {
|
|
count++;
|
|
if (isFlat) {
|
|
str += (lang[w] === '' ? (isFlat[w] || w) : lang[w]) + '\n';
|
|
} else {
|
|
const key = ' "' + w.replace(/"/g, '\\"') + '": ';
|
|
str += key + '"' + lang[w].replace(/"/g, '\\"') + '",\n';
|
|
}
|
|
}
|
|
}
|
|
if (!count) return isFlat ? '' : '{\n}';
|
|
if (isFlat) {
|
|
return str;
|
|
} else {
|
|
return str.substring(0, str.length - 2) + '\n}';
|
|
}
|
|
}
|
|
|
|
function readWordJs(src) {
|
|
try {
|
|
let words;
|
|
if (fs.existsSync(src + 'js/' + fileName)) {
|
|
words = fs.readFileSync(src + 'js/' + fileName).toString();
|
|
} else {
|
|
words = fs.readFileSync(src + fileName).toString();
|
|
}
|
|
|
|
const lines = words.split(/\r\n|\r|\n/g);
|
|
let i = 0;
|
|
while (!lines[i].match(/^systemDictionary = {/)) {
|
|
i++;
|
|
}
|
|
lines.splice(0, i);
|
|
|
|
// remove last empty lines
|
|
i = lines.length - 1;
|
|
while (!lines[i]) {
|
|
i--;
|
|
}
|
|
if (i < lines.length - 1) {
|
|
lines.splice(i + 1);
|
|
}
|
|
|
|
lines[0] = lines[0].replace('systemDictionary = ', '');
|
|
lines[lines.length - 1] = lines[lines.length - 1].trim().replace(/};$/, '}');
|
|
words = lines.join('\n');
|
|
const resultFunc = new Function('return ' + words + ';');
|
|
|
|
return resultFunc();
|
|
} catch (e) {
|
|
return null;
|
|
}
|
|
}
|
|
function padRight(text, totalLength) {
|
|
return text + (text.length < totalLength ? new Array(totalLength - text.length).join(' ') : '');
|
|
}
|
|
function writeWordJs(data, src) {
|
|
let text = '// DO NOT EDIT THIS FILE!!! IT WILL BE AUTOMATICALLY GENERATED FROM src/i18n\n';
|
|
text += '/*global systemDictionary:true */\n';
|
|
text += '\'use strict\';\n\n';
|
|
|
|
text += 'systemDictionary = {\n';
|
|
for (const word in data) {
|
|
if (data.hasOwnProperty(word)) {
|
|
text += ' ' + padRight('"' + word.replace(/"/g, '\\"') + '": {', 50);
|
|
let line = '';
|
|
for (const lang in data[word]) {
|
|
if (data[word].hasOwnProperty(lang)) {
|
|
line += '"' + lang + '": "' + padRight(data[word][lang].replace(/"/g, '\\"') + '",', 50) + ' ';
|
|
}
|
|
}
|
|
if (line) {
|
|
line = line.trim();
|
|
line = line.substring(0, line.length - 1);
|
|
}
|
|
text += line + '},\n';
|
|
}
|
|
}
|
|
text += '};';
|
|
|
|
if (fs.existsSync(src + 'js/')) {
|
|
fs.writeFileSync(src + 'js/' + fileName, text);
|
|
} else {
|
|
fs.writeFileSync(src + '' + fileName, text);
|
|
}
|
|
}
|
|
|
|
const EMPTY = '';
|
|
|
|
function words2languages(src) {
|
|
const langs = Object.assign({}, languages);
|
|
const data = readWordJs(src);
|
|
if (data) {
|
|
for (const word in data) {
|
|
if (data.hasOwnProperty(word)) {
|
|
for (const lang in data[word]) {
|
|
if (data[word].hasOwnProperty(lang)) {
|
|
langs[lang][word] = data[word][lang];
|
|
// pre-fill all other languages
|
|
for (const j in langs) {
|
|
if (langs.hasOwnProperty(j)) {
|
|
langs[j][word] = langs[j][word] || EMPTY;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (!fs.existsSync(src + 'i18n/')) {
|
|
fs.mkdirSync(src + 'i18n/');
|
|
}
|
|
for (const l in langs) {
|
|
if (!langs.hasOwnProperty(l)) continue;
|
|
const keys = Object.keys(langs[l]);
|
|
//keys.sort();
|
|
let obj = {};
|
|
for (let k = 0; k < keys.length; k++) {
|
|
obj[keys[k]] = langs[l][keys[k]];
|
|
}
|
|
if (!fs.existsSync(src + 'i18n/' + l)) {
|
|
fs.mkdirSync(src + 'i18n/' + l);
|
|
}
|
|
|
|
fs.writeFileSync(src + 'i18n/' + l + '/translations.json', lang2data(obj));
|
|
}
|
|
} else {
|
|
console.error('Cannot read or parse ' + fileName);
|
|
}
|
|
}
|
|
function words2languagesFlat(src) {
|
|
const langs = Object.assign({}, languages);
|
|
const data = readWordJs(src);
|
|
if (data) {
|
|
for (const word in data) {
|
|
if (data.hasOwnProperty(word)) {
|
|
for (const lang in data[word]) {
|
|
if (data[word].hasOwnProperty(lang)) {
|
|
langs[lang][word] = data[word][lang];
|
|
// pre-fill all other languages
|
|
for (const j in langs) {
|
|
if (langs.hasOwnProperty(j)) {
|
|
langs[j][word] = langs[j][word] || EMPTY;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
const keys = Object.keys(langs.en);
|
|
//keys.sort();
|
|
for (const l in langs) {
|
|
if (!langs.hasOwnProperty(l)) continue;
|
|
let obj = {};
|
|
for (let k = 0; k < keys.length; k++) {
|
|
obj[keys[k]] = langs[l][keys[k]];
|
|
}
|
|
langs[l] = obj;
|
|
}
|
|
if (!fs.existsSync(src + 'i18n/')) {
|
|
fs.mkdirSync(src + 'i18n/');
|
|
}
|
|
for (const ll in langs) {
|
|
if (!langs.hasOwnProperty(ll)) continue;
|
|
if (!fs.existsSync(src + 'i18n/' + ll)) {
|
|
fs.mkdirSync(src + 'i18n/' + ll);
|
|
}
|
|
|
|
fs.writeFileSync(src + 'i18n/' + ll + '/flat.txt', lang2data(langs[ll], langs.en));
|
|
}
|
|
fs.writeFileSync(src + 'i18n/flat.txt', keys.join('\n'));
|
|
} else {
|
|
console.error('Cannot read or parse ' + fileName);
|
|
}
|
|
}
|
|
function languagesFlat2words(src) {
|
|
const dirs = fs.readdirSync(src + 'i18n/');
|
|
let langs = {};
|
|
let bigOne = {};
|
|
const order = Object.keys(languages);
|
|
dirs.sort((a, b) => {
|
|
const posA = order.indexOf(a);
|
|
const posB = order.indexOf(b);
|
|
if (posA === -1 && posB === -1) {
|
|
if (a > b) return 1;
|
|
if (a < b) return -1;
|
|
return 0;
|
|
} else if (posA === -1) {
|
|
return -1;
|
|
} else if (posB === -1) {
|
|
return 1;
|
|
} else {
|
|
if (posA > posB) return 1;
|
|
if (posA < posB) return -1;
|
|
return 0;
|
|
}
|
|
});
|
|
const keys = fs.readFileSync(src + 'i18n/flat.txt').toString().split('\n');
|
|
|
|
for (let l = 0; l < dirs.length; l++) {
|
|
if (dirs[l] === 'flat.txt') continue;
|
|
const lang = dirs[l];
|
|
const values = fs.readFileSync(src + 'i18n/' + lang + '/flat.txt').toString().split('\n');
|
|
langs[lang] = {};
|
|
keys.forEach(function (word, i) {
|
|
langs[lang][word] = values[i].replace(/<\/ i>/g, '</i>').replace(/<\/ b>/g, '</b>').replace(/<\/ span>/g, '</span>').replace(/% s/g, ' %s');
|
|
});
|
|
|
|
const words = langs[lang];
|
|
for (const word in words) {
|
|
if (words.hasOwnProperty(word)) {
|
|
bigOne[word] = bigOne[word] || {};
|
|
if (words[word] !== EMPTY) {
|
|
bigOne[word][lang] = words[word];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// read actual words.js
|
|
const aWords = readWordJs();
|
|
|
|
const temporaryIgnore = ['pt', 'fr', 'nl', 'flat.txt'];
|
|
if (aWords) {
|
|
// Merge words together
|
|
for (const w in aWords) {
|
|
if (aWords.hasOwnProperty(w)) {
|
|
if (!bigOne[w]) {
|
|
console.warn('Take from actual words.js: ' + w);
|
|
bigOne[w] = aWords[w]
|
|
}
|
|
dirs.forEach(function (lang) {
|
|
if (temporaryIgnore.indexOf(lang) !== -1) return;
|
|
if (!bigOne[w][lang]) {
|
|
console.warn('Missing "' + lang + '": ' + w);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
writeWordJs(bigOne, src);
|
|
}
|
|
function languages2words(src) {
|
|
const dirs = fs.readdirSync(src + 'i18n/');
|
|
const langs = {};
|
|
const bigOne = {};
|
|
const order = Object.keys(languages);
|
|
dirs.sort((a, b) => {
|
|
const posA = order.indexOf(a);
|
|
const posB = order.indexOf(b);
|
|
if (posA === -1 && posB === -1) {
|
|
if (a > b) return 1;
|
|
if (a < b) return -1;
|
|
return 0;
|
|
} else if (posA === -1) {
|
|
return -1;
|
|
} else if (posB === -1) {
|
|
return 1;
|
|
} else {
|
|
if (posA > posB) return 1;
|
|
if (posA < posB) return -1;
|
|
return 0;
|
|
}
|
|
});
|
|
for (let l = 0; l < dirs.length; l++) {
|
|
if (dirs[l] === 'flat.txt') continue;
|
|
const lang = dirs[l];
|
|
langs[lang] = fs.readFileSync(src + 'i18n/' + lang + '/translations.json').toString();
|
|
langs[lang] = JSON.parse(langs[lang]);
|
|
const words = langs[lang];
|
|
for (const word in words) {
|
|
if (words.hasOwnProperty(word)) {
|
|
bigOne[word] = bigOne[word] || {};
|
|
if (words[word] !== EMPTY) {
|
|
bigOne[word][lang] = words[word];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// read actual words.js
|
|
const aWords = readWordJs();
|
|
|
|
const temporaryIgnore = ['pt', 'fr', 'nl', 'it'];
|
|
if (aWords) {
|
|
// Merge words together
|
|
for (const w in aWords) {
|
|
if (aWords.hasOwnProperty(w)) {
|
|
if (!bigOne[w]) {
|
|
console.warn('Take from actual words.js: ' + w);
|
|
bigOne[w] = aWords[w]
|
|
}
|
|
dirs.forEach(function (lang) {
|
|
if (temporaryIgnore.indexOf(lang) !== -1) return;
|
|
if (!bigOne[w][lang]) {
|
|
console.warn('Missing "' + lang + '": ' + w);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
writeWordJs(bigOne, src);
|
|
}
|
|
|
|
gulp.task('words2languages', done => {
|
|
words2languages('./src/');
|
|
done();
|
|
});
|
|
|
|
gulp.task('words2languagesFlat', done => {
|
|
words2languagesFlat('./src/');
|
|
done();
|
|
});
|
|
|
|
gulp.task('languagesFlat2words', done => {
|
|
languagesFlat2words('./src/');
|
|
done();
|
|
});
|
|
|
|
gulp.task('languages2words', done => {
|
|
languages2words('./src/');
|
|
done();
|
|
});
|
|
|
|
|
|
gulp.task('updateEditHtml', done => {
|
|
let text = fs.readFileSync('./src/edit.html').toString('utf-8');
|
|
let newText = text.replace(/Version: \d+\.\d+\.\d+<\/div>/, `Version: ${pkg.version}</div>`);
|
|
if (newText !== text) {
|
|
fs.writeFileSync('./src/edit.html', newText);
|
|
}
|
|
done();
|
|
});
|
|
|
|
gulp.task('updatePackages', done => {
|
|
iopackage.common.version = pkg.version;
|
|
iopackage.common.news = iopackage.common.news || {};
|
|
if (!iopackage.common.news[pkg.version]) {
|
|
const news = iopackage.common.news;
|
|
const newNews = {};
|
|
|
|
newNews[pkg.version] = {
|
|
en: 'news',
|
|
de: 'neues',
|
|
ru: 'новое'
|
|
};
|
|
iopackage.common.news = Object.assign(newNews, news);
|
|
}
|
|
fs.writeFileSync('io-package.json', JSON.stringify(iopackage, null, 4));
|
|
done();
|
|
});
|
|
|
|
gulp.task('updateReadme', done => {
|
|
const readme = fs.readFileSync('README.md').toString();
|
|
const pos = readme.indexOf('## Changelog\n');
|
|
if (pos !== -1) {
|
|
const readmeStart = readme.substring(0, pos + '## Changelog\n'.length);
|
|
const readmeEnd = readme.substring(pos + '## Changelog\n'.length);
|
|
|
|
if (readme.indexOf(version) === -1) {
|
|
const timestamp = new Date();
|
|
const date = timestamp.getFullYear() + '-' +
|
|
('0' + (timestamp.getMonth() + 1).toString(10)).slice(-2) + '-' +
|
|
('0' + (timestamp.getDate()).toString(10)).slice(-2);
|
|
|
|
let news = '';
|
|
if (iopackage.common.news && iopackage.common.news[pkg.version]) {
|
|
news += '* ' + iopackage.common.news[pkg.version].en;
|
|
}
|
|
|
|
fs.writeFileSync('README.md', readmeStart + '### ' + version + ' (' + date + ')\n' + (news ? news + '\n\n' : '\n') + readmeEnd);
|
|
}
|
|
}
|
|
done();
|
|
});
|
|
|
|
gulp.task('clean', () => {
|
|
return del([
|
|
'src/js/words.js',
|
|
'www/**/*'
|
|
]);
|
|
});
|
|
|
|
gulp.task('flotJS', () => {
|
|
return gulp.src([
|
|
'./src/lib/js/jquery.flot.min.js',
|
|
'./src/lib/js/jquery.flot.resize.min.js',
|
|
'./src/lib/js/jquery.flot.time.min.js',
|
|
'./src/lib/js/jquery.flot.categories.min.js',
|
|
'./src/lib/js/jquery.flot.spline.min.js',
|
|
'./src/lib/js/jquery.flot.selection.min.js',
|
|
'./src/lib/js/jquery.flot.hiddengraphs.js',
|
|
'./src/lib/js/jquery.flot.fillbetween.js',
|
|
'./src/lib/js/jquery.flot.navigate.min.js',
|
|
'./src/lib/js/jquery.flot.dashes.js',
|
|
'./src/lib/js/jquery.flot.grow.js',
|
|
'./src/lib/js/jquery-deparam.js',
|
|
'./src/js/days.js',
|
|
'./src/js/chart.js',
|
|
'./src/js/data.js'
|
|
])
|
|
.pipe(sourcemaps.init())
|
|
.pipe(concat('flot.js'))
|
|
.pipe(uglify())
|
|
.pipe(sourcemaps.write('.'))
|
|
.pipe(gulp.dest('./www/js'));
|
|
});
|
|
|
|
gulp.task('editJS', ['languages2words'], () => {
|
|
return gulp.src([
|
|
'./src/lib/js/jquery-deparam.js',
|
|
'./src/lib/js/jquery.colorpicker.js',
|
|
'./src/js/words.js',
|
|
'./src/js/settings.js',
|
|
'./src/js/edit.js',
|
|
])
|
|
.pipe(sourcemaps.init())
|
|
.pipe(concat('edit.js'))
|
|
.pipe(uglify())
|
|
.on('error', function (err) {
|
|
gutil.log(gutil.colors.red('[Error]'), err.toString());
|
|
})
|
|
.pipe(sourcemaps.write('.'))
|
|
.pipe(gulp.dest('./www/js'));
|
|
});
|
|
|
|
gulp.task('indexHTML', () => {
|
|
return gulp.src([
|
|
'./src/index.html'
|
|
])
|
|
.pipe(sourcemaps.init())
|
|
.pipe(concat('index.html'))
|
|
.pipe(htmlmin({collapseWhitespace: true, removeComments: true}))
|
|
.pipe(sourcemaps.write('.'))
|
|
.pipe(gulp.dest('./www/'));
|
|
});
|
|
gulp.task('editHTML', ['updateEditHtml'], () => {
|
|
return gulp.src([
|
|
'./src/edit.html'
|
|
])
|
|
.pipe(sourcemaps.init())
|
|
.pipe(concat('edit.html'))
|
|
.pipe(htmlmin({collapseWhitespace: true, removeComments: true}))
|
|
.pipe(sourcemaps.write('.'))
|
|
.pipe(gulp.dest('./www/'));
|
|
});
|
|
|
|
gulp.task('copyCSS', () => {
|
|
return gulp.src([
|
|
'./src/lib/css/**/*'
|
|
])
|
|
.pipe(gulp.dest('./www/css'));
|
|
});
|
|
|
|
gulp.task('copyImg', () => {
|
|
return gulp.src([
|
|
'./src/img/favicon.png'
|
|
])
|
|
.pipe(gulp.dest('./www/img'));
|
|
});
|
|
|
|
gulp.task('default', ['flotJS', 'editJS', 'indexHTML', 'editHTML', 'copyCSS', 'copyImg']); |