This commit is contained in:
かっこかり 2025-09-14 05:47:20 +05:30 committed by GitHub
commit f33d741980
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 74 additions and 24 deletions

View File

@ -5,7 +5,13 @@ SPDX-License-Identifier: AGPL-3.0-only
<!-- eslint-disable vue/no-v-html --> <!-- eslint-disable vue/no-v-html -->
<template> <template>
<div :class="[$style.codeBlockRoot, { [$style.codeEditor]: codeEditor }, (darkMode ? $style.dark : $style.light)]" v-html="html"></div> <div
:class="[$style.codeBlockRoot, {
[$style.codeEditor]: codeEditor,
[$style.outerStyle]: !codeEditor && withOuterStyle,
[$style.dark]: darkMode,
[$style.light]: !darkMode,
}]" v-html="html"></div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
@ -15,11 +21,15 @@ import type { BundledLanguage } from 'shiki/langs';
import { getHighlighter, getTheme } from '@/utility/code-highlighter.js'; import { getHighlighter, getTheme } from '@/utility/code-highlighter.js';
import { store } from '@/store.js'; import { store } from '@/store.js';
const props = defineProps<{ const props = withDefaults(defineProps<{
code: string; code: string;
lang?: string; lang?: string;
codeEditor?: boolean; codeEditor?: boolean;
}>(); withOuterStyle?: boolean;
}>(), {
codeEditor: false,
withOuterStyle: true,
});
const highlighter = await getHighlighter(); const highlighter = await getHighlighter();
const darkMode = store.r.darkMode; const darkMode = store.r.darkMode;
@ -73,17 +83,13 @@ watch(() => props.lang, (to) => {
<style module lang="scss"> <style module lang="scss">
.codeBlockRoot :global(.shiki) { .codeBlockRoot :global(.shiki) {
padding: 1em;
margin: 0;
overflow: auto; overflow: auto;
font-family: Consolas, Monaco, Andale Mono, Ubuntu Mono, monospace; font-family: Consolas, Monaco, Andale Mono, Ubuntu Mono, monospace;
color: var(--shiki-fallback); color: var(--shiki-fallback);
background-color: var(--shiki-fallback-bg);
& span { & span {
color: var(--shiki-fallback); color: var(--shiki-fallback);
background-color: var(--shiki-fallback-bg);
} }
& pre, & pre,
@ -92,26 +98,40 @@ watch(() => props.lang, (to) => {
} }
} }
.outerStyle.codeBlockRoot :global(.shiki) {
padding: 1em;
margin: .5em 0;
border-radius: 8px;
border: 1px solid var(--MI_THEME-divider);
background-color: var(--shiki-fallback-bg);
}
.light.codeBlockRoot :global(.shiki) { .light.codeBlockRoot :global(.shiki) {
color: var(--shiki-light); color: var(--shiki-light);
background-color: var(--shiki-light-bg);
& span { & span {
color: var(--shiki-light); color: var(--shiki-light);
background-color: var(--shiki-light-bg);
} }
} }
.light.outerStyle.codeBlockRoot :global(.shiki),
.light.codeEditor.codeBlockRoot :global(.shiki) {
background-color: var(--shiki-light-bg);
}
.dark.codeBlockRoot :global(.shiki) { .dark.codeBlockRoot :global(.shiki) {
color: var(--shiki-dark); color: var(--shiki-dark);
background-color: var(--shiki-dark-bg);
& span { & span {
color: var(--shiki-dark); color: var(--shiki-dark);
background-color: var(--shiki-dark-bg);
} }
} }
.dark.outerStyle.codeBlockRoot :global(.shiki),
.dark.codeEditor.codeBlockRoot :global(.shiki) {
background-color: var(--shiki-dark-bg);
}
.codeBlockRoot.codeEditor { .codeBlockRoot.codeEditor {
min-width: 100%; min-width: 100%;
height: 100%; height: 100%;

View File

@ -5,15 +5,32 @@ SPDX-License-Identifier: AGPL-3.0-only
<template> <template>
<div :class="$style.codeBlockRoot"> <div :class="$style.codeBlockRoot">
<button v-if="copyButton" :class="$style.codeBlockCopyButton" class="_button" @click="copy"> <button v-if="copyButton" :class="[$style.codeBlockCopyButton, { [$style.withOuterStyle]: withOuterStyle }]" class="_button" @click="copy">
<i class="ti ti-copy"></i> <i class="ti ti-copy"></i>
</button> </button>
<Suspense> <Suspense>
<template #fallback> <template #fallback>
<MkLoading/> <pre
class="_selectable"
:class="[$style.codeBlockFallbackRoot, {
[$style.outerStyle]: withOuterStyle,
}]"
><code :class="$style.codeBlockFallbackCode">Loading...</code></pre>
</template> </template>
<XCode v-if="show && lang" class="_selectable" :code="code" :lang="lang"/> <XCode
<pre v-else-if="show" class="_selectable" :class="$style.codeBlockFallbackRoot"><code :class="$style.codeBlockFallbackCode">{{ code }}</code></pre> v-if="show && lang"
class="_selectable"
:code="code"
:lang="lang"
:withOuterStyle="withOuterStyle"
/>
<pre
v-else-if="show"
class="_selectable"
:class="[$style.codeBlockFallbackRoot, {
[$style.outerStyle]: withOuterStyle,
}]"
><code :class="$style.codeBlockFallbackCode">{{ code }}</code></pre>
<button v-else :class="$style.codePlaceholderRoot" @click="show = true"> <button v-else :class="$style.codePlaceholderRoot" @click="show = true">
<div :class="$style.codePlaceholderContainer"> <div :class="$style.codePlaceholderContainer">
<div><i class="ti ti-code"></i> {{ i18n.ts.code }}</div> <div><i class="ti ti-code"></i> {{ i18n.ts.code }}</div>
@ -26,7 +43,6 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup> <script lang="ts" setup>
import { defineAsyncComponent, ref } from 'vue'; import { defineAsyncComponent, ref } from 'vue';
import * as os from '@/os.js';
import MkLoading from '@/components/global/MkLoading.vue'; import MkLoading from '@/components/global/MkLoading.vue';
import { i18n } from '@/i18n.js'; import { i18n } from '@/i18n.js';
import { copyToClipboard } from '@/utility/copy-to-clipboard.js'; import { copyToClipboard } from '@/utility/copy-to-clipboard.js';
@ -36,10 +52,12 @@ const props = withDefaults(defineProps<{
code: string; code: string;
forceShow?: boolean; forceShow?: boolean;
copyButton?: boolean; copyButton?: boolean;
withOuterStyle?: boolean;
lang?: string; lang?: string;
}>(), { }>(), {
copyButton: true, copyButton: true,
forceShow: false, forceShow: false,
withOuterStyle: true,
}); });
const show = ref(props.forceShow === true ? true : !prefer.s.dataSaver.code); const show = ref(props.forceShow === true ? true : !prefer.s.dataSaver.code);
@ -58,9 +76,15 @@ function copy() {
.codeBlockCopyButton { .codeBlockCopyButton {
position: absolute; position: absolute;
opacity: 0.5;
top: 0;
right: 0;
&.withOuterStyle {
top: 8px; top: 8px;
right: 8px; right: 8px;
opacity: 0.5; }
&:hover { &:hover {
opacity: 0.8; opacity: 0.8;
@ -70,11 +94,17 @@ function copy() {
.codeBlockFallbackRoot { .codeBlockFallbackRoot {
display: block; display: block;
overflow-wrap: anywhere; overflow-wrap: anywhere;
padding: 1em;
margin: 0;
overflow: auto; overflow: auto;
} }
.outerStyle.codeBlockFallbackRoot {
background: var(--MI_THEME-bg);
padding: 1em;
margin: .5em 0;
border-radius: 8px;
border: 1px solid var(--MI_THEME-divider);
}
.codeBlockFallbackCode { .codeBlockFallbackCode {
font-family: Consolas, Monaco, Andale Mono, Ubuntu Mono, monospace; font-family: Consolas, Monaco, Andale Mono, Ubuntu Mono, monospace;
} }

View File

@ -101,9 +101,9 @@ SPDX-License-Identifier: AGPL-3.0-only
<template #value>{{ Math.floor(job.progress) }}%</template> <template #value>{{ Math.floor(job.progress) }}%</template>
</MkKeyValue> </MkKeyValue>
</div> </div>
<MkFolder :withSpacer="false"> <MkFolder>
<template #label>Options</template> <template #label>Options</template>
<MkCode :code="JSON5.stringify(job.opts, null, '\t')" lang="js"/> <MkCode :code="JSON5.stringify(job.opts, null, '\t')" lang="json5" :withOuterStyle="false"/>
</MkFolder> </MkFolder>
</div> </div>
<div v-else-if="tab === 'timeline'"> <div v-else-if="tab === 'timeline'">
@ -143,7 +143,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</MkTl> </MkTl>
</div> </div>
<div v-else-if="tab === 'data'"> <div v-else-if="tab === 'data'">
<MkCode :code="JSON5.stringify(job.data, null, '\t')" lang="js"/> <MkCode :code="JSON5.stringify(job.data, null, '\t')" lang="json5"/>
</div> </div>
<div v-else-if="tab === 'dataEdit'" class="_gaps_s"> <div v-else-if="tab === 'dataEdit'" class="_gaps_s">
<MkCodeEditor v-model="editData" lang="json5"></MkCodeEditor> <MkCodeEditor v-model="editData" lang="json5"></MkCodeEditor>
@ -153,7 +153,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkCode :code="JSON5.stringify(job.returnValue, null, '\t')" lang="json5"/> <MkCode :code="JSON5.stringify(job.returnValue, null, '\t')" lang="json5"/>
</div> </div>
<div v-else-if="tab === 'error'" class="_gaps_s"> <div v-else-if="tab === 'error'" class="_gaps_s">
<MkCode v-for="log in job.stacktrace" :code="log" lang="stacktrace"/> <MkCode v-for="log in job.stacktrace" :code="log"/>
</div> </div>
<div v-else-if="tab === 'logs'"> <div v-else-if="tab === 'logs'">
<MkButton primary rounded @click="loadLogs()"><i class="ti ti-refresh"></i> Load logs</MkButton> <MkButton primary rounded @click="loadLogs()"><i class="ti ti-refresh"></i> Load logs</MkButton>