fix 2
This commit is contained in:
32
src/App.vue
32
src/App.vue
@@ -1,15 +1,26 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { defineAsyncComponent, onUnmounted, ref, watch } from 'vue';
|
||||||
import RequestPanel from './components/RequestPanel.vue';
|
import RequestPanel from './components/RequestPanel.vue';
|
||||||
import ResponsePanel from './components/ResponsePanel.vue';
|
import ResponsePanel from './components/ResponsePanel.vue';
|
||||||
import Sidebar from './components/Sidebar.vue';
|
import Sidebar from './components/Sidebar.vue';
|
||||||
import SettingsModal from './components/SettingsModal.vue';
|
|
||||||
import { ref, onUnmounted } from 'vue';
|
const SettingsModal = defineAsyncComponent(() => import('./components/SettingsModal.vue'));
|
||||||
|
const PANEL_HEIGHT_STORAGE_KEY = 'topPanelHeight';
|
||||||
|
const DEFAULT_TOP_PANEL_HEIGHT = 50;
|
||||||
|
|
||||||
|
const clampPanelHeight = (value: number) => {
|
||||||
|
if (Number.isNaN(value)) return DEFAULT_TOP_PANEL_HEIGHT;
|
||||||
|
return Math.min(80, Math.max(20, value));
|
||||||
|
};
|
||||||
|
|
||||||
const showSettings = ref(false);
|
const showSettings = ref(false);
|
||||||
const topPanelHeight = ref(50); // Percentage
|
const topPanelHeight = ref(
|
||||||
|
clampPanelHeight(Number(localStorage.getItem(PANEL_HEIGHT_STORAGE_KEY)) || DEFAULT_TOP_PANEL_HEIGHT)
|
||||||
|
);
|
||||||
const isDragging = ref(false);
|
const isDragging = ref(false);
|
||||||
|
|
||||||
const startDrag = () => {
|
const startDrag = (event: MouseEvent) => {
|
||||||
|
event.preventDefault();
|
||||||
isDragging.value = true;
|
isDragging.value = true;
|
||||||
window.addEventListener('mousemove', onDrag);
|
window.addEventListener('mousemove', onDrag);
|
||||||
window.addEventListener('mouseup', stopDrag);
|
window.addEventListener('mouseup', stopDrag);
|
||||||
@@ -19,13 +30,8 @@ const onDrag = (e: MouseEvent) => {
|
|||||||
if (!isDragging.value) return;
|
if (!isDragging.value) return;
|
||||||
|
|
||||||
const containerHeight = window.innerHeight;
|
const containerHeight = window.innerHeight;
|
||||||
let newPercentage = (e.clientY / containerHeight) * 100;
|
const newPercentage = (e.clientY / containerHeight) * 100;
|
||||||
|
topPanelHeight.value = clampPanelHeight(newPercentage);
|
||||||
// Clamp between 20% and 80%
|
|
||||||
if (newPercentage < 20) newPercentage = 20;
|
|
||||||
if (newPercentage > 80) newPercentage = 80;
|
|
||||||
|
|
||||||
topPanelHeight.value = newPercentage;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const stopDrag = () => {
|
const stopDrag = () => {
|
||||||
@@ -38,6 +44,10 @@ onUnmounted(() => {
|
|||||||
window.removeEventListener('mousemove', onDrag);
|
window.removeEventListener('mousemove', onDrag);
|
||||||
window.removeEventListener('mouseup', stopDrag);
|
window.removeEventListener('mouseup', stopDrag);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
watch(topPanelHeight, (value) => {
|
||||||
|
localStorage.setItem(PANEL_HEIGHT_STORAGE_KEY, clampPanelHeight(value).toString());
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|||||||
65
src/components/CodeEditor.vue
Normal file
65
src/components/CodeEditor.vue
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { computed } from 'vue';
|
||||||
|
import { Codemirror } from 'vue-codemirror';
|
||||||
|
import { json } from '@codemirror/lang-json';
|
||||||
|
import { oneDark } from '@codemirror/theme-one-dark';
|
||||||
|
import { EditorView } from '@codemirror/view';
|
||||||
|
import { useSettingsStore } from '../stores/settingsStore';
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<{
|
||||||
|
modelValue?: string;
|
||||||
|
placeholder?: string;
|
||||||
|
readOnly?: boolean;
|
||||||
|
language?: 'json' | 'text';
|
||||||
|
}>(), {
|
||||||
|
modelValue: '',
|
||||||
|
placeholder: '',
|
||||||
|
readOnly: false,
|
||||||
|
language: 'text',
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
'update:modelValue': [value: string];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const settings = useSettingsStore();
|
||||||
|
|
||||||
|
const extensions = computed(() => {
|
||||||
|
const theme = EditorView.theme({
|
||||||
|
'&': {
|
||||||
|
backgroundColor: 'transparent !important',
|
||||||
|
height: '100%',
|
||||||
|
},
|
||||||
|
'.cm-content, .cm-gutter': {
|
||||||
|
fontFamily: `${settings.editorFontFamily} !important`,
|
||||||
|
},
|
||||||
|
'.cm-gutters': {
|
||||||
|
backgroundColor: 'transparent !important',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return [
|
||||||
|
oneDark,
|
||||||
|
theme,
|
||||||
|
...(props.language === 'json' ? [json()] : []),
|
||||||
|
...(props.readOnly ? [EditorView.editable.of(false)] : []),
|
||||||
|
];
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Codemirror
|
||||||
|
:model-value="props.modelValue"
|
||||||
|
:placeholder="props.placeholder"
|
||||||
|
:style="{
|
||||||
|
height: '100%',
|
||||||
|
fontSize: settings.editorFontSize + 'px',
|
||||||
|
fontFamily: settings.editorFontFamily,
|
||||||
|
}"
|
||||||
|
:autofocus="false"
|
||||||
|
:indent-with-tab="true"
|
||||||
|
:tab-size="2"
|
||||||
|
:extensions="extensions"
|
||||||
|
@update:model-value="emit('update:modelValue', $event)"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
@@ -1,55 +1,32 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed } from 'vue';
|
import { defineAsyncComponent, ref } from 'vue';
|
||||||
import { useRequestStore } from '../stores/requestStore';
|
import { useRequestStore } from '../stores/requestStore';
|
||||||
import { useSettingsStore } from '../stores/settingsStore';
|
|
||||||
import KeyValueEditor from './KeyValueEditor.vue';
|
import KeyValueEditor from './KeyValueEditor.vue';
|
||||||
import AuthPanel from './AuthPanel.vue';
|
import AuthPanel from './AuthPanel.vue';
|
||||||
import CustomSelect from './CustomSelect.vue';
|
import CustomSelect from './CustomSelect.vue';
|
||||||
import { invoke } from '@tauri-apps/api/core';
|
import { invoke } from '@tauri-apps/api/core';
|
||||||
import { Codemirror } from 'vue-codemirror';
|
|
||||||
import { json } from '@codemirror/lang-json';
|
|
||||||
import { oneDark } from '@codemirror/theme-one-dark';
|
|
||||||
import { EditorView } from '@codemirror/view';
|
|
||||||
import { Play, Loader2 } from 'lucide-vue-next';
|
import { Play, Loader2 } from 'lucide-vue-next';
|
||||||
|
|
||||||
|
const CodeEditor = defineAsyncComponent(() => import('./CodeEditor.vue'));
|
||||||
const store = useRequestStore();
|
const store = useRequestStore();
|
||||||
const settings = useSettingsStore();
|
|
||||||
const activeTab = ref('params');
|
const activeTab = ref('params');
|
||||||
const isLoading = ref(false);
|
const isLoading = ref(false);
|
||||||
|
|
||||||
const extensions = computed(() => {
|
|
||||||
const theme = EditorView.theme({
|
|
||||||
"&": {
|
|
||||||
backgroundColor: "transparent !important",
|
|
||||||
height: "100%",
|
|
||||||
},
|
|
||||||
".cm-content, .cm-gutter": {
|
|
||||||
fontFamily: `${settings.editorFontFamily} !important`
|
|
||||||
},
|
|
||||||
".cm-gutters": {
|
|
||||||
backgroundColor: "transparent !important"
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return [json(), oneDark, theme];
|
|
||||||
});
|
|
||||||
|
|
||||||
const methods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'];
|
const methods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'];
|
||||||
|
|
||||||
const executeRequest = async () => {
|
const executeRequest = async () => {
|
||||||
if (isLoading.value || !store.activeRequest.url) return;
|
if (isLoading.value || !store.activeRequest.url) return;
|
||||||
|
|
||||||
isLoading.value = true;
|
isLoading.value = true;
|
||||||
|
store.setRequestError(null);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Prepare headers and params map
|
|
||||||
const headers: Record<string, string> = {};
|
const headers: Record<string, string> = {};
|
||||||
store.activeRequest.headers.filter(h => h.enabled && h.key).forEach(h => headers[h.key] = h.value);
|
store.activeRequest.headers.filter(h => h.enabled && h.key).forEach(h => headers[h.key] = h.value);
|
||||||
|
|
||||||
const params: Record<string, string> = {};
|
const params: Record<string, string> = {};
|
||||||
store.activeRequest.params.filter(p => p.enabled && p.key).forEach(p => params[p.key] = p.value);
|
store.activeRequest.params.filter(p => p.enabled && p.key).forEach(p => params[p.key] = p.value);
|
||||||
|
|
||||||
// Execute
|
|
||||||
const response: any = await invoke('execute_request', {
|
const response: any = await invoke('execute_request', {
|
||||||
method: store.activeRequest.method,
|
method: store.activeRequest.method,
|
||||||
url: store.activeRequest.url,
|
url: store.activeRequest.url,
|
||||||
@@ -59,7 +36,7 @@ const executeRequest = async () => {
|
|||||||
auth: store.activeRequest.auth,
|
auth: store.activeRequest.auth,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Update Store
|
store.setRequestError(null);
|
||||||
store.activeRequest.response = {
|
store.activeRequest.response = {
|
||||||
status: response.status,
|
status: response.status,
|
||||||
headers: response.headers,
|
headers: response.headers,
|
||||||
@@ -68,12 +45,12 @@ const executeRequest = async () => {
|
|||||||
size: new Blob([response.body]).size
|
size: new Blob([response.body]).size
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add to history if successful
|
|
||||||
store.addToHistory(store.activeRequest);
|
store.addToHistory(store.activeRequest);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
alert('Request Failed: ' + error);
|
store.activeRequest.response = undefined;
|
||||||
|
store.setRequestError(String(error));
|
||||||
} finally {
|
} finally {
|
||||||
isLoading.value = false;
|
isLoading.value = false;
|
||||||
}
|
}
|
||||||
@@ -109,6 +86,13 @@ const executeRequest = async () => {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="store.requestError"
|
||||||
|
class="mx-4 mt-4 rounded-lg border border-rose-500/30 bg-rose-500/10 px-3 py-2 text-sm text-rose-200"
|
||||||
|
>
|
||||||
|
{{ store.requestError }}
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Configuration Tabs -->
|
<!-- Configuration Tabs -->
|
||||||
<div class="flex border-b border-slate-800">
|
<div class="flex border-b border-slate-800">
|
||||||
<button
|
<button
|
||||||
@@ -137,18 +121,10 @@ const executeRequest = async () => {
|
|||||||
/>
|
/>
|
||||||
</KeepAlive>
|
</KeepAlive>
|
||||||
<div v-if="activeTab === 'body'" class="h-full w-full overflow-hidden">
|
<div v-if="activeTab === 'body'" class="h-full w-full overflow-hidden">
|
||||||
<Codemirror
|
<CodeEditor
|
||||||
v-model="store.activeRequest.body"
|
v-model="store.activeRequest.body"
|
||||||
placeholder="Request Body (JSON)"
|
placeholder="Request Body (JSON)"
|
||||||
:style="{
|
language="json"
|
||||||
height: '100%',
|
|
||||||
fontSize: settings.editorFontSize + 'px',
|
|
||||||
fontFamily: settings.editorFontFamily
|
|
||||||
}"
|
|
||||||
:autofocus="true"
|
|
||||||
:indent-with-tab="true"
|
|
||||||
:tab-size="2"
|
|
||||||
:extensions="extensions"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<KeepAlive>
|
<KeepAlive>
|
||||||
|
|||||||
@@ -1,16 +1,12 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, ref } from 'vue';
|
import { computed, defineAsyncComponent, ref } from 'vue';
|
||||||
import { useRequestStore } from '../stores/requestStore';
|
import { useRequestStore } from '../stores/requestStore';
|
||||||
import { useSettingsStore } from '../stores/settingsStore';
|
|
||||||
import { Codemirror } from 'vue-codemirror';
|
|
||||||
import { json } from '@codemirror/lang-json';
|
|
||||||
import { oneDark } from '@codemirror/theme-one-dark';
|
|
||||||
import { EditorView } from '@codemirror/view';
|
|
||||||
import { Clipboard, Check } from 'lucide-vue-next';
|
import { Clipboard, Check } from 'lucide-vue-next';
|
||||||
|
|
||||||
|
const CodeEditor = defineAsyncComponent(() => import('./CodeEditor.vue'));
|
||||||
const store = useRequestStore();
|
const store = useRequestStore();
|
||||||
const settings = useSettingsStore();
|
|
||||||
const isCopied = ref(false);
|
const isCopied = ref(false);
|
||||||
|
const activeTab = ref<'body' | 'headers'>('body');
|
||||||
|
|
||||||
const isJsonResponse = computed(() => {
|
const isJsonResponse = computed(() => {
|
||||||
const response = store.activeRequest.response;
|
const response = store.activeRequest.response;
|
||||||
@@ -29,26 +25,14 @@ const isJsonResponse = computed(() => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const extensions = computed(() => {
|
const formattedHeaders = computed(() => {
|
||||||
const theme = EditorView.theme({
|
const response = store.activeRequest.response;
|
||||||
"&": {
|
if (!response) return '';
|
||||||
backgroundColor: "transparent !important",
|
|
||||||
height: "100%"
|
|
||||||
},
|
|
||||||
".cm-content, .cm-gutter": {
|
|
||||||
fontFamily: `${settings.editorFontFamily} !important`
|
|
||||||
},
|
|
||||||
".cm-gutters": {
|
|
||||||
backgroundColor: "transparent !important"
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return [
|
return Object.entries(response.headers)
|
||||||
oneDark,
|
.sort(([keyA], [keyB]) => keyA.localeCompare(keyB))
|
||||||
theme,
|
.map(([key, value]) => `${key}: ${value}`)
|
||||||
EditorView.editable.of(false),
|
.join('\n');
|
||||||
...(isJsonResponse.value ? [json()] : []),
|
|
||||||
];
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const formattedBody = computed(() => {
|
const formattedBody = computed(() => {
|
||||||
@@ -61,6 +45,10 @@ const formattedBody = computed(() => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const displayedContent = computed(() => (
|
||||||
|
activeTab.value === 'headers' ? formattedHeaders.value : formattedBody.value
|
||||||
|
));
|
||||||
|
|
||||||
const statusColor = computed(() => {
|
const statusColor = computed(() => {
|
||||||
const s = store.activeRequest.response?.status || 0;
|
const s = store.activeRequest.response?.status || 0;
|
||||||
if (s >= 200 && s < 300) return 'text-emerald-400';
|
if (s >= 200 && s < 300) return 'text-emerald-400';
|
||||||
@@ -69,9 +57,9 @@ const statusColor = computed(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const copyToClipboard = async () => {
|
const copyToClipboard = async () => {
|
||||||
if (!formattedBody.value) return;
|
if (!displayedContent.value) return;
|
||||||
try {
|
try {
|
||||||
await navigator.clipboard.writeText(formattedBody.value);
|
await navigator.clipboard.writeText(displayedContent.value);
|
||||||
isCopied.value = true;
|
isCopied.value = true;
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
isCopied.value = false;
|
isCopied.value = false;
|
||||||
@@ -99,29 +87,49 @@ const copyToClipboard = async () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button
|
<div class="flex items-center gap-2">
|
||||||
@click="copyToClipboard"
|
<div class="flex rounded-lg border border-slate-800 bg-slate-900 p-0.5">
|
||||||
class="p-1.5 text-slate-400 hover:text-indigo-400 hover:bg-indigo-500/10 rounded transition-colors"
|
<button
|
||||||
title="Copy Body"
|
@click="activeTab = 'body'"
|
||||||
>
|
class="rounded-md px-2.5 py-1 transition-colors"
|
||||||
<Check v-if="isCopied" class="w-3.5 h-3.5" />
|
:class="activeTab === 'body' ? 'bg-indigo-500/15 text-indigo-300' : 'text-slate-400 hover:text-slate-200'"
|
||||||
<Clipboard v-else class="w-3.5 h-3.5" />
|
>
|
||||||
</button>
|
Body
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
@click="activeTab = 'headers'"
|
||||||
|
class="rounded-md px-2.5 py-1 transition-colors"
|
||||||
|
:class="activeTab === 'headers' ? 'bg-indigo-500/15 text-indigo-300' : 'text-slate-400 hover:text-slate-200'"
|
||||||
|
>
|
||||||
|
Headers
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button
|
||||||
|
@click="copyToClipboard"
|
||||||
|
class="p-1.5 text-slate-400 hover:text-indigo-400 hover:bg-indigo-500/10 rounded transition-colors"
|
||||||
|
:title="activeTab === 'headers' ? 'Copy Headers' : 'Copy Body'"
|
||||||
|
>
|
||||||
|
<Check v-if="isCopied" class="w-3.5 h-3.5" />
|
||||||
|
<Clipboard v-else class="w-3.5 h-3.5" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Output -->
|
<!-- Output -->
|
||||||
<div class="flex-1 overflow-hidden">
|
<div class="flex-1 overflow-hidden">
|
||||||
<Codemirror
|
<CodeEditor
|
||||||
:model-value="formattedBody"
|
:model-value="displayedContent"
|
||||||
:style="{
|
:language="activeTab === 'body' && isJsonResponse ? 'json' : 'text'"
|
||||||
height: '100%',
|
:read-only="true"
|
||||||
fontSize: settings.editorFontSize + 'px',
|
|
||||||
fontFamily: settings.editorFontFamily
|
|
||||||
}"
|
|
||||||
:extensions="extensions"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-else-if="store.requestError" class="flex-1 flex items-center justify-center p-6">
|
||||||
|
<div class="max-w-2xl rounded-xl border border-rose-500/30 bg-rose-500/10 p-4 text-sm text-rose-200">
|
||||||
|
{{ store.requestError }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div v-else class="flex-1 flex items-center justify-center text-slate-600 text-sm">
|
<div v-else class="flex-1 flex items-center justify-center text-slate-600 text-sm">
|
||||||
No response yet
|
No response yet
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -128,6 +128,7 @@ export const useRequestStore = defineStore('request', () => {
|
|||||||
// State
|
// State
|
||||||
const history = ref<RequestData[]>([]);
|
const history = ref<RequestData[]>([]);
|
||||||
const activeRequest = ref<RequestData>(createDefaultRequest());
|
const activeRequest = ref<RequestData>(createDefaultRequest());
|
||||||
|
const requestError = ref<string | null>(null);
|
||||||
|
|
||||||
// Load history from local storage
|
// Load history from local storage
|
||||||
const savedHistory = localStorage.getItem('request_history');
|
const savedHistory = localStorage.getItem('request_history');
|
||||||
@@ -169,6 +170,7 @@ export const useRequestStore = defineStore('request', () => {
|
|||||||
|
|
||||||
const resetActiveRequest = () => {
|
const resetActiveRequest = () => {
|
||||||
activeRequest.value = createDefaultRequest();
|
activeRequest.value = createDefaultRequest();
|
||||||
|
requestError.value = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
const loadRequest = (req: RequestData) => {
|
const loadRequest = (req: RequestData) => {
|
||||||
@@ -178,6 +180,11 @@ export const useRequestStore = defineStore('request', () => {
|
|||||||
if (loaded.headers.length === 0) loaded.headers.push(createEmptyKeyValue());
|
if (loaded.headers.length === 0) loaded.headers.push(createEmptyKeyValue());
|
||||||
|
|
||||||
activeRequest.value = loaded;
|
activeRequest.value = loaded;
|
||||||
|
requestError.value = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const setRequestError = (message: string | null) => {
|
||||||
|
requestError.value = message;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Watch and Save
|
// Watch and Save
|
||||||
@@ -188,10 +195,12 @@ export const useRequestStore = defineStore('request', () => {
|
|||||||
return {
|
return {
|
||||||
history,
|
history,
|
||||||
activeRequest,
|
activeRequest,
|
||||||
|
requestError,
|
||||||
addToHistory,
|
addToHistory,
|
||||||
clearHistory,
|
clearHistory,
|
||||||
deleteHistoryItem,
|
deleteHistoryItem,
|
||||||
loadRequest,
|
loadRequest,
|
||||||
resetActiveRequest
|
resetActiveRequest,
|
||||||
|
setRequestError,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -7,6 +7,21 @@ const host = process.env.TAURI_DEV_HOST;
|
|||||||
// https://vite.dev/config/
|
// https://vite.dev/config/
|
||||||
export default defineConfig(async () => ({
|
export default defineConfig(async () => ({
|
||||||
plugins: [vue()],
|
plugins: [vue()],
|
||||||
|
build: {
|
||||||
|
rollupOptions: {
|
||||||
|
output: {
|
||||||
|
manualChunks: {
|
||||||
|
codemirror: [
|
||||||
|
'vue-codemirror',
|
||||||
|
'@codemirror/lang-json',
|
||||||
|
'@codemirror/theme-one-dark',
|
||||||
|
'@codemirror/view',
|
||||||
|
],
|
||||||
|
vue: ['vue', 'pinia'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
// Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build`
|
// Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build`
|
||||||
//
|
//
|
||||||
|
|||||||
Reference in New Issue
Block a user