diff --git a/build/build.js b/build/build.js index 401714b9..7306415e 100644 --- a/build/build.js +++ b/build/build.js @@ -1,7 +1,7 @@ const fs = require('fs'); const path = require('path'); -const child = require('child_process'); const { argv } = require('yargs'); +const { sync } = require('cross-spawn'); const compilerOptionsBase = { target: 'es2019', @@ -52,7 +52,7 @@ for (const package of packages) { if (package === 'ui-default') continue; const basedir = path.resolve(process.cwd(), 'packages', package); const files = fs.readdirSync(basedir); - if (!files.includes('src') && !files.map(n => n.split('.')[1]).includes('ts') && package !== 'utils') continue; + if (!files.includes('src') && !files.map((n) => n.split('.')[1]).includes('ts') && package !== 'utils') continue; if (package !== 'hydrooj') config.references.push({ path: `packages/${package}` }); fs.writeFileSync( path.resolve(basedir, 'tsconfig.json'), @@ -64,17 +64,17 @@ for (const package of packages) { if (!fs.statSync(path.resolve(basedir, 'src', file)).isFile()) continue; const name = file.split('.')[0]; if (['handler', 'service', 'lib', 'model', 'script'].includes(name)) { - fs.writeFileSync(path.resolve(basedir, name + '.js'), `module.exports = require('./dist/${name}');\n`); + fs.writeFileSync(path.resolve(basedir, `${name}.js`), `module.exports = require('./dist/${name}');\n`); } } } } fs.writeFileSync(path.resolve(process.cwd(), 'tsconfig.json'), JSON.stringify(config)); -child.execSync('./node_modules/.bin/tsc -b packages/hydrooj', { stdio: 'inherit' }); +sync('./node_modules/.bin/tsc -b packages/hydrooj', { stdio: 'inherit' }); if (argv.watch) { - child.execSync('./node_modules/.bin/tsc -b --watch', { stdio: 'inherit' }); + sync('./node_modules/.bin/tsc -b --watch', { stdio: 'inherit' }); } else { - child.execSync('./node_modules/.bin/tsc -b', { stdio: 'inherit' }); -} \ No newline at end of file + sync('./node_modules/.bin/tsc -b', { stdio: 'inherit' }); +} diff --git a/packages/ui-default/build/config/webpack.js b/packages/ui-default/build/config/webpack.js index f25ba723..54792c17 100644 --- a/packages/ui-default/build/config/webpack.js +++ b/packages/ui-default/build/config/webpack.js @@ -103,6 +103,11 @@ export default function (env = {}) { test: /\.css$/, use: [extractCssLoader(), cssLoader(), postcssLoader()], }, + { + test: /\.wasm$/, + use: [fileLoader()], + type: 'javascript/auto', + }, ], }, optimization: { diff --git a/packages/ui-default/components/highlighter/highlighter.page.js b/packages/ui-default/components/highlighter/highlighter.page.js index 1e9bfcc0..60b4f416 100644 --- a/packages/ui-default/components/highlighter/highlighter.page.js +++ b/packages/ui-default/components/highlighter/highlighter.page.js @@ -1,14 +1,18 @@ import { AutoloadPage } from 'vj/misc/Page'; +import load from 'vj/components/wastyle/index'; +import Notification from 'vj/components/notification/index'; -const highlighterPage = new AutoloadPage('highlighterPage', () => { - import('./prismjs').then((module) => { - const prismjs = module.default; - function runHighlight($container) { - prismjs.highlightBlocks($container); - } - runHighlight($('body')); - $(document).on('vjContentNew', (e) => runHighlight($(e.target))); - }); +const highlighterPage = new AutoloadPage('highlighterPage', async () => { + const [{ default: prismjs }, [success, format]] = await Promise.all([ + import('./prismjs'), + load(), + ]); + if (!success) Notification.error(`Astyle load fail: ${format}`); + function runHighlight($container) { + prismjs.highlightBlocks($container, success ? format : null); + } + runHighlight($('body')); + $(document).on('vjContentNew', (e) => runHighlight($(e.target))); }); export default highlighterPage; diff --git a/packages/ui-default/components/highlighter/prismjs.js b/packages/ui-default/components/highlighter/prismjs.js index 26a086ea..4947c9d9 100644 --- a/packages/ui-default/components/highlighter/prismjs.js +++ b/packages/ui-default/components/highlighter/prismjs.js @@ -11,7 +11,7 @@ To add a new language to highlight: import Prism from 'prismjs'; import Clipboard from 'clipboard'; -import Notification from 'vj/components/notification'; +import Notification from 'vj/components/notification/index'; import i18n from 'vj/utils/i18n'; import languageMeta from './meta'; @@ -95,16 +95,24 @@ Prism.hooks.add('before-highlight', (env) => { }); const prismjsApiWrap = { - highlightBlocks: ($dom) => { + highlightBlocks: ($dom, format) => { $dom.find('pre code').get().forEach((code) => { - const $pre = $(code).parent(); + const $code = $(code); + const $pre = $code.parent(); $pre.addClass('syntax-hl'); if ($pre.closest('[data-syntax-hl-show-line-number]')) { $pre.addClass('line-numbers'); } + const language = ($(code).attr('class') || '').trim(); + const astyle = language.match(/astyle-([a-z]+)/); + if (format && astyle && astyle[1]) { + const [success, result] = format($code.text(), `${UserContext.astyleOptions.trim()} mode=${astyle[1]}`); + console.log(success.result); + if (!success) Notification.error('Code format fail'); + else $code.text(result.replace(/^#(include|import)[\t ]*(<|")/gm, (match, p1, p2) => `#${p1} ${p2}`)); + } // try to map the language name - const language = $(code).attr('class'); - const m = (language || '').trim().match(/^language-(.+)$/); + const m = language.match(/language-([a-z]+)/); if (m && m[1]) { const languageName = m[1].toLowerCase(); if (languageExtMap[languageName]) { diff --git a/packages/ui-default/components/wastyle/index.js b/packages/ui-default/components/wastyle/index.js new file mode 100644 index 00000000..98a87907 --- /dev/null +++ b/packages/ui-default/components/wastyle/index.js @@ -0,0 +1,12 @@ +import astyleBinaryUrl from 'wastyle/dist/astyle-optimize-size.wasm'; + +export default async function load() { + const { init, format } = await import('wastyle'); + try { + await init(astyleBinaryUrl); + console.log('WAstyle is ready!'); + return [true, format]; + } catch (e) { + return [false, e.message]; + } +} diff --git a/packages/ui-default/package.json b/packages/ui-default/package.json index 8aec11bf..d5bff3a9 100644 --- a/packages/ui-default/package.json +++ b/packages/ui-default/package.json @@ -97,6 +97,7 @@ "uuid": "^8.3.2", "vinyl-buffer": "^1.0.1", "vj-simplemde": "0.0.8", + "wastyle": "^0.0.5", "webpack": "^4.44.2", "webpack-bundle-analyzer": "^4.4.0", "webpack-dev-server": "^3.11.2" diff --git a/packages/ui-default/setting.yaml b/packages/ui-default/setting.yaml index 2b5da1f2..e8db7baf 100644 --- a/packages/ui-default/setting.yaml +++ b/packages/ui-default/setting.yaml @@ -48,11 +48,11 @@ lang_highlight_id: name: lang_highlight_id desc: Language Highlight ID default: - c: c - cc: cpp - cs: csharp + c: c astyle-c + cc: cpp astyle-c + cs: csharp astyle-cs pas: pascal - java: java + java: java astyle-java py: python py3: python php: php @@ -85,3 +85,12 @@ showInvisibleChar: type: boolean desc: show invisible characters when formatting code category: preference +astyleOptions: + type: text + desc: astyle formatting options + category: preference + value: > + style=java attach-namespaces attach-classes attach-inlines attach-extern-c attach-closing-while + indent-col1-comments break-blocks pad-oper pad-comma pad-header unpad-paren align-pointer=name + break-one-line-headers attach-return-type attach-return-type-decl convert-tabs close-templates + max-code-length=110 break-after-logical