diff --git a/packages/hydrooj/package.json b/packages/hydrooj/package.json index de94e32dd..3d1ae1e20 100644 --- a/packages/hydrooj/package.json +++ b/packages/hydrooj/package.json @@ -11,7 +11,7 @@ "node": ">=14" }, "dependencies": { - "@hydrooj/utils": "^1.0.1", + "@hydrooj/utils": "^1.0.3", "adm-zip": "^0.5.5", "ansi_up": "^5.0.1", "cookies": "^0.8.0", diff --git a/packages/hydrooj/src/entry/common.ts b/packages/hydrooj/src/entry/common.ts index 779ff1434..0a3ce0c51 100644 --- a/packages/hydrooj/src/entry/common.ts +++ b/packages/hydrooj/src/entry/common.ts @@ -89,6 +89,7 @@ export async function setting(pending: string[], fail: string[], modelSetting: t system: modelSetting.SystemSetting, account: modelSetting.AccountSetting, preference: modelSetting.PreferenceSetting, + domain: modelSetting.DomainSetting, }; for (const i of pending) { let p = path.resolve(i, 'setting.yaml'); @@ -105,9 +106,10 @@ export async function setting(pending: string[], fail: string[], modelSetting: t .replace(/\$TEMP/g, os.tmpdir()) .replace(/\$HOME/g, os.homedir()); } - map[cfg[key].category || 'system']( + const category = cfg[key].category || 'system'; + map[category]( modelSetting.Setting( - name, `${name}.${key}`, val, cfg[key].type || 'text', + name, category === 'system' ? `${name}.${key}` : key, val, cfg[key].type || 'text', cfg[key].name || key, cfg[key].desc || '', ), ); diff --git a/packages/ui-default/components/highlighter/highlighter.page.styl b/packages/ui-default/components/highlighter/highlighter.page.styl index b083d40ba..710e84449 100644 --- a/packages/ui-default/components/highlighter/highlighter.page.styl +++ b/packages/ui-default/components/highlighter/highlighter.page.styl @@ -120,3 +120,32 @@ pre > code display: block padding-right: 0.8em text-align: right + +.token.tab:not(:empty), +.token.cr, +.token.lf, +.token.space + position: relative + +.token.tab:not(:empty):before, +.token.cr:before, +.token.lf:before, +.token.space:before + color: #808080 + opacity: 0.6 + position: absolute + +.token.tab:not(:empty):before + content: '\21E5' + +.token.cr:before + content: '\240D' + +.token.crlf:before + content: '\240D\240A' + +.token.lf:before + content: '\240A' + +.token.space:before + content: '\00B7' diff --git a/packages/ui-default/components/highlighter/prismjs.js b/packages/ui-default/components/highlighter/prismjs.js index 273dc1344..26a086ea8 100644 --- a/packages/ui-default/components/highlighter/prismjs.js +++ b/packages/ui-default/components/highlighter/prismjs.js @@ -51,6 +51,49 @@ try { // snowpack } +const invisibles = { + tab: /\t/, + crlf: /\r\n/, + lf: /\n/, + cr: /\r/, + space: / /, +}; + +function addInvisibles(grammar) { + if (!grammar || grammar.tab) return; + for (const name in invisibles) { + if (Object.prototype.hasOwnProperty.call(invisibles, name)) { + grammar[name] = invisibles[name]; + } + } + for (const name in grammar) { + if (Object.prototype.hasOwnProperty.call(grammar, name) && !invisibles[name]) { + if (name === 'rest') addInvisibles(grammar.rest); + else handlerInvisiblesToken(grammar, name); // eslint-disable-line no-use-before-define + } + } +} + +function handlerInvisiblesToken(tokens, name) { + const value = tokens[name]; + const type = Prism.util.type(value); + if (type === 'RegExp') { + const inside = {}; + tokens[name] = { pattern: value, inside }; + addInvisibles(inside); + } else if (type === 'Array') { + for (let i = 0, l = value.length; i < l; i++) handlerInvisiblesToken(value, i); + } else { + const inside = value.inside || (value.inside = {}); + addInvisibles(inside); + } +} + +Prism.hooks.add('before-highlight', (env) => { + console.log(UserContext.showInvisibleChar); + if (UserContext.showInvisibleChar) addInvisibles(env.grammar); +}); + const prismjsApiWrap = { highlightBlocks: ($dom) => { $dom.find('pre code').get().forEach((code) => { diff --git a/packages/ui-default/setting.yaml b/packages/ui-default/setting.yaml index 764c1a757..2b5da1f27 100644 --- a/packages/ui-default/setting.yaml +++ b/packages/ui-default/setting.yaml @@ -81,3 +81,7 @@ lang_monaco_modes: go: go rb: ruby jl: julia +showInvisibleChar: + type: boolean + desc: show invisible characters when formatting code + category: preference