diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 80ce8e0c8..df80340ff 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -33,10 +33,12 @@ jobs:
path: |
${{ steps.yarn-cache-dir-path.outputs.dir }}
yarn.lock
+ .cache
**/tsconfig.tsbuildinfo
- key: yarn-${{ hashFiles('**/package.json') }}
+ key: ${{ GITHUB_REF_NAME }}
restore-keys: |
- yarn-
+ master
+ main
- name: Config And Install
run: |
[[ ! -z "${{secrets.NPM_TOKEN}}" ]] && echo "npmAuthToken: ${{secrets.NPM_TOKEN}}" >> .yarnrc.yml
diff --git a/packages/ui-default/.eslintrc.js b/packages/ui-default/.eslintrc.js
index 811f1ac0e..c792bbdd3 100644
--- a/packages/ui-default/.eslintrc.js
+++ b/packages/ui-default/.eslintrc.js
@@ -3,7 +3,7 @@ const path = require('path');
module.exports = {
root: true,
parser: '@typescript-eslint/parser',
- plugins: ['@typescript-eslint', 'react'],
+ plugins: ['@typescript-eslint', 'react', 'simple-import-sort'],
env: {
browser: true,
es6: true,
@@ -138,5 +138,16 @@ module.exports = {
'jsx-a11y/anchor-is-valid': 'off',
'jsx-a11y/click-events-have-key-events': 'off',
'jsx-a11y/label-has-associated-control': 'off',
+
+ 'simple-import-sort/imports': [
+ 'warn',
+ {
+ groups: [
+ ['^\\u0000'],
+ ['^(?!vj)(@?\\w.+)', '^vj\\/', '^', '^\\.'],
+ ],
+ },
+ ],
+ 'simple-import-sort/exports': 'off',
},
};
diff --git a/packages/ui-default/backendlib/markdown-it-media.ts b/packages/ui-default/backendlib/markdown-it-media.ts
index 73ff6618e..8e311715d 100644
--- a/packages/ui-default/backendlib/markdown-it-media.ts
+++ b/packages/ui-default/backendlib/markdown-it-media.ts
@@ -26,12 +26,6 @@ function preziParser(url: string) {
const match = url.match(preziRegex);
return match ? match[1] : url;
}
-// TODO: Write regex for staging and local servers.
-const mfrRegex = /^http(?:s?):\/\/(?:www\.)?mfr\.osf\.io\/render\?url=http(?:s?):\/\/osf\.io\/([a-zA-Z0-9]{1,5})\/\?action=download/;
-function mfrParser(url: string) {
- const match = url.match(mfrRegex);
- return match ? match[1] : url;
-}
const EMBED_REGEX = /@\[([a-zA-Z].+?)]\((.*?)[)]/im;
function extractVideoParameters(url: string) {
const parameterMap = new Map();
@@ -82,7 +76,6 @@ function resourceUrl(service: string, src: string, url: string, options) {
+ 'landing_data=bHVZZmNaNDBIWnNjdEVENDRhZDFNZGNIUE43MHdLNWpsdFJLb2ZHanI5N1lQVHkxSHFxazZ0UUNCRHloSXZROHh3PT0&'
+ 'landing_sign=1kD6c0N6aYpMUS0wxnQjxzSqZlEB8qNFdxtdjYhwSuI';
}
- if (service === 'osf') return `https://mfr.osf.io/render?url=https://osf.io/${src}/?action=download`;
return src;
}
@@ -95,26 +88,11 @@ export function Media(md: MarkdownIt) {
vimeo: { width: 500, height: 281 },
vine: { width: 600, height: 600, embed: 'simple' },
prezi: { width: 550, height: 400 },
- osf: { width: '100%', height: '100%' },
pdf: resourceUrl,
};
md.renderer.rules.video = function tokenizeReturn(tokens, idx) {
let src = md.utils.escapeHtml(tokens[idx].attrGet('src'));
const service = md.utils.escapeHtml(tokens[idx].attrGet('service')).toLowerCase();
- const checkUrl = /http(?:s?):\/\/(?:www\.)?[a-zA-Z0-9-:.]{1,}\/render(?:\/)?[a-zA-Z0-9.&;?=:%]{1,}url=http(?:s?):\/\/[a-zA-Z0-9 -:.]{1,}\/[a-zA-Z0-9]{1,5}\/\?[a-zA-Z0-9.=:%]{1,}/;
- let num;
- if (service === 'osf' && src) {
- num = Math.random() * 0x10000;
- if (src.match(checkUrl)) {
- return `
';
- }
- return `';
- }
if (service === 'bilibili') {
if (src.startsWith('http')) src = src.split('/').pop();
if (src.toLowerCase().startsWith('av')) src = src.toLowerCase().split('av')[1];
@@ -171,7 +149,6 @@ export function Media(md: MarkdownIt) {
else if (service === 'vimeo') src = vimeoParser(src);
else if (service === 'vine') src = vineParser(src);
else if (service === 'prezi') src = preziParser(src);
- else if (service === 'osf') src = mfrParser(src);
if (src === ')') src = '';
const serviceStart = oldPos + 2;
if (!silent) {
diff --git a/packages/ui-default/build/config/webpack.js b/packages/ui-default/build/config/webpack.ts
similarity index 70%
rename from packages/ui-default/build/config/webpack.js
rename to packages/ui-default/build/config/webpack.ts
index 9e616f93b..7a96f814a 100644
--- a/packages/ui-default/build/config/webpack.js
+++ b/packages/ui-default/build/config/webpack.ts
@@ -1,25 +1,21 @@
/* eslint-disable global-require */
/* eslint-disable import/no-extraneous-dependencies */
-import { dirname } from 'path';
-import webpack from 'webpack';
import { CleanWebpackPlugin } from 'clean-webpack-plugin';
+import CopyWebpackPlugin from 'copy-webpack-plugin';
import { ESBuildMinifyPlugin } from 'esbuild-loader';
+import FriendlyErrorsPlugin from 'friendly-errors-webpack-plugin';
import ExtractCssPlugin from 'mini-css-extract-plugin';
import MonacoWebpackPlugin from 'monaco-editor-webpack-plugin';
-import FriendlyErrorsPlugin from 'friendly-errors-webpack-plugin';
-import CopyWebpackPlugin from 'copy-webpack-plugin';
-import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';
+import { dirname } from 'path';
import SpeedMeasurePlugin from 'speed-measure-webpack-plugin';
+import webpack from 'webpack';
+import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';
import WebpackBar from 'webpackbar';
-import mapWebpackUrlPrefix from '../utils/mapWebpackUrlPrefix';
import root from '../utils/root';
-const beautifyOutputUrl = mapWebpackUrlPrefix([
- { prefix: 'misc/.iconfont', replace: './ui/iconfont' },
-]);
const smp = new SpeedMeasurePlugin();
-export default function (env = {}) {
+export default function (env: { production?: boolean, measure?: boolean } = {}) {
function esbuildLoader() {
return {
loader: 'esbuild-loader',
@@ -41,28 +37,7 @@ export default function (env = {}) {
function postcssLoader() {
return {
loader: 'postcss-loader',
- options: { sourceMap: env.production, config: { path: root('postcss.config.js') } },
- };
- }
-
- function fileLoader() {
- return {
- loader: 'file-loader',
- options: {
- name(resourcePath) {
- if (resourcePath.includes('node_modules')) {
- const extra = resourcePath.split('node_modules')[1];
- const moduleName = extra.split('/')[0];
- if (extra.includes('@fontsource')) {
- return `fonts/${extra.substr(2).replace(/\\/g, '/')}?[contenthash]`;
- }
- if (['katex', 'monaco-editor'].includes(moduleName)) return `modules/${moduleName}/[name].[ext]?[contenthash]`;
- return `modules/${extra.substr(1).replace(/\\/g, '/')}?[contenthash]`;
- }
- if (resourcePath.includes('misc/.iconfont')) return 'modules/icon/[name].[ext]?[contenthash]';
- return '[path][name].[ext]?[contenthash]';
- },
- },
+ options: { postcssOptions: { sourceMap: env.production, config: root('postcss.config.js') } },
};
}
@@ -76,24 +51,45 @@ export default function (env = {}) {
};
}
- const config = {
- bail: true,
+ function stylusLoader() {
+ return {
+ loader: 'stylus-loader',
+ options: {
+ stylusOptions: {
+ preferPathResolver: 'webpack',
+ use: [require('rupture')()], // eslint-disable-line global-require
+ import: ['~vj/common/common.inc.styl'],
+ },
+ },
+ };
+ }
+
+ const config: import('webpack').Configuration = {
+ // bail: !env.production,
mode: (env.production || env.measure) ? 'production' : 'development',
- profile: true,
+ profile: env.measure,
context: root(),
+ stats: {
+ preset: 'errors-warnings',
+ },
devtool: env.production ? 'source-map' : false,
entry: {
hydro: './entry.js',
polyfill: './polyfill.ts',
'default.theme': './theme/default.js',
},
+ cache: {
+ type: 'filesystem',
+ cacheDirectory: root('../../.cache'),
+ idleTimeout: 30000,
+ },
output: {
path: root('public'),
publicPath: '/', // overwrite in entry.js
hashFunction: 'sha1',
hashDigest: 'hex',
hashDigestLength: 10,
- filename: '[name].js?[hash]',
+ filename: '[name].js?[contenthash]',
chunkFilename: '[name].[chunkhash].chunk.js',
},
resolve: {
@@ -114,33 +110,60 @@ export default function (env = {}) {
use: { loader: '@svgr/webpack', options: { icon: true } },
},
{
- use: [fileLoader()],
+ type: 'asset/resource',
},
],
},
{
test: /\.(ttf|eot|woff|woff2|png|jpg|jpeg|gif)$/,
- use: [fileLoader()],
+ type: 'asset/resource',
+ generator: {
+ filename: (pathData) => {
+ const p = pathData.module.resource.replace(/\\/g, '/');
+ const filename = p.split('/').pop();
+ if (p.includes('node_modules')) {
+ const extra = p.split('node_modules')[1];
+ const moduleName = extra.split('/')[0];
+ if (extra.includes('@fontsource')) {
+ return `fonts/${filename}?[hash]`;
+ }
+ if (['katex', 'monaco-editor'].includes(moduleName)) {
+ return `modules/${moduleName}/${filename}?[hash]`;
+ }
+ return `modules/${extra.substr(1)}?[hash]`;
+ }
+ if (p.includes('.iconfont')) return `${filename}?[hash]`;
+ return `${p.split('ui-default')[1].substring(1)}?[hash]`;
+ },
+ },
+ },
+ {
+ test: /\.ts$/,
+ include: /@types\//,
+ type: 'asset/inline',
+ generator: {
+ dataUrl: (buf) => buf.toString(),
+ },
},
{
test: /\.[jt]sx?$/,
+ exclude: /@types\//,
use: [esbuildLoader()],
},
{
test: /\.styl$/,
- use: [extractCssLoader(), cssLoader(), postcssLoader(), 'stylus-loader'],
+ use: [extractCssLoader(), cssLoader(), postcssLoader(), stylusLoader()],
},
{
test: /\.css$/,
use: [extractCssLoader(), cssLoader(), postcssLoader()],
},
- {
- test: /\.wasm$/,
- use: [fileLoader()],
- type: 'javascript/auto',
- },
],
},
+ experiments: {
+ asyncWebAssembly: true,
+ syncWebAssembly: true,
+ },
optimization: {
splitChunks: {
minSize: 256000,
@@ -149,7 +172,7 @@ export default function (env = {}) {
automaticNameDelimiter: '-',
cacheGroups: {
style: {
- test: /\.(css|styl|less|sass|scss)$/,
+ test: /\.(css|styl|less|s[ac]ss)$/,
priority: 99,
name: 'style',
},
@@ -199,20 +222,10 @@ export default function (env = {}) {
monaco: 'monaco-editor/esm/vs/editor/editor.api',
}),
new ExtractCssPlugin({
- filename: '[name].css?[hash:10]',
- }),
- new webpack.LoaderOptionsPlugin({
- test: /\.styl$/,
- stylus: {
- default: {
- preferPathResolver: 'webpack',
- use: [require('rupture')()], // eslint-disable-line global-require
- import: ['~vj/common/common.inc.styl'],
- },
- },
+ filename: '[name].css?[fullhash:10]',
}),
new FriendlyErrorsPlugin(),
- new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
+ new webpack.IgnorePlugin({ resourceRegExp: /(^\.\/locale$|mathjax|abcjs)/ }),
new CopyWebpackPlugin({
patterns: [
{ from: root('static') },
@@ -221,16 +234,7 @@ export default function (env = {}) {
],
}),
new webpack.DefinePlugin({
- 'process.env': {
- NODE_ENV: env.production ? '"production"' : '"debug"',
- VERSION: JSON.stringify(require('@hydrooj/ui-default/package.json').version),
- },
- }),
- new webpack.LoaderOptionsPlugin({
- options: {
- context: root(),
- customInterpolateName: beautifyOutputUrl,
- },
+ 'process.env.VERSION': JSON.stringify(require('@hydrooj/ui-default/package.json').version),
}),
new webpack.NormalModuleReplacementPlugin(/\/(vscode-)?nls\.js/, require.resolve('../../components/monaco/nls')),
new MonacoWebpackPlugin({
diff --git a/packages/ui-default/build/main.ts b/packages/ui-default/build/main.ts
index 9251fffd9..4430a9a91 100644
--- a/packages/ui-default/build/main.ts
+++ b/packages/ui-default/build/main.ts
@@ -19,19 +19,17 @@ async function runWebpack({
}) {
const compiler = webpack(webpackConfig({ watch, production, measure }));
if (dev) {
- const server = new WebpackDevServer(compiler, {
+ const server = new WebpackDevServer({
+ port: 8000,
compress: true,
hot: true,
- disableHostCheck: true,
- stats: 'none',
- index: root('public'),
proxy: {
- context: (path) => !path.includes('sockjs-node'),
+ context: (path) => path !== '/ws' && !path.startsWith('/vendors.js'),
target: 'http://localhost:2333',
ws: true,
},
- });
- return server.listen(8000);
+ }, compiler);
+ return server.start();
}
return new Promise((resolve, reject) => {
function compilerCallback(err, stats) {
@@ -85,15 +83,10 @@ async function main() {
if (fs.existsSync('public/polyfill.js')) {
fs.copyFileSync('public/polyfill.js', `public/polyfill-${pkg.version}.js`);
}
- if (fs.existsSync('public/default.theme.css')) {
- fs.copyFileSync('public/default.theme.css', `public/default-${pkg.version}.theme.css`);
- }
if (argv.options.production) {
- fs.removeSync('public/vditor/dist/js/mathjax');
fs.removeSync('public/vditor/dist/js/echarts');
fs.removeSync('public/vditor/dist/js/graphviz');
fs.removeSync('public/vditor/dist/js/mermaid');
- fs.removeSync('public/vditor/dist/js/abcjs');
const files = fs.readdirSync('public');
files.filter((i) => /(^[in]\..+|worker)\.js\.map$/.test(i)).forEach((i) => fs.removeSync(`public/${i}`));
}
diff --git a/packages/ui-default/build/utils/mapWebpackUrlPrefix.js b/packages/ui-default/build/utils/mapWebpackUrlPrefix.js
deleted file mode 100644
index 53caf8edb..000000000
--- a/packages/ui-default/build/utils/mapWebpackUrlPrefix.js
+++ /dev/null
@@ -1,18 +0,0 @@
-/* eslint-disable import/no-extraneous-dependencies */
-import { escapeRegExp } from 'lodash';
-
-export default function mapWebpackUrlPrefix(mapList) {
- const rules = mapList.map((mappingRule) => {
- const regex = mappingRule.prefix.split('/').map((s) => escapeRegExp(s)).join('[\\/\\\\]');
- return {
- from: new RegExp(`^${regex}`, mappingRule.flag),
- to: mappingRule.replace,
- };
- });
- return function mapUrl(url) {
- rules.forEach((rule) => {
- url = url.replace(rule.from, rule.to);
- });
- return url;
- };
-}
diff --git a/packages/ui-default/components/DOMAttachedObject.ts b/packages/ui-default/components/DOMAttachedObject.ts
index ba50e241e..7c9f43a9d 100644
--- a/packages/ui-default/components/DOMAttachedObject.ts
+++ b/packages/ui-default/components/DOMAttachedObject.ts
@@ -1,3 +1,5 @@
+import $ from 'jquery';
+
let removalChecker = null;
const res = [];
diff --git a/packages/ui-default/components/autocomplete/DomainSelectAutoComplete.tsx b/packages/ui-default/components/autocomplete/DomainSelectAutoComplete.tsx
index 9b2987419..66d38f7ac 100644
--- a/packages/ui-default/components/autocomplete/DomainSelectAutoComplete.tsx
+++ b/packages/ui-default/components/autocomplete/DomainSelectAutoComplete.tsx
@@ -1,6 +1,6 @@
+import { assign } from 'lodash';
import React from 'react';
import ReactDOM from 'react-dom/client';
-import { assign } from 'lodash';
import DOMAttachedObject from 'vj/components/DOMAttachedObject';
import AutoComplete from '.';
import DomainSelectAutoCompleteFC from './components/DomainSelectAutoComplete';
diff --git a/packages/ui-default/components/autocomplete/ProblemSelectAutoComplete.tsx b/packages/ui-default/components/autocomplete/ProblemSelectAutoComplete.tsx
index b50261df1..d92685598 100644
--- a/packages/ui-default/components/autocomplete/ProblemSelectAutoComplete.tsx
+++ b/packages/ui-default/components/autocomplete/ProblemSelectAutoComplete.tsx
@@ -1,6 +1,6 @@
+import { assign } from 'lodash';
import React from 'react';
import ReactDOM from 'react-dom/client';
-import { assign } from 'lodash';
import DOMAttachedObject from 'vj/components/DOMAttachedObject';
import AutoComplete from '.';
import ProblemSelectAutoCompleteFC from './components/ProblemSelectAutoComplete';
diff --git a/packages/ui-default/components/autocomplete/UserSelectAutoComplete.tsx b/packages/ui-default/components/autocomplete/UserSelectAutoComplete.tsx
index 01652016a..c9e06bb4f 100644
--- a/packages/ui-default/components/autocomplete/UserSelectAutoComplete.tsx
+++ b/packages/ui-default/components/autocomplete/UserSelectAutoComplete.tsx
@@ -1,6 +1,6 @@
+import { assign } from 'lodash';
import React from 'react';
import ReactDOM from 'react-dom/client';
-import { assign } from 'lodash';
import DOMAttachedObject from 'vj/components/DOMAttachedObject';
import AutoComplete, { AutoCompleteOptions } from '.';
import UserSelectAutoCompleteFC from './components/UserSelectAutoComplete';
diff --git a/packages/ui-default/components/autocomplete/components/AutoComplete.tsx b/packages/ui-default/components/autocomplete/components/AutoComplete.tsx
index 823280653..276d3a3b3 100644
--- a/packages/ui-default/components/autocomplete/components/AutoComplete.tsx
+++ b/packages/ui-default/components/autocomplete/components/AutoComplete.tsx
@@ -1,12 +1,13 @@
/* eslint-disable jsx-a11y/role-supports-aria-props */
/* eslint-disable jsx-a11y/no-noninteractive-element-interactions */
+import { debounce, uniqueId } from 'lodash';
+import PropTypes from 'prop-types';
import React, {
- forwardRef, useState, useRef, useImperativeHandle, useEffect,
+ forwardRef, useEffect,
+ useImperativeHandle, useRef, useState,
} from 'react';
import { DndProvider, useDrag, useDrop } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
-import PropTypes from 'prop-types';
-import { debounce, uniqueId } from 'lodash';
import Icon from 'vj/components/react/IconComponent';
export interface AutoCompleteProps- {
diff --git a/packages/ui-default/components/autocomplete/components/CustomSelectAutoComplete.tsx b/packages/ui-default/components/autocomplete/components/CustomSelectAutoComplete.tsx
index f8cd5acd8..9afc9b171 100644
--- a/packages/ui-default/components/autocomplete/components/CustomSelectAutoComplete.tsx
+++ b/packages/ui-default/components/autocomplete/components/CustomSelectAutoComplete.tsx
@@ -1,5 +1,5 @@
-import React from 'react';
import PropTypes from 'prop-types';
+import React from 'react';
import AutoComplete from './AutoComplete';
type DefaultProps = {
diff --git a/packages/ui-default/components/autocomplete/components/DomainSelectAutoComplete.tsx b/packages/ui-default/components/autocomplete/components/DomainSelectAutoComplete.tsx
index 6eb83820c..acd65bf7a 100644
--- a/packages/ui-default/components/autocomplete/components/DomainSelectAutoComplete.tsx
+++ b/packages/ui-default/components/autocomplete/components/DomainSelectAutoComplete.tsx
@@ -1,7 +1,7 @@
-import React, { forwardRef } from 'react';
-import PropTypes from 'prop-types';
-import request from 'vj/utils/request';
import type { DomainDoc } from 'hydrooj/src/interface';
+import PropTypes from 'prop-types';
+import React, { forwardRef } from 'react';
+import request from 'vj/utils/request';
import AutoComplete, { AutoCompleteHandle, AutoCompleteProps } from './AutoComplete';
const DomainSelectAutoComplete = forwardRef, AutoCompleteProps>((props, ref) => (
diff --git a/packages/ui-default/components/autocomplete/components/FileSelectAutoComplete.tsx b/packages/ui-default/components/autocomplete/components/FileSelectAutoComplete.tsx
index 4ff950c0c..2c13d9055 100644
--- a/packages/ui-default/components/autocomplete/components/FileSelectAutoComplete.tsx
+++ b/packages/ui-default/components/autocomplete/components/FileSelectAutoComplete.tsx
@@ -1,5 +1,5 @@
-import React from 'react';
import PropTypes from 'prop-types';
+import React from 'react';
import AutoComplete from './AutoComplete';
type DefaultProps = {
diff --git a/packages/ui-default/components/autocomplete/components/ProblemSelectAutoComplete.tsx b/packages/ui-default/components/autocomplete/components/ProblemSelectAutoComplete.tsx
index c54a9f121..b4aa4bde6 100644
--- a/packages/ui-default/components/autocomplete/components/ProblemSelectAutoComplete.tsx
+++ b/packages/ui-default/components/autocomplete/components/ProblemSelectAutoComplete.tsx
@@ -1,8 +1,8 @@
-import React, { forwardRef } from 'react';
+import type { ProblemDoc } from 'hydrooj/src/interface';
import PropTypes from 'prop-types';
+import React, { forwardRef } from 'react';
import api, { gql } from 'vj/utils/api';
import request from 'vj/utils/request';
-import type { ProblemDoc } from 'hydrooj/src/interface';
import AutoComplete, { AutoCompleteHandle, AutoCompleteProps } from './AutoComplete';
const ProblemSelectAutoComplete = forwardRef, AutoCompleteProps>((props, ref) => (
diff --git a/packages/ui-default/components/autocomplete/components/UserSelectAutoComplete.tsx b/packages/ui-default/components/autocomplete/components/UserSelectAutoComplete.tsx
index 42274ce46..0618ba8d5 100644
--- a/packages/ui-default/components/autocomplete/components/UserSelectAutoComplete.tsx
+++ b/packages/ui-default/components/autocomplete/components/UserSelectAutoComplete.tsx
@@ -1,7 +1,7 @@
-import React, { forwardRef } from 'react';
-import PropTypes from 'prop-types';
-import api, { gql } from 'vj/utils/api';
import type { Udoc } from 'hydrooj/src/interface';
+import PropTypes from 'prop-types';
+import React, { forwardRef } from 'react';
+import api, { gql } from 'vj/utils/api';
import AutoComplete, { AutoCompleteHandle, AutoCompleteProps } from './AutoComplete';
// eslint-disable-next-line prefer-arrow-callback
diff --git a/packages/ui-default/components/autocomplete/index.tsx b/packages/ui-default/components/autocomplete/index.tsx
index 1e1ad8361..02672468c 100644
--- a/packages/ui-default/components/autocomplete/index.tsx
+++ b/packages/ui-default/components/autocomplete/index.tsx
@@ -1,6 +1,6 @@
+import { assign } from 'lodash';
import React from 'react';
import ReactDOM from 'react-dom/client';
-import { assign } from 'lodash';
import DOMAttachedObject from 'vj/components/DOMAttachedObject';
import AutoCompleteFC from './components/AutoComplete';
diff --git a/packages/ui-default/components/calendar/index.js b/packages/ui-default/components/calendar/index.js
index 2893901cc..4714de643 100644
--- a/packages/ui-default/components/calendar/index.js
+++ b/packages/ui-default/components/calendar/index.js
@@ -1,3 +1,4 @@
+import $ from 'jquery';
import _ from 'lodash';
import moment from 'moment';
import tpl from 'vj/utils/tpl';
diff --git a/packages/ui-default/components/contest/contest.page.ts b/packages/ui-default/components/contest/contest.page.ts
index 420dc95fa..2b6ac5e78 100644
--- a/packages/ui-default/components/contest/contest.page.ts
+++ b/packages/ui-default/components/contest/contest.page.ts
@@ -1,8 +1,9 @@
+import $ from 'jquery';
+import Notification from 'vj/components/notification';
import { AutoloadPage } from 'vj/misc/Page';
import delay from 'vj/utils/delay';
import i18n from 'vj/utils/i18n';
import request from 'vj/utils/request';
-import Notification from 'vj/components/notification';
const contestPage = new AutoloadPage('contestPage', () => {
$('[data-contest-code]').on('click', (ev) => {
diff --git a/packages/ui-default/components/datepicker/datepicker.page.ts b/packages/ui-default/components/datepicker/datepicker.page.ts
index 8b722058d..4cc34419d 100644
--- a/packages/ui-default/components/datepicker/datepicker.page.ts
+++ b/packages/ui-default/components/datepicker/datepicker.page.ts
@@ -1,3 +1,4 @@
+import $ from 'jquery';
import { AutoloadPage } from 'vj/misc/Page';
const datepickerPage = new AutoloadPage('datepickerPage', async () => {
diff --git a/packages/ui-default/components/dialog/DomDialog.ts b/packages/ui-default/components/dialog/DomDialog.ts
index 04dbe3d23..2ffaa2136 100644
--- a/packages/ui-default/components/dialog/DomDialog.ts
+++ b/packages/ui-default/components/dialog/DomDialog.ts
@@ -1,3 +1,4 @@
+import $ from 'jquery';
import _ from 'lodash';
import DOMAttachedObject from 'vj/components/DOMAttachedObject';
import zIndexManager from 'vj/utils/zIndexManager';
diff --git a/packages/ui-default/components/dialog/index.ts b/packages/ui-default/components/dialog/index.ts
index 0be5aa5c8..5c061d2c4 100644
--- a/packages/ui-default/components/dialog/index.ts
+++ b/packages/ui-default/components/dialog/index.ts
@@ -1,5 +1,6 @@
-import tpl from 'vj/utils/tpl';
+import $ from 'jquery';
import i18n from 'vj/utils/i18n';
+import tpl from 'vj/utils/tpl';
import DomDialog, { DialogOptions } from './DomDialog';
export class Dialog {
diff --git a/packages/ui-default/components/discussion/CommentBox.js b/packages/ui-default/components/discussion/CommentBox.js
index a2a85cc38..a1e2f1655 100644
--- a/packages/ui-default/components/discussion/CommentBox.js
+++ b/packages/ui-default/components/discussion/CommentBox.js
@@ -1,8 +1,9 @@
+import $ from 'jquery';
import _ from 'lodash';
import DOMAttachedObject from 'vj/components/DOMAttachedObject';
-import request from 'vj/utils/request';
import TextareaHandler from 'vj/components/editor/textareaHandler';
import Notification from 'vj/components/notification';
+import request from 'vj/utils/request';
let initialized = false;
const $template = $('.dczcomments__box').eq(0).clone();
diff --git a/packages/ui-default/components/discussion/comments.page.tsx b/packages/ui-default/components/discussion/comments.page.tsx
index 6917cd2e6..cb2031500 100644
--- a/packages/ui-default/components/discussion/comments.page.tsx
+++ b/packages/ui-default/components/discussion/comments.page.tsx
@@ -1,13 +1,13 @@
import 'jquery.easing';
-import { AutoloadPage } from 'vj/misc/Page';
-import CommentBox from 'vj/components/discussion/CommentBox';
+import $ from 'jquery';
import { ConfirmDialog } from 'vj/components/dialog';
-
+import CommentBox from 'vj/components/discussion/CommentBox';
+import { AutoloadPage } from 'vj/misc/Page';
import delay from 'vj/utils/delay';
-import { slideDown, slideUp } from 'vj/utils/slide';
-import request from 'vj/utils/request';
import i18n from 'vj/utils/i18n';
+import request from 'vj/utils/request';
+import { slideDown, slideUp } from 'vj/utils/slide';
import tpl from 'vj/utils/tpl';
const $replyTemplate = $('.commentbox-container').eq(0).clone();
diff --git a/packages/ui-default/components/discussion/reaction.page.tsx b/packages/ui-default/components/discussion/reaction.page.tsx
index b2bf6ab86..9f0720709 100644
--- a/packages/ui-default/components/discussion/reaction.page.tsx
+++ b/packages/ui-default/components/discussion/reaction.page.tsx
@@ -1,12 +1,12 @@
import 'jquery.easing';
+import { Popover } from '@blueprintjs/core';
+import $ from 'jquery';
+import { chunk } from 'lodash';
import * as React from 'react';
import ReactDOM from 'react-dom/client';
-import { Popover } from '@blueprintjs/core';
import { AutoloadPage } from 'vj/misc/Page';
-
import request from 'vj/utils/request';
-import { chunk } from 'lodash';
function renderReactions(reactions, self, rootEle) {
let html = '';
diff --git a/packages/ui-default/components/dropdown/Dropdown.js b/packages/ui-default/components/dropdown/Dropdown.js
index 8aa0e81d3..758092076 100644
--- a/packages/ui-default/components/dropdown/Dropdown.js
+++ b/packages/ui-default/components/dropdown/Dropdown.js
@@ -1,10 +1,9 @@
-import Drop from 'tether-drop';
import _ from 'lodash';
-import DOMAttachedObject from 'vj/components/DOMAttachedObject';
+import Drop from 'tether-drop';
import responsiveCutoff from 'vj/breakpoints.json';
-
-import zIndexManager from 'vj/utils/zIndexManager';
+import DOMAttachedObject from 'vj/components/DOMAttachedObject';
import { isBelow } from 'vj/utils/mediaQuery';
+import zIndexManager from 'vj/utils/zIndexManager';
export default class Dropdown extends DOMAttachedObject {
static DOMAttachKey = 'vjDropdownInstance';
diff --git a/packages/ui-default/components/editor/index.ts b/packages/ui-default/components/editor/index.ts
index dcd8d65a5..6c5b420c5 100644
--- a/packages/ui-default/components/editor/index.ts
+++ b/packages/ui-default/components/editor/index.ts
@@ -1,7 +1,8 @@
+import $ from 'jquery';
import _ from 'lodash';
-import Notification from 'vj/components/notification';
-import DOMAttachedObject from 'vj/components/DOMAttachedObject';
import { nanoid } from 'nanoid';
+import DOMAttachedObject from 'vj/components/DOMAttachedObject';
+import Notification from 'vj/components/notification';
import i18n from 'vj/utils/i18n';
import request from 'vj/utils/request';
diff --git a/packages/ui-default/components/footer/footer.page.ts b/packages/ui-default/components/footer/footer.page.ts
index 13f7c402f..dddeb6b6a 100644
--- a/packages/ui-default/components/footer/footer.page.ts
+++ b/packages/ui-default/components/footer/footer.page.ts
@@ -1,7 +1,8 @@
+import $ from 'jquery';
+import responsiveCutoff from 'vj/breakpoints.json';
import { AutoloadPage } from 'vj/misc/Page';
import { isBelow } from 'vj/utils/mediaQuery';
-import { slideUp, slideDown } from 'vj/utils/slide';
-import responsiveCutoff from 'vj/breakpoints.json';
+import { slideDown, slideUp } from 'vj/utils/slide';
const footerPage = new AutoloadPage('footerPage', () => {
if (!$('.footer').length) return;
diff --git a/packages/ui-default/components/form/form.page.ts b/packages/ui-default/components/form/form.page.ts
index 029ae4135..aa9f8eacc 100644
--- a/packages/ui-default/components/form/form.page.ts
+++ b/packages/ui-default/components/form/form.page.ts
@@ -1,3 +1,4 @@
+import $ from 'jquery';
import { AutoloadPage } from 'vj/misc/Page';
import delay from 'vj/utils/delay';
diff --git a/packages/ui-default/components/form/multiSelectCheckbox.page.js b/packages/ui-default/components/form/multiSelectCheckbox.page.js
index f9a6caa67..c2ae9d0bb 100644
--- a/packages/ui-default/components/form/multiSelectCheckbox.page.js
+++ b/packages/ui-default/components/form/multiSelectCheckbox.page.js
@@ -1,3 +1,4 @@
+import $ from 'jquery';
import { AutoloadPage } from 'vj/misc/Page';
const lastSelectionByGroup = {};
diff --git a/packages/ui-default/components/form/textbox.page.ts b/packages/ui-default/components/form/textbox.page.ts
index b6824af0c..816aeec37 100644
--- a/packages/ui-default/components/form/textbox.page.ts
+++ b/packages/ui-default/components/form/textbox.page.ts
@@ -1,3 +1,4 @@
+import $ from 'jquery';
import { AutoloadPage } from 'vj/misc/Page';
const textboxPage = new AutoloadPage('textboxPage', () => {
diff --git a/packages/ui-default/components/highlighter/highlighter.page.ts b/packages/ui-default/components/highlighter/highlighter.page.ts
index a43e92ec9..4778fc38b 100644
--- a/packages/ui-default/components/highlighter/highlighter.page.ts
+++ b/packages/ui-default/components/highlighter/highlighter.page.ts
@@ -1,6 +1,7 @@
+import $ from 'jquery';
import { AutoloadPage } from 'vj/misc/Page';
-import tpl from 'vj/utils/tpl';
import i18n from 'vj/utils/i18n';
+import tpl from 'vj/utils/tpl';
const highlighterPage = new AutoloadPage('highlighterPage', () => {
import('./prismjs').then(({ default: prismjs }) => {
diff --git a/packages/ui-default/components/highlighter/prismjs.js b/packages/ui-default/components/highlighter/prismjs.js
index dfb136135..21ae80912 100644
--- a/packages/ui-default/components/highlighter/prismjs.js
+++ b/packages/ui-default/components/highlighter/prismjs.js
@@ -1,11 +1,14 @@
-import Prism from 'prismjs';
-import components from 'prismjs/components';
-import getLoader from 'prismjs/dependencies';
+import Prism from 'prismjs'; // eslint-disable-line
+
import 'prismjs/plugins/toolbar/prism-toolbar';
import 'prismjs/plugins/toolbar/prism-toolbar.css';
import 'prismjs/plugins/line-numbers/prism-line-numbers';
import 'prismjs/plugins/line-numbers/prism-line-numbers.css';
+
import Clipboard from 'clipboard';
+import $ from 'jquery';
+import components from 'prismjs/components';
+import getLoader from 'prismjs/dependencies';
import Notification from 'vj/components/notification/index';
import i18n from 'vj/utils/i18n';
import languageMeta from './meta';
diff --git a/packages/ui-default/components/hint.ts b/packages/ui-default/components/hint.ts
index becbb43b6..e8e7159c3 100644
--- a/packages/ui-default/components/hint.ts
+++ b/packages/ui-default/components/hint.ts
@@ -1,3 +1,4 @@
+import $ from 'jquery';
import { InfoDialog } from 'vj/components/dialog';
import i18n from 'vj/utils/i18n';
import tpl from 'vj/utils/tpl';
diff --git a/packages/ui-default/components/hitokoto/index.page.js b/packages/ui-default/components/hitokoto/index.page.js
index b738d8553..d70b0dcc3 100644
--- a/packages/ui-default/components/hitokoto/index.page.js
+++ b/packages/ui-default/components/hitokoto/index.page.js
@@ -1,6 +1,7 @@
+import $ from 'jquery';
import { AutoloadPage } from 'vj/misc/Page';
-import request from 'vj/utils/request';
import i18n from 'vj/utils/i18n';
+import request from 'vj/utils/request';
import tpl from 'vj/utils/tpl';
const hitokotoPage = new AutoloadPage('hitokotoPage', () => {
diff --git a/packages/ui-default/components/hotkey/hotkey.page.js b/packages/ui-default/components/hotkey/hotkey.page.js
index e4537a6df..72de894d6 100644
--- a/packages/ui-default/components/hotkey/hotkey.page.js
+++ b/packages/ui-default/components/hotkey/hotkey.page.js
@@ -1,3 +1,4 @@
+import $ from 'jquery';
import _ from 'lodash';
import { AutoloadPage } from 'vj/misc/Page';
diff --git a/packages/ui-default/components/katex/katex.page.js b/packages/ui-default/components/katex/katex.page.js
index 078d866bb..f3a4c970b 100644
--- a/packages/ui-default/components/katex/katex.page.js
+++ b/packages/ui-default/components/katex/katex.page.js
@@ -1,3 +1,4 @@
+import $ from 'jquery';
import { AutoloadPage } from 'vj/misc/Page';
const katexPage = new AutoloadPage('katexPage', () => {
diff --git a/packages/ui-default/components/languageselect.tsx b/packages/ui-default/components/languageselect.tsx
index 9ec2d95f7..1721bb1c4 100644
--- a/packages/ui-default/components/languageselect.tsx
+++ b/packages/ui-default/components/languageselect.tsx
@@ -1,3 +1,4 @@
+import $ from 'jquery';
import React from 'react';
import ReactDOM from 'react-dom/client';
import i18n from 'vj/utils/i18n';
diff --git a/packages/ui-default/components/marker/Marker.js b/packages/ui-default/components/marker/Marker.js
index dffd84609..4a4ce3236 100644
--- a/packages/ui-default/components/marker/Marker.js
+++ b/packages/ui-default/components/marker/Marker.js
@@ -1,6 +1,7 @@
+import $ from 'jquery';
import _ from 'lodash';
-import delay from 'vj/utils/delay';
import Tooltip from 'vj/components/tooltip/Tooltip';
+import delay from 'vj/utils/delay';
import i18n from 'vj/utils/i18n';
const MARKER_ID = `marker_${Math.floor(Math.random() * 0xFFFFFF).toString(16)}`;
diff --git a/packages/ui-default/components/marker/MarkerReactive.js b/packages/ui-default/components/marker/MarkerReactive.js
index 897c7cca5..38022e5c6 100644
--- a/packages/ui-default/components/marker/MarkerReactive.js
+++ b/packages/ui-default/components/marker/MarkerReactive.js
@@ -1,7 +1,7 @@
+import $ from 'jquery';
import _ from 'lodash';
-
-import delay from 'vj/utils/delay';
import DOMAttachedObject from 'vj/components/DOMAttachedObject';
+import delay from 'vj/utils/delay';
import Marker from './Marker';
export default class MarkerReactive extends DOMAttachedObject {
diff --git a/packages/ui-default/components/media/media.page.js b/packages/ui-default/components/media/media.page.js
index 552f70dc0..69f55bddb 100644
--- a/packages/ui-default/components/media/media.page.js
+++ b/packages/ui-default/components/media/media.page.js
@@ -1,3 +1,4 @@
+import $ from 'jquery';
import { AutoloadPage } from 'vj/misc/Page';
import request from 'vj/utils/request';
diff --git a/packages/ui-default/components/menu/menu-heading.page.js b/packages/ui-default/components/menu/menu-heading.page.js
index 5a71dc021..7ac908bfb 100644
--- a/packages/ui-default/components/menu/menu-heading.page.js
+++ b/packages/ui-default/components/menu/menu-heading.page.js
@@ -1,3 +1,4 @@
+import $ from 'jquery';
import { AutoloadPage } from 'vj/misc/Page';
import tpl from 'vj/utils/tpl';
diff --git a/packages/ui-default/components/menu/menu.page.js b/packages/ui-default/components/menu/menu.page.js
index 23b1de448..74c746998 100644
--- a/packages/ui-default/components/menu/menu.page.js
+++ b/packages/ui-default/components/menu/menu.page.js
@@ -1,6 +1,7 @@
+import $ from 'jquery';
import { AutoloadPage } from 'vj/misc/Page';
-import { slideDown } from 'vj/utils/slide';
import delay from 'vj/utils/delay';
+import { slideDown } from 'vj/utils/slide';
function expandMenu($menu) {
slideDown($menu, 500, { opacity: 0 }, { opacity: 1 });
diff --git a/packages/ui-default/components/message/index.page.ts b/packages/ui-default/components/message/index.page.ts
index b6728dff6..146f65aaa 100644
--- a/packages/ui-default/components/message/index.page.ts
+++ b/packages/ui-default/components/message/index.page.ts
@@ -1,11 +1,11 @@
-import { AutoloadPage } from 'vj/misc/Page';
+import { nanoid } from 'nanoid';
+import ReconnectingWebsocket from 'reconnecting-websocket';
import { InfoDialog } from 'vj/components/dialog';
import VjNotification from 'vj/components/notification/index';
-import ReconnectingWebsocket from 'reconnecting-websocket';
import { FLAG_ALERT } from 'vj/constant/message';
+import { AutoloadPage } from 'vj/misc/Page';
import i18n from 'vj/utils/i18n';
import tpl from 'vj/utils/tpl';
-import { nanoid } from 'nanoid';
const onmessage = (msg) => {
console.log('Received message', msg);
diff --git a/packages/ui-default/components/messagepad/DialogueListItemComponent.jsx b/packages/ui-default/components/messagepad/DialogueListItemComponent.jsx
index b2777109c..dd75b8c02 100644
--- a/packages/ui-default/components/messagepad/DialogueListItemComponent.jsx
+++ b/packages/ui-default/components/messagepad/DialogueListItemComponent.jsx
@@ -1,5 +1,5 @@
-import PropTypes from 'prop-types';
import classNames from 'classnames';
+import PropTypes from 'prop-types';
export default function DialogueListItemComponent(props) {
const {
diff --git a/packages/ui-default/components/messagepad/MessageComponent.jsx b/packages/ui-default/components/messagepad/MessageComponent.jsx
index de0c3ceb8..12ac5ccb9 100644
--- a/packages/ui-default/components/messagepad/MessageComponent.jsx
+++ b/packages/ui-default/components/messagepad/MessageComponent.jsx
@@ -1,5 +1,5 @@
-import PropTypes from 'prop-types';
import classNames from 'classnames';
+import PropTypes from 'prop-types';
export default function MessageComponent(props) {
const {
diff --git a/packages/ui-default/components/messagepad/MessagePadDialogueContentContainer.jsx b/packages/ui-default/components/messagepad/MessagePadDialogueContentContainer.jsx
index 1d748a816..3f34d5ff2 100644
--- a/packages/ui-default/components/messagepad/MessagePadDialogueContentContainer.jsx
+++ b/packages/ui-default/components/messagepad/MessagePadDialogueContentContainer.jsx
@@ -1,9 +1,11 @@
+import 'jquery-scroll-lock';
+import 'jquery.easing';
+
+import $ from 'jquery';
+import moment from 'moment';
import React from 'react';
import { connect } from 'react-redux';
import TimeAgo from 'timeago-react';
-import moment from 'moment';
-import 'jquery-scroll-lock';
-import 'jquery.easing';
import i18n from 'vj/utils/i18n';
import { parse as parseMongoId } from 'vj/utils/mongoId';
import Message from './MessageComponent';
diff --git a/packages/ui-default/components/messagepad/MessagePadDialogueListContainer.jsx b/packages/ui-default/components/messagepad/MessagePadDialogueListContainer.jsx
index 1c967e603..cdf9e9f62 100644
--- a/packages/ui-default/components/messagepad/MessagePadDialogueListContainer.jsx
+++ b/packages/ui-default/components/messagepad/MessagePadDialogueListContainer.jsx
@@ -1,8 +1,9 @@
-import React from 'react';
-import _ from 'lodash';
-import { connect } from 'react-redux';
import 'jquery-scroll-lock';
+import $ from 'jquery';
+import _ from 'lodash';
+import React from 'react';
+import { connect } from 'react-redux';
import i18n from 'vj/utils/i18n';
import ListItem from './DialogueListItemComponent';
diff --git a/packages/ui-default/components/messagepad/MessagePadInputContainer.jsx b/packages/ui-default/components/messagepad/MessagePadInputContainer.jsx
index 53e8fc58a..ff7b6d3f7 100644
--- a/packages/ui-default/components/messagepad/MessagePadInputContainer.jsx
+++ b/packages/ui-default/components/messagepad/MessagePadInputContainer.jsx
@@ -1,9 +1,8 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import { connect } from 'react-redux';
import classNames from 'classnames';
+import PropTypes from 'prop-types';
+import React from 'react';
+import { connect } from 'react-redux';
import Icon from 'vj/components/react/IconComponent';
-
import request from 'vj/utils/request';
const mapStateToProps = (state) => ({
diff --git a/packages/ui-default/components/messagepad/index.jsx b/packages/ui-default/components/messagepad/index.jsx
index bee7f9989..d62f8975e 100644
--- a/packages/ui-default/components/messagepad/index.jsx
+++ b/packages/ui-default/components/messagepad/index.jsx
@@ -1,12 +1,11 @@
-import React from 'react';
import PropTypes from 'prop-types';
+import React from 'react';
import { connect } from 'react-redux';
-
-import request from 'vj/utils/request';
-import i18n from 'vj/utils/i18n';
import Icon from 'vj/components/react/IconComponent';
-import MessagePadDialogueList from './MessagePadDialogueListContainer';
+import i18n from 'vj/utils/i18n';
+import request from 'vj/utils/request';
import MessagePadDialogueContent from './MessagePadDialogueContentContainer';
+import MessagePadDialogueList from './MessagePadDialogueListContainer';
import MessagePadInput from './MessagePadInputContainer';
const mapDispatchToProps = (dispatch) => ({
diff --git a/packages/ui-default/components/messagepad/reducers/activeId.js b/packages/ui-default/components/messagepad/reducers/activeId.js
index 8af2782c8..406e9cd20 100644
--- a/packages/ui-default/components/messagepad/reducers/activeId.js
+++ b/packages/ui-default/components/messagepad/reducers/activeId.js
@@ -1,5 +1,7 @@
import 'jquery.easing';
+import $ from 'jquery';
+
function scrollToViewport() {
const BOUND_TOP = 60;
const BOUND_BOTTOM = 20;
diff --git a/packages/ui-default/components/monaco/index.ts b/packages/ui-default/components/monaco/index.ts
index a2d2209da..d6c243782 100644
--- a/packages/ui-default/components/monaco/index.ts
+++ b/packages/ui-default/components/monaco/index.ts
@@ -1,11 +1,13 @@
-import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
+import './monaco.styl';
+
+import $ from 'jquery';
import { EditorAction, registerEditorAction } from 'monaco-editor/esm/vs/editor/browser/editorExtensions';
+import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
import { IQuickInputService } from 'monaco-editor/esm/vs/platform/quickinput/common/quickInput';
import list from 'monaco-themes/themes/themelist.json';
import { nanoid } from 'nanoid';
import i18n from 'vj/utils/i18n';
import request from 'vj/utils/request';
-import './monaco.styl';
export default monaco;
export const customOptions: monaco.editor.IStandaloneDiffEditorConstructionOptions = JSON.parse(localStorage.getItem('editor.config') || '{}');
diff --git a/packages/ui-default/components/monaco/languages/markdown.ts b/packages/ui-default/components/monaco/languages/markdown.ts
index d1f9c95f3..3676257a8 100644
--- a/packages/ui-default/components/monaco/languages/markdown.ts
+++ b/packages/ui-default/components/monaco/languages/markdown.ts
@@ -1,6 +1,6 @@
-import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
-import list from 'emojis-list';
import keyword from 'emojis-keywords';
+import list from 'emojis-list';
+import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
import api, { gql } from 'vj/utils/api';
const qqEmojies = [
diff --git a/packages/ui-default/components/monaco/languages/typescript.ts b/packages/ui-default/components/monaco/languages/typescript.ts
index a2da14831..f339379d5 100644
--- a/packages/ui-default/components/monaco/languages/typescript.ts
+++ b/packages/ui-default/components/monaco/languages/typescript.ts
@@ -1,6 +1,6 @@
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
-const types = require.context('!!raw-loader!@types/node/', true, /\.d\.ts$/);
+const types = require.context('@types/node/', true, /\.d\.ts$/, 'lazy-once');
const diagnosticsOptions: monaco.languages.typescript.DiagnosticsOptions = {
noSemanticValidation: false,
@@ -24,17 +24,21 @@ const libUri = 'ts:filename/basic.d.ts';
monaco.languages.typescript.javascriptDefaults.addExtraLib(libSource, libUri);
monaco.editor.createModel(libSource, 'typescript', monaco.Uri.parse(libUri));
const modules = [];
-for (const key of types.keys()) {
- const val = types(key).default.replace('declare var require: NodeRequire;', '');
- if (val.includes('declare module ')) {
- modules.push(val.toString().split('declare module \'')[1].split('\'')[0]);
+(async () => {
+ for (const key of types.keys()) {
+ if (!key.startsWith('.')) continue;
+ const m = await types(key);
+ const val = m.replace('declare var require: NodeRequire;', '');
+ if (val.includes('declare module ')) {
+ modules.push(val.toString().split('declare module \'')[1].split('\'')[0]);
+ }
+ const uri = `ts:node/${key.split('./')[1]}`;
+ monaco.languages.typescript.javascriptDefaults.addExtraLib(val, uri);
+ monaco.editor.createModel(val, 'typescript', monaco.Uri.parse(uri));
}
- const uri = `ts:node/${key.split('./')[1]}`;
- monaco.languages.typescript.javascriptDefaults.addExtraLib(val, uri);
- monaco.editor.createModel(val, 'typescript', monaco.Uri.parse(uri));
-}
-let val = 'declare var require:';
-for (const m of modules) val += `((id:'${m}')=>(typeof import('${m}')))&`;
-val += '((id:string)=>any)';
-monaco.languages.typescript.javascriptDefaults.addExtraLib(val, 'ts:node/require.d.ts');
-monaco.editor.createModel(val, 'typescript', monaco.Uri.parse('ts:node/require.d.ts'));
+ let val = 'declare var require:';
+ for (const m of modules) val += `((id:'${m}')=>(typeof import('${m}')))&`;
+ val += '((id:string)=>any)';
+ monaco.languages.typescript.javascriptDefaults.addExtraLib(val, 'ts:node/require.d.ts');
+ monaco.editor.createModel(val, 'typescript', monaco.Uri.parse('ts:node/require.d.ts'));
+})();
diff --git a/packages/ui-default/components/navigation/navigation.page.js b/packages/ui-default/components/navigation/navigation.page.js
index bdc0af630..1f3391ee9 100644
--- a/packages/ui-default/components/navigation/navigation.page.js
+++ b/packages/ui-default/components/navigation/navigation.page.js
@@ -1,12 +1,13 @@
+import $ from 'jquery';
import Slideout from 'slideout';
+import UserSelectAutoComplete from 'vj/components/autocomplete/UserSelectAutoComplete';
+import { ActionDialog } from 'vj/components/dialog';
import createHint from 'vj/components/hint';
-import tpl from 'vj/utils/tpl';
+import Notification from 'vj/components/notification';
+import { AutoloadPage } from 'vj/misc/Page';
import i18n from 'vj/utils/i18n';
import request from 'vj/utils/request';
-import { ActionDialog } from 'vj/components/dialog';
-import Notification from 'vj/components/notification';
-import UserSelectAutoComplete from 'vj/components/autocomplete/UserSelectAutoComplete';
-import { AutoloadPage } from 'vj/misc/Page';
+import tpl from 'vj/utils/tpl';
function handleNavLogoutClick(ev) {
const $logoutLink = $(ev.currentTarget);
diff --git a/packages/ui-default/components/notification/index.js b/packages/ui-default/components/notification/index.js
index 4a9fadc74..ed2315717 100644
--- a/packages/ui-default/components/notification/index.js
+++ b/packages/ui-default/components/notification/index.js
@@ -1,4 +1,5 @@
-import { Position, Toaster, Intent } from '@blueprintjs/core';
+import { Intent, Position, Toaster } from '@blueprintjs/core';
+import $ from 'jquery';
import tpl from 'vj/utils/tpl';
import zIndexManager from 'vj/utils/zIndexManager';
diff --git a/packages/ui-default/components/notification/notification.page.js b/packages/ui-default/components/notification/notification.page.js
index 800c54cee..0060a503e 100644
--- a/packages/ui-default/components/notification/notification.page.js
+++ b/packages/ui-default/components/notification/notification.page.js
@@ -1,5 +1,5 @@
-import { AutoloadPage } from 'vj/misc/Page';
import Notification from 'vj/components/notification/index';
+import { AutoloadPage } from 'vj/misc/Page';
import i18n from 'vj/utils/i18n';
export default new AutoloadPage('notificationPage', (pagename) => {
diff --git a/packages/ui-default/components/problem/create.page.js b/packages/ui-default/components/problem/create.page.js
index fd431b863..a95415e94 100644
--- a/packages/ui-default/components/problem/create.page.js
+++ b/packages/ui-default/components/problem/create.page.js
@@ -1,7 +1,8 @@
-import { NamedPage } from 'vj/misc/Page';
+import $ from 'jquery';
import { InfoDialog } from 'vj/components/dialog';
-import tpl from 'vj/utils/tpl';
+import { NamedPage } from 'vj/misc/Page';
import i18n from 'vj/utils/i18n';
+import tpl from 'vj/utils/tpl';
export default new NamedPage(['problem_create', 'problem_edit'], () => {
$('input[name="pid"]').on('blur', () => {
diff --git a/packages/ui-default/components/problem/list.page.js b/packages/ui-default/components/problem/list.page.js
index 13ad2d589..f4b872ca3 100644
--- a/packages/ui-default/components/problem/list.page.js
+++ b/packages/ui-default/components/problem/list.page.js
@@ -1,3 +1,4 @@
+import $ from 'jquery';
import { AutoloadPage } from 'vj/misc/Page';
export default new AutoloadPage('problemListPage', () => {
diff --git a/packages/ui-default/components/problemconfig/BasicForm.tsx b/packages/ui-default/components/problemconfig/BasicForm.tsx
index 0d34abcaf..c5dbd9939 100644
--- a/packages/ui-default/components/problemconfig/BasicForm.tsx
+++ b/packages/ui-default/components/problemconfig/BasicForm.tsx
@@ -1,8 +1,8 @@
import React from 'react';
import { useDispatch, useSelector } from 'react-redux';
import i18n from 'vj/utils/i18n';
-import type { RootState } from './reducer/index';
import FileSelectAutoComplete from '../autocomplete/components/FileSelectAutoComplete';
+import type { RootState } from './reducer/index';
export function FormItem({
columns, label, children, helpText = '', disableLabel = false, ...props
diff --git a/packages/ui-default/components/problemconfig/ProblemConfigEditor.tsx b/packages/ui-default/components/problemconfig/ProblemConfigEditor.tsx
index ab8b2955f..555d785f5 100644
--- a/packages/ui-default/components/problemconfig/ProblemConfigEditor.tsx
+++ b/packages/ui-default/components/problemconfig/ProblemConfigEditor.tsx
@@ -1,11 +1,12 @@
-import React from 'react';
-import type { editor } from 'monaco-editor';
-import { connect } from 'react-redux';
-import { load } from 'vj/components/monaco/loader';
-import Editor from 'vj/components/editor';
import { diffLines } from 'diff';
-import yaml from 'js-yaml';
import type { ProblemConfigFile, TestCaseConfig } from 'hydrooj/src/interface';
+import $ from 'jquery';
+import yaml from 'js-yaml';
+import type { editor } from 'monaco-editor';
+import React from 'react';
+import { connect } from 'react-redux';
+import Editor from 'vj/components/editor';
+import { load } from 'vj/components/monaco/loader';
const mapStateToProps = (state) => ({
config: state.config,
diff --git a/packages/ui-default/components/problemconfig/ProblemConfigForm.tsx b/packages/ui-default/components/problemconfig/ProblemConfigForm.tsx
index 5aeb8c490..a1ef91bbe 100644
--- a/packages/ui-default/components/problemconfig/ProblemConfigForm.tsx
+++ b/packages/ui-default/components/problemconfig/ProblemConfigForm.tsx
@@ -1,14 +1,14 @@
+import {
+ Card, InputGroup, Tab, Tabs, Tag,
+} from '@blueprintjs/core';
import React from 'react';
import { useDispatch, useSelector } from 'react-redux';
import i18n from 'vj/utils/i18n';
-import {
- Card, Tab, Tabs, InputGroup, Tag,
-} from '@blueprintjs/core';
-import type { RootState } from './reducer/index';
import CustomSelectAutoComplete from '../autocomplete/components/CustomSelectAutoComplete';
import FileSelectAutoComplete from '../autocomplete/components/FileSelectAutoComplete';
import { FormItem } from './BasicForm';
import ProblemType from './ProblemType';
+import type { RootState } from './reducer/index';
import { TaskConfig } from './SubtaskTable';
function FileIOConfig() {
diff --git a/packages/ui-default/components/problemconfig/ProblemType.tsx b/packages/ui-default/components/problemconfig/ProblemType.tsx
index 3525a6d80..8d2c653b9 100644
--- a/packages/ui-default/components/problemconfig/ProblemType.tsx
+++ b/packages/ui-default/components/problemconfig/ProblemType.tsx
@@ -1,11 +1,11 @@
-import React from 'react';
-import { useDispatch, useSelector } from 'react-redux';
-import i18n from 'vj/utils/i18n';
import {
Card, Switch, Tab, Tabs,
} from '@blueprintjs/core';
-import type { RootState } from './reducer/index';
+import React from 'react';
+import { useDispatch, useSelector } from 'react-redux';
+import i18n from 'vj/utils/i18n';
import { FormItem, ManagedSelect, SingleFileSelect } from './BasicForm';
+import type { RootState } from './reducer/index';
export default function ProblemType() {
const Type = useSelector((state: RootState) => state.config.type);
diff --git a/packages/ui-default/components/problemconfig/SubtaskTable.tsx b/packages/ui-default/components/problemconfig/SubtaskTable.tsx
index 9bc1583c3..89b5b3c78 100644
--- a/packages/ui-default/components/problemconfig/SubtaskTable.tsx
+++ b/packages/ui-default/components/problemconfig/SubtaskTable.tsx
@@ -1,9 +1,9 @@
import { Card, NumericInput, Tag } from '@blueprintjs/core';
-import { pick, isEqual } from 'lodash';
-import React from 'react';
-import { useSelector, useDispatch } from 'react-redux';
+import { parseMemoryMB, parseTimeMS } from '@hydrooj/utils/lib/common';
import { SubtaskConfig } from 'hydrooj/src/interface';
-import { parseTimeMS, parseMemoryMB } from '@hydrooj/utils/lib/common';
+import { isEqual, pick } from 'lodash';
+import React from 'react';
+import { useDispatch, useSelector } from 'react-redux';
import i18n from 'vj/utils/i18n';
import CustomSelectAutoComplete from '../autocomplete/components/CustomSelectAutoComplete';
import { FormItem } from './BasicForm';
diff --git a/packages/ui-default/components/problemconfig/TestCasesTable.tsx b/packages/ui-default/components/problemconfig/TestCasesTable.tsx
index 689f46be9..2731d8414 100644
--- a/packages/ui-default/components/problemconfig/TestCasesTable.tsx
+++ b/packages/ui-default/components/problemconfig/TestCasesTable.tsx
@@ -1,12 +1,12 @@
+import { NumericInput, Tag } from '@blueprintjs/core';
+import { parseMemoryMB, parseTimeMS } from '@hydrooj/utils/lib/common';
+import type { SubtaskConfig } from 'hydrooj/src/interface';
+import { isEqual } from 'lodash';
import React from 'react';
import { useDispatch, useSelector } from 'react-redux';
import i18n from 'vj/utils/i18n';
-import { isEqual } from 'lodash';
-import { Tag, NumericInput } from '@blueprintjs/core';
-import { parseTimeMS, parseMemoryMB } from '@hydrooj/utils/lib/common';
-import type { SubtaskConfig } from 'hydrooj/src/interface';
-import type { RootState } from './reducer/index';
import FileSelectAutoComplete from '../autocomplete/components/FileSelectAutoComplete';
+import type { RootState } from './reducer/index';
const eq = (a: SubtaskConfig, b: SubtaskConfig) => isEqual(a, b);
const eqArr = (a: any[], b: any[]) => isEqual(a, b);
diff --git a/packages/ui-default/components/problemconfig/reducer/config.ts b/packages/ui-default/components/problemconfig/reducer/config.ts
index 711168ca8..d370d9500 100644
--- a/packages/ui-default/components/problemconfig/reducer/config.ts
+++ b/packages/ui-default/components/problemconfig/reducer/config.ts
@@ -1,7 +1,7 @@
-import yaml from 'js-yaml';
-import type { ProblemConfigFile } from 'hydrooj/src/interface';
-import { cloneDeep } from 'lodash';
import { parseMemoryMB, parseTimeMS } from '@hydrooj/utils/lib/common';
+import type { ProblemConfigFile } from 'hydrooj/src/interface';
+import yaml from 'js-yaml';
+import { cloneDeep } from 'lodash';
type State = ProblemConfigFile & { __loaded: boolean };
diff --git a/packages/ui-default/components/react-splitpane/SplitPaneFillOverlayComponent.jsx b/packages/ui-default/components/react-splitpane/SplitPaneFillOverlayComponent.jsx
index 6acc38436..0576694dc 100644
--- a/packages/ui-default/components/react-splitpane/SplitPaneFillOverlayComponent.jsx
+++ b/packages/ui-default/components/react-splitpane/SplitPaneFillOverlayComponent.jsx
@@ -1,5 +1,5 @@
-import PropTypes from 'prop-types';
import classNames from 'classnames';
+import PropTypes from 'prop-types';
export default function SplitPaneFillOverlayComponent(props) {
const {
diff --git a/packages/ui-default/components/react/DomComponent.tsx b/packages/ui-default/components/react/DomComponent.tsx
index d83ca3ec2..065d923af 100644
--- a/packages/ui-default/components/react/DomComponent.tsx
+++ b/packages/ui-default/components/react/DomComponent.tsx
@@ -1,5 +1,6 @@
-import React from 'react';
+import $ from 'jquery';
import { omit } from 'lodash';
+import React from 'react';
const tempDoms = {};
diff --git a/packages/ui-default/components/react/IconComponent.jsx b/packages/ui-default/components/react/IconComponent.jsx
index 46974a9ca..c14ac53ec 100644
--- a/packages/ui-default/components/react/IconComponent.jsx
+++ b/packages/ui-default/components/react/IconComponent.jsx
@@ -1,5 +1,5 @@
-import PropTypes from 'prop-types';
import classNames from 'classnames';
+import PropTypes from 'prop-types';
export default function IconComponent(props) {
const {
diff --git a/packages/ui-default/components/rotator/index.js b/packages/ui-default/components/rotator/index.js
index 0308d16d3..9fa1a7e57 100644
--- a/packages/ui-default/components/rotator/index.js
+++ b/packages/ui-default/components/rotator/index.js
@@ -1,3 +1,4 @@
+import $ from 'jquery';
import _ from 'lodash';
import DOMAttachedObject from 'vj/components/DOMAttachedObject';
import delay from 'vj/utils/delay';
diff --git a/packages/ui-default/components/scratchpad/DataInputComponent.jsx b/packages/ui-default/components/scratchpad/DataInputComponent.jsx
index 28d490138..bd3a580aa 100644
--- a/packages/ui-default/components/scratchpad/DataInputComponent.jsx
+++ b/packages/ui-default/components/scratchpad/DataInputComponent.jsx
@@ -1,5 +1,5 @@
-import PropTypes from 'prop-types';
import classNames from 'classnames';
+import PropTypes from 'prop-types';
export default function DataInputComponent(props) {
const {
diff --git a/packages/ui-default/components/scratchpad/PanelButtonComponent.jsx b/packages/ui-default/components/scratchpad/PanelButtonComponent.jsx
index d9a0149a4..24937954e 100644
--- a/packages/ui-default/components/scratchpad/PanelButtonComponent.jsx
+++ b/packages/ui-default/components/scratchpad/PanelButtonComponent.jsx
@@ -1,5 +1,5 @@
-import PropTypes from 'prop-types';
import classNames from 'classnames';
+import PropTypes from 'prop-types';
export default function PanelButtonComponent(props) {
const {
diff --git a/packages/ui-default/components/scratchpad/PanelComponent.jsx b/packages/ui-default/components/scratchpad/PanelComponent.jsx
index 8a2aaa8dc..88908fe85 100644
--- a/packages/ui-default/components/scratchpad/PanelComponent.jsx
+++ b/packages/ui-default/components/scratchpad/PanelComponent.jsx
@@ -1,6 +1,6 @@
-import React from 'react';
-import PropTypes from 'prop-types';
import classNames from 'classnames';
+import PropTypes from 'prop-types';
+import React from 'react';
import SplitPaneFillOverlay from 'vj/components/react-splitpane/SplitPaneFillOverlayComponent';
export default function PanelComponent(props) {
diff --git a/packages/ui-default/components/scratchpad/ScratchpadPretestContainer.jsx b/packages/ui-default/components/scratchpad/ScratchpadPretestContainer.jsx
index 68ea4d228..b2ef89cf3 100644
--- a/packages/ui-default/components/scratchpad/ScratchpadPretestContainer.jsx
+++ b/packages/ui-default/components/scratchpad/ScratchpadPretestContainer.jsx
@@ -1,11 +1,10 @@
+import AnsiUp from 'ansi_up';
import React from 'react';
import { connect } from 'react-redux';
-import AnsiUp from 'ansi_up';
-
-import i18n from 'vj/utils/i18n';
import Icon from 'vj/components/react/IconComponent';
-import Panel from './PanelComponent';
+import i18n from 'vj/utils/i18n';
import DataInput from './DataInputComponent';
+import Panel from './PanelComponent';
const AU = new AnsiUp();
diff --git a/packages/ui-default/components/scratchpad/ScratchpadRecordsContainer.jsx b/packages/ui-default/components/scratchpad/ScratchpadRecordsContainer.jsx
index 6e892604c..886c6441e 100644
--- a/packages/ui-default/components/scratchpad/ScratchpadRecordsContainer.jsx
+++ b/packages/ui-default/components/scratchpad/ScratchpadRecordsContainer.jsx
@@ -1,8 +1,8 @@
+import classNames from 'classnames';
import React from 'react';
import { connect } from 'react-redux';
-import classNames from 'classnames';
-import i18n from 'vj/utils/i18n';
import Icon from 'vj/components/react/IconComponent';
+import i18n from 'vj/utils/i18n';
import Panel from './PanelComponent';
import ScratchpadRecordsRow from './ScratchpadRecordsRowContainer';
diff --git a/packages/ui-default/components/scratchpad/ScratchpadRecordsRowContainer.jsx b/packages/ui-default/components/scratchpad/ScratchpadRecordsRowContainer.jsx
index 15b6db21b..af5525dcb 100644
--- a/packages/ui-default/components/scratchpad/ScratchpadRecordsRowContainer.jsx
+++ b/packages/ui-default/components/scratchpad/ScratchpadRecordsRowContainer.jsx
@@ -1,15 +1,14 @@
-import React from 'react';
import classNames from 'classnames';
+import _ from 'lodash';
+import moment from 'moment';
+import React from 'react';
import { connect } from 'react-redux';
import TimeAgo from 'timeago-react';
-import moment from 'moment';
-import _ from 'lodash';
-
-import substitute from 'vj/utils/substitute';
-import emulateAnchorClick from 'vj/utils/emulateAnchorClick';
-import { parse as parseMongoId } from 'vj/utils/mongoId';
-import i18n from 'vj/utils/i18n';
import * as recordEnum from 'vj/constant/record';
+import emulateAnchorClick from 'vj/utils/emulateAnchorClick';
+import i18n from 'vj/utils/i18n';
+import { parse as parseMongoId } from 'vj/utils/mongoId';
+import substitute from 'vj/utils/substitute';
const shouldShowDetail = (data) => recordEnum.STATUS_SCRATCHPAD_SHOW_DETAIL_FLAGS[data.status];
diff --git a/packages/ui-default/components/scratchpad/ScratchpadToolbarContainer.jsx b/packages/ui-default/components/scratchpad/ScratchpadToolbarContainer.jsx
index e9c0abc0d..a18dd3d5d 100644
--- a/packages/ui-default/components/scratchpad/ScratchpadToolbarContainer.jsx
+++ b/packages/ui-default/components/scratchpad/ScratchpadToolbarContainer.jsx
@@ -1,16 +1,15 @@
/* eslint-disable react/static-property-placement */
import _ from 'lodash';
-import React from 'react';
import PropTypes from 'prop-types';
+import React from 'react';
import { connect } from 'react-redux';
-
-import i18n from 'vj/utils/i18n';
-import request from 'vj/utils/request';
import Icon from 'vj/components/react/IconComponent';
import getAvailableLangs from 'vj/utils/availableLangs';
+import i18n from 'vj/utils/i18n';
+import request from 'vj/utils/request';
import Toolbar, {
- ToolbarItemComponent as ToolbarItem,
ToolbarButtonComponent as ToolbarButton,
+ ToolbarItemComponent as ToolbarItem,
ToolbarSplitComponent as ToolbarSplit,
} from './ToolbarComponent';
diff --git a/packages/ui-default/components/scratchpad/ToolbarComponent.jsx b/packages/ui-default/components/scratchpad/ToolbarComponent.jsx
index 39467a1ce..35b49b67f 100644
--- a/packages/ui-default/components/scratchpad/ToolbarComponent.jsx
+++ b/packages/ui-default/components/scratchpad/ToolbarComponent.jsx
@@ -1,5 +1,5 @@
-import PropTypes from 'prop-types';
import classNames from 'classnames';
+import PropTypes from 'prop-types';
export default function ToolbarComponent(props) {
const {
diff --git a/packages/ui-default/components/scratchpad/index.jsx b/packages/ui-default/components/scratchpad/index.jsx
index 918e030b7..b2f7cb5a2 100644
--- a/packages/ui-default/components/scratchpad/index.jsx
+++ b/packages/ui-default/components/scratchpad/index.jsx
@@ -1,14 +1,15 @@
-import React from 'react';
-import SplitPane from 'react-split-pane';
-import { useDispatch, useSelector } from 'react-redux';
-import _ from 'lodash';
-import SplitPaneFillOverlay from 'vj/components/react-splitpane/SplitPaneFillOverlayComponent';
import ProblemIcon from '@vscode/codicons/src/icons/file.svg?react';
+import $ from 'jquery';
+import _ from 'lodash';
+import React from 'react';
+import { useDispatch, useSelector } from 'react-redux';
+import SplitPane from 'react-split-pane';
import Dom from 'vj/components/react/DomComponent';
-import ScratchpadToolbar from './ScratchpadToolbarContainer';
+import SplitPaneFillOverlay from 'vj/components/react-splitpane/SplitPaneFillOverlayComponent';
import ScratchpadEditor from './ScratchpadEditorContainer';
import ScratchpadPretest from './ScratchpadPretestContainer';
import ScratchpadRecords from './ScratchpadRecordsContainer';
+import ScratchpadToolbar from './ScratchpadToolbarContainer';
function buildNestedPane([a, ...panes], mode = 'horizontal') {
const elements = [
diff --git a/packages/ui-default/components/scratchpad/reducers/index.ts b/packages/ui-default/components/scratchpad/reducers/index.ts
index 363c885cd..ea6b984f2 100644
--- a/packages/ui-default/components/scratchpad/reducers/index.ts
+++ b/packages/ui-default/components/scratchpad/reducers/index.ts
@@ -1,9 +1,9 @@
import { combineReducers } from 'redux';
-import ui from './ui';
import editor from './editor';
import pretest from './pretest';
import records from './records';
import state from './state';
+import ui from './ui';
const reducer = combineReducers({
ui,
diff --git a/packages/ui-default/components/signin/signInDialog.page.js b/packages/ui-default/components/signin/signInDialog.page.js
index 3b8bc1c87..36ddbdc5f 100644
--- a/packages/ui-default/components/signin/signInDialog.page.js
+++ b/packages/ui-default/components/signin/signInDialog.page.js
@@ -1,9 +1,10 @@
-import { AutoloadPage } from 'vj/misc/Page';
+import $ from 'jquery';
+import responsiveCutoff from 'vj/breakpoints.json';
import DomDialog from 'vj/components/dialog/DomDialog';
import { InfoDialog } from 'vj/components/dialog/index';
-import responsiveCutoff from 'vj/breakpoints.json';
-import { isBelow } from 'vj/utils/mediaQuery';
+import { AutoloadPage } from 'vj/misc/Page';
import i18n from 'vj/utils/i18n';
+import { isBelow } from 'vj/utils/mediaQuery';
import tpl from 'vj/utils/tpl';
const signinDialogPage = new AutoloadPage('signinDialogPage', null, () => {
diff --git a/packages/ui-default/components/smoothscroll/smoothscroll.page.js b/packages/ui-default/components/smoothscroll/smoothscroll.page.js
index 67a0e3fa2..0b086ce66 100644
--- a/packages/ui-default/components/smoothscroll/smoothscroll.page.js
+++ b/packages/ui-default/components/smoothscroll/smoothscroll.page.js
@@ -1,4 +1,6 @@
import 'jquery.easing';
+
+import $ from 'jquery';
import { AutoloadPage } from 'vj/misc/Page';
const smoothScrollPage = new AutoloadPage('smoothScrollPage', null, () => {
diff --git a/packages/ui-default/components/star/star.page.js b/packages/ui-default/components/star/star.page.js
index ddf600035..fbb426cd3 100644
--- a/packages/ui-default/components/star/star.page.js
+++ b/packages/ui-default/components/star/star.page.js
@@ -1,3 +1,4 @@
+import $ from 'jquery';
import { AutoloadPage } from 'vj/misc/Page';
import request from 'vj/utils/request';
diff --git a/packages/ui-default/components/sticky/sticky.page.js b/packages/ui-default/components/sticky/sticky.page.js
index 1c560e954..ba41385c2 100644
--- a/packages/ui-default/components/sticky/sticky.page.js
+++ b/packages/ui-default/components/sticky/sticky.page.js
@@ -1,8 +1,10 @@
import 'sticky-kit/dist/sticky-kit';
+
+import $ from 'jquery';
import _ from 'lodash';
-import { isBelow, isAbove } from 'vj/utils/mediaQuery';
-import { AutoloadPage } from 'vj/misc/Page';
import responsiveCutoff from 'vj/breakpoints.json';
+import { AutoloadPage } from 'vj/misc/Page';
+import { isAbove, isBelow } from 'vj/utils/mediaQuery';
const navHeight = isBelow(responsiveCutoff.mobile)
? 0
diff --git a/packages/ui-default/components/tab/Tab.js b/packages/ui-default/components/tab/Tab.js
index b6c9a79d6..64ab314cc 100644
--- a/packages/ui-default/components/tab/Tab.js
+++ b/packages/ui-default/components/tab/Tab.js
@@ -1,3 +1,4 @@
+import $ from 'jquery';
import _ from 'lodash';
import DOMAttachedObject from 'vj/components/DOMAttachedObject';
diff --git a/packages/ui-default/components/table/StyledTable.js b/packages/ui-default/components/table/StyledTable.js
index 31101553d..facd19e13 100644
--- a/packages/ui-default/components/table/StyledTable.js
+++ b/packages/ui-default/components/table/StyledTable.js
@@ -1,8 +1,10 @@
import 'sticky-kit/dist/sticky-kit';
+
+import $ from 'jquery';
import _ from 'lodash';
+import responsiveCutoff from 'vj/breakpoints.json';
import DOMAttachedObject from 'vj/components/DOMAttachedObject';
import { isBelow } from 'vj/utils/mediaQuery';
-import responsiveCutoff from 'vj/breakpoints.json';
const navHeight = isBelow(responsiveCutoff.mobile)
? 0
diff --git a/packages/ui-default/components/time/time.page.js b/packages/ui-default/components/time/time.page.js
index fe5dfcb13..47b44e92f 100644
--- a/packages/ui-default/components/time/time.page.js
+++ b/packages/ui-default/components/time/time.page.js
@@ -1,3 +1,4 @@
+import $ from 'jquery';
import * as timeago from 'timeago.js';
import { AutoloadPage } from 'vj/misc/Page';
import i18n from 'vj/utils/i18n';
diff --git a/packages/ui-default/components/tooltip/Tooltip.js b/packages/ui-default/components/tooltip/Tooltip.js
index 3562f998a..09fc4e72c 100644
--- a/packages/ui-default/components/tooltip/Tooltip.js
+++ b/packages/ui-default/components/tooltip/Tooltip.js
@@ -1,5 +1,5 @@
-import Drop from 'tether-drop';
import _ from 'lodash';
+import Drop from 'tether-drop';
import DOMAttachedObject from 'vj/components/DOMAttachedObject';
export default class Tooltip extends DOMAttachedObject {
diff --git a/packages/ui-default/components/tooltip/tooltip.page.js b/packages/ui-default/components/tooltip/tooltip.page.js
index f6fbe5c0b..c6c3eaeb0 100644
--- a/packages/ui-default/components/tooltip/tooltip.page.js
+++ b/packages/ui-default/components/tooltip/tooltip.page.js
@@ -1,3 +1,4 @@
+import $ from 'jquery';
import { AutoloadPage } from 'vj/misc/Page';
import Tooltip from './Tooltip';
diff --git a/packages/ui-default/components/vote/vote.page.js b/packages/ui-default/components/vote/vote.page.js
index 9051c2e12..ddda0ca7a 100644
--- a/packages/ui-default/components/vote/vote.page.js
+++ b/packages/ui-default/components/vote/vote.page.js
@@ -1,3 +1,4 @@
+import $ from 'jquery';
import Rotator from 'vj/components/rotator';
import { AutoloadPage } from 'vj/misc/Page';
import request from 'vj/utils/request';
diff --git a/packages/ui-default/components/zipDownloader/index.js b/packages/ui-default/components/zipDownloader/index.js
index eb3c3e183..817e8d7b7 100644
--- a/packages/ui-default/components/zipDownloader/index.js
+++ b/packages/ui-default/components/zipDownloader/index.js
@@ -1,12 +1,12 @@
import { dump } from 'js-yaml';
+import PQueue from 'p-queue';
import streamsaver from 'streamsaver';
-import { createZipStream } from 'vj/utils/zip';
-import pipeStream from 'vj/utils/pipeStream';
-import i18n from 'vj/utils/i18n';
-import request from 'vj/utils/request';
-import PQueue from 'p-queue/dist/index';
import Notification from 'vj/components/notification';
import api, { gql } from 'vj/utils/api';
+import i18n from 'vj/utils/i18n';
+import pipeStream from 'vj/utils/pipeStream';
+import request from 'vj/utils/request';
+import { createZipStream } from 'vj/utils/zip';
let isBeforeUnloadTriggeredByLibrary = !window.isSecureContext;
function onBeforeUnload(e) {
diff --git a/packages/ui-default/entry.js b/packages/ui-default/entry.js
index a3f176dc0..c9645d492 100644
--- a/packages/ui-default/entry.js
+++ b/packages/ui-default/entry.js
@@ -1,3 +1,4 @@
+import $ from 'jquery';
import * as bus from './bus';
window.Hydro = {
diff --git a/packages/ui-default/handler.ts b/packages/ui-default/handler.ts
index fb4a728af..fa59d46eb 100644
--- a/packages/ui-default/handler.ts
+++ b/packages/ui-default/handler.ts
@@ -1,19 +1,19 @@
/* eslint-disable no-return-await */
/* eslint-disable camelcase */
import crypto from 'crypto';
-import { join } from 'path';
-import { ObjectID } from 'mongodb';
-import * as bus from 'hydrooj/src/service/bus';
-import { Route, Handler } from 'hydrooj/src/service/server';
+import esbuild from 'esbuild';
import { PERM, PRIV } from 'hydrooj/src/model/builtin';
-import * as system from 'hydrooj/src/model/system';
-import user from 'hydrooj/src/model/user';
import * as contest from 'hydrooj/src/model/contest';
import problem from 'hydrooj/src/model/problem';
import * as setting from 'hydrooj/src/model/setting';
-import esbuild from 'esbuild';
-import { tmpdir } from 'os';
+import * as system from 'hydrooj/src/model/system';
+import user from 'hydrooj/src/model/user';
+import * as bus from 'hydrooj/src/service/bus';
import { UiContextBase } from 'hydrooj/src/service/layers/base';
+import { Handler, Route } from 'hydrooj/src/service/server';
+import { ObjectID } from 'mongodb';
+import { tmpdir } from 'os';
+import { join } from 'path';
import markdown from './backendlib/markdown';
declare module 'hydrooj/src/interface' {
diff --git a/packages/ui-default/hydro.ts b/packages/ui-default/hydro.ts
index 20d45eaae..8f47764df 100644
--- a/packages/ui-default/hydro.ts
+++ b/packages/ui-default/hydro.ts
@@ -1,5 +1,7 @@
import './modules';
import 'jquery.transit';
+
+import $ from 'jquery';
import _ from 'lodash';
import Notification from 'vj/components/notification';
import PageLoader from 'vj/misc/PageLoader';
diff --git a/packages/ui-default/misc/icons/template/webicon.styl b/packages/ui-default/misc/icons/template/webicon.styl
index 556dead8d..54504cc16 100644
--- a/packages/ui-default/misc/icons/template/webicon.styl
+++ b/packages/ui-default/misc/icons/template/webicon.styl
@@ -9,7 +9,7 @@
font-style: normal
.icon
- font-family: $icon-font-name, $primary-font-family !important
+ font-family: $icon-font-name !important
speak: none
font-style: normal
font-weight: normal
diff --git a/packages/ui-default/modules.js b/packages/ui-default/modules.js
index 3269aeaf7..633abe958 100644
--- a/packages/ui-default/modules.js
+++ b/packages/ui-default/modules.js
@@ -1,9 +1,3 @@
-import $ from 'jquery';
-import _ from 'lodash';
-import React from 'react';
-import ReactDOM from 'react-dom';
-import * as redux from 'react-redux';
-
import './utils/delay';
import './utils/emulateAnchorClick';
import './utils/i18n';
@@ -19,13 +13,18 @@ import './utils/substitute';
import './utils/tpl';
import './utils/zIndexManager';
import './utils/zip';
-
import './components/autocomplete';
import './components/dialog';
import './components/notification';
import './components/nprogress';
import './components/monaco/loader';
+import $ from 'jquery';
+import _ from 'lodash';
+import React from 'react';
+import ReactDOM from 'react-dom';
+import * as redux from 'react-redux';
+
const modules = {
_, $, React, redux, ReactDOM,
};
diff --git a/packages/ui-default/package.json b/packages/ui-default/package.json
index 38101b8de..cdc151933 100644
--- a/packages/ui-default/package.json
+++ b/packages/ui-default/package.json
@@ -1,6 +1,6 @@
{
"name": "@hydrooj/ui-default",
- "version": "4.38.34",
+ "version": "4.39.0",
"author": "undefined ",
"license": "AGPL-3.0",
"main": "hydro.js",
@@ -20,7 +20,7 @@
"@fontsource/source-code-pro": "^4.5.10",
"@fontsource/ubuntu-mono": "^4.5.10",
"@hydrooj/utils": "workspace:*",
- "@svgr/webpack": "^5",
+ "@svgr/webpack": "^6.3.1",
"@types/gulp-if": "^0.0.34",
"@types/jquery": "^3.5.14",
"@types/json-schema": "^7.0.11",
@@ -30,15 +30,15 @@
"@types/qrcode": "^1.4.2",
"@types/react-dom": "^18.0.6",
"@types/redux-logger": "^3.0.9",
- "autoprefixer": "^9.8.8",
+ "autoprefixer": "^10.4.8",
"browser-update": "^3.3.38",
"chalk": "^5.0.1",
"chunk-progress-webpack-plugin": "^2.0.1",
"classnames": "^2.3.1",
"clean-webpack-plugin": "^4.0.0",
"clipboard": "^2.0.11",
- "copy-webpack-plugin": "^6.4.1",
- "css-loader": "^4.3.0",
+ "copy-webpack-plugin": "^11.0.0",
+ "css-loader": "^6.7.1",
"diff": "^5.1.0",
"diff-dom": "^4.2.3",
"echarts": "^5.3.3",
@@ -46,7 +46,6 @@
"emojis-list": "2.1.0",
"esbuild-loader": "^2.19.0",
"fancy-log": "^2.0.0",
- "file-loader": "^6.2.0",
"friendly-errors-webpack-plugin": "^1.7.0",
"graphiql": "1.8.9",
"gulp": "^4.0.2",
@@ -71,14 +70,13 @@
"normalize.css": "^8.0.1",
"nprogress": "^0.2.0",
"pickadate": "^3.6.4",
- "plugin-error": "^1.0.1",
- "postcss-loader": "^3.0.0",
+ "plugin-error": "^2.0.0",
+ "postcss-loader": "^7.0.1",
"prism-themes": "^1.9.0",
"prismjs": "^1.28.0",
"prop-types": "^15.8.1",
"qrcode": "^1.5.1",
"queue-microtask": "^1.2.3",
- "raw-loader": "^4.0.2",
"react": "^18.2.0",
"react-dnd": "^16.0.1",
"react-dnd-html5-backend": "^16.0.1",
@@ -94,10 +92,10 @@
"slideout": "^1.0.1",
"speed-measure-webpack-plugin": "^1.5.0",
"sticky-kit": "^1.1.3",
- "style-loader": "^2.0.0",
+ "style-loader": "^3.3.1",
"stylus": "^0.58.1",
- "stylus-loader": "^3.0.2",
- "tether": "^1.4.7",
+ "stylus-loader": "^7.0.0",
+ "tether": "1.4.7",
"tether-drop": "^1.4.2",
"thirty-two": "^1.0.2",
"through2": "^4.0.2",
@@ -106,9 +104,9 @@
"vditor": "^3.8.15",
"vinyl-buffer": "^1.0.1",
"web-streams-polyfill": "^3.2.1",
- "webpack": "^4.46.0",
+ "webpack": "^5.74.0",
"webpack-bundle-analyzer": "^4.5.0",
- "webpack-dev-server": "^3.11.3",
+ "webpack-dev-server": "^4.9.3",
"webpackbar": "^5.0.2"
},
"dependencies": {
diff --git a/packages/ui-default/pages/api.page.tsx b/packages/ui-default/pages/api.page.tsx
index 06732dd2e..f6faf465c 100644
--- a/packages/ui-default/pages/api.page.tsx
+++ b/packages/ui-default/pages/api.page.tsx
@@ -1,9 +1,10 @@
/* eslint-disable react/function-component-definition */
-import { NamedPage } from 'vj/misc/Page';
-import request from 'vj/utils/request';
+import 'graphiql/graphiql.css';
+
import React from 'react';
import ReactDOM from 'react-dom/client';
-import 'graphiql/graphiql.css';
+import { NamedPage } from 'vj/misc/Page';
+import request from 'vj/utils/request';
const Logo = () => Hydro API Console ;
const defaultQuery = `\
diff --git a/packages/ui-default/pages/contest_edit.page.ts b/packages/ui-default/pages/contest_edit.page.ts
index 6a544412b..0efd92faf 100644
--- a/packages/ui-default/pages/contest_edit.page.ts
+++ b/packages/ui-default/pages/contest_edit.page.ts
@@ -1,9 +1,10 @@
-import { NamedPage } from 'vj/misc/Page';
-import { ConfirmDialog } from 'vj/components/dialog';
+import $ from 'jquery';
import ProblemSelectAutoComplete from 'vj/components/autocomplete/ProblemSelectAutoComplete';
-import tpl from 'vj/utils/tpl';
+import { ConfirmDialog } from 'vj/components/dialog';
+import { NamedPage } from 'vj/misc/Page';
import i18n from 'vj/utils/i18n';
import request from 'vj/utils/request';
+import tpl from 'vj/utils/tpl';
const page = new NamedPage(['contest_edit', 'contest_create', 'homework_create', 'homework_edit'], (pagename) => {
ProblemSelectAutoComplete.getOrConstruct($('[name="pids"]'), { multi: true, clearDefaultValue: false });
diff --git a/packages/ui-default/pages/contest_main.page.ts b/packages/ui-default/pages/contest_main.page.ts
index 8bfb602b2..79d26397b 100644
--- a/packages/ui-default/pages/contest_main.page.ts
+++ b/packages/ui-default/pages/contest_main.page.ts
@@ -1,3 +1,4 @@
+import $ from 'jquery';
import { NamedPage } from 'vj/misc/Page';
const page = new NamedPage('contest_main', () => {
diff --git a/packages/ui-default/pages/domain_group.page.ts b/packages/ui-default/pages/domain_group.page.ts
index a990104c8..9f58cc271 100644
--- a/packages/ui-default/pages/domain_group.page.ts
+++ b/packages/ui-default/pages/domain_group.page.ts
@@ -1,14 +1,13 @@
+import $ from 'jquery';
import _ from 'lodash';
-
-import { NamedPage } from 'vj/misc/Page';
+import UserSelectAutoComplete from 'vj/components/autocomplete/UserSelectAutoComplete';
+import { ActionDialog, ConfirmDialog } from 'vj/components/dialog';
import Notification from 'vj/components/notification';
-import { ConfirmDialog, ActionDialog } from 'vj/components/dialog';
-
-import tpl from 'vj/utils/tpl';
+import { NamedPage } from 'vj/misc/Page';
+import api, { gql } from 'vj/utils/api';
import delay from 'vj/utils/delay';
import i18n from 'vj/utils/i18n';
-import UserSelectAutoComplete from 'vj/components/autocomplete/UserSelectAutoComplete';
-import api, { gql } from 'vj/utils/api';
+import tpl from 'vj/utils/tpl';
function update(name: string, uids: number[]) {
return api(gql`
diff --git a/packages/ui-default/pages/domain_join_applications.page.ts b/packages/ui-default/pages/domain_join_applications.page.ts
index bb4a6528e..75177b2f9 100644
--- a/packages/ui-default/pages/domain_join_applications.page.ts
+++ b/packages/ui-default/pages/domain_join_applications.page.ts
@@ -1,5 +1,6 @@
-import { NamedPage } from 'vj/misc/Page';
+import $ from 'jquery';
import * as domainEnum from 'vj/constant/domain';
+import { NamedPage } from 'vj/misc/Page';
const page = new NamedPage('domain_join_applications', () => {
const $role = $('[name="role"]');
diff --git a/packages/ui-default/pages/domain_role.page.js b/packages/ui-default/pages/domain_role.page.js
index 6398988ef..2f2a7d6de 100644
--- a/packages/ui-default/pages/domain_role.page.js
+++ b/packages/ui-default/pages/domain_role.page.js
@@ -1,13 +1,12 @@
+import $ from 'jquery';
import _ from 'lodash';
-
-import { NamedPage } from 'vj/misc/Page';
+import { ActionDialog, ConfirmDialog } from 'vj/components/dialog';
import Notification from 'vj/components/notification';
-import { ConfirmDialog, ActionDialog } from 'vj/components/dialog';
-
-import request from 'vj/utils/request';
-import tpl from 'vj/utils/tpl';
+import { NamedPage } from 'vj/misc/Page';
import delay from 'vj/utils/delay';
import i18n from 'vj/utils/i18n';
+import request from 'vj/utils/request';
+import tpl from 'vj/utils/tpl';
const page = new NamedPage('domain_role', () => {
const createRoleDialog = new ActionDialog({
diff --git a/packages/ui-default/pages/domain_user.page.js b/packages/ui-default/pages/domain_user.page.js
index 472cbba9f..d4dad3d87 100644
--- a/packages/ui-default/pages/domain_user.page.js
+++ b/packages/ui-default/pages/domain_user.page.js
@@ -1,14 +1,13 @@
+import $ from 'jquery';
import _ from 'lodash';
-
-import { NamedPage } from 'vj/misc/Page';
-import Notification from 'vj/components/notification';
-import { ConfirmDialog, ActionDialog } from 'vj/components/dialog';
import UserSelectAutoComplete from 'vj/components/autocomplete/UserSelectAutoComplete';
-
-import request from 'vj/utils/request';
-import tpl from 'vj/utils/tpl';
+import { ActionDialog, ConfirmDialog } from 'vj/components/dialog';
+import Notification from 'vj/components/notification';
+import { NamedPage } from 'vj/misc/Page';
import delay from 'vj/utils/delay';
import i18n from 'vj/utils/i18n';
+import request from 'vj/utils/request';
+import tpl from 'vj/utils/tpl';
const page = new NamedPage('domain_user', () => {
const addUserSelector = UserSelectAutoComplete.getOrConstruct($('.dialog__body--add-user [name="user"]'));
diff --git a/packages/ui-default/pages/files.page.js b/packages/ui-default/pages/files.page.js
index 740d55d66..67140ab7c 100644
--- a/packages/ui-default/pages/files.page.js
+++ b/packages/ui-default/pages/files.page.js
@@ -1,12 +1,13 @@
-import _ from 'lodash';
import Clipboard from 'clipboard';
-import { NamedPage } from 'vj/misc/Page';
-import Notification from 'vj/components/notification';
+import $ from 'jquery';
+import _ from 'lodash';
import { ConfirmDialog, Dialog } from 'vj/components/dialog/index';
-import request from 'vj/utils/request';
-import pjax from 'vj/utils/pjax';
-import tpl from 'vj/utils/tpl';
+import Notification from 'vj/components/notification';
+import { NamedPage } from 'vj/misc/Page';
import i18n from 'vj/utils/i18n';
+import pjax from 'vj/utils/pjax';
+import request from 'vj/utils/request';
+import tpl from 'vj/utils/tpl';
function onBeforeUnload(e) {
e.returnValue = '';
diff --git a/packages/ui-default/pages/home_messages.page.jsx b/packages/ui-default/pages/home_messages.page.jsx
index d6b2258f4..fad56c913 100644
--- a/packages/ui-default/pages/home_messages.page.jsx
+++ b/packages/ui-default/pages/home_messages.page.jsx
@@ -1,12 +1,13 @@
-import { NamedPage } from 'vj/misc/Page';
+import $ from 'jquery';
import React from 'react';
import { createRoot } from 'react-dom/client';
+import UserSelectAutoComplete from 'vj/components/autocomplete/UserSelectAutoComplete';
+import { ActionDialog } from 'vj/components/dialog';
+import VjNotification from 'vj/components/notification';
+import { NamedPage } from 'vj/misc/Page';
import api, { gql } from 'vj/utils/api';
import loadReactRedux from 'vj/utils/loadReactRedux';
import parseQueryString from 'vj/utils/parseQueryString';
-import VjNotification from 'vj/components/notification';
-import { ActionDialog } from 'vj/components/dialog';
-import UserSelectAutoComplete from 'vj/components/autocomplete/UserSelectAutoComplete';
const page = new NamedPage('home_messages', () => {
let reduxStore;
diff --git a/packages/ui-default/pages/home_preference.page.jsx b/packages/ui-default/pages/home_preference.page.jsx
index 16adcc01d..0fb57776d 100644
--- a/packages/ui-default/pages/home_preference.page.jsx
+++ b/packages/ui-default/pages/home_preference.page.jsx
@@ -1,9 +1,10 @@
+import $ from 'jquery';
+import { renderLanguageSelect } from 'vj/components/languageselect';
import { NamedPage } from 'vj/misc/Page';
+import getAvailableLangs from 'vj/utils/availableLangs';
+import delay from 'vj/utils/delay';
import i18n from 'vj/utils/i18n';
import tpl from 'vj/utils/tpl';
-import getAvailableLangs from 'vj/utils/availableLangs';
-import { renderLanguageSelect } from 'vj/components/languageselect';
-import delay from 'vj/utils/delay';
async function initCodeLangHelper() {
const $el = $(tpl``);
diff --git a/packages/ui-default/pages/home_security.page.ts b/packages/ui-default/pages/home_security.page.ts
index a3bc54339..7837bc5ac 100644
--- a/packages/ui-default/pages/home_security.page.ts
+++ b/packages/ui-default/pages/home_security.page.ts
@@ -1,12 +1,13 @@
-import { NamedPage } from 'vj/misc/Page';
+import $ from 'jquery';
import QRCode from 'qrcode';
import b32 from 'thirty-two';
-import Notification from 'vj/components/notification';
-import i18n from 'vj/utils/i18n';
-import tpl from 'vj/utils/tpl';
import { ActionDialog } from 'vj/components/dialog';
+import Notification from 'vj/components/notification';
+import { NamedPage } from 'vj/misc/Page';
import api, { gql } from 'vj/utils/api';
import delay from 'vj/utils/delay';
+import i18n from 'vj/utils/i18n';
+import tpl from 'vj/utils/tpl';
export default new NamedPage('home_security', () => {
$(document).on('click', '[name="tfa_enable"]', async () => {
diff --git a/packages/ui-default/pages/homework_main.page.js b/packages/ui-default/pages/homework_main.page.js
index cad2ef490..1ee7d7636 100644
--- a/packages/ui-default/pages/homework_main.page.js
+++ b/packages/ui-default/pages/homework_main.page.js
@@ -1,3 +1,4 @@
+import $ from 'jquery';
import { NamedPage } from 'vj/misc/Page';
import i18n from 'vj/utils/i18n';
import { parse as parseMongoId } from 'vj/utils/mongoId';
diff --git a/packages/ui-default/pages/manage_dashboard.page.js b/packages/ui-default/pages/manage_dashboard.page.js
index 9186a1ab0..aff9977c3 100644
--- a/packages/ui-default/pages/manage_dashboard.page.js
+++ b/packages/ui-default/pages/manage_dashboard.page.js
@@ -1,3 +1,4 @@
+import $ from 'jquery';
import { NamedPage } from 'vj/misc/Page';
const page = new NamedPage('manage_dashboard', async () => {
diff --git a/packages/ui-default/pages/manage_script.page.js b/packages/ui-default/pages/manage_script.page.js
index 095817e01..a36ef089b 100644
--- a/packages/ui-default/pages/manage_script.page.js
+++ b/packages/ui-default/pages/manage_script.page.js
@@ -1,7 +1,7 @@
-import { NamedPage } from 'vj/misc/Page';
-import Notification from 'vj/components/notification';
+import $ from 'jquery';
import { ActionDialog } from 'vj/components/dialog';
-
+import Notification from 'vj/components/notification';
+import { NamedPage } from 'vj/misc/Page';
import request from 'vj/utils/request';
const page = new NamedPage('manage_script', () => {
diff --git a/packages/ui-default/pages/manage_user_import.page.js b/packages/ui-default/pages/manage_user_import.page.js
index b73492481..38148f520 100644
--- a/packages/ui-default/pages/manage_user_import.page.js
+++ b/packages/ui-default/pages/manage_user_import.page.js
@@ -1,8 +1,9 @@
-import { NamedPage } from 'vj/misc/Page';
+import $ from 'jquery';
import Notification from 'vj/components/notification';
+import { NamedPage } from 'vj/misc/Page';
+import delay from 'vj/utils/delay';
import i18n from 'vj/utils/i18n';
import request from 'vj/utils/request';
-import delay from 'vj/utils/delay';
const page = new NamedPage('manage_user_import', () => {
async function post(draft) {
diff --git a/packages/ui-default/pages/problem_config.page.tsx b/packages/ui-default/pages/problem_config.page.tsx
index f73dbad86..ee8ced08d 100644
--- a/packages/ui-default/pages/problem_config.page.tsx
+++ b/packages/ui-default/pages/problem_config.page.tsx
@@ -1,17 +1,18 @@
-import { NamedPage } from 'vj/misc/Page';
-import request from 'vj/utils/request';
+import { normalizeSubtasks, readSubtasksFromFiles, size } from '@hydrooj/utils/lib/common';
+import { SubtaskType } from 'hydrooj/src/interface';
+import $ from 'jquery';
+import yaml from 'js-yaml';
import React from 'react';
import { createRoot } from 'react-dom/client';
-import loadReactRedux from 'vj/utils/loadReactRedux';
-import i18n from 'vj/utils/i18n';
-import yaml from 'js-yaml';
-import Notification from 'vj/components/notification';
import Dialog, { ConfirmDialog } from 'vj/components/dialog/index';
-import download from 'vj/components/zipDownloader';
-import { size, readSubtasksFromFiles, normalizeSubtasks } from '@hydrooj/utils/lib/common';
-import tpl from 'vj/utils/tpl';
-import { SubtaskType } from 'hydrooj/src/interface';
+import Notification from 'vj/components/notification';
import { configYamlFormat } from 'vj/components/problemconfig/ProblemConfigEditor';
+import download from 'vj/components/zipDownloader';
+import { NamedPage } from 'vj/misc/Page';
+import i18n from 'vj/utils/i18n';
+import loadReactRedux from 'vj/utils/loadReactRedux';
+import request from 'vj/utils/request';
+import tpl from 'vj/utils/tpl';
function onBeforeUnload(e) {
e.returnValue = '';
diff --git a/packages/ui-default/pages/problem_detail.page.jsx b/packages/ui-default/pages/problem_detail.page.jsx
index 2aa18d4ee..d7439a0d6 100644
--- a/packages/ui-default/pages/problem_detail.page.jsx
+++ b/packages/ui-default/pages/problem_detail.page.jsx
@@ -1,15 +1,16 @@
-import yaml from 'js-yaml';
-import { createRoot } from 'react-dom/client';
-import React from 'react';
import { getScoreColor } from '@hydrooj/utils/lib/status';
-import { NamedPage } from 'vj/misc/Page';
+import $ from 'jquery';
+import yaml from 'js-yaml';
+import React from 'react';
+import { createRoot } from 'react-dom/client';
import { downloadProblemSet } from 'vj/components/zipDownloader';
-import loadReactRedux from 'vj/utils/loadReactRedux';
+import { NamedPage } from 'vj/misc/Page';
import delay from 'vj/utils/delay';
+import i18n from 'vj/utils/i18n';
+import loadReactRedux from 'vj/utils/loadReactRedux';
import pjax from 'vj/utils/pjax';
import request from 'vj/utils/request';
import tpl from 'vj/utils/tpl';
-import i18n from 'vj/utils/i18n';
class ProblemPageExtender {
constructor() {
diff --git a/packages/ui-default/pages/problem_edit.page.js b/packages/ui-default/pages/problem_edit.page.js
index c041b5880..f3bacd479 100644
--- a/packages/ui-default/pages/problem_edit.page.js
+++ b/packages/ui-default/pages/problem_edit.page.js
@@ -1,15 +1,16 @@
+import { size } from '@hydrooj/utils/lib/common';
+import $ from 'jquery';
import _ from 'lodash';
-import { NamedPage } from 'vj/misc/Page';
-import request from 'vj/utils/request';
-import tpl from 'vj/utils/tpl';
-import i18n from 'vj/utils/i18n';
import Dialog, { ConfirmDialog } from 'vj/components/dialog';
import Dropdown from 'vj/components/dropdown/Dropdown';
import Editor from 'vj/components/editor/index';
import Notification from 'vj/components/notification';
-import { slideDown, slideUp } from 'vj/utils/slide';
import download from 'vj/components/zipDownloader';
-import { size } from '@hydrooj/utils/lib/common';
+import { NamedPage } from 'vj/misc/Page';
+import i18n from 'vj/utils/i18n';
+import request from 'vj/utils/request';
+import { slideDown, slideUp } from 'vj/utils/slide';
+import tpl from 'vj/utils/tpl';
const categories = {};
const dirtyCategories = [];
diff --git a/packages/ui-default/pages/problem_files.page.js b/packages/ui-default/pages/problem_files.page.js
index 1f633665f..c27cac623 100644
--- a/packages/ui-default/pages/problem_files.page.js
+++ b/packages/ui-default/pages/problem_files.page.js
@@ -1,15 +1,17 @@
+import $ from 'jquery';
import _ from 'lodash';
-import { NamedPage } from 'vj/misc/Page';
-import Notification from 'vj/components/notification';
import {
- ConfirmDialog, ActionDialog, InfoDialog, Dialog,
+ ActionDialog, ConfirmDialog, Dialog,
+ InfoDialog,
} from 'vj/components/dialog/index';
-import download from 'vj/components/zipDownloader';
import createHint from 'vj/components/hint';
-import request from 'vj/utils/request';
-import pjax from 'vj/utils/pjax';
-import tpl from 'vj/utils/tpl';
+import Notification from 'vj/components/notification';
+import download from 'vj/components/zipDownloader';
+import { NamedPage } from 'vj/misc/Page';
import i18n from 'vj/utils/i18n';
+import pjax from 'vj/utils/pjax';
+import request from 'vj/utils/request';
+import tpl from 'vj/utils/tpl';
async function downloadProblemFilesAsArchive(type, files) {
const { links, pdoc } = await request.post('', { operation: 'get_links', files, type });
diff --git a/packages/ui-default/pages/problem_main.page.js b/packages/ui-default/pages/problem_main.page.js
index 0620ec4f2..446bce2fa 100644
--- a/packages/ui-default/pages/problem_main.page.js
+++ b/packages/ui-default/pages/problem_main.page.js
@@ -1,16 +1,16 @@
-import _ from 'lodash';
import $ from 'jquery';
-import { NamedPage } from 'vj/misc/Page';
-import Notification from 'vj/components/notification';
+import _ from 'lodash';
import { ActionDialog, ConfirmDialog } from 'vj/components/dialog';
import Dropdown from 'vj/components/dropdown/Dropdown';
import createHint from 'vj/components/hint';
+import Notification from 'vj/components/notification';
import { downloadProblemSet } from 'vj/components/zipDownloader';
+import { NamedPage } from 'vj/misc/Page';
+import delay from 'vj/utils/delay';
+import i18n from 'vj/utils/i18n';
import pjax from 'vj/utils/pjax';
import request from 'vj/utils/request';
import tpl from 'vj/utils/tpl';
-import delay from 'vj/utils/delay';
-import i18n from 'vj/utils/i18n';
const categories = {};
const dirtyCategories = [];
diff --git a/packages/ui-default/pages/problem_sidebar.page.ts b/packages/ui-default/pages/problem_sidebar.page.ts
index e92d54ca7..c5f2e2a33 100644
--- a/packages/ui-default/pages/problem_sidebar.page.ts
+++ b/packages/ui-default/pages/problem_sidebar.page.ts
@@ -1,9 +1,10 @@
-import { NamedPage } from 'vj/misc/Page';
-import tpl from 'vj/utils/tpl';
-import i18n from 'vj/utils/i18n';
-import request from 'vj/utils/request';
+import $ from 'jquery';
import { ActionDialog, ConfirmDialog } from 'vj/components/dialog';
import Notification from 'vj/components/notification';
+import { NamedPage } from 'vj/misc/Page';
+import i18n from 'vj/utils/i18n';
+import request from 'vj/utils/request';
+import tpl from 'vj/utils/tpl';
const page = new NamedPage([
'problem_create', 'problem_edit', 'problem_solution', 'problem_submit',
diff --git a/packages/ui-default/pages/problem_submit.page.tsx b/packages/ui-default/pages/problem_submit.page.tsx
index 80be18380..e365892e1 100644
--- a/packages/ui-default/pages/problem_submit.page.tsx
+++ b/packages/ui-default/pages/problem_submit.page.tsx
@@ -1,6 +1,7 @@
+import $ from 'jquery';
+import { renderLanguageSelect } from 'vj/components/languageselect';
import { NamedPage } from 'vj/misc/Page';
import getAvailableLangs from 'vj/utils/availableLangs';
-import { renderLanguageSelect } from 'vj/components/languageselect';
const page = new NamedPage(['problem_submit', 'contest_detail_problem_submit', 'homework_detail_problem_submit'], async () => {
const { config } = UiContext.pdoc;
diff --git a/packages/ui-default/pages/record_detail.page.ts b/packages/ui-default/pages/record_detail.page.ts
index 4969ab709..e1522a490 100644
--- a/packages/ui-default/pages/record_detail.page.ts
+++ b/packages/ui-default/pages/record_detail.page.ts
@@ -1,3 +1,4 @@
+import $ from 'jquery';
import { NamedPage } from 'vj/misc/Page';
const page = new NamedPage('record_detail', async () => {
diff --git a/packages/ui-default/pages/record_main.page.ts b/packages/ui-default/pages/record_main.page.ts
index 8f0bd0f24..160f3b156 100644
--- a/packages/ui-default/pages/record_main.page.ts
+++ b/packages/ui-default/pages/record_main.page.ts
@@ -1,8 +1,9 @@
-import { NamedPage } from 'vj/misc/Page';
-import UserSelectAutoComplete from 'vj/components/autocomplete/UserSelectAutoComplete';
+import $ from 'jquery';
import ProblemSelectAutoComplete from 'vj/components/autocomplete/ProblemSelectAutoComplete';
-import tpl from 'vj/utils/tpl';
+import UserSelectAutoComplete from 'vj/components/autocomplete/UserSelectAutoComplete';
+import { NamedPage } from 'vj/misc/Page';
import getAvailableLangs from 'vj/utils/availableLangs';
+import tpl from 'vj/utils/tpl';
const page = new NamedPage('record_main', async () => {
const [{ default: WebSocket }, { DiffDOM }] = await Promise.all([
diff --git a/packages/ui-default/pages/training_detail.page.ts b/packages/ui-default/pages/training_detail.page.ts
index fee720848..672ec90ed 100644
--- a/packages/ui-default/pages/training_detail.page.ts
+++ b/packages/ui-default/pages/training_detail.page.ts
@@ -1,3 +1,4 @@
+import $ from 'jquery';
import { NamedPage } from 'vj/misc/Page';
import { slideDown, slideUp } from 'vj/utils/slide';
diff --git a/packages/ui-default/pages/training_edit.page.ts b/packages/ui-default/pages/training_edit.page.ts
index 6c8ed5c33..777d5bf11 100644
--- a/packages/ui-default/pages/training_edit.page.ts
+++ b/packages/ui-default/pages/training_edit.page.ts
@@ -1,8 +1,9 @@
-import { NamedPage } from 'vj/misc/Page';
+import $ from 'jquery';
import { ConfirmDialog } from 'vj/components/dialog';
-import tpl from 'vj/utils/tpl';
+import { NamedPage } from 'vj/misc/Page';
import i18n from 'vj/utils/i18n';
import request from 'vj/utils/request';
+import tpl from 'vj/utils/tpl';
export default new NamedPage('training_edit', () => {
let confirmed = false;
diff --git a/packages/ui-default/pages/user_detail.page.js b/packages/ui-default/pages/user_detail.page.js
index 9bd691eed..27c57effd 100644
--- a/packages/ui-default/pages/user_detail.page.js
+++ b/packages/ui-default/pages/user_detail.page.js
@@ -1,9 +1,10 @@
import Clipboard from 'clipboard';
-import { NamedPage } from 'vj/misc/Page';
-import substitute from 'vj/utils/substitute';
+import $ from 'jquery';
import Notification from 'vj/components/notification';
-import i18n from 'vj/utils/i18n';
+import { NamedPage } from 'vj/misc/Page';
import base64 from 'vj/utils/base64';
+import i18n from 'vj/utils/i18n';
+import substitute from 'vj/utils/substitute';
const page = new NamedPage('user_detail', () => {
$('[data-copy]').get().forEach((el) => {
diff --git a/packages/ui-default/pages/user_login.page.ts b/packages/ui-default/pages/user_login.page.ts
index 54a814d19..20e1b064e 100644
--- a/packages/ui-default/pages/user_login.page.ts
+++ b/packages/ui-default/pages/user_login.page.ts
@@ -1,3 +1,4 @@
+import $ from 'jquery';
import { AutoloadPage } from 'vj/misc/Page';
import api, { gql } from 'vj/utils/api';
diff --git a/packages/ui-default/polyfill.ts b/packages/ui-default/polyfill.ts
index cf95aff6c..ce083f44d 100644
--- a/packages/ui-default/polyfill.ts
+++ b/packages/ui-default/polyfill.ts
@@ -1,7 +1,8 @@
-import queueMicrotask from 'queue-microtask';
-import browserUpdate from 'browser-update';
import 'matchmedia-polyfill';
+import browserUpdate from 'browser-update';
+import queueMicrotask from 'queue-microtask';
+
window.queueMicrotask = queueMicrotask;
browserUpdate({
required: {
diff --git a/packages/ui-default/templates/layout/html5.html b/packages/ui-default/templates/layout/html5.html
index b3d088b47..d9349d55a 100644
--- a/packages/ui-default/templates/layout/html5.html
+++ b/packages/ui-default/templates/layout/html5.html
@@ -61,23 +61,11 @@
var UserContext = '{{ UserContext|json|jsesc|safe }}';
- {% if process.env.DEV and vite %}
-
-
-
+
+ {% if process.env.DEV %}
+
{% else %}
-
- {% if process.env.DEV %}
-
- {% else %}
-
- {% endif %}
+
{% endif %}
{% endif %}
{% block script %}{% endblock %}
diff --git a/packages/ui-default/theme/default.js b/packages/ui-default/theme/default.js
index c53a9f24f..c8d3dc556 100644
--- a/packages/ui-default/theme/default.js
+++ b/packages/ui-default/theme/default.js
@@ -5,7 +5,6 @@ import 'pickadate/lib/themes/classic.date.css';
import 'pickadate/lib/themes/classic.time.css';
import 'katex/dist/katex.min.css';
import '@blueprintjs/core/lib/css/blueprint.css';
-
import '@fontsource/fira-code';
import '@fontsource/source-code-pro';
import '@fontsource/roboto-mono';
@@ -14,19 +13,16 @@ import '@fontsource/ubuntu-mono';
import '@fontsource/pt-mono';
import '@fontsource/dm-mono';
import '@fontsource/jetbrains-mono';
-
import 'vj/misc/float.styl';
import 'vj/misc/typography.styl';
import 'vj/misc/textalign.styl';
import 'vj/misc/grid.styl';
import 'vj/misc/slideout.styl';
-
import 'vj/misc/.iconfont/webicon.styl';
import 'vj/misc/immersive.styl';
import 'vj/misc/structure.styl';
import 'vj/misc/section.styl';
import 'vj/misc/nothing.styl';
-
import 'vj/components/editor/cmeditor.styl';
import 'vj/components/datepicker/datepicker.styl';
import 'vj/components/katex/katex.styl';
diff --git a/packages/ui-default/utils/pjax.js b/packages/ui-default/utils/pjax.js
index b664bb974..7abe08d30 100644
--- a/packages/ui-default/utils/pjax.js
+++ b/packages/ui-default/utils/pjax.js
@@ -1,10 +1,11 @@
// Modified from jquery-pjax to support multiple fragments and jQuery 3.0
// https://github.com/defunkt/jquery-pjax/blob/master/jquery.pjax.js
+import $ from 'jquery';
import { nanoid } from 'nanoid';
import Notification from 'vj/components/notification';
import NProgress from 'vj/components/nprogress';
-import request from './request';
+import request from 'vj/utils/request';
const pjax = {};
diff --git a/packages/ui-default/utils/request.js b/packages/ui-default/utils/request.js
index 0bb63e501..bfba69b23 100644
--- a/packages/ui-default/utils/request.js
+++ b/packages/ui-default/utils/request.js
@@ -1,3 +1,4 @@
+import $ from 'jquery';
import i18n from './i18n';
const request = {
diff --git a/packages/ui-default/utils/tpl.ts b/packages/ui-default/utils/tpl.ts
index 80771c8af..21d574877 100644
--- a/packages/ui-default/utils/tpl.ts
+++ b/packages/ui-default/utils/tpl.ts
@@ -30,4 +30,4 @@ export function rawHtml(html: string) {
};
}
-global.Hydro.utils.tpl = tpl;
+window.Hydro.utils.tpl = tpl;
diff --git a/packages/utils/lib/common.ts b/packages/utils/lib/common.ts
index 3549e2223..0e6c9dc04 100644
--- a/packages/utils/lib/common.ts
+++ b/packages/utils/lib/common.ts
@@ -1,5 +1,3 @@
-import { inspect } from 'util';
-
declare global {
interface StringConstructor {
random: (digit?: number, dict?: string) => string;
@@ -33,24 +31,23 @@ String.random = function random(digit = 32, dict = defaultDict) {
return str;
};
-String.prototype.format = function formatStr(...args) {
- let result = this;
- if (args.length) {
- if (args.length === 1 && typeof args[0] === 'object') {
- const t = args[0];
- for (const key in t) {
- if (!key.startsWith('_') && t[key] !== undefined) {
- if (t._inspect && typeof t[key] === 'object') {
- t[key] = inspect(t[key], { colors: process?.stderr?.isTTY });
+if (!String.prototype.format) {
+ String.prototype.format = function formatStr(...args) {
+ let result = this;
+ if (args.length) {
+ if (args.length === 1 && typeof args[0] === 'object') {
+ const t = args[0];
+ for (const key in t) {
+ if (!key.startsWith('_') && t[key] !== undefined) {
+ const reg = new RegExp(`(\\{${key}\\})`, 'g');
+ result = result.replace(reg, t[key]);
}
- const reg = new RegExp(`(\\{${key}\\})`, 'g');
- result = result.replace(reg, t[key]);
}
- }
- } else return this.formatFromArray(args);
- }
- return result;
-};
+ } else return this.formatFromArray(args);
+ }
+ return result;
+ };
+}
String.prototype.formatFromArray = function formatStr(args) {
let result = this;
diff --git a/packages/utils/lib/utils.ts b/packages/utils/lib/utils.ts
index 0872fe915..d7e36460e 100644
--- a/packages/utils/lib/utils.ts
+++ b/packages/utils/lib/utils.ts
@@ -1,6 +1,7 @@
import os from 'os';
import path from 'path';
import { Duplex } from 'stream';
+import { inspect } from 'util';
import fs from 'fs-extra';
import type { Moment } from 'moment-timezone';
import { isMoment } from 'moment-timezone';
@@ -29,6 +30,25 @@ export function folderSize(folderPath: string) {
return size;
}
+String.prototype.format = function formatStr(...args) {
+ let result = this;
+ if (args.length) {
+ if (args.length === 1 && typeof args[0] === 'object') {
+ const t = args[0];
+ for (const key in t) {
+ if (!key.startsWith('_') && t[key] !== undefined) {
+ if (t._inspect && typeof t[key] === 'object') {
+ t[key] = inspect(t[key], { colors: process?.stderr?.isTTY });
+ }
+ const reg = new RegExp(`(\\{${key}\\})`, 'g');
+ result = result.replace(reg, t[key]);
+ }
+ }
+ } else return this.formatFromArray(args);
+ }
+ return result;
+};
+
export function isClass(obj: any, strict = false) {
if (typeof obj !== 'function') return false;
const str = obj.toString();
diff --git a/packages/utils/package.json b/packages/utils/package.json
index 5d4096a50..f4fe3e047 100644
--- a/packages/utils/package.json
+++ b/packages/utils/package.json
@@ -1,6 +1,6 @@
{
"name": "@hydrooj/utils",
- "version": "1.3.3",
+ "version": "1.3.4",
"description": "hydrooj utils",
"main": "package.json",
"repository": "https://github.com/hydro-dev/Hydro.git",