summaryrefslogtreecommitdiff
path: root/packages/frontend/src/components/MkCode.core.vue
diff options
context:
space:
mode:
authorかっこかり <67428053+kakkokari-gtyih@users.noreply.github.com>2023-10-29 14:12:40 +0900
committerGitHub <noreply@github.com>2023-10-29 14:12:40 +0900
commit1a8243f1cace06c2eb872177d39536f76c9a8f5d (patch)
treed75937ed6b116a98e3139d98b34bea4344c86f3e /packages/frontend/src/components/MkCode.core.vue
parentenhance(frontend): tweak about-misskey page (diff)
downloadsharkey-1a8243f1cace06c2eb872177d39536f76c9a8f5d.tar.gz
sharkey-1a8243f1cace06c2eb872177d39536f76c9a8f5d.tar.bz2
sharkey-1a8243f1cace06c2eb872177d39536f76c9a8f5d.zip
MkCodeのパースエンジンをShikiに変更 (#12102)
* (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>
Diffstat (limited to 'packages/frontend/src/components/MkCode.core.vue')
-rw-r--r--packages/frontend/src/components/MkCode.core.vue85
1 files changed, 77 insertions, 8 deletions
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>