mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 01:38:19 +08:00
ui: remove babel
This commit is contained in:
1 parent
ff943b620e
commit
c7c70a6abb
23 files changed
+466
-606
No files matched your search
@@ -3,8 +3,8 @@ const path = require('path');
|
|||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
root: true,
|
root: true,
|
||||||
parser: '@babel/eslint-parser',
|
parser: '@typescript-eslint/parser',
|
||||||
plugins: ['babel', 'react'],
|
plugins: ['@typescript-eslint', 'react'],
|
||||||
env: {
|
env: {
|
||||||
browser: true,
|
browser: true,
|
||||||
es6: true,
|
es6: true,
|
||||||
@@ -14,15 +14,14 @@ module.exports = {
|
|||||||
extends: ['airbnb'],
|
extends: ['airbnb'],
|
||||||
parserOptions: {
|
parserOptions: {
|
||||||
sourceType: 'module',
|
sourceType: 'module',
|
||||||
ecmaVersion: 7,
|
ecmaVersion: 2020,
|
||||||
ecmaFeatures: {
|
ecmaFeatures: {
|
||||||
impliedStrict: true,
|
impliedStrict: true,
|
||||||
experimentalObjectRestSpread: true,
|
experimentalObjectRestSpread: true,
|
||||||
jsx: true,
|
jsx: true,
|
||||||
|
defaultParams: true,
|
||||||
legacyDecorators: true,
|
legacyDecorators: true,
|
||||||
},
|
allowImportExportEverywhere: true,
|
||||||
babelOptions: {
|
|
||||||
configFile: `${__dirname}/babel.config.js`,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
@@ -48,21 +47,25 @@ module.exports = {
|
|||||||
window: true,
|
window: true,
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
|
'@typescript-eslint/dot-notation': 'off',
|
||||||
|
'@typescript-eslint/no-implied-eval': 'off',
|
||||||
|
'@typescript-eslint/no-throw-literal': 'off',
|
||||||
|
'@typescript-eslint/return-await': 'off',
|
||||||
|
|
||||||
// FIXME A bug with eslint-parser
|
// FIXME A bug with eslint-parser
|
||||||
'template-curly-spacing': 'off',
|
'template-curly-spacing': 'off',
|
||||||
indent: 'off',
|
|
||||||
|
|
||||||
'comma-dangle': [
|
'comma-dangle': [
|
||||||
'error',
|
'error',
|
||||||
'always-multiline',
|
'always-multiline',
|
||||||
],
|
],
|
||||||
// indent: [
|
indent: [
|
||||||
// 'error',
|
'error',
|
||||||
// 2,
|
2,
|
||||||
// {
|
{
|
||||||
// SwitchCase: 0,
|
SwitchCase: 0,
|
||||||
// },
|
},
|
||||||
// ],
|
],
|
||||||
'max-len': ['error', 150],
|
'max-len': ['error', 150],
|
||||||
quotes: 'warn',
|
quotes: 'warn',
|
||||||
'class-methods-use-this': 'off',
|
'class-methods-use-this': 'off',
|
||||||
|
|||||||
@@ -1,46 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
plugins: [
|
|
||||||
'lodash',
|
|
||||||
'@babel/plugin-transform-runtime',
|
|
||||||
'@babel/plugin-syntax-dynamic-import',
|
|
||||||
'@babel/plugin-syntax-import-meta',
|
|
||||||
'@babel/plugin-proposal-json-strings',
|
|
||||||
['@babel/plugin-proposal-class-properties', { loose: true }],
|
|
||||||
'@babel/plugin-proposal-function-sent',
|
|
||||||
'@babel/plugin-proposal-export-namespace-from',
|
|
||||||
'@babel/plugin-proposal-numeric-separator',
|
|
||||||
'@babel/plugin-proposal-throw-expressions',
|
|
||||||
[
|
|
||||||
'prismjs',
|
|
||||||
{
|
|
||||||
languages: [
|
|
||||||
'clike',
|
|
||||||
'c',
|
|
||||||
'cpp',
|
|
||||||
'pascal',
|
|
||||||
'java',
|
|
||||||
'python',
|
|
||||||
'java',
|
|
||||||
'python',
|
|
||||||
'php',
|
|
||||||
'rust',
|
|
||||||
'haskell',
|
|
||||||
'javascript',
|
|
||||||
'go',
|
|
||||||
'ruby',
|
|
||||||
'csharp',
|
|
||||||
'julia',
|
|
||||||
],
|
|
||||||
plugins: [
|
|
||||||
'toolbar',
|
|
||||||
'line-numbers',
|
|
||||||
],
|
|
||||||
css: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
],
|
|
||||||
presets: [
|
|
||||||
['@babel/preset-env', { loose: true, modules: false }],
|
|
||||||
'@babel/preset-react',
|
|
||||||
],
|
|
||||||
};
|
|
||||||
@@ -1,7 +1,34 @@
|
|||||||
require('@babel/register')({
|
const esbuild = require('esbuild');
|
||||||
plugins: ['@babel/plugin-transform-runtime'],
|
const fs = require('fs');
|
||||||
presets: [['@babel/preset-env', { loose: true }]],
|
|
||||||
});
|
let transformTimeUsage = 0;
|
||||||
|
let transformCount = 0;
|
||||||
|
let displayTimeout;
|
||||||
|
function transform(filename) {
|
||||||
|
const start = new Date();
|
||||||
|
const result = esbuild.buildSync({
|
||||||
|
entryPoints: [filename],
|
||||||
|
sourcemap: 'inline',
|
||||||
|
platform: 'node',
|
||||||
|
format: 'cjs',
|
||||||
|
target: 'node12',
|
||||||
|
jsx: 'transform',
|
||||||
|
write: false,
|
||||||
|
});
|
||||||
|
if (result.warnings.length) console.warn(result.warnings);
|
||||||
|
transformTimeUsage += new Date().getTime() - start.getTime();
|
||||||
|
transformCount++;
|
||||||
|
if (displayTimeout) clearTimeout(displayTimeout);
|
||||||
|
displayTimeout = setTimeout(() => console.log(`Transformed ${transformCount} files. (${transformTimeUsage}ms)`), 1000);
|
||||||
|
return result.outputFiles[0].text;
|
||||||
|
}
|
||||||
|
require.extensions['.js'] = function loader(module, filename) {
|
||||||
|
if (!filename.includes('node_modules')) {
|
||||||
|
return module._compile(transform(filename), filename);
|
||||||
|
}
|
||||||
|
const content = fs.readFileSync(filename, 'utf-8');
|
||||||
|
return module._compile(content, filename);
|
||||||
|
};
|
||||||
const main = require('./main.js');
|
const main = require('./main.js');
|
||||||
|
|
||||||
if (!module.parent) main();
|
if (!module.parent) main();
|
||||||
@@ -279,7 +279,7 @@ export default class Calendar {
|
|||||||
for (; vIndex < vIndexMax; ++vIndex) {
|
for (; vIndex < vIndexMax; ++vIndex) {
|
||||||
if (_.every(_
|
if (_.every(_
|
||||||
.range(beginDay, endDay + 1)
|
.range(beginDay, endDay + 1)
|
||||||
.map((day) => !dayBitmap[day][vIndex]) // eslint-disable-line no-loop-func
|
.map((day) => !dayBitmap[day][vIndex]), // eslint-disable-line no-loop-func
|
||||||
)) { // eslint-disable-line function-paren-newline
|
)) { // eslint-disable-line function-paren-newline
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,20 +5,20 @@ import request from 'vj/utils/request';
|
|||||||
import Notification from 'vj/components/notification';
|
import Notification from 'vj/components/notification';
|
||||||
|
|
||||||
const contestPage = new AutoloadPage('contestPage', () => {
|
const contestPage = new AutoloadPage('contestPage', () => {
|
||||||
$('[data-contest-code]').on('click', (ev) => {
|
$('[data-contest-code]').on('click', (ev) => {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
// eslint-disable-next-line no-alert
|
// eslint-disable-next-line no-alert
|
||||||
const code = prompt(i18n('Invitation code:'));
|
const code = prompt(i18n('Invitation code:'));
|
||||||
request.post('', {
|
request.post('', {
|
||||||
operation: 'attend',
|
operation: 'attend',
|
||||||
code,
|
code,
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
Notification.success(i18n('Successfully attended'));
|
Notification.success(i18n('Successfully attended'));
|
||||||
delay(1000).then(() => window.location.reload());
|
delay(1000).then(() => window.location.reload());
|
||||||
}).catch((e) => {
|
}).catch((e) => {
|
||||||
Notification.error(e.message || e);
|
Notification.error(e.message || e);
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
export default contestPage;
|
export default contestPage;
|
||||||
@@ -42,7 +42,7 @@ export default class DomDialog extends DOMAttachedObject {
|
|||||||
{
|
{
|
||||||
duration: 100,
|
duration: 100,
|
||||||
easing: 'easeOutCubic',
|
easing: 'easeOutCubic',
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const $dgContent = this.$dom.find('.dialog__content');
|
const $dgContent = this.$dom.find('.dialog__content');
|
||||||
|
|||||||
@@ -2,42 +2,42 @@ import { AutoloadPage } from 'vj/misc/Page';
|
|||||||
import request from 'vj/utils/request';
|
import request from 'vj/utils/request';
|
||||||
|
|
||||||
export default new AutoloadPage('media', async () => {
|
export default new AutoloadPage('media', async () => {
|
||||||
async function parseMedia($dom = $(document.body)) {
|
async function parseMedia($dom = $(document.body)) {
|
||||||
const items = [];
|
const items = [];
|
||||||
const resolvers = [];
|
const resolvers = [];
|
||||||
const users = $dom.find('div[data-user]');
|
const users = $dom.find('div[data-user]');
|
||||||
const resolve = (ele, item) => {
|
const resolve = (ele, item) => {
|
||||||
items.push(item);
|
items.push(item);
|
||||||
resolvers.push((html) => html && $(ele).replaceWith($(html)));
|
resolvers.push((html) => html && $(ele).replaceWith($(html)));
|
||||||
};
|
};
|
||||||
users.get().forEach((ele) => resolve(ele, { type: 'user', id: +$(ele).text() }));
|
users.get().forEach((ele) => resolve(ele, { type: 'user', id: +$(ele).text() }));
|
||||||
$dom.find('.typo').get().forEach((el) => {
|
$dom.find('.typo').get().forEach((el) => {
|
||||||
$(el).find('a[href]').get().forEach((ele) => {
|
$(el).find('a[href]').get().forEach((ele) => {
|
||||||
if ($(ele).parent().hasClass('user-profile-link')) return;
|
if ($(ele).parent().hasClass('user-profile-link')) return;
|
||||||
let target = $(ele).attr('href');
|
let target = $(ele).attr('href');
|
||||||
let { domainId } = UiContext;
|
let { domainId } = UiContext;
|
||||||
if (target.startsWith(UiContext.url_prefix)) {
|
if (target.startsWith(UiContext.url_prefix)) {
|
||||||
target.replace(UiContext.url_prefix, '');
|
target.replace(UiContext.url_prefix, '');
|
||||||
if (!target.startsWith('/')) target = `/${target}`;
|
if (!target.startsWith('/')) target = `/${target}`;
|
||||||
}
|
}
|
||||||
if (!target.startsWith('/') || target.startsWith('//')) return;
|
if (!target.startsWith('/') || target.startsWith('//')) return;
|
||||||
if (target.startsWith('/d/')) {
|
if (target.startsWith('/d/')) {
|
||||||
const [, , domain, ...extra] = target.split('/');
|
const [, , domain, ...extra] = target.split('/');
|
||||||
domainId = domain;
|
domainId = domain;
|
||||||
target = `/${extra.join('/')}`;
|
target = `/${extra.join('/')}`;
|
||||||
}
|
}
|
||||||
const [, category, data, extra] = target.split('/');
|
const [, category, data, extra] = target.split('/');
|
||||||
if (!data) return;
|
if (!data) return;
|
||||||
if (category === 'user' && Number.isInteger(+data) && !extra) resolve(ele, { type: 'user', id: +data });
|
if (category === 'user' && Number.isInteger(+data) && !extra) resolve(ele, { type: 'user', id: +data });
|
||||||
if (category === 'p' && !extra) resolve(ele, { type: 'problem', id: data, domainId });
|
if (category === 'p' && !extra) resolve(ele, { type: 'problem', id: data, domainId });
|
||||||
if (category === 'contest' && !extra) resolve(ele, { type: 'contest', id: data, domainId });
|
if (category === 'contest' && !extra) resolve(ele, { type: 'contest', id: data, domainId });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
if (!items.length) return;
|
if (!items.length) return;
|
||||||
const res = await request.post(`/d/${UiContext.domainId}/media`, { items });
|
const res = await request.post(`/d/${UiContext.domainId}/media`, { items });
|
||||||
for (let i = 0; i < res.length; i++) resolvers[i](res[i]);
|
for (let i = 0; i < res.length; i++) resolvers[i](res[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
await parseMedia();
|
await parseMedia();
|
||||||
$(document).on('vjContentNew', (e) => parseMedia($(e.target)));
|
$(document).on('vjContentNew', (e) => parseMedia($(e.target)));
|
||||||
});
|
});
|
||||||
@@ -3,12 +3,12 @@ import Notification from 'vj/components/notification/index';
|
|||||||
import i18n from 'vj/utils/i18n';
|
import i18n from 'vj/utils/i18n';
|
||||||
|
|
||||||
export default new AutoloadPage('notificationPage', (pagename) => {
|
export default new AutoloadPage('notificationPage', (pagename) => {
|
||||||
const message = i18n(`Hint::Page::${pagename}`);
|
const message = i18n(`Hint::Page::${pagename}`);
|
||||||
const item = localStorage.getItem(`hint.${message}`);
|
const item = localStorage.getItem(`hint.${message}`);
|
||||||
if (message !== `Hint::Page::${pagename}` && !item) {
|
if (message !== `Hint::Page::${pagename}` && !item) {
|
||||||
Notification.info(message, message.length * 500);
|
Notification.info(message, message.length * 500);
|
||||||
localStorage.setItem(`hint.${message}`, true);
|
localStorage.setItem(`hint.${message}`, true);
|
||||||
}
|
}
|
||||||
const text = new URL(window.location.href).searchParams.get('notification');
|
const text = new URL(window.location.href).searchParams.get('notification');
|
||||||
if (text) Notification.success(text);
|
if (text) Notification.success(text);
|
||||||
});
|
});
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
import { AutoloadPage } from 'vj/misc/Page';
|
import { AutoloadPage } from 'vj/misc/Page';
|
||||||
|
|
||||||
export default new AutoloadPage('problemListPage', () => {
|
export default new AutoloadPage('problemListPage', () => {
|
||||||
|
$('.col--problem-name>a').attr('target', '_blank');
|
||||||
|
$(document).on('vjContentNew', () => {
|
||||||
$('.col--problem-name>a').attr('target', '_blank');
|
$('.col--problem-name>a').attr('target', '_blank');
|
||||||
$(document).on('vjContentNew', () => {
|
});
|
||||||
$('.col--problem-name>a').attr('target', '_blank');
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
@@ -3,20 +3,20 @@ export default function reducer(state = {
|
|||||||
code: localStorage.getItem(`${UserContext._id}/${UiContext.pdoc.domainId}/${UiContext.pdoc.docId}`) || UiContext.codeTemplate,
|
code: localStorage.getItem(`${UserContext._id}/${UiContext.pdoc.domainId}/${UiContext.pdoc.docId}`) || UiContext.codeTemplate,
|
||||||
}, action) {
|
}, action) {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case 'SCRATCHPAD_EDITOR_UPDATE_CODE': {
|
case 'SCRATCHPAD_EDITOR_UPDATE_CODE': {
|
||||||
localStorage.setItem(`${UserContext._id}/${UiContext.pdoc.domainId}/${UiContext.pdoc.docId}`, action.payload);
|
localStorage.setItem(`${UserContext._id}/${UiContext.pdoc.domainId}/${UiContext.pdoc.docId}`, action.payload);
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
code: action.payload,
|
code: action.payload,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case 'SCRATCHPAD_EDITOR_SET_LANG': {
|
case 'SCRATCHPAD_EDITOR_SET_LANG': {
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
lang: action.payload,
|
lang: action.payload,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -17,88 +17,88 @@ export default function reducer(state = {
|
|||||||
isPosting: false,
|
isPosting: false,
|
||||||
}, action) {
|
}, action) {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case 'SCRATCHPAD_UI_CHANGE_SIZE': {
|
case 'SCRATCHPAD_UI_CHANGE_SIZE': {
|
||||||
const { uiElement, size } = action.payload;
|
const { uiElement, size } = action.payload;
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
[uiElement]: {
|
[uiElement]: {
|
||||||
...state[uiElement],
|
...state[uiElement],
|
||||||
size,
|
size,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case 'SCRATCHPAD_UI_SET_VISIBILITY': {
|
case 'SCRATCHPAD_UI_SET_VISIBILITY': {
|
||||||
const { uiElement, visibility } = action.payload;
|
const { uiElement, visibility } = action.payload;
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
[uiElement]: {
|
[uiElement]: {
|
||||||
...state[uiElement],
|
...state[uiElement],
|
||||||
visible: visibility,
|
visible: visibility,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case 'SCRATCHPAD_UI_TOGGLE_VISIBILITY': {
|
case 'SCRATCHPAD_UI_TOGGLE_VISIBILITY': {
|
||||||
const { uiElement } = action.payload;
|
const { uiElement } = action.payload;
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
[uiElement]: {
|
[uiElement]: {
|
||||||
...state[uiElement],
|
...state[uiElement],
|
||||||
visible: !state[uiElement].visible,
|
visible: !state[uiElement].visible,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case 'SCRATCHPAD_POST_PRETEST_PENDING':
|
case 'SCRATCHPAD_POST_PRETEST_PENDING':
|
||||||
case 'SCRATCHPAD_POST_SUBMIT_PENDING': {
|
case 'SCRATCHPAD_POST_SUBMIT_PENDING': {
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
isPosting: true,
|
isPosting: true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case 'SCRATCHPAD_POST_PRETEST_FULFILLED':
|
case 'SCRATCHPAD_POST_PRETEST_FULFILLED':
|
||||||
case 'SCRATCHPAD_POST_SUBMIT_FULFILLED': {
|
case 'SCRATCHPAD_POST_SUBMIT_FULFILLED': {
|
||||||
Notification.success(i18n('Submitted.'));
|
Notification.success(i18n('Submitted.'));
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
isPosting: false,
|
isPosting: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case 'SCRATCHPAD_POST_PRETEST_REJECTED':
|
case 'SCRATCHPAD_POST_PRETEST_REJECTED':
|
||||||
case 'SCRATCHPAD_POST_SUBMIT_REJECTED': {
|
case 'SCRATCHPAD_POST_SUBMIT_REJECTED': {
|
||||||
Notification.error(action.payload.message);
|
Notification.error(action.payload.message);
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
isPosting: false,
|
isPosting: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case 'SCRATCHPAD_RECORDS_LOAD_SUBMISSIONS_PENDING': {
|
case 'SCRATCHPAD_RECORDS_LOAD_SUBMISSIONS_PENDING': {
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
records: {
|
records: {
|
||||||
...state.records,
|
...state.records,
|
||||||
isLoading: true,
|
isLoading: true,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case 'SCRATCHPAD_RECORDS_LOAD_SUBMISSIONS_REJECTED': {
|
case 'SCRATCHPAD_RECORDS_LOAD_SUBMISSIONS_REJECTED': {
|
||||||
Notification.error(action.payload.message);
|
Notification.error(action.payload.message);
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
records: {
|
records: {
|
||||||
...state.records,
|
...state.records,
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case 'SCRATCHPAD_RECORDS_LOAD_SUBMISSIONS_FULFILLED': {
|
case 'SCRATCHPAD_RECORDS_LOAD_SUBMISSIONS_FULFILLED': {
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
records: {
|
records: {
|
||||||
...state.records,
|
...state.records,
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -66,7 +66,7 @@ export default class Tab extends DOMAttachedObject {
|
|||||||
{
|
{
|
||||||
duration: TAB_TRANSITION_DURATION,
|
duration: TAB_TRANSITION_DURATION,
|
||||||
easing: 'linear',
|
easing: 'linear',
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
$newTab
|
$newTab
|
||||||
.transition(
|
.transition(
|
||||||
@@ -74,7 +74,7 @@ export default class Tab extends DOMAttachedObject {
|
|||||||
{
|
{
|
||||||
duration: TAB_TRANSITION_DURATION,
|
duration: TAB_TRANSITION_DURATION,
|
||||||
easing: 'linear',
|
easing: 'linear',
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
await this.$content
|
await this.$content
|
||||||
.transition({
|
.transition({
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
import astyleBinaryUrl from 'wastyle/dist/astyle-optimize-size.wasm';
|
import astyleBinaryUrl from 'wastyle/dist/astyle-optimize-size.wasm';
|
||||||
|
|
||||||
export default async function load() {
|
export default async function load() {
|
||||||
const { init, format } = await import('wastyle');
|
const { init, format } = await import('wastyle');
|
||||||
try {
|
try {
|
||||||
await init(astyleBinaryUrl);
|
await init(astyleBinaryUrl);
|
||||||
console.log('WAstyle is ready!');
|
console.log('WAstyle is ready!');
|
||||||
const formatter = (code, options) => {
|
const formatter = (code, options) => {
|
||||||
const [success, result] = format(code, options);
|
const [success, result] = format(code, options);
|
||||||
return [success, (result || '').replace(/^#(include|import)[\t ]*(<|")/gm, (match, p1, p2) => `#${p1} ${p2}`)];
|
return [success, (result || '').replace(/^#(include|import)[\t ]*(<|")/gm, (match, p1, p2) => `#${p1} ${p2}`)];
|
||||||
};
|
};
|
||||||
return [true, formatter];
|
return [true, formatter];
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return [false, e.message];
|
return [false, e.message];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -86,7 +86,7 @@ export async function downloadProblemSet(pids, name = 'Export') {
|
|||||||
});
|
});
|
||||||
let { links } = await request.post(
|
let { links } = await request.post(
|
||||||
`/d/${UiContext.domainId}/p/${pid}/files`,
|
`/d/${UiContext.domainId}/p/${pid}/files`,
|
||||||
{ operation: 'get_links', files: (pdoc.data || []).map((i) => i.name), type: 'testdata' }
|
{ operation: 'get_links', files: (pdoc.data || []).map((i) => i.name), type: 'testdata' },
|
||||||
);
|
);
|
||||||
for (const filename of Object.keys(links)) {
|
for (const filename of Object.keys(links)) {
|
||||||
targets.push({ filename: `${pid}/testdata/${filename}`, url: links[filename] });
|
targets.push({ filename: `${pid}/testdata/${filename}`, url: links[filename] });
|
||||||
|
|||||||
@@ -16,6 +16,6 @@ console.log(
|
|||||||
/ __ / /_/ / /_/ / / / /_/ /
|
/ __ / /_/ / /_/ / / / /_/ /
|
||||||
/_/ /_/\\__, /\\__,_/_/ \\____/
|
/_/ /_/\\__, /\\__,_/_/ \\____/
|
||||||
/____/
|
/____/
|
||||||
`
|
`,
|
||||||
);
|
);
|
||||||
import('./hydro');
|
import('./hydro');
|
||||||
@@ -1,28 +1,15 @@
|
|||||||
{
|
{
|
||||||
"name": "@hydrooj/ui-default",
|
"name": "@hydrooj/ui-default",
|
||||||
"version": "4.16.4",
|
"version": "4.17.0",
|
||||||
"author": "undefined <i@undefined.moe>",
|
"author": "undefined <i@undefined.moe>",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"main": "hydro.js",
|
"main": "hydro.js",
|
||||||
"repository": "https://github.com/hydro-dev/Hydro.git",
|
"repository": "https://github.com/hydro-dev/Hydro.git",
|
||||||
"preferUnplugged": true,
|
"preferUnplugged": true,
|
||||||
|
"scripts": {
|
||||||
|
"lint": "eslint ."
|
||||||
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "^7.14.8",
|
|
||||||
"@babel/core": "^7.15.0",
|
|
||||||
"@babel/eslint-parser": "7.15.0",
|
|
||||||
"@babel/plugin-proposal-class-properties": "^7.14.5",
|
|
||||||
"@babel/plugin-proposal-export-namespace-from": "^7.14.5",
|
|
||||||
"@babel/plugin-proposal-function-sent": "^7.14.5",
|
|
||||||
"@babel/plugin-proposal-json-strings": "^7.14.5",
|
|
||||||
"@babel/plugin-proposal-numeric-separator": "^7.14.5",
|
|
||||||
"@babel/plugin-proposal-throw-expressions": "^7.14.5",
|
|
||||||
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
|
||||||
"@babel/plugin-syntax-import-meta": "^7.10.4",
|
|
||||||
"@babel/plugin-transform-runtime": "^7.15.0",
|
|
||||||
"@babel/preset-env": "^7.15.0",
|
|
||||||
"@babel/preset-react": "^7.14.5",
|
|
||||||
"@babel/register": "^7.14.5",
|
|
||||||
"@babel/runtime-corejs3": "^7.14.9",
|
|
||||||
"@blockly/block-extension-tooltip": "^1.0.15",
|
"@blockly/block-extension-tooltip": "^1.0.15",
|
||||||
"@blueprintjs/core": "^3.47.0",
|
"@blueprintjs/core": "^3.47.0",
|
||||||
"@blueprintjs/icons": "^3.27.0",
|
"@blueprintjs/icons": "^3.27.0",
|
||||||
@@ -33,22 +20,20 @@
|
|||||||
"@undefined-moe/monaco-yaml": "^2.5.0",
|
"@undefined-moe/monaco-yaml": "^2.5.0",
|
||||||
"ansi_up": "^5.0.1",
|
"ansi_up": "^5.0.1",
|
||||||
"autoprefixer": "^9.8.6",
|
"autoprefixer": "^9.8.6",
|
||||||
"babel-loader": "^8.2.2",
|
|
||||||
"babel-plugin-lodash": "^3.3.4",
|
|
||||||
"babel-plugin-prismjs": "^2.1.0",
|
|
||||||
"blockly": "^6.20210701.0",
|
"blockly": "^6.20210701.0",
|
||||||
"chalk": "^4.1.2",
|
"chalk": "^4.1.2",
|
||||||
"classnames": "^2.3.1",
|
"classnames": "^2.3.1",
|
||||||
|
"clean-webpack-plugin": "^4.0.0-alpha.0",
|
||||||
"clipboard": "^2.0.8",
|
"clipboard": "^2.0.8",
|
||||||
"copy-webpack-plugin": "^6.4.1",
|
"copy-webpack-plugin": "^6.4.1",
|
||||||
"css-loader": "^4.3.0",
|
"css-loader": "^4.3.0",
|
||||||
"diff-dom": "^4.2.2",
|
"diff-dom": "^4.2.2",
|
||||||
"echarts": "^5.1.2",
|
"echarts": "^5.1.2",
|
||||||
"emojify.js": "^1.1.0",
|
"emojify.js": "^1.1.0",
|
||||||
|
"esbuild-loader": "^2.14.0",
|
||||||
"eslint": "^7.32.0",
|
"eslint": "^7.32.0",
|
||||||
"eslint-config-airbnb": "^18.2.1",
|
"eslint-config-airbnb": "^18.2.1",
|
||||||
"eslint-import-resolver-webpack": "^0.13.1",
|
"eslint-import-resolver-webpack": "^0.13.1",
|
||||||
"eslint-plugin-babel": "^5.3.1",
|
|
||||||
"eslint-plugin-import": "^2.23.4",
|
"eslint-plugin-import": "^2.23.4",
|
||||||
"eslint-plugin-jsx-a11y": "^6.4.1",
|
"eslint-plugin-jsx-a11y": "^6.4.1",
|
||||||
"eslint-plugin-react": "^7.24.0",
|
"eslint-plugin-react": "^7.24.0",
|
||||||
@@ -111,9 +96,7 @@
|
|||||||
"webpackbar": "^5.0.0-3"
|
"webpackbar": "^5.0.0-3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"clean-webpack-plugin": "^4.0.0-alpha.0",
|
|
||||||
"esbuild": "^0.12.18",
|
"esbuild": "^0.12.18",
|
||||||
"esbuild-loader": "^2.14.0",
|
|
||||||
"js-yaml": "^4.1.0",
|
"js-yaml": "^4.1.0",
|
||||||
"jsesc": "^3.0.2",
|
"jsesc": "^3.0.2",
|
||||||
"katex": "^0.13.13",
|
"katex": "^0.13.13",
|
||||||
|
|||||||
@@ -9,37 +9,37 @@ import tpl from 'vj/utils/tpl';
|
|||||||
import i18n from 'vj/utils/i18n';
|
import i18n from 'vj/utils/i18n';
|
||||||
|
|
||||||
function onBeforeUnload(e) {
|
function onBeforeUnload(e) {
|
||||||
e.returnValue = '';
|
e.returnValue = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
const page = new NamedPage('home_files', () => {
|
const page = new NamedPage('home_files', () => {
|
||||||
function ensureAndGetSelectedFiles() {
|
function ensureAndGetSelectedFiles() {
|
||||||
const files = _.map(
|
const files = _.map(
|
||||||
$('.home-files tbody [data-checkbox-group="user_files"]:checked'),
|
$('.home-files tbody [data-checkbox-group="user_files"]:checked'),
|
||||||
(ch) => $(ch).closest('tr').attr('data-filename'),
|
(ch) => $(ch).closest('tr').attr('data-filename'),
|
||||||
);
|
);
|
||||||
if (files.length === 0) {
|
if (files.length === 0) {
|
||||||
Notification.error(i18n('Please select at least one file to perform this operation.'));
|
Notification.error(i18n('Please select at least one file to perform this operation.'));
|
||||||
return null;
|
return null;
|
||||||
}
|
|
||||||
return files;
|
|
||||||
}
|
}
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
|
||||||
async function handleClickUpload(files) {
|
async function handleClickUpload(files) {
|
||||||
if (!files) {
|
if (!files) {
|
||||||
const input = document.createElement('input');
|
const input = document.createElement('input');
|
||||||
input.type = 'file';
|
input.type = 'file';
|
||||||
input.multiple = true;
|
input.multiple = true;
|
||||||
input.click();
|
input.click();
|
||||||
await new Promise((resolve) => { input.onchange = resolve; });
|
await new Promise((resolve) => { input.onchange = resolve; });
|
||||||
files = input.files;
|
files = input.files;
|
||||||
}
|
}
|
||||||
if (!files.length) {
|
if (!files.length) {
|
||||||
Notification.warn(i18n('No file selected.'));
|
Notification.warn(i18n('No file selected.'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const dialog = new Dialog({
|
const dialog = new Dialog({
|
||||||
$body: `
|
$body: `
|
||||||
<div class="file-label" style="text-align: center; margin-bottom: 5px; color: gray; font-size: small;"></div>
|
<div class="file-label" style="text-align: center; margin-bottom: 5px; color: gray; font-size: small;"></div>
|
||||||
<div class="bp3-progress-bar bp3-intent-primary bp3-no-stripes">
|
<div class="bp3-progress-bar bp3-intent-primary bp3-no-stripes">
|
||||||
<div class="file-progress bp3-progress-meter" style="width: 0"></div>
|
<div class="file-progress bp3-progress-meter" style="width: 0"></div>
|
||||||
@@ -48,127 +48,127 @@ const page = new NamedPage('home_files', () => {
|
|||||||
<div class="bp3-progress-bar bp3-intent-primary bp3-no-stripes">
|
<div class="bp3-progress-bar bp3-intent-primary bp3-no-stripes">
|
||||||
<div class="upload-progress bp3-progress-meter" style="width: 0"></div>
|
<div class="upload-progress bp3-progress-meter" style="width: 0"></div>
|
||||||
</div>`,
|
</div>`,
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
Notification.info(i18n('Uploading files...'));
|
||||||
|
window.addEventListener('beforeunload', onBeforeUnload);
|
||||||
|
dialog.open();
|
||||||
|
const $uploadLabel = dialog.$dom.find('.dialog__body .upload-label');
|
||||||
|
const $uploadProgress = dialog.$dom.find('.dialog__body .upload-progress');
|
||||||
|
const $fileLabel = dialog.$dom.find('.dialog__body .file-label');
|
||||||
|
const $fileProgress = dialog.$dom.find('.dialog__body .file-progress');
|
||||||
|
for (const i in files) {
|
||||||
|
if (Number.isNaN(+i)) continue;
|
||||||
|
const file = files[i];
|
||||||
|
const data = new FormData();
|
||||||
|
data.append('filename', file.name);
|
||||||
|
data.append('file', file);
|
||||||
|
data.append('operation', 'upload_file');
|
||||||
|
await request.postFile('', data, {
|
||||||
|
xhr() {
|
||||||
|
const xhr = new XMLHttpRequest();
|
||||||
|
xhr.upload.addEventListener('loadstart', () => {
|
||||||
|
$fileLabel.text(`[${+i + 1}/${files.length}] ${file.name}`);
|
||||||
|
$fileProgress.width(`${Math.round((+i + 1) / files.length * 100)}%`);
|
||||||
|
$uploadLabel.text(i18n('Uploading... ({0}%)', 0));
|
||||||
|
$uploadProgress.width(0);
|
||||||
|
});
|
||||||
|
xhr.upload.addEventListener('progress', (e) => {
|
||||||
|
if (e.lengthComputable) {
|
||||||
|
const percentComplete = Math.round((e.loaded / e.total) * 100);
|
||||||
|
if (percentComplete === 100) $uploadLabel.text(i18n('Processing...'));
|
||||||
|
else $uploadLabel.text(i18n('Uploading... ({0}%)', percentComplete));
|
||||||
|
$uploadProgress.width(`${percentComplete}%`);
|
||||||
|
}
|
||||||
|
}, false);
|
||||||
|
return xhr;
|
||||||
|
},
|
||||||
});
|
});
|
||||||
try {
|
}
|
||||||
Notification.info(i18n('Uploading files...'));
|
window.removeEventListener('beforeunload', onBeforeUnload);
|
||||||
window.addEventListener('beforeunload', onBeforeUnload);
|
Notification.success(i18n('File uploaded successfully.'));
|
||||||
dialog.open();
|
await pjax.request({ push: false });
|
||||||
const $uploadLabel = dialog.$dom.find('.dialog__body .upload-label');
|
} catch (e) {
|
||||||
const $uploadProgress = dialog.$dom.find('.dialog__body .upload-progress');
|
console.error(e);
|
||||||
const $fileLabel = dialog.$dom.find('.dialog__body .file-label');
|
Notification.error(i18n('File upload failed: {0}', e.toString()));
|
||||||
const $fileProgress = dialog.$dom.find('.dialog__body .file-progress');
|
} finally {
|
||||||
for (const i in files) {
|
dialog.close();
|
||||||
if (Number.isNaN(+i)) continue;
|
|
||||||
const file = files[i];
|
|
||||||
const data = new FormData();
|
|
||||||
data.append('filename', file.name);
|
|
||||||
data.append('file', file);
|
|
||||||
data.append('operation', 'upload_file');
|
|
||||||
await request.postFile('', data, {
|
|
||||||
xhr() {
|
|
||||||
const xhr = new XMLHttpRequest();
|
|
||||||
xhr.upload.addEventListener('loadstart', () => {
|
|
||||||
$fileLabel.text(`[${+i + 1}/${files.length}] ${file.name}`);
|
|
||||||
$fileProgress.width(`${Math.round((+i + 1) / files.length * 100)}%`);
|
|
||||||
$uploadLabel.text(i18n('Uploading... ({0}%)', 0));
|
|
||||||
$uploadProgress.width(0);
|
|
||||||
});
|
|
||||||
xhr.upload.addEventListener('progress', (e) => {
|
|
||||||
if (e.lengthComputable) {
|
|
||||||
const percentComplete = Math.round((e.loaded / e.total) * 100);
|
|
||||||
if (percentComplete === 100) $uploadLabel.text(i18n('Processing...'));
|
|
||||||
else $uploadLabel.text(i18n('Uploading... ({0}%)', percentComplete));
|
|
||||||
$uploadProgress.width(`${percentComplete}%`);
|
|
||||||
}
|
|
||||||
}, false);
|
|
||||||
return xhr;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
window.removeEventListener('beforeunload', onBeforeUnload);
|
|
||||||
Notification.success(i18n('File uploaded successfully.'));
|
|
||||||
await pjax.request({ push: false });
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
Notification.error(i18n('File upload failed: {0}', e.toString()));
|
|
||||||
} finally {
|
|
||||||
dialog.close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function handleClickRemoveSelected() {
|
async function handleClickRemoveSelected() {
|
||||||
const selectedFiles = ensureAndGetSelectedFiles();
|
const selectedFiles = ensureAndGetSelectedFiles();
|
||||||
if (selectedFiles === null) return;
|
if (selectedFiles === null) return;
|
||||||
const action = await new ConfirmDialog({
|
const action = await new ConfirmDialog({
|
||||||
$body: tpl`
|
$body: tpl`
|
||||||
<div class="typo">
|
<div class="typo">
|
||||||
<p>${i18n('Confirm to delete the selected files?')}</p>
|
<p>${i18n('Confirm to delete the selected files?')}</p>
|
||||||
</div>`,
|
</div>`,
|
||||||
}).open();
|
}).open();
|
||||||
if (action !== 'yes') return;
|
if (action !== 'yes') return;
|
||||||
try {
|
try {
|
||||||
await request.post('', {
|
await request.post('', {
|
||||||
operation: 'delete_files',
|
operation: 'delete_files',
|
||||||
files: selectedFiles,
|
files: selectedFiles,
|
||||||
});
|
});
|
||||||
Notification.success(i18n('Selected files have been deleted.'));
|
Notification.success(i18n('Selected files have been deleted.'));
|
||||||
await pjax.request({ push: false });
|
await pjax.request({ push: false });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
Notification.error(error.message);
|
Notification.error(error.message);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {JQuery.DragOverEvent<HTMLElement, undefined, HTMLElement, HTMLElement>} ev
|
* @param {JQuery.DragOverEvent<HTMLElement, undefined, HTMLElement, HTMLElement>} ev
|
||||||
*/
|
*/
|
||||||
function handleDragOver(ev) {
|
function handleDragOver(ev) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
// TODO display a drag-drop allowed hint
|
// TODO display a drag-drop allowed hint
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {JQuery.DropEvent<HTMLElement, undefined, HTMLElement, HTMLElement>} ev
|
* @param {JQuery.DropEvent<HTMLElement, undefined, HTMLElement, HTMLElement>} ev
|
||||||
*/
|
*/
|
||||||
function handleDrop(ev) {
|
function handleDrop(ev) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
if (!$('[name="upload_testdata"]').length) {
|
if (!$('[name="upload_testdata"]').length) {
|
||||||
Notification.error(i18n("You don't have permission to upload file."));
|
Notification.error(i18n("You don't have permission to upload file."));
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
ev = ev.originalEvent;
|
|
||||||
const files = [];
|
|
||||||
if (ev.dataTransfer.items) {
|
|
||||||
for (let i = 0; i < ev.dataTransfer.items.length; i++) {
|
|
||||||
if (ev.dataTransfer.items[i].kind === 'file') {
|
|
||||||
const file = ev.dataTransfer.items[i].getAsFile();
|
|
||||||
files.push(file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (let i = 0; i < ev.dataTransfer.files.length; i++) {
|
|
||||||
files.push(ev.dataTransfer.files[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
handleClickUpload(files);
|
|
||||||
}
|
}
|
||||||
|
ev = ev.originalEvent;
|
||||||
|
const files = [];
|
||||||
|
if (ev.dataTransfer.items) {
|
||||||
|
for (let i = 0; i < ev.dataTransfer.items.length; i++) {
|
||||||
|
if (ev.dataTransfer.items[i].kind === 'file') {
|
||||||
|
const file = ev.dataTransfer.items[i].getAsFile();
|
||||||
|
files.push(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (let i = 0; i < ev.dataTransfer.files.length; i++) {
|
||||||
|
files.push(ev.dataTransfer.files[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
handleClickUpload(files);
|
||||||
|
}
|
||||||
|
|
||||||
const clip = new Clipboard('.home-files .col--name', {
|
const clip = new Clipboard('.home-files .col--name', {
|
||||||
text: (trigger) => {
|
text: (trigger) => {
|
||||||
const filename = trigger.closest('[data-filename]').getAttribute('data-filename');
|
const filename = trigger.closest('[data-filename]').getAttribute('data-filename');
|
||||||
return new URL(`/file/${UserContext._id}/${filename}`, window.location.href).toString();
|
return new URL(`/file/${UserContext._id}/${filename}`, window.location.href).toString();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
clip.on('success', () => {
|
clip.on('success', () => {
|
||||||
Notification.success(i18n('Download link copied to clipboard!'), 1000);
|
Notification.success(i18n('Download link copied to clipboard!'), 1000);
|
||||||
});
|
});
|
||||||
clip.on('error', () => {
|
clip.on('error', () => {
|
||||||
Notification.error(i18n('Copy failed :('));
|
Notification.error(i18n('Copy failed :('));
|
||||||
});
|
});
|
||||||
$(document).on('click', '.home-files .col--name', (ev) => ev.preventDefault());
|
$(document).on('click', '.home-files .col--name', (ev) => ev.preventDefault());
|
||||||
$(document).on('click', '[name="upload_file"]', () => handleClickUpload());
|
$(document).on('click', '[name="upload_file"]', () => handleClickUpload());
|
||||||
$(document).on('click', '[name="remove_selected"]', () => handleClickRemoveSelected());
|
$(document).on('click', '[name="remove_selected"]', () => handleClickRemoveSelected());
|
||||||
$(document).on('dragover', '.home-files', (ev) => handleDragOver(ev));
|
$(document).on('dragover', '.home-files', (ev) => handleDragOver(ev));
|
||||||
$(document).on('drop', '.home-files', (ev) => handleDrop(ev));
|
$(document).on('drop', '.home-files', (ev) => handleDrop(ev));
|
||||||
});
|
});
|
||||||
|
|
||||||
export default page;
|
export default page;
|
||||||
@@ -7,7 +7,7 @@ function setOptions($el, options) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const page = new NamedPage(['problem_submit', 'contest_detail_problem_submit', 'homework_detail_problem_submit'], async (name) => {
|
const page = new NamedPage(['problem_submit', 'contest_detail_problem_submit', 'homework_detail_problem_submit'], async () => {
|
||||||
$(document).on('click', '[name="problem-sidebar__show-category"]', (ev) => {
|
$(document).on('click', '[name="problem-sidebar__show-category"]', (ev) => {
|
||||||
$(ev.currentTarget).hide();
|
$(ev.currentTarget).hide();
|
||||||
$('[name="problem-sidebar__categories"]').show();
|
$('[name="problem-sidebar__categories"]').show();
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
plugins: {
|
plugins: {
|
||||||
autoprefixer: {},
|
autoprefixer: {},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -1,106 +0,0 @@
|
|||||||
/* eslint-disable no-restricted-syntax */
|
|
||||||
/* eslint-disable no-unused-vars */
|
|
||||||
/* eslint-disable import/no-extraneous-dependencies */
|
|
||||||
/* eslint-disable no-eval */
|
|
||||||
const fs = require('fs');
|
|
||||||
const path = require('path');
|
|
||||||
const yaml = require('js-yaml');
|
|
||||||
|
|
||||||
const name = process.argv[2];
|
|
||||||
|
|
||||||
const IGNORE_CHECK = ['en'];
|
|
||||||
const IGNORE_MISSING = [
|
|
||||||
'?', 'AC', 'ID', 'MD5', 'URL',
|
|
||||||
];
|
|
||||||
const RE_TEMPLATE = /_\(['"]([\s\S])*?['"]\)/gmi;
|
|
||||||
const RE_UI = /i18n\(['"]([\s\S])*?['"](,.*?)?\)/gmi;
|
|
||||||
const TEMPLATE_ROOT = path.resolve(__dirname, '..', 'templates');
|
|
||||||
const LOCALE_ROOT = path.resolve(__dirname, '..', 'locales');
|
|
||||||
const texts = {};
|
|
||||||
const result = {};
|
|
||||||
const locales = fs.readdirSync(LOCALE_ROOT);
|
|
||||||
let currentFile = '';
|
|
||||||
|
|
||||||
function _(str, format) {
|
|
||||||
if (!texts[str]) texts[str] = [currentFile];
|
|
||||||
else texts[str].push(currentFile);
|
|
||||||
}
|
|
||||||
const i18n = _; // lgtm [js/unused-local-variable]
|
|
||||||
const Setting = _; // lgtm [js/unused-local-variable]
|
|
||||||
|
|
||||||
function scanTemplate(folder, relative = 'templates') {
|
|
||||||
const files = fs.readdirSync(folder);
|
|
||||||
for (const file of files) {
|
|
||||||
const p = path.join(folder, file);
|
|
||||||
if (fs.statSync(p).isDirectory()) {
|
|
||||||
scanTemplate(p, path.join(relative, file));
|
|
||||||
} else {
|
|
||||||
currentFile = path.join(relative, file);
|
|
||||||
const f = fs.readFileSync(p).toString();
|
|
||||||
f.replace(RE_TEMPLATE, (substr) => {
|
|
||||||
try {
|
|
||||||
// eslint-disable-next-line no-eval
|
|
||||||
eval(substr);
|
|
||||||
} catch (e) {
|
|
||||||
console.error('Cannot parse: ', substr, ' in file ', p);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function scanUi(folder, relative = '') {
|
|
||||||
const files = fs.readdirSync(folder);
|
|
||||||
for (const file of files) {
|
|
||||||
const p = path.join(folder, file);
|
|
||||||
if (fs.statSync(p).isDirectory()) {
|
|
||||||
scanUi(p, path.join(relative, file));
|
|
||||||
} else {
|
|
||||||
currentFile = path.join(relative, file);
|
|
||||||
const f = fs.readFileSync(p).toString();
|
|
||||||
f.replace(RE_UI, (substr) => {
|
|
||||||
try {
|
|
||||||
eval(substr);
|
|
||||||
} catch (e) {
|
|
||||||
if (e.message.endsWith('is not defined')) {
|
|
||||||
global[e.message.split(' ')[0]] = () => { };
|
|
||||||
try {
|
|
||||||
eval(substr);
|
|
||||||
} catch (err) {
|
|
||||||
console.error('Cannot parse: ', substr, ' in file ', p);
|
|
||||||
}
|
|
||||||
} else console.error('Cannot parse: ', substr, ' in file ', p);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
scanTemplate(TEMPLATE_ROOT);
|
|
||||||
scanUi(path.join(process.cwd(), 'components'));
|
|
||||||
scanUi(path.join(process.cwd(), 'pages'));
|
|
||||||
scanUi(path.join(process.cwd(), 'misc'));
|
|
||||||
if (!name) {
|
|
||||||
for (const locale of locales) {
|
|
||||||
if (!IGNORE_CHECK.includes(locale.split('.')[0])) {
|
|
||||||
const p = path.join(LOCALE_ROOT, locale);
|
|
||||||
const f = fs.readFileSync(p).toString();
|
|
||||||
const l = yaml.safeLoad(f);
|
|
||||||
for (const str in texts) {
|
|
||||||
if (!l[str]) {
|
|
||||||
if (result[str]) result[str].locale.push(locale);
|
|
||||||
else result[str] = { source: texts[str], locale: [locale] };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const p = path.join(LOCALE_ROOT, name);
|
|
||||||
const f = fs.readFileSync(p).toString();
|
|
||||||
const l = yaml.safeLoad(f);
|
|
||||||
for (const str in texts) {
|
|
||||||
if (!l[str]) result[str] = texts[str];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (const str of IGNORE_MISSING) delete result[str];
|
|
||||||
console.log(`${Object.keys(result).length} translations missing.`);
|
|
||||||
fs.writeFileSync(path.join(__dirname, '..', '__result.json'), JSON.stringify(result, null, 2));
|
|
||||||
console.log(`Result wrote to ${path.resolve(__dirname, '..', '__result.json')}`);
|
|
||||||
@@ -1,104 +1,104 @@
|
|||||||
const Base64 = {
|
const Base64 = {
|
||||||
_keyStr: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',
|
_keyStr: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',
|
||||||
|
|
||||||
encode(input) {
|
encode(input) {
|
||||||
let output = '';
|
let output = '';
|
||||||
let chr1;
|
let chr1;
|
||||||
let chr2;
|
let chr2;
|
||||||
let chr3;
|
let chr3;
|
||||||
let enc1;
|
let enc1;
|
||||||
let enc2;
|
let enc2;
|
||||||
let enc3;
|
let enc3;
|
||||||
let enc4;
|
let enc4;
|
||||||
let i = 0;
|
let i = 0;
|
||||||
input = Base64._utf8_encode(input);
|
input = Base64._utf8_encode(input);
|
||||||
while (i < input.length) {
|
while (i < input.length) {
|
||||||
chr1 = input.charCodeAt(i++);
|
chr1 = input.charCodeAt(i++);
|
||||||
chr2 = input.charCodeAt(i++);
|
chr2 = input.charCodeAt(i++);
|
||||||
chr3 = input.charCodeAt(i++);
|
chr3 = input.charCodeAt(i++);
|
||||||
enc1 = chr1 >> 2;
|
enc1 = chr1 >> 2;
|
||||||
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
|
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
|
||||||
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
|
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
|
||||||
enc4 = chr3 & 63;
|
enc4 = chr3 & 63;
|
||||||
if (Number.isNaN(chr2)) enc3 = enc4 = 64;
|
if (Number.isNaN(chr2)) enc3 = enc4 = 64;
|
||||||
else if (Number.isNaN(chr3)) enc4 = 64;
|
else if (Number.isNaN(chr3)) enc4 = 64;
|
||||||
output = output
|
output = output
|
||||||
+ this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2)
|
+ this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2)
|
||||||
+ this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
|
+ this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
|
||||||
}
|
}
|
||||||
return output;
|
return output;
|
||||||
},
|
},
|
||||||
|
|
||||||
decode(input) {
|
decode(input) {
|
||||||
let output = '';
|
let output = '';
|
||||||
let chr1;
|
let chr1;
|
||||||
let chr2;
|
let chr2;
|
||||||
let chr3;
|
let chr3;
|
||||||
let enc1;
|
let enc1;
|
||||||
let enc2;
|
let enc2;
|
||||||
let enc3;
|
let enc3;
|
||||||
let enc4;
|
let enc4;
|
||||||
let i = 0;
|
let i = 0;
|
||||||
input = input.replace(/[^A-Za-z0-9+/=]/g, '');
|
input = input.replace(/[^A-Za-z0-9+/=]/g, '');
|
||||||
while (i < input.length) {
|
while (i < input.length) {
|
||||||
enc1 = this._keyStr.indexOf(input.charAt(i++));
|
enc1 = this._keyStr.indexOf(input.charAt(i++));
|
||||||
enc2 = this._keyStr.indexOf(input.charAt(i++));
|
enc2 = this._keyStr.indexOf(input.charAt(i++));
|
||||||
enc3 = this._keyStr.indexOf(input.charAt(i++));
|
enc3 = this._keyStr.indexOf(input.charAt(i++));
|
||||||
enc4 = this._keyStr.indexOf(input.charAt(i++));
|
enc4 = this._keyStr.indexOf(input.charAt(i++));
|
||||||
chr1 = (enc1 << 2) | (enc2 >> 4);
|
chr1 = (enc1 << 2) | (enc2 >> 4);
|
||||||
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
|
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
|
||||||
chr3 = ((enc3 & 3) << 6) | enc4;
|
chr3 = ((enc3 & 3) << 6) | enc4;
|
||||||
output += String.fromCharCode(chr1);
|
output += String.fromCharCode(chr1);
|
||||||
if (enc3 !== 64) output += String.fromCharCode(chr2);
|
if (enc3 !== 64) output += String.fromCharCode(chr2);
|
||||||
if (enc4 !== 64) output += String.fromCharCode(chr3);
|
if (enc4 !== 64) output += String.fromCharCode(chr3);
|
||||||
}
|
}
|
||||||
output = Base64._utf8_decode(output);
|
output = Base64._utf8_decode(output);
|
||||||
return output;
|
return output;
|
||||||
},
|
},
|
||||||
|
|
||||||
_utf8_encode(string) {
|
_utf8_encode(string) {
|
||||||
string = string.replace(/\r\n/g, '\n');
|
string = string.replace(/\r\n/g, '\n');
|
||||||
let utftext = '';
|
let utftext = '';
|
||||||
for (let n = 0; n < string.length; n++) {
|
for (let n = 0; n < string.length; n++) {
|
||||||
const c = string.charCodeAt(n);
|
const c = string.charCodeAt(n);
|
||||||
if (c < 128) {
|
if (c < 128) {
|
||||||
utftext += String.fromCharCode(c);
|
utftext += String.fromCharCode(c);
|
||||||
} else if ((c > 127) && (c < 2048)) {
|
} else if ((c > 127) && (c < 2048)) {
|
||||||
utftext += String.fromCharCode((c >> 6) | 192);
|
utftext += String.fromCharCode((c >> 6) | 192);
|
||||||
utftext += String.fromCharCode((c & 63) | 128);
|
utftext += String.fromCharCode((c & 63) | 128);
|
||||||
} else {
|
} else {
|
||||||
utftext += String.fromCharCode((c >> 12) | 224);
|
utftext += String.fromCharCode((c >> 12) | 224);
|
||||||
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
|
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
|
||||||
utftext += String.fromCharCode((c & 63) | 128);
|
utftext += String.fromCharCode((c & 63) | 128);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return utftext;
|
return utftext;
|
||||||
},
|
},
|
||||||
|
|
||||||
_utf8_decode(utftext) {
|
_utf8_decode(utftext) {
|
||||||
let string = '';
|
let string = '';
|
||||||
let i = 0;
|
let i = 0;
|
||||||
let c = 0;
|
let c = 0;
|
||||||
let c2 = 0;
|
let c2 = 0;
|
||||||
let c3 = 0;
|
let c3 = 0;
|
||||||
while (i < utftext.length) {
|
while (i < utftext.length) {
|
||||||
c = utftext.charCodeAt(i);
|
c = utftext.charCodeAt(i);
|
||||||
if (c < 128) {
|
if (c < 128) {
|
||||||
string += String.fromCharCode(c);
|
string += String.fromCharCode(c);
|
||||||
i++;
|
i++;
|
||||||
} else if ((c > 191) && (c < 224)) {
|
} else if ((c > 191) && (c < 224)) {
|
||||||
c2 = utftext.charCodeAt(i + 1);
|
c2 = utftext.charCodeAt(i + 1);
|
||||||
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
|
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
|
||||||
i += 2;
|
i += 2;
|
||||||
} else {
|
} else {
|
||||||
c2 = utftext.charCodeAt(i + 1);
|
c2 = utftext.charCodeAt(i + 1);
|
||||||
c3 = utftext.charCodeAt(i + 2);
|
c3 = utftext.charCodeAt(i + 2);
|
||||||
string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
|
string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
|
||||||
i += 3;
|
i += 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return string;
|
return string;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Base64;
|
export default Base64;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
export default function cloneAttributes(from, to) {
|
export default function cloneAttributes(from, to) {
|
||||||
const attributes = from.prop('attributes');
|
const attributes = from.prop('attributes');
|
||||||
$.each(attributes, function () {
|
$.each(attributes, function () {
|
||||||
to.attr(this.name, this.value);
|
to.attr(this.name, this.value);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
import i18n from './i18n';
|
import i18n from './i18n';
|
||||||
import substitute from './substitute';
|
|
||||||
|
|
||||||
const request = {
|
const request = {
|
||||||
/**
|
/**
|
||||||
@@ -24,7 +23,7 @@ const request = {
|
|||||||
} else if (typeof jqXHR.responseJSON === 'object' && jqXHR.responseJSON.error) {
|
} else if (typeof jqXHR.responseJSON === 'object' && jqXHR.responseJSON.error) {
|
||||||
const { error } = jqXHR.responseJSON;
|
const { error } = jqXHR.responseJSON;
|
||||||
if (error.params) {
|
if (error.params) {
|
||||||
const message = substitute(error.message, ...error.params);
|
const message = i18n(error.message, ...error.params);
|
||||||
const err = new Error(message);
|
const err = new Error(message);
|
||||||
err.rawMessage = error.message;
|
err.rawMessage = error.message;
|
||||||
err.params = error.params;
|
err.params = error.params;
|
||||||
|
|||||||
Reference in new issue
Block a user