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>
This commit is contained in:
		
							parent
							
								
									feedad7d8b
								
							
						
					
					
						commit
						1a8243f1ca
					
				
					 12 changed files with 380 additions and 93 deletions
				
			
		| 
						 | 
				
			
			@ -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を返却することでノートを非表示にできるようになりました
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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": {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										166
									
								
								packages/frontend/src/components/MkCodeEditor.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										166
									
								
								packages/frontend/src/components/MkCodeEditor.vue
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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>
 | 
			
		||||
| 
						 | 
				
			
			@ -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}`"/>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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();
 | 
			
		||||
});
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										31
									
								
								packages/frontend/src/scripts/code-highlighter.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								packages/frontend/src/scripts/code-highlighter.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										87
									
								
								pnpm-lock.yaml
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										87
									
								
								pnpm-lock.yaml
									
										
									
										generated
									
									
									
								
							| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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(),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue