From 1a8243f1cace06c2eb872177d39536f76c9a8f5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?= <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Sun, 29 Oct 2023 14:12:40 +0900 Subject: [PATCH] =?UTF-8?q?MkCode=E3=81=AE=E3=83=91=E3=83=BC=E3=82=B9?= =?UTF-8?q?=E3=82=A8=E3=83=B3=E3=82=B8=E3=83=B3=E3=82=92Shiki=E3=81=AB?= =?UTF-8?q?=E5=A4=89=E6=9B=B4=20(#12102)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * (swap) prism -> shiki * fix styles * (bump) aiscript-vscode to v0.0.5 * refactor * replace prism-editor (beta) * Update scratchpad.vue * (enhance) MkCodeEditor自動インデント改行 * (fix) lint * (add) scratchpad: MkStickyContainer * Update CHANGELOG.md * clean up --------- Co-authored-by: syuilo <Syuilotan@yahoo.co.jp> --- CHANGELOG.md | 3 + packages/frontend/package.json | 4 +- .../frontend/src/components/MkCode.core.vue | 85 ++++++++- packages/frontend/src/components/MkCode.vue | 21 ++- .../frontend/src/components/MkCodeEditor.vue | 166 ++++++++++++++++++ packages/frontend/src/pages/flash/flash.vue | 2 +- packages/frontend/src/pages/scratchpad.vue | 60 +++---- .../frontend/src/pages/settings/plugin.vue | 2 +- .../frontend/src/scripts/code-highlighter.ts | 31 ++++ packages/frontend/src/style.scss | 4 - pnpm-lock.yaml | 87 +++++---- scripts/build-assets.mjs | 8 + 12 files changed, 380 insertions(+), 93 deletions(-) create mode 100644 packages/frontend/src/components/MkCodeEditor.vue create mode 100644 packages/frontend/src/scripts/code-highlighter.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index aa65bf8135..b909b26cae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,9 @@ - Feat: プラグイン・テーマを外部サイトから直接インストールできるようになりました - 外部サイトでの実装が必要です。詳細は Misskey Hub をご覧ください https://misskey-hub.net/docs/advanced/publish-on-your-website.html +- Enhance: コードのシンタックスハイライトエンジンをShikiに変更 + - AiScriptのシンタックスハイライトに対応 + - MFMでAiScriptをハイライトする場合、コードブロックの開始部分を ` ```is ` もしくは ` ```aiscript ` としてください - Enhance: データセーバー有効時はアニメーション付きのアバター画像が停止するように - Enhance: プラグインを削除した際には、使用されていたアクセストークンも同時に削除されるようになりました - Enhance: プラグインで`Plugin:register_note_view_interruptor`を用いてnoteの代わりにnullを返却することでノートを非表示にできるようになりました diff --git a/packages/frontend/package.json b/packages/frontend/package.json index f8492b3e56..fe35519d27 100644 --- a/packages/frontend/package.json +++ b/packages/frontend/package.json @@ -29,6 +29,7 @@ "@vue/compiler-sfc": "3.3.7", "astring": "1.8.6", "autosize": "6.0.1", + "aiscript-vscode": "github:aiscript-dev/aiscript-vscode#v0.0.5", "broadcast-channel": "5.5.1", "browser-image-resizer": "github:misskey-dev/browser-image-resizer#v2.2.1-misskey.3", "buraha": "0.0.1", @@ -54,11 +55,11 @@ "mfm-js": "0.23.3", "misskey-js": "workspace:*", "photoswipe": "5.4.2", - "prismjs": "1.29.0", "punycode": "2.3.0", "querystring": "0.2.1", "rollup": "4.1.4", "sanitize-html": "2.11.0", + "shiki": "^0.14.5", "sass": "1.69.5", "strict-event-emitter-types": "2.0.0", "textarea-caret": "3.1.0", @@ -74,7 +75,6 @@ "vanilla-tilt": "1.8.1", "vite": "4.5.0", "vue": "3.3.7", - "vue-prism-editor": "2.0.0-alpha.2", "vuedraggable": "next" }, "devDependencies": { diff --git a/packages/frontend/src/components/MkCode.core.vue b/packages/frontend/src/components/MkCode.core.vue index a1300be1f6..4ec3540419 100644 --- a/packages/frontend/src/components/MkCode.core.vue +++ b/packages/frontend/src/components/MkCode.core.vue @@ -5,21 +5,90 @@ SPDX-License-Identifier: AGPL-3.0-only <!-- eslint-disable vue/no-v-html --> <template> -<code v-if="inline" :class="`language-${prismLang}`" style="overflow-wrap: anywhere;" v-html="html"></code> -<pre v-else :class="`language-${prismLang}`"><code :class="`language-${prismLang}`" v-html="html"></code></pre> +<div :class="['codeBlockRoot', { 'codeEditor': codeEditor }]" v-html="html"></div> </template> <script lang="ts" setup> -import { computed } from 'vue'; -import Prism from 'prismjs'; -import 'prismjs/themes/prism-okaidia.css'; +import { ref, computed, watch } from 'vue'; +import { BUNDLED_LANGUAGES } from 'shiki'; +import type { Lang as ShikiLang } from 'shiki'; +import { getHighlighter } from '@/scripts/code-highlighter.js'; const props = defineProps<{ code: string; lang?: string; - inline?: boolean; + codeEditor?: boolean; }>(); -const prismLang = computed(() => Prism.languages[props.lang] ? props.lang : 'js'); -const html = computed(() => Prism.highlight(props.code, Prism.languages[prismLang.value], prismLang.value)); +const highlighter = await getHighlighter(); + +const codeLang = ref<ShikiLang | 'aiscript'>('js'); +const html = computed(() => highlighter.codeToHtml(props.code, { + lang: codeLang.value, + theme: 'dark-plus', +})); + +async function fetchLanguage(to: string): Promise<void> { + const language = to as ShikiLang; + + // Check for the loaded languages, and load the language if it's not loaded yet. + if (!highlighter.getLoadedLanguages().includes(language)) { + // Check if the language is supported by Shiki + const bundles = BUNDLED_LANGUAGES.filter((bundle) => { + // Languages are specified by their id, they can also have aliases (i. e. "js" and "javascript") + return bundle.id === language || bundle.aliases?.includes(language); + }); + if (bundles.length > 0) { + await highlighter.loadLanguage(language); + codeLang.value = language; + } else { + codeLang.value = 'js'; + } + } else { + codeLang.value = language; + } +} + +watch(() => props.lang, (to) => { + if (codeLang.value === to || !to) return; + return new Promise((resolve) => { + fetchLanguage(to).then(() => resolve); + }); +}, { immediate: true, }); </script> + +<style scoped lang="scss"> +.codeBlockRoot :deep(.shiki) { + padding: 1em; + margin: .5em 0; + overflow: auto; + border-radius: .3em; + + & pre, + & code { + font-family: Consolas, Monaco, Andale Mono, Ubuntu Mono, monospace; + } +} + +.codeBlockRoot.codeEditor { + min-width: 100%; + height: 100%; + + & :deep(.shiki) { + padding: 12px; + margin: 0; + border-radius: 6px; + min-height: 130px; + pointer-events: none; + min-width: calc(100% - 24px); + height: 100%; + display: inline-block; + line-height: 1.5em; + font-size: 1em; + overflow: visible; + text-rendering: inherit; + text-transform: inherit; + white-space: pre; + } +} +</style> diff --git a/packages/frontend/src/components/MkCode.vue b/packages/frontend/src/components/MkCode.vue index 8972b1863b..b39e6ff23c 100644 --- a/packages/frontend/src/components/MkCode.vue +++ b/packages/frontend/src/components/MkCode.vue @@ -4,11 +4,18 @@ SPDX-License-Identifier: AGPL-3.0-only --> <template> -<XCode :code="code" :lang="lang" :inline="inline"/> + <Suspense> + <template #fallback> + <MkLoading v-if="!inline ?? true" /> + </template> + <code v-if="inline" :class="$style.codeInlineRoot">{{ code }}</code> + <XCode v-else :code="code" :lang="lang"/> + </Suspense> </template> <script lang="ts" setup> import { defineAsyncComponent } from 'vue'; +import MkLoading from '@/components/global/MkLoading.vue'; defineProps<{ code: string; @@ -18,3 +25,15 @@ defineProps<{ const XCode = defineAsyncComponent(() => import('@/components/MkCode.core.vue')); </script> + +<style module lang="scss"> +.codeInlineRoot { + display: inline-block; + font-family: Consolas, Monaco, Andale Mono, Ubuntu Mono, monospace; + overflow-wrap: anywhere; + color: #D4D4D4; + background: #1E1E1E; + padding: .1em; + border-radius: .3em; +} +</style> diff --git a/packages/frontend/src/components/MkCodeEditor.vue b/packages/frontend/src/components/MkCodeEditor.vue new file mode 100644 index 0000000000..2d56a61963 --- /dev/null +++ b/packages/frontend/src/components/MkCodeEditor.vue @@ -0,0 +1,166 @@ +<!-- +SPDX-FileCopyrightText: syuilo and other misskey contributors +SPDX-License-Identifier: AGPL-3.0-only +--> + +<template> +<div :class="[$style.codeEditorRoot, { [$style.disabled]: disabled, [$style.focused]: focused }]"> + <div :class="$style.codeEditorScroller"> + <textarea + ref="inputEl" + v-model="vModel" + :class="[$style.textarea]" + :disabled="disabled" + :required="required" + :readonly="readonly" + autocomplete="off" + wrap="off" + spellcheck="false" + @focus="focused = true" + @blur="focused = false" + @keydown="onKeydown($event)" + @input="onInput" + ></textarea> + <XCode :class="$style.codeEditorHighlighter" :codeEditor="true" :code="v" :lang="lang"/> + </div> +</div> +</template> + +<script lang="ts" setup> +import { ref, watch, toRefs, shallowRef, nextTick } from 'vue'; +import XCode from '@/components/MkCode.core.vue'; + +const props = withDefaults(defineProps<{ + modelValue: string | null; + lang: string; + required?: boolean; + readonly?: boolean; + disabled?: boolean; +}>(), { + lang: 'js', +}); + +const emit = defineEmits<{ + (ev: 'change', _ev: KeyboardEvent): void; + (ev: 'keydown', _ev: KeyboardEvent): void; + (ev: 'enter'): void; + (ev: 'update:modelValue', value: string): void; +}>(); + +const { modelValue } = toRefs(props); +const vModel = ref<string>(modelValue.value ?? ''); +const v = ref<string>(modelValue.value ?? ''); +const focused = ref(false); +const changed = ref(false); +const inputEl = shallowRef<HTMLTextAreaElement>(); + +const onInput = (ev) => { + v.value = ev.target?.value ?? v.value; + changed.value = true; + emit('change', ev); +}; + +const onKeydown = (ev: KeyboardEvent) => { + if (ev.isComposing || ev.key === 'Process' || ev.keyCode === 229) return; + + emit('keydown', ev); + + if (ev.code === 'Enter') { + const pos = inputEl.value?.selectionStart ?? 0; + const posEnd = inputEl.value?.selectionEnd ?? vModel.value.length; + if (pos === posEnd) { + const lines = vModel.value.slice(0, pos).split('\n'); + const currentLine = lines[lines.length - 1]; + const currentLineSpaces = currentLine.match(/^\s+/); + const posDelta = currentLineSpaces ? currentLineSpaces[0].length : 0; + ev.preventDefault(); + vModel.value = vModel.value.slice(0, pos) + '\n' + (currentLineSpaces ? currentLineSpaces[0] : '') + vModel.value.slice(pos); + v.value = vModel.value; + nextTick(() => { + inputEl.value?.setSelectionRange(pos + 1 + posDelta, pos + 1 + posDelta); + }); + } + emit('enter'); + } + + if (ev.key === 'Tab') { + const pos = inputEl.value?.selectionStart ?? 0; + const posEnd = inputEl.value?.selectionEnd ?? vModel.value.length; + vModel.value = vModel.value.slice(0, pos) + '\t' + vModel.value.slice(posEnd); + v.value = vModel.value; + nextTick(() => { + inputEl.value?.setSelectionRange(pos + 1, pos + 1); + }); + ev.preventDefault(); + } +}; + +const updated = () => { + changed.value = false; + emit('update:modelValue', v.value); +}; + +watch(modelValue, newValue => { + v.value = newValue ?? ''; +}); + +watch(v, () => { + updated(); +}); +</script> + +<style lang="scss" module> +.codeEditorRoot { + min-width: 100%; + max-width: 100%; + overflow-x: auto; + overflow-y: hidden; + box-sizing: border-box; + margin: 0; + padding: 0; + color: var(--fg); + border: solid 1px var(--panel); + transition: border-color 0.1s ease-out; + font-family: Consolas, Monaco, Andale Mono, Ubuntu Mono, monospace; + &:hover { + border-color: var(--inputBorderHover) !important; + } +} + +.focused.codeEditorRoot { + border-color: var(--accent) !important; + border-radius: 6px; +} + +.codeEditorScroller { + position: relative; + display: inline-block; + min-width: 100%; + height: 100%; +} + +.textarea { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + display: inline-block; + appearance: none; + resize: none; + text-align: left; + color: transparent; + caret-color: rgb(225, 228, 232); + background-color: transparent; + border: 0; + outline: 0; + padding: 12px; + line-height: 1.5em; + font-size: 1em; + font-family: Consolas, Monaco, Andale Mono, Ubuntu Mono, monospace; +} + +.textarea::selection { + color: #fff; +} +</style> diff --git a/packages/frontend/src/pages/flash/flash.vue b/packages/frontend/src/pages/flash/flash.vue index 32a835831c..ebf117ffbf 100644 --- a/packages/frontend/src/pages/flash/flash.vue +++ b/packages/frontend/src/pages/flash/flash.vue @@ -36,7 +36,7 @@ SPDX-License-Identifier: AGPL-3.0-only <template #icon><i class="ti ti-code"></i></template> <template #label>{{ i18n.ts._play.viewSource }}</template> - <MkCode :code="flash.script" :inline="false" class="_monospace"/> + <MkCode :code="flash.script" lang="is" :inline="false" class="_monospace"/> </MkFolder> <div :class="$style.footer"> <Mfm :text="`By @${flash.user.username}`"/> diff --git a/packages/frontend/src/pages/scratchpad.vue b/packages/frontend/src/pages/scratchpad.vue index 3dfd2d661f..f8d3187bd4 100644 --- a/packages/frontend/src/pages/scratchpad.vue +++ b/packages/frontend/src/pages/scratchpad.vue @@ -4,46 +4,46 @@ SPDX-License-Identifier: AGPL-3.0-only --> <template> -<MkSpacer :contentMax="800"> - <div :class="$style.root"> - <div :class="$style.editor" class="_panel"> - <PrismEditor v-model="code" class="_monospace" :class="$style.code" :highlight="highlighter" :lineNumbers="false"/> - <MkButton style="position: absolute; top: 8px; right: 8px;" primary @click="run()"><i class="ti ti-player-play"></i></MkButton> - </div> +<MkStickyContainer> + <template #header><MkPageHeader/></template> - <MkContainer v-if="root && components.length > 1" :key="uiKey" :foldable="true"> - <template #header>UI</template> - <div :class="$style.ui"> - <MkAsUi :component="root" :components="components" size="small"/> + <MkSpacer :contentMax="800"> + <div :class="$style.root"> + <div class="_gaps_s"> + <div :class="$style.editor" class="_panel"> + <MkCodeEditor v-model="code" lang="aiscript"/> + </div> + <MkButton primary @click="run()"><i class="ti ti-player-play"></i></MkButton> </div> - </MkContainer> - <MkContainer :foldable="true" class=""> - <template #header>{{ i18n.ts.output }}</template> - <div :class="$style.logs"> - <div v-for="log in logs" :key="log.id" class="log" :class="{ print: log.print }">{{ log.text }}</div> + <MkContainer v-if="root && components.length > 1" :key="uiKey" :foldable="true"> + <template #header>UI</template> + <div :class="$style.ui"> + <MkAsUi :component="root" :components="components" size="small"/> + </div> + </MkContainer> + + <MkContainer :foldable="true" class=""> + <template #header>{{ i18n.ts.output }}</template> + <div :class="$style.logs"> + <div v-for="log in logs" :key="log.id" class="log" :class="{ print: log.print }">{{ log.text }}</div> + </div> + </MkContainer> + + <div class=""> + {{ i18n.ts.scratchpadDescription }} </div> - </MkContainer> - - <div class=""> - {{ i18n.ts.scratchpadDescription }} </div> - </div> -</MkSpacer> + </MkSpacer> +</MkStickyContainer> </template> <script lang="ts" setup> import { onDeactivated, onUnmounted, Ref, ref, watch } from 'vue'; -import 'prismjs'; -import { highlight, languages } from 'prismjs/components/prism-core'; -import 'prismjs/components/prism-clike'; -import 'prismjs/components/prism-javascript'; -import 'prismjs/themes/prism-okaidia.css'; -import { PrismEditor } from 'vue-prism-editor'; -import 'vue-prism-editor/dist/prismeditor.min.css'; import { Interpreter, Parser, utils } from '@syuilo/aiscript'; import MkContainer from '@/components/MkContainer.vue'; import MkButton from '@/components/MkButton.vue'; +import MkCodeEditor from '@/components/MkCodeEditor.vue'; import { createAiScriptEnv } from '@/scripts/aiscript/api.js'; import * as os from '@/os.js'; import { $i } from '@/account.js'; @@ -152,10 +152,6 @@ async function run() { } } -function highlighter(code) { - return highlight(code, languages.js, 'javascript'); -} - onDeactivated(() => { if (aiscript) aiscript.abort(); }); diff --git a/packages/frontend/src/pages/settings/plugin.vue b/packages/frontend/src/pages/settings/plugin.vue index d72d8d00f3..5ebd74ef7a 100644 --- a/packages/frontend/src/pages/settings/plugin.vue +++ b/packages/frontend/src/pages/settings/plugin.vue @@ -50,7 +50,7 @@ SPDX-License-Identifier: AGPL-3.0-only <MkButton inline @click="copy(plugin)"><i class="ti ti-copy"></i> {{ i18n.ts.copy }}</MkButton> </div> - <MkCode :code="plugin.src ?? ''"/> + <MkCode :code="plugin.src ?? ''" lang="is"/> </div> </MkFolder> </div> diff --git a/packages/frontend/src/scripts/code-highlighter.ts b/packages/frontend/src/scripts/code-highlighter.ts new file mode 100644 index 0000000000..957669122e --- /dev/null +++ b/packages/frontend/src/scripts/code-highlighter.ts @@ -0,0 +1,31 @@ +import { setWasm, setCDN, Highlighter, getHighlighter as _getHighlighter } from 'shiki'; + +setWasm('/assets/shiki/dist/onig.wasm'); +setCDN('/assets/shiki/'); + +let _highlighter: Highlighter | null = null; + +export async function getHighlighter(): Promise<Highlighter> { + if (!_highlighter) { + return await initHighlighter(); + } + return _highlighter; +} + +export async function initHighlighter() { + const highlighter = await _getHighlighter({ + theme: 'dark-plus', + langs: ['js'], + }); + + await highlighter.loadLanguage({ + path: 'languages/aiscript.tmLanguage.json', + id: 'aiscript', + scopeName: 'source.aiscript', + aliases: ['is', 'ais'], + }); + + _highlighter = highlighter; + + return highlighter; +} diff --git a/packages/frontend/src/style.scss b/packages/frontend/src/style.scss index c644fc76da..c22879d677 100644 --- a/packages/frontend/src/style.scss +++ b/packages/frontend/src/style.scss @@ -400,10 +400,6 @@ hr { font-family: Fira code, Fira Mono, Consolas, Menlo, Courier, monospace !important; } -.prism-editor__textarea:focus { - outline: none; -} - ._zoom { transition-duration: 0.5s, 0.5s; transition-property: opacity, transform; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4d47134d43..0ffd449494 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -673,6 +673,9 @@ importers: '@vue/compiler-sfc': specifier: 3.3.7 version: 3.3.7 + aiscript-vscode: + specifier: github:aiscript-dev/aiscript-vscode#v0.0.5 + version: github.com/aiscript-dev/aiscript-vscode/a8fa5bb41885391cdb6a6e3165eaa6e4868da86e astring: specifier: 1.8.6 version: 1.8.6 @@ -754,9 +757,6 @@ importers: photoswipe: specifier: 5.4.2 version: 5.4.2 - prismjs: - specifier: 1.29.0 - version: 1.29.0 punycode: specifier: 2.3.0 version: 2.3.0 @@ -772,6 +772,9 @@ importers: sass: specifier: 1.69.5 version: 1.69.5 + shiki: + specifier: ^0.14.5 + version: 0.14.5 strict-event-emitter-types: specifier: 2.0.0 version: 2.0.0 @@ -814,9 +817,6 @@ importers: vue: specifier: 3.3.7 version: 3.3.7(typescript@5.2.2) - vue-prism-editor: - specifier: 2.0.0-alpha.2 - version: 2.0.0-alpha.2(vue@3.3.7) vuedraggable: specifier: next version: 4.1.0(vue@3.3.7) @@ -871,10 +871,10 @@ importers: version: 7.5.1 '@storybook/vue3': specifier: 7.5.1 - version: 7.5.1(@vue/compiler-core@3.3.6)(vue@3.3.7) + version: 7.5.1(@vue/compiler-core@3.3.7)(vue@3.3.7) '@storybook/vue3-vite': specifier: 7.5.1 - version: 7.5.1(@vue/compiler-core@3.3.6)(react-dom@18.2.0)(react@18.2.0)(typescript@5.2.2)(vite@4.5.0)(vue@3.3.7) + version: 7.5.1(@vue/compiler-core@3.3.7)(react-dom@18.2.0)(react@18.2.0)(typescript@5.2.2)(vite@4.5.0)(vue@3.3.7) '@testing-library/vue': specifier: 7.0.0 version: 7.0.0(@vue/compiler-sfc@3.3.7)(vue@3.3.7) @@ -6867,7 +6867,7 @@ packages: file-system-cache: 2.3.0 dev: true - /@storybook/vue3-vite@7.5.1(@vue/compiler-core@3.3.6)(react-dom@18.2.0)(react@18.2.0)(typescript@5.2.2)(vite@4.5.0)(vue@3.3.7): + /@storybook/vue3-vite@7.5.1(@vue/compiler-core@3.3.7)(react-dom@18.2.0)(react@18.2.0)(typescript@5.2.2)(vite@4.5.0)(vue@3.3.7): resolution: {integrity: sha512-5bO5BactTbyOxxeRw8U6t3FqqfTvVLTefzg1NLDkKt2iAL6lGBSsPTKMgpy3dt+cxdiqEis67niQL68ZtW02Zw==} engines: {node: ^14.18 || >=16} peerDependencies: @@ -6877,7 +6877,7 @@ packages: dependencies: '@storybook/builder-vite': 7.5.1(typescript@5.2.2)(vite@4.5.0) '@storybook/core-server': 7.5.1 - '@storybook/vue3': 7.5.1(@vue/compiler-core@3.3.6)(vue@3.3.7) + '@storybook/vue3': 7.5.1(@vue/compiler-core@3.3.7)(vue@3.3.7) '@vitejs/plugin-vue': 4.4.0(vite@4.5.0)(vue@3.3.7) magic-string: 0.30.3 react: 18.2.0 @@ -6896,7 +6896,7 @@ packages: - vue dev: true - /@storybook/vue3@7.5.1(@vue/compiler-core@3.3.6)(vue@3.3.7): + /@storybook/vue3@7.5.1(@vue/compiler-core@3.3.7)(vue@3.3.7): resolution: {integrity: sha512-9srw2rnSYaU45kkunXT8+bX3QMO2QPV6MCWRayKo7Pl+B0H/euHvxPSZb1X8mRpgLtYgVgSNJFoNbk/2Fn8z8g==} engines: {node: '>=16.0.0'} peerDependencies: @@ -6908,7 +6908,7 @@ packages: '@storybook/global': 5.0.0 '@storybook/preview-api': 7.5.1 '@storybook/types': 7.5.1 - '@vue/compiler-core': 3.3.6 + '@vue/compiler-core': 3.3.7 lodash: 4.17.21 ts-dedent: 2.2.0 type-fest: 2.19.0 @@ -8367,15 +8367,6 @@ packages: postcss: 8.4.31 source-map-js: 1.0.2 - /@vue/compiler-ssr@3.3.6: - resolution: {integrity: sha512-QTIHAfDCHhjXlYGkUg5KH7YwYtdUM1vcFl/FxFDlD6d0nXAmnjizka3HITp8DGudzHndv2PjKVS44vqqy0vP4w==} - requiresBuild: true - dependencies: - '@vue/compiler-dom': 3.3.6 - '@vue/shared': 3.3.6 - dev: true - optional: true - /@vue/compiler-ssr@3.3.7: resolution: {integrity: sha512-TxOfNVVeH3zgBc82kcUv+emNHo+vKnlRrkv8YvQU5+Y5LJGJwSNzcmLUoxD/dNzv0bhQ/F0s+InlgV0NrApJZg==} dependencies: @@ -8428,17 +8419,6 @@ packages: '@vue/shared': 3.3.7 csstype: 3.1.2 - /@vue/server-renderer@3.3.6(vue@3.3.7): - resolution: {integrity: sha512-kgLoN43W4ERdZ6dpyy+gnk2ZHtcOaIr5Uc/WUP5DRwutgvluzu2pudsZGoD2b7AEJHByUVMa9k6Sho5lLRCykw==} - peerDependencies: - vue: 3.3.6 - dependencies: - '@vue/compiler-ssr': 3.3.6 - '@vue/shared': 3.3.6 - vue: 3.3.7(typescript@5.2.2) - dev: true - optional: true - /@vue/server-renderer@3.3.7(vue@3.3.7): resolution: {integrity: sha512-UlpKDInd1hIZiNuVVVvLgxpfnSouxKQOSE2bOfQpBuGwxRV/JqqTCyyjXUWiwtVMyeRaZhOYYqntxElk8FhBhw==} peerDependencies: @@ -8466,8 +8446,8 @@ packages: js-beautify: 1.14.6 vue: 3.3.7(typescript@5.2.2) optionalDependencies: - '@vue/compiler-dom': 3.3.6 - '@vue/server-renderer': 3.3.6(vue@3.3.7) + '@vue/compiler-dom': 3.3.7 + '@vue/server-renderer': 3.3.7(vue@3.3.7) dev: true /@webgpu/types@0.1.30: @@ -8687,6 +8667,10 @@ packages: resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} engines: {node: '>=12'} + /ansi-sequence-parser@1.1.1: + resolution: {integrity: sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg==} + dev: false + /ansi-styles@3.2.1: resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} engines: {node: '>=4'} @@ -13942,7 +13926,6 @@ packages: /jsonc-parser@3.2.0: resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} - dev: true /jsonfile@4.0.0: resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} @@ -16251,6 +16234,7 @@ packages: /prismjs@1.29.0: resolution: {integrity: sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==} engines: {node: '>=6'} + dev: true /private-ip@2.3.3: resolution: {integrity: sha512-5zyFfekIVUOTVbL92hc8LJOtE/gyGHeREHkJ2yTyByP8Q2YZVoBqLg3EfYLeF0oVvGqtaEX2t2Qovja0/gStXw==} @@ -17480,6 +17464,15 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} + /shiki@0.14.5: + resolution: {integrity: sha512-1gCAYOcmCFONmErGTrS1fjzJLA7MGZmKzrBNX7apqSwhyITJg2O102uFzXUeBxNnEkDA9vHIKLyeKq0V083vIw==} + dependencies: + ansi-sequence-parser: 1.1.1 + jsonc-parser: 3.2.0 + vscode-oniguruma: 1.7.0 + vscode-textmate: 8.0.0 + dev: false + /side-channel@1.0.4: resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} dependencies: @@ -19232,6 +19225,14 @@ packages: resolution: {integrity: sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==} engines: {node: '>=0.10.0'} + /vscode-oniguruma@1.7.0: + resolution: {integrity: sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==} + dev: false + + /vscode-textmate@8.0.0: + resolution: {integrity: sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==} + dev: false + /vue-component-type-helpers@1.8.22: resolution: {integrity: sha512-LK3wJHs3vJxHG292C8cnsRusgyC5SEZDCzDCD01mdE/AoREFMl2tzLRuzwyuEsOIz13tqgBcnvysN3Lxsa14Fw==} dev: true @@ -19295,15 +19296,6 @@ packages: vue: 3.3.7(typescript@5.2.2) dev: true - /vue-prism-editor@2.0.0-alpha.2(vue@3.3.7): - resolution: {integrity: sha512-Gu42ba9nosrE+gJpnAEuEkDMqG9zSUysIR8SdXUw8MQKDjBnnNR9lHC18uOr/ICz7yrA/5c7jHJr9lpElODC7w==} - engines: {node: '>=10'} - peerDependencies: - vue: ^3.0.0 - dependencies: - vue: 3.3.7(typescript@5.2.2) - dev: false - /vue-template-compiler@2.7.14: resolution: {integrity: sha512-zyA5Y3ArvVG0NacJDkkzJuPQDF8RFeRlzV2vLeSnhSpieO6LK2OVbdLPi5MPPs09Ii+gMO8nY4S3iKQxBxDmWQ==} dependencies: @@ -19765,6 +19757,13 @@ packages: readable-stream: 3.6.0 dev: false + github.com/aiscript-dev/aiscript-vscode/a8fa5bb41885391cdb6a6e3165eaa6e4868da86e: + resolution: {tarball: https://codeload.github.com/aiscript-dev/aiscript-vscode/tar.gz/a8fa5bb41885391cdb6a6e3165eaa6e4868da86e} + name: aiscript-vscode + version: 0.0.5 + engines: {vscode: ^1.83.0} + dev: false + github.com/misskey-dev/browser-image-resizer/0227e860621e55cbed0aabe6dc601096a7748c4a: resolution: {tarball: https://codeload.github.com/misskey-dev/browser-image-resizer/tar.gz/0227e860621e55cbed0aabe6dc601096a7748c4a} name: browser-image-resizer diff --git a/scripts/build-assets.mjs b/scripts/build-assets.mjs index a8a2cafa5f..1ffcec8aa3 100644 --- a/scripts/build-assets.mjs +++ b/scripts/build-assets.mjs @@ -33,6 +33,13 @@ async function copyFrontendLocales() { } } +async function copyFrontendShikiAssets() { + await fs.cp('./packages/frontend/node_modules/shiki/dist', './built/_frontend_dist_/shiki/dist', { dereference: true, recursive: true }); + await fs.cp('./packages/frontend/node_modules/shiki/languages', './built/_frontend_dist_/shiki/languages', { dereference: true, recursive: true }); + await fs.cp('./packages/frontend/node_modules/aiscript-vscode/aiscript/syntaxes', './built/_frontend_dist_/shiki/languages', { dereference: true, recursive: true }); + await fs.cp('./packages/frontend/node_modules/shiki/themes', './built/_frontend_dist_/shiki/themes', { dereference: true, recursive: true }); +} + async function copyBackendViews() { await fs.cp('./packages/backend/src/server/web/views', './packages/backend/built/server/web/views', { recursive: true }); } @@ -72,6 +79,7 @@ async function build() { copyFrontendFonts(), copyFrontendTablerIcons(), copyFrontendLocales(), + copyFrontendShikiAssets(), copyBackendViews(), buildBackendScript(), buildBackendStyle(),