mirror of
https://github.com/doocs/md.git
synced 2024-11-28 13:36:32 +08:00
Compare commits
6 Commits
377150060d
...
356beb5ea6
Author | SHA1 | Date | |
---|---|---|---|
|
356beb5ea6 | ||
|
e8b2c18c6d | ||
|
8e93889ae4 | ||
|
d8a3d06330 | ||
|
ecb51c10f1 | ||
|
21d5259f35 |
@ -93,7 +93,7 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<script id="MathJax-script" src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js"></script>
|
<script id="MathJax-script" src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js"></script>
|
||||||
<script type="module" src="/src/main.js"></script>
|
<script type="module" src="/src/main.ts"></script>
|
||||||
</body>
|
</body>
|
||||||
<script src="https://cdn-doocs.oss-cn-shenzhen.aliyuncs.com/gh/wechatsync/article-syncjs@latest/dist/main.js"></script>
|
<script src="https://cdn-doocs.oss-cn-shenzhen.aliyuncs.com/gh/wechatsync/article-syncjs@latest/dist/main.js"></script>
|
||||||
</html>
|
</html>
|
||||||
|
2810
package-lock.json
generated
2810
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
49
package.json
49
package.json
@ -8,7 +8,8 @@
|
|||||||
"dev": "vite --host",
|
"dev": "vite --host",
|
||||||
"build": "run-p type-check \"build:only {@}\" --",
|
"build": "run-p type-check \"build:only {@}\" --",
|
||||||
"build:only": "vite build",
|
"build:only": "vite build",
|
||||||
"build:h5-netlify": "cross-env SERVER_ENV=NETLIFY vite build",
|
"build:h5-netlify": "run-p type-check \"build:h5-netlify:only {@}\" --",
|
||||||
|
"build:h5-netlify:only": "cross-env SERVER_ENV=NETLIFY vite build",
|
||||||
"build:cli": "npm run build && npm run shx rm -rf md-cli/dist && npm run shx rm -rf dist/**/*.map && npm run shx cp -r dist md-cli/ && cd md-cli && npm run pack",
|
"build:cli": "npm run build && npm run shx rm -rf md-cli/dist && npm run shx rm -rf dist/**/*.map && npm run shx cp -r dist md-cli/ && cd md-cli && npm run pack",
|
||||||
"build:analyze": "cross-env ANALYZE=true vite build",
|
"build:analyze": "cross-env ANALYZE=true vite build",
|
||||||
"preview": "npm run build && vite preview",
|
"preview": "npm run build && vite preview",
|
||||||
@ -19,8 +20,8 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@element-plus/icons-vue": "^2.3.1",
|
"@element-plus/icons-vue": "^2.3.1",
|
||||||
"@vueuse/core": "^11.0.1",
|
"@vueuse/core": "^11.1.0",
|
||||||
"axios": "^1.7.4",
|
"axios": "^1.7.7",
|
||||||
"buffer-from": "^1.1.2",
|
"buffer-from": "^1.1.2",
|
||||||
"class-variance-authority": "^0.7.0",
|
"class-variance-authority": "^0.7.0",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
@ -29,54 +30,54 @@
|
|||||||
"cos-js-sdk-v5": "^1.8.4",
|
"cos-js-sdk-v5": "^1.8.4",
|
||||||
"crypto-js": "^4.2.0",
|
"crypto-js": "^4.2.0",
|
||||||
"csstype": "^3.1.3",
|
"csstype": "^3.1.3",
|
||||||
"element-plus": "^2.8.0",
|
"element-plus": "^2.8.3",
|
||||||
"es-toolkit": "^1.16.0",
|
"es-toolkit": "^1.19.0",
|
||||||
"form-data": "4.0.0",
|
"form-data": "4.0.0",
|
||||||
"highlight.js": "^11.10.0",
|
"highlight.js": "^11.10.0",
|
||||||
"juice": "^8.0.0",
|
"juice": "^11.0.0",
|
||||||
"lucide-vue-next": "^0.428.0",
|
"lucide-vue-next": "^0.441.0",
|
||||||
"marked": "^14.1.1",
|
"marked": "^14.1.2",
|
||||||
"mermaid": "^11.1.0",
|
"mermaid": "^11.2.1",
|
||||||
"minio": "7.1.3",
|
"minio": "7.1.3",
|
||||||
"node-fetch": "^3.3.2",
|
"node-fetch": "^3.3.2",
|
||||||
"pinia": "^2.2.2",
|
"pinia": "^2.2.2",
|
||||||
"qiniu-js": "^3.4.2",
|
"qiniu-js": "^3.4.2",
|
||||||
"radix-vue": "^1.9.4",
|
"radix-vue": "^1.9.5",
|
||||||
"tailwind-merge": "^2.5.2",
|
"tailwind-merge": "^2.5.2",
|
||||||
"tailwindcss-animate": "^1.0.7",
|
"tailwindcss-animate": "^1.0.7",
|
||||||
"tiny-oss": "^0.5.1",
|
"tiny-oss": "^0.5.1",
|
||||||
"uuid": "^10.0.0",
|
"uuid": "^10.0.0",
|
||||||
"vue": "^3.4.38"
|
"vue": "^3.5.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@antfu/eslint-config": "2.26.0",
|
"@antfu/eslint-config": "3.6.2",
|
||||||
"@types/buffer-from": "^1.1.3",
|
"@types/buffer-from": "^1.1.3",
|
||||||
"@types/codemirror": "^5.60.15",
|
"@types/codemirror": "^5.60.15",
|
||||||
"@types/crypto-js": "^4.2.2",
|
"@types/crypto-js": "^4.2.2",
|
||||||
"@types/node": "^22.4.1",
|
"@types/node": "^22.5.5",
|
||||||
"@types/uuid": "^10.0.0",
|
"@types/uuid": "^10.0.0",
|
||||||
"@unocss/eslint-plugin": "^0.62.2",
|
"@unocss/eslint-plugin": "^0.62.4",
|
||||||
"@vitejs/plugin-vue": "^5.1.2",
|
"@vitejs/plugin-vue": "^5.1.3",
|
||||||
"autoprefixer": "^10.4.20",
|
"autoprefixer": "^10.4.20",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"eslint": "^9.9.0",
|
"eslint": "^9.10.0",
|
||||||
"eslint-plugin-format": "^0.1.2",
|
"eslint-plugin-format": "^0.1.2",
|
||||||
"less": "^4.2.0",
|
"less": "^4.2.0",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"postcss": "^8.4.41",
|
"postcss": "^8.4.47",
|
||||||
"prettier": "^3.3.3",
|
"prettier": "^3.3.3",
|
||||||
"rollup-plugin-visualizer": "^5.12.0",
|
"rollup-plugin-visualizer": "^5.12.0",
|
||||||
"shx": "^0.3.4",
|
"shx": "^0.3.4",
|
||||||
"simple-git-hooks": "^2.11.1",
|
"simple-git-hooks": "^2.11.1",
|
||||||
"tailwindcss": "^3.4.10",
|
"tailwindcss": "^3.4.12",
|
||||||
"typescript": "^5.5.4",
|
"typescript": "^5.6.2",
|
||||||
"unocss": "^0.62.2",
|
"unocss": "^0.62.4",
|
||||||
"unplugin-auto-import": "^0.18.2",
|
"unplugin-auto-import": "^0.18.3",
|
||||||
"unplugin-vue-components": "^0.27.4",
|
"unplugin-vue-components": "^0.27.4",
|
||||||
"vite": "^5.4.2",
|
"vite": "^5.4.6",
|
||||||
"vite-plugin-node-polyfills": "^0.22.0",
|
"vite-plugin-node-polyfills": "^0.22.0",
|
||||||
"vite-plugin-vue-devtools": "^7.3.9",
|
"vite-plugin-vue-devtools": "^7.4.5",
|
||||||
"vue-tsc": "^2.0.29"
|
"vue-tsc": "^2.1.6"
|
||||||
},
|
},
|
||||||
"simple-git-hooks": {
|
"simple-git-hooks": {
|
||||||
"pre-commit": "npx lint-staged"
|
"pre-commit": "npx lint-staged"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<script setup>
|
<script setup lang="ts">
|
||||||
import CodemirrorEditor from '@/views/CodemirrorEditor.vue'
|
import CodemirrorEditor from '@/views/CodemirrorEditor.vue'
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -94,12 +94,3 @@ section {
|
|||||||
display: table;
|
display: table;
|
||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ele ui */
|
|
||||||
.el-form-item {
|
|
||||||
margin-bottom: 0 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-tooltip {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
<script setup>
|
<script setup lang="ts">
|
||||||
|
import { useDisplayStore, useStore } from '@/stores'
|
||||||
|
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
|
|
||||||
import { useStore } from '@/stores'
|
|
||||||
|
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
|
const displayStore = useDisplayStore()
|
||||||
|
|
||||||
function editTabName() {
|
function editTabName() {
|
||||||
ElMessageBox.prompt(`请输入新的方案名称`, `编辑方案名称`, {
|
ElMessageBox.prompt(`请输入新的方案名称`, `编辑方案名称`, {
|
||||||
@ -23,7 +24,7 @@ function editTabName() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleTabsEdit(targetName, action) {
|
function handleTabsEdit(targetName: string, action: string) {
|
||||||
if (action === `add`) {
|
if (action === `add`) {
|
||||||
ElMessageBox.prompt(`请输入方案名称`, `新建自定义 CSS`, {
|
ElMessageBox.prompt(`请输入方案名称`, `新建自定义 CSS`, {
|
||||||
confirmButtonText: `确认`,
|
confirmButtonText: `确认`,
|
||||||
@ -67,7 +68,7 @@ function handleTabsEdit(targetName, action) {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<transition enter-active-class="bounceInRight">
|
<transition enter-active-class="bounceInRight">
|
||||||
<el-col v-show="store.isShowCssEditor" :span="8" class="cssEditor-wrapper order-1 h-full flex flex-col border-l-1">
|
<el-col v-show="displayStore.isShowCssEditor" :span="8" class="cssEditor-wrapper order-1 h-full flex flex-col border-l-1">
|
||||||
<el-tabs
|
<el-tabs
|
||||||
v-model="store.cssContentConfig.active"
|
v-model="store.cssContentConfig.active"
|
||||||
type="border-card"
|
type="border-card"
|
||||||
@ -86,7 +87,7 @@ function handleTabsEdit(targetName, action) {
|
|||||||
<el-icon
|
<el-icon
|
||||||
v-if="store.cssContentConfig.active === item.name"
|
v-if="store.cssContentConfig.active === item.name"
|
||||||
class="ml-1"
|
class="ml-1"
|
||||||
@click="editTabName(item.name)"
|
@click="editTabName()"
|
||||||
>
|
>
|
||||||
<ElIconEditPen />
|
<ElIconEditPen />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
@ -142,7 +143,7 @@ function handleTabsEdit(targetName, action) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
:deep(.el-tabs__content) {
|
:deep(.el-tabs__content) {
|
||||||
padding: 0;
|
padding: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 当 tab 为激活状态时,隐藏关闭按钮
|
// 当 tab 为激活状态时,隐藏关闭按钮
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<script setup>
|
<script setup lang="ts">
|
||||||
import {
|
import {
|
||||||
Dialog,
|
Dialog,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
@ -16,7 +16,7 @@ const props = defineProps({
|
|||||||
|
|
||||||
const emit = defineEmits([`close`])
|
const emit = defineEmits([`close`])
|
||||||
|
|
||||||
function onUpdate(val) {
|
function onUpdate(val: boolean) {
|
||||||
if (!val) {
|
if (!val) {
|
||||||
emit(`close`)
|
emit(`close`)
|
||||||
}
|
}
|
||||||
@ -28,7 +28,7 @@ const links = [
|
|||||||
{ label: `GitCode 仓库`, url: `https://gitcode.com/doocs/md` },
|
{ label: `GitCode 仓库`, url: `https://gitcode.com/doocs/md` },
|
||||||
]
|
]
|
||||||
|
|
||||||
function onRedirect(url) {
|
function onRedirect(url: string) {
|
||||||
window.open(url, `_blank`)
|
window.open(url, `_blank`)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,25 +1,28 @@
|
|||||||
<script setup>
|
<script setup lang="ts">
|
||||||
import { useStore } from '@/stores'
|
import {
|
||||||
|
MenubarContent,
|
||||||
|
MenubarItem,
|
||||||
|
MenubarMenu,
|
||||||
|
MenubarTrigger,
|
||||||
|
} from '@/components/ui/menubar'
|
||||||
|
import { useDisplayStore } from '@/stores'
|
||||||
|
import { TableIcon, UploadCloudIcon } from 'lucide-vue-next'
|
||||||
|
|
||||||
const store = useStore()
|
const { toggleShowInsertFormDialog, toggleShowUploadImgDialog } = useDisplayStore()
|
||||||
|
|
||||||
const { toggleShowInsertFormDialog, toggleShowUploadImgDialog } = store
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<MenubarMenu>
|
<MenubarMenu>
|
||||||
<MenubarTrigger> 编辑 </MenubarTrigger>
|
<MenubarTrigger>
|
||||||
|
编辑
|
||||||
|
</MenubarTrigger>
|
||||||
<MenubarContent align="start">
|
<MenubarContent align="start">
|
||||||
<MenubarItem @click="toggleShowUploadImgDialog()">
|
<MenubarItem @click="toggleShowUploadImgDialog()">
|
||||||
<el-icon class="mr-2 h-4 w-4">
|
<UploadCloudIcon class="mr-2 h-4 w-4" />
|
||||||
<ElIconUpload />
|
|
||||||
</el-icon>
|
|
||||||
上传图片
|
上传图片
|
||||||
</MenubarItem>
|
</MenubarItem>
|
||||||
<MenubarItem @click="toggleShowInsertFormDialog()">
|
<MenubarItem @click="toggleShowInsertFormDialog()">
|
||||||
<el-icon class="mr-2 h-4 w-4">
|
<TableIcon class="mr-2 h-4 w-4" />
|
||||||
<ElIconGrid />
|
|
||||||
</el-icon>
|
|
||||||
插入表格
|
插入表格
|
||||||
</MenubarItem>
|
</MenubarItem>
|
||||||
</MenubarContent>
|
</MenubarContent>
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<script setup>
|
<script setup lang="ts">
|
||||||
import { storeToRefs } from 'pinia'
|
|
||||||
|
|
||||||
import { useStore } from '@/stores'
|
import { useStore } from '@/stores'
|
||||||
|
|
||||||
|
import { storeToRefs } from 'pinia'
|
||||||
|
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<script setup>
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
|
|
||||||
import AboutDialog from './AboutDialog.vue'
|
import AboutDialog from './AboutDialog.vue'
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
<script setup>
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue'
|
|
||||||
import { storeToRefs } from 'pinia'
|
|
||||||
import {
|
import {
|
||||||
Dialog,
|
Dialog,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
@ -8,30 +6,34 @@ import {
|
|||||||
DialogHeader,
|
DialogHeader,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
} from '@/components/ui/dialog'
|
} from '@/components/ui/dialog'
|
||||||
|
|
||||||
import { useStore } from '@/stores'
|
import { useStore } from '@/stores'
|
||||||
|
import { storeToRefs } from 'pinia'
|
||||||
|
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
const { output } = storeToRefs(store)
|
const { output } = storeToRefs(store)
|
||||||
|
|
||||||
const dialogVisible = ref(false)
|
const dialogVisible = ref(false)
|
||||||
|
|
||||||
const form = ref({
|
const form = ref<any>({
|
||||||
title: ``,
|
title: ``,
|
||||||
desc: ``,
|
desc: ``,
|
||||||
thumb: ``,
|
thumb: ``,
|
||||||
content: ``,
|
content: ``,
|
||||||
|
auto: {},
|
||||||
})
|
})
|
||||||
|
|
||||||
function prePost() {
|
function prePost() {
|
||||||
let auto = {}
|
let auto = {}
|
||||||
try {
|
try {
|
||||||
auto = {
|
auto = {
|
||||||
thumb: document.querySelector(`#output img`)?.src,
|
thumb: document.querySelector<HTMLImageElement>(`#output img`)?.src,
|
||||||
title: [1, 2, 3, 4, 5, 6]
|
title: [1, 2, 3, 4, 5, 6]
|
||||||
.map(h => document.querySelector(`#output h${h}`))
|
.map(h => document.querySelector(`#output h${h}`)!)
|
||||||
.filter(h => h)[0].textContent,
|
.filter(h => h)[0]
|
||||||
desc: document.querySelector(`#output p`).textContent,
|
.textContent,
|
||||||
|
desc: document.querySelector(`#output p`)!.textContent,
|
||||||
content: output.value,
|
content: output.value,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -45,10 +47,16 @@ function prePost() {
|
|||||||
dialogVisible.value = true
|
dialogVisible.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
syncPost: (data: { thumb: string, title: string, desc: string, content: string }) => void
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function post() {
|
function post() {
|
||||||
dialogVisible.value = false
|
dialogVisible.value = false;
|
||||||
// 使用 window.$syncer 可以检测是否安装插件
|
// 使用 window.$syncer 可以检测是否安装插件
|
||||||
window.syncPost({
|
(window.syncPost)({
|
||||||
thumb: form.value.thumb || form.value.auto.thumb,
|
thumb: form.value.thumb || form.value.auto.thumb,
|
||||||
title: form.value.title || form.value.auto.title,
|
title: form.value.title || form.value.auto.title,
|
||||||
desc: form.value.desc || form.value.auto.desc,
|
desc: form.value.desc || form.value.auto.desc,
|
||||||
@ -56,7 +64,7 @@ function post() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function onUpdate(val) {
|
function onUpdate(val: boolean) {
|
||||||
if (!val) {
|
if (!val) {
|
||||||
dialogVisible.value = false
|
dialogVisible.value = false
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,9 @@
|
|||||||
<script setup>
|
<script setup lang="ts">
|
||||||
import { nextTick, ref } from 'vue'
|
|
||||||
import { storeToRefs } from 'pinia'
|
|
||||||
|
|
||||||
import StyleOptionMenu from './StyleOptionMenu.vue'
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
HoverCard,
|
HoverCard,
|
||||||
HoverCardContent,
|
HoverCardContent,
|
||||||
HoverCardTrigger,
|
HoverCardTrigger,
|
||||||
} from '@/components/ui/hover-card'
|
} from '@/components/ui/hover-card'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
codeBlockThemeOptions,
|
codeBlockThemeOptions,
|
||||||
colorOptions,
|
colorOptions,
|
||||||
@ -18,9 +12,14 @@ import {
|
|||||||
legendOptions,
|
legendOptions,
|
||||||
themeOptions,
|
themeOptions,
|
||||||
} from '@/config'
|
} from '@/config'
|
||||||
import { useStore } from '@/stores'
|
|
||||||
|
import { useDisplayStore, useStore } from '@/stores'
|
||||||
|
import { storeToRefs } from 'pinia'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import StyleOptionMenu from './StyleOptionMenu.vue'
|
||||||
|
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
|
const { toggleShowCssEditor } = useDisplayStore()
|
||||||
|
|
||||||
const {
|
const {
|
||||||
theme,
|
theme,
|
||||||
@ -42,25 +41,19 @@ const {
|
|||||||
codeBlockThemeChanged,
|
codeBlockThemeChanged,
|
||||||
legendChanged,
|
legendChanged,
|
||||||
macCodeBlockChanged,
|
macCodeBlockChanged,
|
||||||
toggleShowCssEditor,
|
|
||||||
} = store
|
} = store
|
||||||
|
|
||||||
const colorPicker = ref(null)
|
const colorPicker = ref<HTMLElement & { show: () => void } | null>(null)
|
||||||
|
|
||||||
function showPicker() {
|
function showPicker() {
|
||||||
colorPicker.value.show()
|
colorPicker.value?.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 自定义CSS样式
|
// 自定义CSS样式
|
||||||
function customStyle() {
|
function customStyle() {
|
||||||
toggleShowCssEditor()
|
toggleShowCssEditor()
|
||||||
nextTick(() => {
|
|
||||||
if (!cssEditor.value) {
|
|
||||||
cssEditor.value.refresh()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
cssEditor.value.refresh()
|
cssEditor.value!.refresh()
|
||||||
}, 50)
|
}, 50)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@ -114,7 +107,7 @@ function customStyle() {
|
|||||||
自定义主题色
|
自定义主题色
|
||||||
</HoverCardTrigger>
|
</HoverCardTrigger>
|
||||||
<HoverCardContent side="right" class="w-min">
|
<HoverCardContent side="right" class="w-min">
|
||||||
<el-color-picker
|
<ElColorPicker
|
||||||
ref="colorPicker"
|
ref="colorPicker"
|
||||||
v-model="primaryColor"
|
v-model="primaryColor"
|
||||||
:teleported="false"
|
:teleported="false"
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<script setup>
|
<script setup lang="ts">
|
||||||
|
import type { IConfigOption } from '@/types'
|
||||||
import {
|
import {
|
||||||
MenubarItem,
|
MenubarItem,
|
||||||
MenubarSub,
|
MenubarSub,
|
||||||
@ -6,26 +7,14 @@ import {
|
|||||||
MenubarSubTrigger,
|
MenubarSubTrigger,
|
||||||
} from '@/components/ui/menubar'
|
} from '@/components/ui/menubar'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps<{
|
||||||
title: {
|
title: string
|
||||||
type: String,
|
options: IConfigOption[]
|
||||||
required: true,
|
current: string
|
||||||
},
|
change: <T>(val: T) => void
|
||||||
options: {
|
}>()
|
||||||
type: Array,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
current: {
|
|
||||||
type: String,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
change: {
|
|
||||||
type: Function,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
function setStyle(title, value) {
|
function setStyle(title: string, value: string) {
|
||||||
switch (title) {
|
switch (title) {
|
||||||
case `字体`:
|
case `字体`:
|
||||||
return { fontFamily: value }
|
return { fontFamily: value }
|
||||||
|
@ -1,14 +1,23 @@
|
|||||||
<script setup>
|
<script setup lang="ts">
|
||||||
import { nextTick } from 'vue'
|
import { Button } from '@/components/ui/button'
|
||||||
import { storeToRefs } from 'pinia'
|
import {
|
||||||
import { ElNotification } from 'element-plus'
|
Menubar,
|
||||||
import { Moon, Paintbrush, Sun } from 'lucide-vue-next'
|
MenubarContent,
|
||||||
|
MenubarItem,
|
||||||
|
MenubarMenu,
|
||||||
|
MenubarSeparator,
|
||||||
|
MenubarShortcut,
|
||||||
|
MenubarTrigger,
|
||||||
|
} from '@/components/ui/menubar'
|
||||||
|
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectItem,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue,
|
||||||
|
} from '@/components/ui/select'
|
||||||
|
|
||||||
import PostInfo from './PostInfo.vue'
|
|
||||||
import FileDropdown from './FileDropdown.vue'
|
|
||||||
import HelpDropdown from './HelpDropdown.vue'
|
|
||||||
import StyleDropdown from './StyleDropdown.vue'
|
|
||||||
import EditDropdown from './EditDropdown.vue'
|
|
||||||
import {
|
import {
|
||||||
altSign,
|
altSign,
|
||||||
codeBlockThemeOptions,
|
codeBlockThemeOptions,
|
||||||
@ -21,29 +30,20 @@ import {
|
|||||||
shiftSign,
|
shiftSign,
|
||||||
themeOptions,
|
themeOptions,
|
||||||
} from '@/config'
|
} from '@/config'
|
||||||
|
import { useDisplayStore, useStore } from '@/stores'
|
||||||
import {
|
|
||||||
Select,
|
|
||||||
SelectContent,
|
|
||||||
SelectItem,
|
|
||||||
SelectTrigger,
|
|
||||||
SelectValue,
|
|
||||||
} from '@/components/ui/select'
|
|
||||||
import {
|
|
||||||
Menubar,
|
|
||||||
MenubarContent,
|
|
||||||
MenubarItem,
|
|
||||||
MenubarMenu,
|
|
||||||
MenubarSeparator,
|
|
||||||
MenubarShortcut,
|
|
||||||
MenubarTrigger,
|
|
||||||
} from '@/components/ui/menubar'
|
|
||||||
|
|
||||||
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'
|
|
||||||
import { Button } from '@/components/ui/button'
|
|
||||||
|
|
||||||
import { mergeCss, solveWeChatImage } from '@/utils'
|
import { mergeCss, solveWeChatImage } from '@/utils'
|
||||||
import { useStore } from '@/stores'
|
import { ElNotification } from 'element-plus'
|
||||||
|
import { Moon, Paintbrush, Sun } from 'lucide-vue-next'
|
||||||
|
import { storeToRefs } from 'pinia'
|
||||||
|
|
||||||
|
import { nextTick } from 'vue'
|
||||||
|
import EditDropdown from './EditDropdown.vue'
|
||||||
|
|
||||||
|
import FileDropdown from './FileDropdown.vue'
|
||||||
|
import HelpDropdown from './HelpDropdown.vue'
|
||||||
|
|
||||||
|
import PostInfo from './PostInfo.vue'
|
||||||
|
import StyleDropdown from './StyleDropdown.vue'
|
||||||
|
|
||||||
const emit = defineEmits([`addFormat`, `formatContent`, `startCopy`, `endCopy`])
|
const emit = defineEmits([`addFormat`, `formatContent`, `startCopy`, `endCopy`])
|
||||||
|
|
||||||
@ -78,9 +78,10 @@ const formatItems = [
|
|||||||
kbd: [altSign, shiftSign, `F`],
|
kbd: [altSign, shiftSign, `F`],
|
||||||
emitArgs: [`formatContent`],
|
emitArgs: [`formatContent`],
|
||||||
},
|
},
|
||||||
]
|
] as const
|
||||||
|
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
|
const displayStore = useDisplayStore()
|
||||||
|
|
||||||
const { isDark, isCiteStatus, output, primaryColor } = storeToRefs(store)
|
const { isDark, isCiteStatus, output, primaryColor } = storeToRefs(store)
|
||||||
|
|
||||||
@ -90,7 +91,7 @@ const { toggleDark, editorRefresh, citeStatusChanged } = store
|
|||||||
function copy() {
|
function copy() {
|
||||||
emit(`startCopy`)
|
emit(`startCopy`)
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
function modifyHtmlStructure(htmlString) {
|
function modifyHtmlStructure(htmlString: string) {
|
||||||
// 创建一个 div 元素来暂存原始 HTML 字符串
|
// 创建一个 div 元素来暂存原始 HTML 字符串
|
||||||
const tempDiv = document.createElement(`div`)
|
const tempDiv = document.createElement(`div`)
|
||||||
tempDiv.innerHTML = htmlString
|
tempDiv.innerHTML = htmlString
|
||||||
@ -98,7 +99,7 @@ function copy() {
|
|||||||
const originalItems = tempDiv.querySelectorAll(`li > ul, li > ol`)
|
const originalItems = tempDiv.querySelectorAll(`li > ul, li > ol`)
|
||||||
|
|
||||||
originalItems.forEach((originalItem) => {
|
originalItems.forEach((originalItem) => {
|
||||||
originalItem.parentElement.insertAdjacentElement(`afterend`, originalItem)
|
originalItem.parentElement!.insertAdjacentElement(`afterend`, originalItem)
|
||||||
})
|
})
|
||||||
|
|
||||||
// 返回修改后的 HTML 字符串
|
// 返回修改后的 HTML 字符串
|
||||||
@ -114,7 +115,7 @@ function copy() {
|
|||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
solveWeChatImage()
|
solveWeChatImage()
|
||||||
|
|
||||||
const clipboardDiv = document.getElementById(`output`)
|
const clipboardDiv = document.getElementById(`output`)!
|
||||||
clipboardDiv.innerHTML = mergeCss(clipboardDiv.innerHTML)
|
clipboardDiv.innerHTML = mergeCss(clipboardDiv.innerHTML)
|
||||||
clipboardDiv.innerHTML = modifyHtmlStructure(clipboardDiv.innerHTML)
|
clipboardDiv.innerHTML = modifyHtmlStructure(clipboardDiv.innerHTML)
|
||||||
clipboardDiv.innerHTML = clipboardDiv.innerHTML
|
clipboardDiv.innerHTML = clipboardDiv.innerHTML
|
||||||
@ -125,14 +126,14 @@ function copy() {
|
|||||||
.replaceAll(`var(--md-primary-color)`, primaryColor.value)
|
.replaceAll(`var(--md-primary-color)`, primaryColor.value)
|
||||||
.replaceAll(/--md-primary-color:.+?;/g, ``)
|
.replaceAll(/--md-primary-color:.+?;/g, ``)
|
||||||
clipboardDiv.focus()
|
clipboardDiv.focus()
|
||||||
window.getSelection().removeAllRanges()
|
window.getSelection()!.removeAllRanges()
|
||||||
const range = document.createRange()
|
const range = document.createRange()
|
||||||
|
|
||||||
range.setStartBefore(clipboardDiv.firstChild)
|
range.setStartBefore(clipboardDiv.firstChild!)
|
||||||
range.setEndAfter(clipboardDiv.lastChild)
|
range.setEndAfter(clipboardDiv.lastChild!)
|
||||||
window.getSelection().addRange(range)
|
window.getSelection()!.addRange(range)
|
||||||
document.execCommand(`copy`)
|
document.execCommand(`copy`)
|
||||||
window.getSelection().removeAllRanges()
|
window.getSelection()!.removeAllRanges()
|
||||||
clipboardDiv.innerHTML = output.value
|
clipboardDiv.innerHTML = output.value
|
||||||
|
|
||||||
if (isBeforeDark) {
|
if (isBeforeDark) {
|
||||||
@ -153,6 +154,13 @@ function copy() {
|
|||||||
})
|
})
|
||||||
}, 350)
|
}, 350)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function customStyle() {
|
||||||
|
displayStore.toggleShowCssEditor()
|
||||||
|
setTimeout(() => {
|
||||||
|
store.cssEditor!.refresh()
|
||||||
|
}, 50)
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -165,8 +173,8 @@ function copy() {
|
|||||||
<MenubarContent class="w-60" align="start">
|
<MenubarContent class="w-60" align="start">
|
||||||
<MenubarItem
|
<MenubarItem
|
||||||
v-for="{ label, kbd, emitArgs } in formatItems"
|
v-for="{ label, kbd, emitArgs } in formatItems"
|
||||||
:key="kbd"
|
:key="label"
|
||||||
@click="$emit(...emitArgs)"
|
@click="emitArgs[0] === 'addFormat' ? $emit(emitArgs[0], emitArgs[1]) : $emit(emitArgs[0])"
|
||||||
>
|
>
|
||||||
<el-icon class="mr-2 h-4 w-4" />
|
<el-icon class="mr-2 h-4 w-4" />
|
||||||
{{ label }}
|
{{ label }}
|
||||||
@ -371,6 +379,31 @@ function copy() {
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="space-y-2">
|
||||||
|
<h2>自定义 CSS 面板</h2>
|
||||||
|
<div class="grid grid-cols-5 justify-items-center gap-2">
|
||||||
|
<Button
|
||||||
|
class="w-full"
|
||||||
|
variant="outline"
|
||||||
|
:class="{
|
||||||
|
'border-black dark:border-white': displayStore.isShowCssEditor,
|
||||||
|
}"
|
||||||
|
@click="!displayStore.isShowCssEditor && customStyle()"
|
||||||
|
>
|
||||||
|
开启
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
class="w-full"
|
||||||
|
variant="outline"
|
||||||
|
:class="{
|
||||||
|
'border-black dark:border-white': !displayStore.isShowCssEditor,
|
||||||
|
}"
|
||||||
|
@click="displayStore.isShowCssEditor && customStyle()"
|
||||||
|
>
|
||||||
|
关闭
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<h2>编辑区位置</h2>
|
<h2>编辑区位置</h2>
|
||||||
<div class="grid grid-cols-5 justify-items-center gap-2">
|
<div class="grid grid-cols-5 justify-items-center gap-2">
|
||||||
@ -421,6 +454,17 @@ function copy() {
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="space-y-2">
|
||||||
|
<h2>样式配置</h2>
|
||||||
|
<div>
|
||||||
|
<Button
|
||||||
|
class="w-full"
|
||||||
|
@click="store.resetStyleConfirm()"
|
||||||
|
>
|
||||||
|
重置
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</PopoverContent>
|
</PopoverContent>
|
||||||
</Popover>
|
</Popover>
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
<script setup>
|
<script setup lang="ts">
|
||||||
import { ref, toRaw } from 'vue'
|
|
||||||
import {
|
import {
|
||||||
Dialog,
|
Dialog,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
@ -7,17 +6,19 @@ import {
|
|||||||
DialogHeader,
|
DialogHeader,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
} from '@/components/ui/dialog'
|
} from '@/components/ui/dialog'
|
||||||
|
import { useDisplayStore, useStore } from '@/stores'
|
||||||
|
|
||||||
import { useStore } from '@/stores'
|
|
||||||
import { createTable } from '@/utils'
|
import { createTable } from '@/utils'
|
||||||
|
import { ref, toRaw } from 'vue'
|
||||||
|
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
|
const displayStore = useDisplayStore()
|
||||||
|
|
||||||
const { toggleShowInsertFormDialog } = store
|
const { toggleShowInsertFormDialog } = displayStore
|
||||||
|
|
||||||
const rowNum = ref(3)
|
const rowNum = ref(3)
|
||||||
const colNum = ref(3)
|
const colNum = ref(3)
|
||||||
const tableData = ref({})
|
const tableData = ref<Record<string, string>>({})
|
||||||
|
|
||||||
function resetVal() {
|
function resetVal() {
|
||||||
rowNum.value = 3
|
rowNum.value = 3
|
||||||
@ -32,12 +33,12 @@ function insertTable() {
|
|||||||
cols: colNum.value,
|
cols: colNum.value,
|
||||||
data: tableData.value,
|
data: tableData.value,
|
||||||
})
|
})
|
||||||
toRaw(store.editor).replaceSelection(`\n${table}\n`, `end`)
|
toRaw(store.editor!).replaceSelection(`\n${table}\n`, `end`)
|
||||||
resetVal()
|
resetVal()
|
||||||
toggleShowInsertFormDialog()
|
toggleShowInsertFormDialog()
|
||||||
}
|
}
|
||||||
|
|
||||||
function onUpdate(val) {
|
function onUpdate(val: boolean) {
|
||||||
if (!val) {
|
if (!val) {
|
||||||
toggleShowInsertFormDialog(false)
|
toggleShowInsertFormDialog(false)
|
||||||
}
|
}
|
||||||
@ -45,7 +46,7 @@ function onUpdate(val) {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Dialog :open="store.isShowInsertFormDialog" @update:open="onUpdate">
|
<Dialog :open="displayStore.isShowInsertFormDialog" @update:open="onUpdate">
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle>插入表格</DialogTitle>
|
<DialogTitle>插入表格</DialogTitle>
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
<script setup>
|
<script setup lang="ts">
|
||||||
import { nextTick, onBeforeMount, ref, watch } from 'vue'
|
|
||||||
import CodeMirror from 'codemirror/lib/codemirror'
|
|
||||||
import { ElMessage } from 'element-plus'
|
|
||||||
import { UploadFilled } from '@element-plus/icons-vue'
|
|
||||||
|
|
||||||
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog'
|
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog'
|
||||||
|
import { useDisplayStore } from '@/stores'
|
||||||
import { checkImage, removeLeft } from '@/utils'
|
import { checkImage, removeLeft } from '@/utils'
|
||||||
import { useStore } from '@/stores'
|
|
||||||
|
import { UploadFilled } from '@element-plus/icons-vue'
|
||||||
|
import CodeMirror from 'codemirror'
|
||||||
|
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
|
import { nextTick, onBeforeMount, ref, watch } from 'vue'
|
||||||
|
|
||||||
const emit = defineEmits([`uploadImage`])
|
const emit = defineEmits([`uploadImage`])
|
||||||
|
|
||||||
const store = useStore()
|
const displayStore = useDisplayStore()
|
||||||
|
|
||||||
const formGitHub = ref({
|
const formGitHub = ref({
|
||||||
repo: ``,
|
repo: ``,
|
||||||
@ -50,6 +50,7 @@ const formQiniu = ref({
|
|||||||
bucket: ``,
|
bucket: ``,
|
||||||
domain: ``,
|
domain: ``,
|
||||||
region: ``,
|
region: ``,
|
||||||
|
path: ``,
|
||||||
})
|
})
|
||||||
|
|
||||||
const minioOSS = ref({
|
const minioOSS = ref({
|
||||||
@ -61,7 +62,7 @@ const minioOSS = ref({
|
|||||||
secretKey: ``,
|
secretKey: ``,
|
||||||
})
|
})
|
||||||
|
|
||||||
const formCustom = ref({
|
const formCustom = ref<{ code: string, editor: CodeMirror.EditorFromTextArea | null }>({
|
||||||
code:
|
code:
|
||||||
localStorage.getItem(`formCustomConfig`)
|
localStorage.getItem(`formCustomConfig`)
|
||||||
|| removeLeft(`
|
|| removeLeft(`
|
||||||
@ -76,7 +77,7 @@ const formCustom = ref({
|
|||||||
errCb(err)
|
errCb(err)
|
||||||
})
|
})
|
||||||
`).trim(),
|
`).trim(),
|
||||||
editor: undefined,
|
editor: null,
|
||||||
})
|
})
|
||||||
|
|
||||||
const options = [
|
const options = [
|
||||||
@ -116,7 +117,7 @@ const options = [
|
|||||||
|
|
||||||
const imgHost = ref(`default`)
|
const imgHost = ref(`default`)
|
||||||
|
|
||||||
const formCustomElInput = ref(null)
|
const formCustomElInput = ref<(HTMLInputElement & { $el: HTMLElement }) | null>(null)
|
||||||
const activeName = ref(`upload`)
|
const activeName = ref(`upload`)
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
@ -124,10 +125,8 @@ watch(
|
|||||||
async (val) => {
|
async (val) => {
|
||||||
if (val === `formCustom`) {
|
if (val === `formCustom`) {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
const textarea = formCustomElInput.value.$el.querySelector(`textarea`)
|
const textarea = formCustomElInput.value!.$el.querySelector(`textarea`)!
|
||||||
formCustom.value.editor
|
formCustom.value.editor ||= CodeMirror.fromTextArea(textarea, {
|
||||||
= formCustom.value.editor
|
|
||||||
|| CodeMirror.fromTextArea(textarea, {
|
|
||||||
mode: `javascript`,
|
mode: `javascript`,
|
||||||
})
|
})
|
||||||
// formCustom.value.editor.setValue(formCustom.value.code)
|
// formCustom.value.editor.setValue(formCustom.value.code)
|
||||||
@ -141,25 +140,25 @@ watch(
|
|||||||
|
|
||||||
onBeforeMount(() => {
|
onBeforeMount(() => {
|
||||||
if (localStorage.getItem(`githubConfig`)) {
|
if (localStorage.getItem(`githubConfig`)) {
|
||||||
formGitHub.value = JSON.parse(localStorage.getItem(`githubConfig`))
|
formGitHub.value = JSON.parse(localStorage.getItem(`githubConfig`)!)
|
||||||
}
|
}
|
||||||
// if (localStorage.getItem(`giteeConfig`)) {
|
// if (localStorage.getItem(`giteeConfig`)) {
|
||||||
// formGitee.value = JSON.parse(localStorage.getItem(`giteeConfig`))
|
// formGitee.value = JSON.parse(localStorage.getItem(`giteeConfig`)!)
|
||||||
// }
|
// }
|
||||||
if (localStorage.getItem(`aliOSSConfig`)) {
|
if (localStorage.getItem(`aliOSSConfig`)) {
|
||||||
formAliOSS.value = JSON.parse(localStorage.getItem(`aliOSSConfig`))
|
formAliOSS.value = JSON.parse(localStorage.getItem(`aliOSSConfig`)!)
|
||||||
}
|
}
|
||||||
if (localStorage.getItem(`txCOSConfig`)) {
|
if (localStorage.getItem(`txCOSConfig`)) {
|
||||||
formTxCOS.value = JSON.parse(localStorage.getItem(`txCOSConfig`))
|
formTxCOS.value = JSON.parse(localStorage.getItem(`txCOSConfig`)!)
|
||||||
}
|
}
|
||||||
if (localStorage.getItem(`qiniuConfig`)) {
|
if (localStorage.getItem(`qiniuConfig`)) {
|
||||||
formQiniu.value = JSON.parse(localStorage.getItem(`qiniuConfig`))
|
formQiniu.value = JSON.parse(localStorage.getItem(`qiniuConfig`)!)
|
||||||
}
|
}
|
||||||
if (localStorage.getItem(`minioConfig`)) {
|
if (localStorage.getItem(`minioConfig`)) {
|
||||||
minioOSS.value = JSON.parse(localStorage.getItem(`minioConfig`))
|
minioOSS.value = JSON.parse(localStorage.getItem(`minioConfig`)!)
|
||||||
}
|
}
|
||||||
if (localStorage.getItem(`imgHost`)) {
|
if (localStorage.getItem(`imgHost`)) {
|
||||||
imgHost.value = localStorage.getItem(`imgHost`)
|
imgHost.value = localStorage.getItem(`imgHost`)!
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -251,12 +250,12 @@ function saveQiniuConfiguration() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function formCustomSave() {
|
function formCustomSave() {
|
||||||
const str = formCustom.value.editor.getValue()
|
const str = formCustom.value.editor!.getValue()
|
||||||
localStorage.setItem(`formCustomConfig`, str)
|
localStorage.setItem(`formCustomConfig`, str)
|
||||||
ElMessage.success(`保存成功`)
|
ElMessage.success(`保存成功`)
|
||||||
}
|
}
|
||||||
|
|
||||||
function beforeImageUpload(file) {
|
function beforeImageUpload(file: File) {
|
||||||
// check image
|
// check image
|
||||||
const checkResult = checkImage(file)
|
const checkResult = checkImage(file)
|
||||||
if (!checkResult.ok) {
|
if (!checkResult.ok) {
|
||||||
@ -277,13 +276,13 @@ function beforeImageUpload(file) {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
function uploadImage(params) {
|
function uploadImage(params: { file: any }) {
|
||||||
emit(`uploadImage`, params.file)
|
emit(`uploadImage`, params.file)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Dialog v-model:open="store.isShowUploadImgDialog">
|
<Dialog v-model:open="displayStore.isShowUploadImgDialog">
|
||||||
<DialogContent class="max-w-max">
|
<DialogContent class="max-w-max">
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle>本地上传</DialogTitle>
|
<DialogTitle>本地上传</DialogTitle>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<script setup>
|
<script setup lang="ts">
|
||||||
import { onMounted, ref } from 'vue'
|
import { onMounted, ref } from 'vue'
|
||||||
|
|
||||||
const loading = ref(true)
|
const loading = ref(true)
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { HTMLAttributes } from 'vue'
|
import type { HTMLAttributes } from 'vue'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
import { Primitive, type PrimitiveProps } from 'radix-vue'
|
import { Primitive, type PrimitiveProps } from 'radix-vue'
|
||||||
import { type ButtonVariants, buttonVariants } from '.'
|
import { type ButtonVariants, buttonVariants } from '.'
|
||||||
import { cn } from '@/lib/utils'
|
|
||||||
|
|
||||||
interface Props extends PrimitiveProps {
|
interface Props extends PrimitiveProps {
|
||||||
variant?: ButtonVariants[`variant`]
|
variant?: ButtonVariants[`variant`]
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { type VariantProps, cva } from 'class-variance-authority'
|
import { cva, type VariantProps } from 'class-variance-authority'
|
||||||
|
|
||||||
export { default as Button } from './Button.vue'
|
export { default as Button } from './Button.vue'
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ContextMenuRoot, useForwardPropsEmits } from 'radix-vue'
|
|
||||||
import type { ContextMenuRootEmits, ContextMenuRootProps } from 'radix-vue'
|
import type { ContextMenuRootEmits, ContextMenuRootProps } from 'radix-vue'
|
||||||
|
import { ContextMenuRoot, useForwardPropsEmits } from 'radix-vue'
|
||||||
|
|
||||||
const props = defineProps<ContextMenuRootProps>()
|
const props = defineProps<ContextMenuRootProps>()
|
||||||
const emits = defineEmits<ContextMenuRootEmits>()
|
const emits = defineEmits<ContextMenuRootEmits>()
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { type HTMLAttributes, computed } from 'vue'
|
import { cn } from '@/lib/utils'
|
||||||
|
import { Check } from 'lucide-vue-next'
|
||||||
import {
|
import {
|
||||||
ContextMenuCheckboxItem,
|
ContextMenuCheckboxItem,
|
||||||
type ContextMenuCheckboxItemEmits,
|
type ContextMenuCheckboxItemEmits,
|
||||||
@ -7,8 +8,7 @@ import {
|
|||||||
ContextMenuItemIndicator,
|
ContextMenuItemIndicator,
|
||||||
useForwardPropsEmits,
|
useForwardPropsEmits,
|
||||||
} from 'radix-vue'
|
} from 'radix-vue'
|
||||||
import { Check } from 'lucide-vue-next'
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
import { cn } from '@/lib/utils'
|
|
||||||
|
|
||||||
const props = defineProps<ContextMenuCheckboxItemProps & { class?: HTMLAttributes[`class`] }>()
|
const props = defineProps<ContextMenuCheckboxItemProps & { class?: HTMLAttributes[`class`] }>()
|
||||||
const emits = defineEmits<ContextMenuCheckboxItemEmits>()
|
const emits = defineEmits<ContextMenuCheckboxItemEmits>()
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { type HTMLAttributes, computed } from 'vue'
|
import { cn } from '@/lib/utils'
|
||||||
import {
|
import {
|
||||||
ContextMenuContent,
|
ContextMenuContent,
|
||||||
type ContextMenuContentEmits,
|
type ContextMenuContentEmits,
|
||||||
@ -7,7 +7,7 @@ import {
|
|||||||
ContextMenuPortal,
|
ContextMenuPortal,
|
||||||
useForwardPropsEmits,
|
useForwardPropsEmits,
|
||||||
} from 'radix-vue'
|
} from 'radix-vue'
|
||||||
import { cn } from '@/lib/utils'
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
const props = defineProps<ContextMenuContentProps & { class?: HTMLAttributes[`class`] }>()
|
const props = defineProps<ContextMenuContentProps & { class?: HTMLAttributes[`class`] }>()
|
||||||
const emits = defineEmits<ContextMenuContentEmits>()
|
const emits = defineEmits<ContextMenuContentEmits>()
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { type HTMLAttributes, computed } from 'vue'
|
import { cn } from '@/lib/utils'
|
||||||
import {
|
import {
|
||||||
ContextMenuItem,
|
ContextMenuItem,
|
||||||
type ContextMenuItemEmits,
|
type ContextMenuItemEmits,
|
||||||
type ContextMenuItemProps,
|
type ContextMenuItemProps,
|
||||||
useForwardPropsEmits,
|
useForwardPropsEmits,
|
||||||
} from 'radix-vue'
|
} from 'radix-vue'
|
||||||
import { cn } from '@/lib/utils'
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
const props = defineProps<ContextMenuItemProps & { class?: HTMLAttributes[`class`], inset?: boolean }>()
|
const props = defineProps<ContextMenuItemProps & { class?: HTMLAttributes[`class`], inset?: boolean }>()
|
||||||
const emits = defineEmits<ContextMenuItemEmits>()
|
const emits = defineEmits<ContextMenuItemEmits>()
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { type HTMLAttributes, computed } from 'vue'
|
|
||||||
import { ContextMenuLabel, type ContextMenuLabelProps } from 'radix-vue'
|
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
|
import { ContextMenuLabel, type ContextMenuLabelProps } from 'radix-vue'
|
||||||
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
const props = defineProps<ContextMenuLabelProps & { class?: HTMLAttributes[`class`], inset?: boolean }>()
|
const props = defineProps<ContextMenuLabelProps & { class?: HTMLAttributes[`class`], inset?: boolean }>()
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { type HTMLAttributes, computed } from 'vue'
|
import { cn } from '@/lib/utils'
|
||||||
|
import { Circle } from 'lucide-vue-next'
|
||||||
import {
|
import {
|
||||||
ContextMenuItemIndicator,
|
ContextMenuItemIndicator,
|
||||||
ContextMenuRadioItem,
|
ContextMenuRadioItem,
|
||||||
@ -7,8 +8,7 @@ import {
|
|||||||
type ContextMenuRadioItemProps,
|
type ContextMenuRadioItemProps,
|
||||||
useForwardPropsEmits,
|
useForwardPropsEmits,
|
||||||
} from 'radix-vue'
|
} from 'radix-vue'
|
||||||
import { Circle } from 'lucide-vue-next'
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
import { cn } from '@/lib/utils'
|
|
||||||
|
|
||||||
const props = defineProps<ContextMenuRadioItemProps & { class?: HTMLAttributes[`class`] }>()
|
const props = defineProps<ContextMenuRadioItemProps & { class?: HTMLAttributes[`class`] }>()
|
||||||
const emits = defineEmits<ContextMenuRadioItemEmits>()
|
const emits = defineEmits<ContextMenuRadioItemEmits>()
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { type HTMLAttributes, computed } from 'vue'
|
import { cn } from '@/lib/utils'
|
||||||
import {
|
import {
|
||||||
ContextMenuSeparator,
|
ContextMenuSeparator,
|
||||||
type ContextMenuSeparatorProps,
|
type ContextMenuSeparatorProps,
|
||||||
} from 'radix-vue'
|
} from 'radix-vue'
|
||||||
import { cn } from '@/lib/utils'
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
const props = defineProps<ContextMenuSeparatorProps & { class?: HTMLAttributes[`class`] }>()
|
const props = defineProps<ContextMenuSeparatorProps & { class?: HTMLAttributes[`class`] }>()
|
||||||
|
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { type HTMLAttributes, computed } from 'vue'
|
import { cn } from '@/lib/utils'
|
||||||
import {
|
import {
|
||||||
ContextMenuSubContent,
|
ContextMenuSubContent,
|
||||||
type DropdownMenuSubContentEmits,
|
type DropdownMenuSubContentEmits,
|
||||||
type DropdownMenuSubContentProps,
|
type DropdownMenuSubContentProps,
|
||||||
useForwardPropsEmits,
|
useForwardPropsEmits,
|
||||||
} from 'radix-vue'
|
} from 'radix-vue'
|
||||||
import { cn } from '@/lib/utils'
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
const props = defineProps<DropdownMenuSubContentProps & { class?: HTMLAttributes[`class`] }>()
|
const props = defineProps<DropdownMenuSubContentProps & { class?: HTMLAttributes[`class`] }>()
|
||||||
const emits = defineEmits<DropdownMenuSubContentEmits>()
|
const emits = defineEmits<DropdownMenuSubContentEmits>()
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { type HTMLAttributes, computed } from 'vue'
|
import { cn } from '@/lib/utils'
|
||||||
|
import { ChevronRight } from 'lucide-vue-next'
|
||||||
import {
|
import {
|
||||||
ContextMenuSubTrigger,
|
ContextMenuSubTrigger,
|
||||||
type ContextMenuSubTriggerProps,
|
type ContextMenuSubTriggerProps,
|
||||||
useForwardProps,
|
useForwardProps,
|
||||||
} from 'radix-vue'
|
} from 'radix-vue'
|
||||||
import { ChevronRight } from 'lucide-vue-next'
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
import { cn } from '@/lib/utils'
|
|
||||||
|
|
||||||
const props = defineProps<ContextMenuSubTriggerProps & { class?: HTMLAttributes[`class`], inset?: boolean }>()
|
const props = defineProps<ContextMenuSubTriggerProps & { class?: HTMLAttributes[`class`], inset?: boolean }>()
|
||||||
|
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
export { default as ContextMenu } from './ContextMenu.vue'
|
export { default as ContextMenu } from './ContextMenu.vue'
|
||||||
export { default as ContextMenuTrigger } from './ContextMenuTrigger.vue'
|
export { default as ContextMenuCheckboxItem } from './ContextMenuCheckboxItem.vue'
|
||||||
export { default as ContextMenuContent } from './ContextMenuContent.vue'
|
export { default as ContextMenuContent } from './ContextMenuContent.vue'
|
||||||
export { default as ContextMenuGroup } from './ContextMenuGroup.vue'
|
export { default as ContextMenuGroup } from './ContextMenuGroup.vue'
|
||||||
export { default as ContextMenuRadioGroup } from './ContextMenuRadioGroup.vue'
|
|
||||||
export { default as ContextMenuItem } from './ContextMenuItem.vue'
|
export { default as ContextMenuItem } from './ContextMenuItem.vue'
|
||||||
export { default as ContextMenuCheckboxItem } from './ContextMenuCheckboxItem.vue'
|
|
||||||
export { default as ContextMenuRadioItem } from './ContextMenuRadioItem.vue'
|
|
||||||
export { default as ContextMenuShortcut } from './ContextMenuShortcut.vue'
|
|
||||||
export { default as ContextMenuSeparator } from './ContextMenuSeparator.vue'
|
|
||||||
export { default as ContextMenuLabel } from './ContextMenuLabel.vue'
|
export { default as ContextMenuLabel } from './ContextMenuLabel.vue'
|
||||||
|
export { default as ContextMenuRadioGroup } from './ContextMenuRadioGroup.vue'
|
||||||
|
export { default as ContextMenuRadioItem } from './ContextMenuRadioItem.vue'
|
||||||
|
export { default as ContextMenuSeparator } from './ContextMenuSeparator.vue'
|
||||||
|
export { default as ContextMenuShortcut } from './ContextMenuShortcut.vue'
|
||||||
export { default as ContextMenuSub } from './ContextMenuSub.vue'
|
export { default as ContextMenuSub } from './ContextMenuSub.vue'
|
||||||
export { default as ContextMenuSubTrigger } from './ContextMenuSubTrigger.vue'
|
|
||||||
export { default as ContextMenuSubContent } from './ContextMenuSubContent.vue'
|
export { default as ContextMenuSubContent } from './ContextMenuSubContent.vue'
|
||||||
|
export { default as ContextMenuSubTrigger } from './ContextMenuSubTrigger.vue'
|
||||||
|
export { default as ContextMenuTrigger } from './ContextMenuTrigger.vue'
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { type HTMLAttributes, computed } from 'vue'
|
import { cn } from '@/lib/utils'
|
||||||
|
import { X } from 'lucide-vue-next'
|
||||||
import {
|
import {
|
||||||
DialogClose,
|
DialogClose,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
@ -9,8 +10,7 @@ import {
|
|||||||
DialogPortal,
|
DialogPortal,
|
||||||
useForwardPropsEmits,
|
useForwardPropsEmits,
|
||||||
} from 'radix-vue'
|
} from 'radix-vue'
|
||||||
import { X } from 'lucide-vue-next'
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
import { cn } from '@/lib/utils'
|
|
||||||
|
|
||||||
const props = defineProps<DialogContentProps & { class?: HTMLAttributes[`class`] }>()
|
const props = defineProps<DialogContentProps & { class?: HTMLAttributes[`class`] }>()
|
||||||
const emits = defineEmits<DialogContentEmits>()
|
const emits = defineEmits<DialogContentEmits>()
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { type HTMLAttributes, computed } from 'vue'
|
|
||||||
import { DialogDescription, type DialogDescriptionProps, useForwardProps } from 'radix-vue'
|
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
|
import { DialogDescription, type DialogDescriptionProps, useForwardProps } from 'radix-vue'
|
||||||
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
const props = defineProps<DialogDescriptionProps & { class?: HTMLAttributes[`class`] }>()
|
const props = defineProps<DialogDescriptionProps & { class?: HTMLAttributes[`class`] }>()
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { type HTMLAttributes, computed } from 'vue'
|
import { cn } from '@/lib/utils'
|
||||||
|
import { X } from 'lucide-vue-next'
|
||||||
import {
|
import {
|
||||||
DialogClose,
|
DialogClose,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
@ -9,8 +10,7 @@ import {
|
|||||||
DialogPortal,
|
DialogPortal,
|
||||||
useForwardPropsEmits,
|
useForwardPropsEmits,
|
||||||
} from 'radix-vue'
|
} from 'radix-vue'
|
||||||
import { X } from 'lucide-vue-next'
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
import { cn } from '@/lib/utils'
|
|
||||||
|
|
||||||
const props = defineProps<DialogContentProps & { class?: HTMLAttributes[`class`] }>()
|
const props = defineProps<DialogContentProps & { class?: HTMLAttributes[`class`] }>()
|
||||||
const emits = defineEmits<DialogContentEmits>()
|
const emits = defineEmits<DialogContentEmits>()
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { type HTMLAttributes, computed } from 'vue'
|
|
||||||
import { DialogTitle, type DialogTitleProps, useForwardProps } from 'radix-vue'
|
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
|
import { DialogTitle, type DialogTitleProps, useForwardProps } from 'radix-vue'
|
||||||
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
const props = defineProps<DialogTitleProps & { class?: HTMLAttributes[`class`] }>()
|
const props = defineProps<DialogTitleProps & { class?: HTMLAttributes[`class`] }>()
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
export { default as Dialog } from './Dialog.vue'
|
export { default as Dialog } from './Dialog.vue'
|
||||||
export { default as DialogClose } from './DialogClose.vue'
|
export { default as DialogClose } from './DialogClose.vue'
|
||||||
export { default as DialogTrigger } from './DialogTrigger.vue'
|
|
||||||
export { default as DialogHeader } from './DialogHeader.vue'
|
|
||||||
export { default as DialogTitle } from './DialogTitle.vue'
|
|
||||||
export { default as DialogDescription } from './DialogDescription.vue'
|
|
||||||
export { default as DialogContent } from './DialogContent.vue'
|
export { default as DialogContent } from './DialogContent.vue'
|
||||||
export { default as DialogScrollContent } from './DialogScrollContent.vue'
|
export { default as DialogDescription } from './DialogDescription.vue'
|
||||||
export { default as DialogFooter } from './DialogFooter.vue'
|
export { default as DialogFooter } from './DialogFooter.vue'
|
||||||
|
export { default as DialogHeader } from './DialogHeader.vue'
|
||||||
|
export { default as DialogScrollContent } from './DialogScrollContent.vue'
|
||||||
|
export { default as DialogTitle } from './DialogTitle.vue'
|
||||||
|
export { default as DialogTrigger } from './DialogTrigger.vue'
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { type HTMLAttributes, computed } from 'vue'
|
import { cn } from '@/lib/utils'
|
||||||
|
import { Check } from 'lucide-vue-next'
|
||||||
import {
|
import {
|
||||||
DropdownMenuCheckboxItem,
|
DropdownMenuCheckboxItem,
|
||||||
type DropdownMenuCheckboxItemEmits,
|
type DropdownMenuCheckboxItemEmits,
|
||||||
@ -7,8 +8,7 @@ import {
|
|||||||
DropdownMenuItemIndicator,
|
DropdownMenuItemIndicator,
|
||||||
useForwardPropsEmits,
|
useForwardPropsEmits,
|
||||||
} from 'radix-vue'
|
} from 'radix-vue'
|
||||||
import { Check } from 'lucide-vue-next'
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
import { cn } from '@/lib/utils'
|
|
||||||
|
|
||||||
const props = defineProps<DropdownMenuCheckboxItemProps & { class?: HTMLAttributes[`class`] }>()
|
const props = defineProps<DropdownMenuCheckboxItemProps & { class?: HTMLAttributes[`class`] }>()
|
||||||
const emits = defineEmits<DropdownMenuCheckboxItemEmits>()
|
const emits = defineEmits<DropdownMenuCheckboxItemEmits>()
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { type HTMLAttributes, computed } from 'vue'
|
import { cn } from '@/lib/utils'
|
||||||
import {
|
import {
|
||||||
DropdownMenuContent,
|
DropdownMenuContent,
|
||||||
type DropdownMenuContentEmits,
|
type DropdownMenuContentEmits,
|
||||||
@ -7,7 +7,7 @@ import {
|
|||||||
DropdownMenuPortal,
|
DropdownMenuPortal,
|
||||||
useForwardPropsEmits,
|
useForwardPropsEmits,
|
||||||
} from 'radix-vue'
|
} from 'radix-vue'
|
||||||
import { cn } from '@/lib/utils'
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<DropdownMenuContentProps & { class?: HTMLAttributes[`class`] }>(),
|
defineProps<DropdownMenuContentProps & { class?: HTMLAttributes[`class`] }>(),
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { type HTMLAttributes, computed } from 'vue'
|
|
||||||
import { DropdownMenuItem, type DropdownMenuItemProps, useForwardProps } from 'radix-vue'
|
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
|
import { DropdownMenuItem, type DropdownMenuItemProps, useForwardProps } from 'radix-vue'
|
||||||
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
const props = defineProps<DropdownMenuItemProps & { class?: HTMLAttributes[`class`], inset?: boolean }>()
|
const props = defineProps<DropdownMenuItemProps & { class?: HTMLAttributes[`class`], inset?: boolean }>()
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { type HTMLAttributes, computed } from 'vue'
|
|
||||||
import { DropdownMenuLabel, type DropdownMenuLabelProps, useForwardProps } from 'radix-vue'
|
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
|
import { DropdownMenuLabel, type DropdownMenuLabelProps, useForwardProps } from 'radix-vue'
|
||||||
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
const props = defineProps<DropdownMenuLabelProps & { class?: HTMLAttributes[`class`], inset?: boolean }>()
|
const props = defineProps<DropdownMenuLabelProps & { class?: HTMLAttributes[`class`], inset?: boolean }>()
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { type HTMLAttributes, computed } from 'vue'
|
import { cn } from '@/lib/utils'
|
||||||
|
import { Circle } from 'lucide-vue-next'
|
||||||
import {
|
import {
|
||||||
DropdownMenuItemIndicator,
|
DropdownMenuItemIndicator,
|
||||||
DropdownMenuRadioItem,
|
DropdownMenuRadioItem,
|
||||||
@ -7,8 +8,7 @@ import {
|
|||||||
type DropdownMenuRadioItemProps,
|
type DropdownMenuRadioItemProps,
|
||||||
useForwardPropsEmits,
|
useForwardPropsEmits,
|
||||||
} from 'radix-vue'
|
} from 'radix-vue'
|
||||||
import { Circle } from 'lucide-vue-next'
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
import { cn } from '@/lib/utils'
|
|
||||||
|
|
||||||
const props = defineProps<DropdownMenuRadioItemProps & { class?: HTMLAttributes[`class`] }>()
|
const props = defineProps<DropdownMenuRadioItemProps & { class?: HTMLAttributes[`class`] }>()
|
||||||
|
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { type HTMLAttributes, computed } from 'vue'
|
import { cn } from '@/lib/utils'
|
||||||
import {
|
import {
|
||||||
DropdownMenuSeparator,
|
DropdownMenuSeparator,
|
||||||
type DropdownMenuSeparatorProps,
|
type DropdownMenuSeparatorProps,
|
||||||
} from 'radix-vue'
|
} from 'radix-vue'
|
||||||
import { cn } from '@/lib/utils'
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
const props = defineProps<DropdownMenuSeparatorProps & {
|
const props = defineProps<DropdownMenuSeparatorProps & {
|
||||||
class?: HTMLAttributes[`class`]
|
class?: HTMLAttributes[`class`]
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { type HTMLAttributes, computed } from 'vue'
|
import { cn } from '@/lib/utils'
|
||||||
import {
|
import {
|
||||||
DropdownMenuSubContent,
|
DropdownMenuSubContent,
|
||||||
type DropdownMenuSubContentEmits,
|
type DropdownMenuSubContentEmits,
|
||||||
type DropdownMenuSubContentProps,
|
type DropdownMenuSubContentProps,
|
||||||
useForwardPropsEmits,
|
useForwardPropsEmits,
|
||||||
} from 'radix-vue'
|
} from 'radix-vue'
|
||||||
import { cn } from '@/lib/utils'
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
const props = defineProps<DropdownMenuSubContentProps & { class?: HTMLAttributes[`class`] }>()
|
const props = defineProps<DropdownMenuSubContentProps & { class?: HTMLAttributes[`class`] }>()
|
||||||
const emits = defineEmits<DropdownMenuSubContentEmits>()
|
const emits = defineEmits<DropdownMenuSubContentEmits>()
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { type HTMLAttributes, computed } from 'vue'
|
import { cn } from '@/lib/utils'
|
||||||
|
import { ChevronRight } from 'lucide-vue-next'
|
||||||
import {
|
import {
|
||||||
DropdownMenuSubTrigger,
|
DropdownMenuSubTrigger,
|
||||||
type DropdownMenuSubTriggerProps,
|
type DropdownMenuSubTriggerProps,
|
||||||
useForwardProps,
|
useForwardProps,
|
||||||
} from 'radix-vue'
|
} from 'radix-vue'
|
||||||
import { ChevronRight } from 'lucide-vue-next'
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
import { cn } from '@/lib/utils'
|
|
||||||
|
|
||||||
const props = defineProps<DropdownMenuSubTriggerProps & { class?: HTMLAttributes[`class`] }>()
|
const props = defineProps<DropdownMenuSubTriggerProps & { class?: HTMLAttributes[`class`] }>()
|
||||||
|
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
export { DropdownMenuPortal } from 'radix-vue'
|
|
||||||
|
|
||||||
export { default as DropdownMenu } from './DropdownMenu.vue'
|
export { default as DropdownMenu } from './DropdownMenu.vue'
|
||||||
export { default as DropdownMenuTrigger } from './DropdownMenuTrigger.vue'
|
|
||||||
|
export { default as DropdownMenuCheckboxItem } from './DropdownMenuCheckboxItem.vue'
|
||||||
export { default as DropdownMenuContent } from './DropdownMenuContent.vue'
|
export { default as DropdownMenuContent } from './DropdownMenuContent.vue'
|
||||||
export { default as DropdownMenuGroup } from './DropdownMenuGroup.vue'
|
export { default as DropdownMenuGroup } from './DropdownMenuGroup.vue'
|
||||||
export { default as DropdownMenuRadioGroup } from './DropdownMenuRadioGroup.vue'
|
|
||||||
export { default as DropdownMenuItem } from './DropdownMenuItem.vue'
|
export { default as DropdownMenuItem } from './DropdownMenuItem.vue'
|
||||||
export { default as DropdownMenuCheckboxItem } from './DropdownMenuCheckboxItem.vue'
|
|
||||||
export { default as DropdownMenuRadioItem } from './DropdownMenuRadioItem.vue'
|
|
||||||
export { default as DropdownMenuShortcut } from './DropdownMenuShortcut.vue'
|
|
||||||
export { default as DropdownMenuSeparator } from './DropdownMenuSeparator.vue'
|
|
||||||
export { default as DropdownMenuLabel } from './DropdownMenuLabel.vue'
|
export { default as DropdownMenuLabel } from './DropdownMenuLabel.vue'
|
||||||
|
export { default as DropdownMenuRadioGroup } from './DropdownMenuRadioGroup.vue'
|
||||||
|
export { default as DropdownMenuRadioItem } from './DropdownMenuRadioItem.vue'
|
||||||
|
export { default as DropdownMenuSeparator } from './DropdownMenuSeparator.vue'
|
||||||
|
export { default as DropdownMenuShortcut } from './DropdownMenuShortcut.vue'
|
||||||
export { default as DropdownMenuSub } from './DropdownMenuSub.vue'
|
export { default as DropdownMenuSub } from './DropdownMenuSub.vue'
|
||||||
export { default as DropdownMenuSubTrigger } from './DropdownMenuSubTrigger.vue'
|
|
||||||
export { default as DropdownMenuSubContent } from './DropdownMenuSubContent.vue'
|
export { default as DropdownMenuSubContent } from './DropdownMenuSubContent.vue'
|
||||||
|
export { default as DropdownMenuSubTrigger } from './DropdownMenuSubTrigger.vue'
|
||||||
|
export { default as DropdownMenuTrigger } from './DropdownMenuTrigger.vue'
|
||||||
|
export { DropdownMenuPortal } from 'radix-vue'
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { type HTMLAttributes, computed } from 'vue'
|
import { cn } from '@/lib/utils'
|
||||||
import {
|
import {
|
||||||
HoverCardContent,
|
HoverCardContent,
|
||||||
type HoverCardContentProps,
|
type HoverCardContentProps,
|
||||||
HoverCardPortal,
|
HoverCardPortal,
|
||||||
useForwardProps,
|
useForwardProps,
|
||||||
} from 'radix-vue'
|
} from 'radix-vue'
|
||||||
import { cn } from '@/lib/utils'
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<HoverCardContentProps & { class?: HTMLAttributes[`class`] }>(),
|
defineProps<HoverCardContentProps & { class?: HTMLAttributes[`class`] }>(),
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
export { default as HoverCard } from './HoverCard.vue'
|
export { default as HoverCard } from './HoverCard.vue'
|
||||||
export { default as HoverCardTrigger } from './HoverCardTrigger.vue'
|
|
||||||
export { default as HoverCardContent } from './HoverCardContent.vue'
|
export { default as HoverCardContent } from './HoverCardContent.vue'
|
||||||
|
export { default as HoverCardTrigger } from './HoverCardTrigger.vue'
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { type HTMLAttributes, computed } from 'vue'
|
import { cn } from '@/lib/utils'
|
||||||
import {
|
import {
|
||||||
MenubarRoot,
|
MenubarRoot,
|
||||||
type MenubarRootEmits,
|
type MenubarRootEmits,
|
||||||
type MenubarRootProps,
|
type MenubarRootProps,
|
||||||
useForwardPropsEmits,
|
useForwardPropsEmits,
|
||||||
} from 'radix-vue'
|
} from 'radix-vue'
|
||||||
import { cn } from '@/lib/utils'
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
const props = defineProps<MenubarRootProps & { class?: HTMLAttributes[`class`] }>()
|
const props = defineProps<MenubarRootProps & { class?: HTMLAttributes[`class`] }>()
|
||||||
const emits = defineEmits<MenubarRootEmits>()
|
const emits = defineEmits<MenubarRootEmits>()
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { type HTMLAttributes, computed } from 'vue'
|
import { cn } from '@/lib/utils'
|
||||||
|
import { Check } from 'lucide-vue-next'
|
||||||
import {
|
import {
|
||||||
MenubarCheckboxItem,
|
MenubarCheckboxItem,
|
||||||
type MenubarCheckboxItemEmits,
|
type MenubarCheckboxItemEmits,
|
||||||
@ -7,8 +8,7 @@ import {
|
|||||||
MenubarItemIndicator,
|
MenubarItemIndicator,
|
||||||
useForwardPropsEmits,
|
useForwardPropsEmits,
|
||||||
} from 'radix-vue'
|
} from 'radix-vue'
|
||||||
import { Check } from 'lucide-vue-next'
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
import { cn } from '@/lib/utils'
|
|
||||||
|
|
||||||
const props = defineProps<MenubarCheckboxItemProps & { class?: HTMLAttributes[`class`] }>()
|
const props = defineProps<MenubarCheckboxItemProps & { class?: HTMLAttributes[`class`] }>()
|
||||||
const emits = defineEmits<MenubarCheckboxItemEmits>()
|
const emits = defineEmits<MenubarCheckboxItemEmits>()
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { type HTMLAttributes, computed } from 'vue'
|
import { cn } from '@/lib/utils'
|
||||||
import {
|
import {
|
||||||
MenubarContent,
|
MenubarContent,
|
||||||
type MenubarContentProps,
|
type MenubarContentProps,
|
||||||
MenubarPortal,
|
MenubarPortal,
|
||||||
useForwardProps,
|
useForwardProps,
|
||||||
} from 'radix-vue'
|
} from 'radix-vue'
|
||||||
import { cn } from '@/lib/utils'
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<MenubarContentProps & { class?: HTMLAttributes[`class`] }>(),
|
defineProps<MenubarContentProps & { class?: HTMLAttributes[`class`] }>(),
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { type HTMLAttributes, computed } from 'vue'
|
import { cn } from '@/lib/utils'
|
||||||
import {
|
import {
|
||||||
MenubarItem,
|
MenubarItem,
|
||||||
type MenubarItemEmits,
|
type MenubarItemEmits,
|
||||||
type MenubarItemProps,
|
type MenubarItemProps,
|
||||||
useForwardPropsEmits,
|
useForwardPropsEmits,
|
||||||
} from 'radix-vue'
|
} from 'radix-vue'
|
||||||
import { cn } from '@/lib/utils'
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
const props = defineProps<MenubarItemProps & { class?: HTMLAttributes[`class`], inset?: boolean }>()
|
const props = defineProps<MenubarItemProps & { class?: HTMLAttributes[`class`], inset?: boolean }>()
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { HTMLAttributes } from 'vue'
|
import type { HTMLAttributes } from 'vue'
|
||||||
import { MenubarLabel, type MenubarLabelProps } from 'radix-vue'
|
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
|
import { MenubarLabel, type MenubarLabelProps } from 'radix-vue'
|
||||||
|
|
||||||
const props = defineProps<MenubarLabelProps & { class?: HTMLAttributes[`class`], inset?: boolean }>()
|
const props = defineProps<MenubarLabelProps & { class?: HTMLAttributes[`class`], inset?: boolean }>()
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { type HTMLAttributes, computed } from 'vue'
|
import { cn } from '@/lib/utils'
|
||||||
|
import { Circle } from 'lucide-vue-next'
|
||||||
import {
|
import {
|
||||||
MenubarItemIndicator,
|
MenubarItemIndicator,
|
||||||
MenubarRadioItem,
|
MenubarRadioItem,
|
||||||
@ -7,8 +8,7 @@ import {
|
|||||||
type MenubarRadioItemProps,
|
type MenubarRadioItemProps,
|
||||||
useForwardPropsEmits,
|
useForwardPropsEmits,
|
||||||
} from 'radix-vue'
|
} from 'radix-vue'
|
||||||
import { Circle } from 'lucide-vue-next'
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
import { cn } from '@/lib/utils'
|
|
||||||
|
|
||||||
const props = defineProps<MenubarRadioItemProps & { class?: HTMLAttributes[`class`] }>()
|
const props = defineProps<MenubarRadioItemProps & { class?: HTMLAttributes[`class`] }>()
|
||||||
const emits = defineEmits<MenubarRadioItemEmits>()
|
const emits = defineEmits<MenubarRadioItemEmits>()
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { type HTMLAttributes, computed } from 'vue'
|
|
||||||
import { MenubarSeparator, type MenubarSeparatorProps, useForwardProps } from 'radix-vue'
|
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
|
import { MenubarSeparator, type MenubarSeparatorProps, useForwardProps } from 'radix-vue'
|
||||||
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
const props = defineProps<MenubarSeparatorProps & { class?: HTMLAttributes[`class`] }>()
|
const props = defineProps<MenubarSeparatorProps & { class?: HTMLAttributes[`class`] }>()
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { type HTMLAttributes, computed } from 'vue'
|
import { cn } from '@/lib/utils'
|
||||||
import {
|
import {
|
||||||
MenubarPortal,
|
MenubarPortal,
|
||||||
MenubarSubContent,
|
MenubarSubContent,
|
||||||
@ -7,7 +7,7 @@ import {
|
|||||||
type MenubarSubContentProps,
|
type MenubarSubContentProps,
|
||||||
useForwardPropsEmits,
|
useForwardPropsEmits,
|
||||||
} from 'radix-vue'
|
} from 'radix-vue'
|
||||||
import { cn } from '@/lib/utils'
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
const props = defineProps<MenubarSubContentProps & { class?: HTMLAttributes[`class`] }>()
|
const props = defineProps<MenubarSubContentProps & { class?: HTMLAttributes[`class`] }>()
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { type HTMLAttributes, computed } from 'vue'
|
|
||||||
import { MenubarSubTrigger, type MenubarSubTriggerProps, useForwardProps } from 'radix-vue'
|
|
||||||
import { ChevronRight } from 'lucide-vue-next'
|
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
|
import { ChevronRight } from 'lucide-vue-next'
|
||||||
|
import { MenubarSubTrigger, type MenubarSubTriggerProps, useForwardProps } from 'radix-vue'
|
||||||
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
const props = defineProps<MenubarSubTriggerProps & { class?: HTMLAttributes[`class`], inset?: boolean }>()
|
const props = defineProps<MenubarSubTriggerProps & { class?: HTMLAttributes[`class`], inset?: boolean }>()
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { type HTMLAttributes, computed } from 'vue'
|
|
||||||
import { MenubarTrigger, type MenubarTriggerProps, useForwardProps } from 'radix-vue'
|
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
|
import { MenubarTrigger, type MenubarTriggerProps, useForwardProps } from 'radix-vue'
|
||||||
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
const props = defineProps<MenubarTriggerProps & { class?: HTMLAttributes[`class`] }>()
|
const props = defineProps<MenubarTriggerProps & { class?: HTMLAttributes[`class`] }>()
|
||||||
|
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
export { default as Menubar } from './Menubar.vue'
|
export { default as Menubar } from './Menubar.vue'
|
||||||
export { default as MenubarItem } from './MenubarItem.vue'
|
export { default as MenubarCheckboxItem } from './MenubarCheckboxItem.vue'
|
||||||
export { default as MenubarContent } from './MenubarContent.vue'
|
export { default as MenubarContent } from './MenubarContent.vue'
|
||||||
export { default as MenubarGroup } from './MenubarGroup.vue'
|
export { default as MenubarGroup } from './MenubarGroup.vue'
|
||||||
|
export { default as MenubarItem } from './MenubarItem.vue'
|
||||||
|
export { default as MenubarLabel } from './MenubarLabel.vue'
|
||||||
export { default as MenubarMenu } from './MenubarMenu.vue'
|
export { default as MenubarMenu } from './MenubarMenu.vue'
|
||||||
export { default as MenubarRadioGroup } from './MenubarRadioGroup.vue'
|
export { default as MenubarRadioGroup } from './MenubarRadioGroup.vue'
|
||||||
export { default as MenubarRadioItem } from './MenubarRadioItem.vue'
|
export { default as MenubarRadioItem } from './MenubarRadioItem.vue'
|
||||||
export { default as MenubarCheckboxItem } from './MenubarCheckboxItem.vue'
|
|
||||||
export { default as MenubarSeparator } from './MenubarSeparator.vue'
|
export { default as MenubarSeparator } from './MenubarSeparator.vue'
|
||||||
|
export { default as MenubarShortcut } from './MenubarShortcut.vue'
|
||||||
export { default as MenubarSub } from './MenubarSub.vue'
|
export { default as MenubarSub } from './MenubarSub.vue'
|
||||||
export { default as MenubarSubContent } from './MenubarSubContent.vue'
|
export { default as MenubarSubContent } from './MenubarSubContent.vue'
|
||||||
export { default as MenubarSubTrigger } from './MenubarSubTrigger.vue'
|
export { default as MenubarSubTrigger } from './MenubarSubTrigger.vue'
|
||||||
export { default as MenubarTrigger } from './MenubarTrigger.vue'
|
export { default as MenubarTrigger } from './MenubarTrigger.vue'
|
||||||
export { default as MenubarShortcut } from './MenubarShortcut.vue'
|
|
||||||
export { default as MenubarLabel } from './MenubarLabel.vue'
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { PopoverRoot, useForwardPropsEmits } from 'radix-vue'
|
|
||||||
import type { PopoverRootEmits, PopoverRootProps } from 'radix-vue'
|
import type { PopoverRootEmits, PopoverRootProps } from 'radix-vue'
|
||||||
|
import { PopoverRoot, useForwardPropsEmits } from 'radix-vue'
|
||||||
|
|
||||||
const props = defineProps<PopoverRootProps>()
|
const props = defineProps<PopoverRootProps>()
|
||||||
const emits = defineEmits<PopoverRootEmits>()
|
const emits = defineEmits<PopoverRootEmits>()
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { type HTMLAttributes, computed } from 'vue'
|
import { cn } from '@/lib/utils'
|
||||||
import {
|
import {
|
||||||
PopoverContent,
|
PopoverContent,
|
||||||
type PopoverContentEmits,
|
type PopoverContentEmits,
|
||||||
@ -7,7 +7,7 @@ import {
|
|||||||
PopoverPortal,
|
PopoverPortal,
|
||||||
useForwardPropsEmits,
|
useForwardPropsEmits,
|
||||||
} from 'radix-vue'
|
} from 'radix-vue'
|
||||||
import { cn } from '@/lib/utils'
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
inheritAttrs: false,
|
inheritAttrs: false,
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
export { default as Popover } from './Popover.vue'
|
export { default as Popover } from './Popover.vue'
|
||||||
export { default as PopoverTrigger } from './PopoverTrigger.vue'
|
|
||||||
export { default as PopoverContent } from './PopoverContent.vue'
|
export { default as PopoverContent } from './PopoverContent.vue'
|
||||||
|
export { default as PopoverTrigger } from './PopoverTrigger.vue'
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { type HTMLAttributes, computed } from 'vue'
|
import { cn } from '@/lib/utils'
|
||||||
import {
|
import {
|
||||||
SelectContent,
|
SelectContent,
|
||||||
type SelectContentEmits,
|
type SelectContentEmits,
|
||||||
@ -8,8 +8,8 @@ import {
|
|||||||
SelectViewport,
|
SelectViewport,
|
||||||
useForwardPropsEmits,
|
useForwardPropsEmits,
|
||||||
} from 'radix-vue'
|
} from 'radix-vue'
|
||||||
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
import { SelectScrollDownButton, SelectScrollUpButton } from '.'
|
import { SelectScrollDownButton, SelectScrollUpButton } from '.'
|
||||||
import { cn } from '@/lib/utils'
|
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
inheritAttrs: false,
|
inheritAttrs: false,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { type HTMLAttributes, computed } from 'vue'
|
|
||||||
import { SelectGroup, type SelectGroupProps } from 'radix-vue'
|
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
|
import { SelectGroup, type SelectGroupProps } from 'radix-vue'
|
||||||
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
const props = defineProps<SelectGroupProps & { class?: HTMLAttributes[`class`] }>()
|
const props = defineProps<SelectGroupProps & { class?: HTMLAttributes[`class`] }>()
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { type HTMLAttributes, computed } from 'vue'
|
import { cn } from '@/lib/utils'
|
||||||
|
import { Check } from 'lucide-vue-next'
|
||||||
import {
|
import {
|
||||||
SelectItem,
|
SelectItem,
|
||||||
SelectItemIndicator,
|
SelectItemIndicator,
|
||||||
@ -7,8 +8,7 @@ import {
|
|||||||
SelectItemText,
|
SelectItemText,
|
||||||
useForwardProps,
|
useForwardProps,
|
||||||
} from 'radix-vue'
|
} from 'radix-vue'
|
||||||
import { Check } from 'lucide-vue-next'
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
import { cn } from '@/lib/utils'
|
|
||||||
|
|
||||||
const props = defineProps<SelectItemProps & { class?: HTMLAttributes[`class`] }>()
|
const props = defineProps<SelectItemProps & { class?: HTMLAttributes[`class`] }>()
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { HTMLAttributes } from 'vue'
|
import type { HTMLAttributes } from 'vue'
|
||||||
import { SelectLabel, type SelectLabelProps } from 'radix-vue'
|
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
|
import { SelectLabel, type SelectLabelProps } from 'radix-vue'
|
||||||
|
|
||||||
const props = defineProps<SelectLabelProps & { class?: HTMLAttributes[`class`] }>()
|
const props = defineProps<SelectLabelProps & { class?: HTMLAttributes[`class`] }>()
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { type HTMLAttributes, computed } from 'vue'
|
|
||||||
import { SelectScrollDownButton, type SelectScrollDownButtonProps, useForwardProps } from 'radix-vue'
|
|
||||||
import { ChevronDown } from 'lucide-vue-next'
|
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
|
import { ChevronDown } from 'lucide-vue-next'
|
||||||
|
import { SelectScrollDownButton, type SelectScrollDownButtonProps, useForwardProps } from 'radix-vue'
|
||||||
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
const props = defineProps<SelectScrollDownButtonProps & { class?: HTMLAttributes[`class`] }>()
|
const props = defineProps<SelectScrollDownButtonProps & { class?: HTMLAttributes[`class`] }>()
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { type HTMLAttributes, computed } from 'vue'
|
|
||||||
import { SelectScrollUpButton, type SelectScrollUpButtonProps, useForwardProps } from 'radix-vue'
|
|
||||||
import { ChevronUp } from 'lucide-vue-next'
|
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
|
import { ChevronUp } from 'lucide-vue-next'
|
||||||
|
import { SelectScrollUpButton, type SelectScrollUpButtonProps, useForwardProps } from 'radix-vue'
|
||||||
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
const props = defineProps<SelectScrollUpButtonProps & { class?: HTMLAttributes[`class`] }>()
|
const props = defineProps<SelectScrollUpButtonProps & { class?: HTMLAttributes[`class`] }>()
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { type HTMLAttributes, computed } from 'vue'
|
|
||||||
import { SelectSeparator, type SelectSeparatorProps } from 'radix-vue'
|
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
|
import { SelectSeparator, type SelectSeparatorProps } from 'radix-vue'
|
||||||
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
const props = defineProps<SelectSeparatorProps & { class?: HTMLAttributes[`class`] }>()
|
const props = defineProps<SelectSeparatorProps & { class?: HTMLAttributes[`class`] }>()
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { type HTMLAttributes, computed } from 'vue'
|
|
||||||
import { SelectIcon, SelectTrigger, type SelectTriggerProps, useForwardProps } from 'radix-vue'
|
|
||||||
import { ChevronDown } from 'lucide-vue-next'
|
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
|
import { ChevronDown } from 'lucide-vue-next'
|
||||||
|
import { SelectIcon, SelectTrigger, type SelectTriggerProps, useForwardProps } from 'radix-vue'
|
||||||
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
const props = defineProps<SelectTriggerProps & { class?: HTMLAttributes[`class`] }>()
|
const props = defineProps<SelectTriggerProps & { class?: HTMLAttributes[`class`] }>()
|
||||||
|
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
export { default as Select } from './Select.vue'
|
export { default as Select } from './Select.vue'
|
||||||
export { default as SelectValue } from './SelectValue.vue'
|
|
||||||
export { default as SelectTrigger } from './SelectTrigger.vue'
|
|
||||||
export { default as SelectContent } from './SelectContent.vue'
|
export { default as SelectContent } from './SelectContent.vue'
|
||||||
export { default as SelectGroup } from './SelectGroup.vue'
|
export { default as SelectGroup } from './SelectGroup.vue'
|
||||||
export { default as SelectItem } from './SelectItem.vue'
|
export { default as SelectItem } from './SelectItem.vue'
|
||||||
export { default as SelectItemText } from './SelectItemText.vue'
|
export { default as SelectItemText } from './SelectItemText.vue'
|
||||||
export { default as SelectLabel } from './SelectLabel.vue'
|
export { default as SelectLabel } from './SelectLabel.vue'
|
||||||
export { default as SelectSeparator } from './SelectSeparator.vue'
|
|
||||||
export { default as SelectScrollUpButton } from './SelectScrollUpButton.vue'
|
|
||||||
export { default as SelectScrollDownButton } from './SelectScrollDownButton.vue'
|
export { default as SelectScrollDownButton } from './SelectScrollDownButton.vue'
|
||||||
|
export { default as SelectScrollUpButton } from './SelectScrollUpButton.vue'
|
||||||
|
export { default as SelectSeparator } from './SelectSeparator.vue'
|
||||||
|
export { default as SelectTrigger } from './SelectTrigger.vue'
|
||||||
|
export { default as SelectValue } from './SelectValue.vue'
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { toMerged } from 'es-toolkit'
|
|
||||||
|
|
||||||
import type { IConfigOption, Theme } from '@/types'
|
import type { IConfigOption, Theme } from '@/types'
|
||||||
|
|
||||||
|
import { toMerged } from 'es-toolkit'
|
||||||
|
|
||||||
const defaultTheme: Theme = {
|
const defaultTheme: Theme = {
|
||||||
base: {
|
base: {
|
||||||
'--md-primary-color': `#000000`,
|
'--md-primary-color': `#000000`,
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import { ElLoading, ElMessage } from 'element-plus'
|
import type { App } from 'vue'
|
||||||
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
|
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
|
||||||
|
import { ElLoading, ElMessage } from 'element-plus'
|
||||||
import 'element-plus/dist/index.css'
|
import 'element-plus/dist/index.css'
|
||||||
import 'element-plus/theme-chalk/dark/css-vars.css'
|
import 'element-plus/theme-chalk/dark/css-vars.css'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
install(app) {
|
install(app: App<Element>) {
|
||||||
// app.use(ElementPlus, { size: `default` })
|
// app.use(ElementPlus, { size: `default` })
|
||||||
|
|
||||||
app.config.globalProperties.$loading = ElLoading.service
|
app.config.globalProperties.$loading = ElLoading.service
|
@ -1,7 +1,7 @@
|
|||||||
|
import { createPinia } from 'pinia'
|
||||||
import { createApp } from 'vue'
|
import { createApp } from 'vue'
|
||||||
import Store from './stores'
|
|
||||||
import ElementPlus from './element'
|
|
||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
|
import ElementPlus from './element'
|
||||||
|
|
||||||
import 'virtual:uno.css'
|
import 'virtual:uno.css'
|
||||||
import 'codemirror/lib/codemirror.css'
|
import 'codemirror/lib/codemirror.css'
|
||||||
@ -22,7 +22,7 @@ import 'codemirror/addon/hint/css-hint'
|
|||||||
|
|
||||||
const app = createApp(App)
|
const app = createApp(App)
|
||||||
|
|
||||||
app.use(Store)
|
app.use(createPinia())
|
||||||
app.use(ElementPlus)
|
app.use(ElementPlus)
|
||||||
|
|
||||||
app.mount(`#app`)
|
app.mount(`#app`)
|
@ -1,15 +1,15 @@
|
|||||||
import { computed, markRaw, onMounted, ref, toRaw, watch } from 'vue'
|
|
||||||
import { createPinia, defineStore } from 'pinia'
|
|
||||||
import { marked } from 'marked'
|
|
||||||
import CodeMirror from 'codemirror'
|
|
||||||
import { useDark, useStorage, useToggle } from '@vueuse/core'
|
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
|
||||||
|
|
||||||
import { altKey, codeBlockThemeOptions, colorOptions, fontFamilyOptions, fontSizeOptions, legendOptions, shiftKey, themeMap, themeOptions } from '@/config'
|
|
||||||
import { initRenderer } from '@/utils/renderer'
|
|
||||||
import DEFAULT_CONTENT from '@/assets/example/markdown.md?raw'
|
import DEFAULT_CONTENT from '@/assets/example/markdown.md?raw'
|
||||||
import DEFAULT_CSS_CONTENT from '@/assets/example/theme-css.txt?raw'
|
import DEFAULT_CSS_CONTENT from '@/assets/example/theme-css.txt?raw'
|
||||||
|
import { altKey, codeBlockThemeOptions, colorOptions, fontFamilyOptions, fontSizeOptions, legendOptions, shiftKey, themeMap, themeOptions } from '@/config'
|
||||||
import { addPrefix, css2json, customCssWithTemplate, customizeTheme, downloadMD, exportHTML, formatDoc } from '@/utils'
|
import { addPrefix, css2json, customCssWithTemplate, customizeTheme, downloadMD, exportHTML, formatDoc } from '@/utils'
|
||||||
|
import { initRenderer } from '@/utils/renderer'
|
||||||
|
import { useDark, useStorage, useToggle } from '@vueuse/core'
|
||||||
|
|
||||||
|
import CodeMirror from 'codemirror'
|
||||||
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
|
import { marked } from 'marked'
|
||||||
|
import { defineStore } from 'pinia'
|
||||||
|
import { computed, markRaw, onMounted, ref, toRaw, watch } from 'vue'
|
||||||
|
|
||||||
export const useStore = defineStore(`store`, () => {
|
export const useStore = defineStore(`store`, () => {
|
||||||
// 是否开启深色模式
|
// 是否开启深色模式
|
||||||
@ -379,23 +379,7 @@ export const useStore = defineStore(`store`, () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const isShowCssEditor = ref(false)
|
|
||||||
const toggleShowCssEditor = useToggle(isShowCssEditor)
|
|
||||||
|
|
||||||
const isShowInsertFormDialog = ref(false)
|
|
||||||
const toggleShowInsertFormDialog = useToggle(isShowInsertFormDialog)
|
|
||||||
|
|
||||||
const isShowUploadImgDialog = ref(false)
|
|
||||||
const toggleShowUploadImgDialog = useToggle(isShowUploadImgDialog)
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
isShowCssEditor,
|
|
||||||
toggleShowCssEditor,
|
|
||||||
isShowInsertFormDialog,
|
|
||||||
toggleShowInsertFormDialog,
|
|
||||||
isShowUploadImgDialog,
|
|
||||||
toggleShowUploadImgDialog,
|
|
||||||
|
|
||||||
isDark,
|
isDark,
|
||||||
toggleDark,
|
toggleDark,
|
||||||
|
|
||||||
@ -444,4 +428,25 @@ export const useStore = defineStore(`store`, () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export default createPinia()
|
export const useDisplayStore = defineStore(`display`, () => {
|
||||||
|
// 是否展示 CSS 编辑器
|
||||||
|
const isShowCssEditor = ref(false)
|
||||||
|
const toggleShowCssEditor = useToggle(isShowCssEditor)
|
||||||
|
|
||||||
|
// 是否展示插入表格对话框
|
||||||
|
const isShowInsertFormDialog = ref(false)
|
||||||
|
const toggleShowInsertFormDialog = useToggle(isShowInsertFormDialog)
|
||||||
|
|
||||||
|
// 是否展示上传图片对话框
|
||||||
|
const isShowUploadImgDialog = ref(false)
|
||||||
|
const toggleShowUploadImgDialog = useToggle(isShowUploadImgDialog)
|
||||||
|
|
||||||
|
return {
|
||||||
|
isShowCssEditor,
|
||||||
|
toggleShowCssEditor,
|
||||||
|
isShowInsertFormDialog,
|
||||||
|
toggleShowInsertFormDialog,
|
||||||
|
isShowUploadImgDialog,
|
||||||
|
toggleShowUploadImgDialog,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
import CryptoJS from 'crypto-js'
|
import { giteeConfig, githubConfig } from '@/config'
|
||||||
import OSS from 'tiny-oss'
|
|
||||||
import * as Minio from 'minio'
|
|
||||||
import COS from 'cos-js-sdk-v5'
|
|
||||||
import Buffer from 'buffer-from'
|
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
|
||||||
import * as qiniu from 'qiniu-js'
|
|
||||||
|
|
||||||
import fetch from '@/utils/fetch'
|
import fetch from '@/utils/fetch'
|
||||||
import { base64encode, safe64, utf16to8 } from '@/utils/tokenTools'
|
import { base64encode, safe64, utf16to8 } from '@/utils/tokenTools'
|
||||||
import * as tokenTools from '@/utils/tokenTools'
|
import * as tokenTools from '@/utils/tokenTools'
|
||||||
import { giteeConfig, githubConfig } from '@/config'
|
import Buffer from 'buffer-from'
|
||||||
|
import COS from 'cos-js-sdk-v5'
|
||||||
|
import CryptoJS from 'crypto-js'
|
||||||
|
|
||||||
|
import * as Minio from 'minio'
|
||||||
|
import * as qiniu from 'qiniu-js'
|
||||||
|
import OSS from 'tiny-oss'
|
||||||
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
|
|
||||||
function getConfig(useDefault: boolean, platform: string) {
|
function getConfig(useDefault: boolean, platform: string) {
|
||||||
if (useDefault) {
|
if (useDefault) {
|
||||||
@ -173,7 +173,7 @@ async function qiniuUpload(file: File) {
|
|||||||
const dir = path ? `${path}/` : ``
|
const dir = path ? `${path}/` : ``
|
||||||
const dateFilename = dir + getDateFilename(file.name)
|
const dateFilename = dir + getDateFilename(file.name)
|
||||||
const observable = qiniu.upload(file, dateFilename, token, {}, { region })
|
const observable = qiniu.upload(file, dateFilename, token, {}, { region })
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise<string>((resolve, reject) => {
|
||||||
observable.subscribe({
|
observable.subscribe({
|
||||||
next: (result) => {
|
next: (result) => {
|
||||||
console.log(result)
|
console.log(result)
|
||||||
@ -229,7 +229,7 @@ async function txCOSFileUpload(file: File) {
|
|||||||
SecretId: secretId,
|
SecretId: secretId,
|
||||||
SecretKey: secretKey,
|
SecretKey: secretKey,
|
||||||
})
|
})
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise<string>((resolve, reject) => {
|
||||||
cos.putObject(
|
cos.putObject(
|
||||||
{
|
{
|
||||||
Bucket: bucket,
|
Bucket: bucket,
|
||||||
@ -277,7 +277,7 @@ async function minioFileUpload(content: string, filename: string) {
|
|||||||
if (isCustomPort) {
|
if (isCustomPort) {
|
||||||
conf.port = p
|
conf.port = p
|
||||||
}
|
}
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise<string>((resolve, reject) => {
|
||||||
const minioClient = new Minio.Client(conf)
|
const minioClient = new Minio.Client(conf)
|
||||||
try {
|
try {
|
||||||
minioClient.putObject(bucket, dateFilename, buffer, (e) => {
|
minioClient.putObject(bucket, dateFilename, buffer, (e) => {
|
||||||
@ -309,7 +309,7 @@ async function formCustomUpload(content: string, file: File) {
|
|||||||
${localStorage.getItem(`formCustomConfig`)}
|
${localStorage.getItem(`formCustomConfig`)}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise<string>((resolve, reject) => {
|
||||||
const exportObj = {
|
const exportObj = {
|
||||||
content, // 待上传图片的 base64
|
content, // 待上传图片的 base64
|
||||||
file, // 待上传图片的 file 对象
|
file, // 待上传图片的 file 对象
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
import juice from 'juice'
|
import type { Block, Inline, Theme } from '@/types'
|
||||||
|
|
||||||
import { format } from 'prettier/standalone'
|
|
||||||
import * as prettierPluginMarkdown from 'prettier/plugins/markdown'
|
|
||||||
import * as prettierPluginBabel from 'prettier/plugins/babel'
|
|
||||||
import * as prettierPluginEstree from 'prettier/plugins/estree'
|
|
||||||
import * as prettierPluginCss from 'prettier/plugins/postcss'
|
|
||||||
import type { PropertiesHyphen } from 'csstype'
|
import type { PropertiesHyphen } from 'csstype'
|
||||||
import { prefix } from '@/config'
|
import { prefix } from '@/config'
|
||||||
import type { Block, Inline, Theme } from '@/types'
|
import juice from 'juice'
|
||||||
|
import * as prettierPluginBabel from 'prettier/plugins/babel'
|
||||||
|
import * as prettierPluginEstree from 'prettier/plugins/estree'
|
||||||
|
import * as prettierPluginMarkdown from 'prettier/plugins/markdown'
|
||||||
|
import * as prettierPluginCss from 'prettier/plugins/postcss'
|
||||||
|
import { format } from 'prettier/standalone'
|
||||||
|
|
||||||
export function addPrefix(str: string) {
|
export function addPrefix(str: string) {
|
||||||
return `${prefix}__${str}`
|
return `${prefix}__${str}`
|
||||||
@ -111,8 +111,6 @@ export function css2json(css: string): Partial<Record<Block | Inline, Properties
|
|||||||
css = css.slice(rbracket + 1).trim()
|
css = css.slice(rbracket + 1).trim()
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`json`, json)
|
|
||||||
|
|
||||||
return json
|
return json
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -253,10 +251,10 @@ export function createTable({ data, rows, cols }: { data: { [k: string]: string
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function toBase64(file: Blob) {
|
export function toBase64(file: Blob) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise<string>((resolve, reject) => {
|
||||||
const reader = new FileReader()
|
const reader = new FileReader()
|
||||||
reader.readAsDataURL(file)
|
reader.readAsDataURL(file)
|
||||||
reader.onload = () => resolve((reader.result as string).split(`,`).pop())
|
reader.onload = () => resolve((reader.result as string).split(`,`).pop()!)
|
||||||
reader.onerror = error => reject(error)
|
reader.onerror = error => reject(error)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import type { Renderer, RendererObject, Tokens } from 'marked'
|
|
||||||
import { marked } from 'marked'
|
|
||||||
import hljs from 'highlight.js'
|
|
||||||
import mermaid from 'mermaid'
|
|
||||||
import { toMerged } from 'es-toolkit'
|
|
||||||
|
|
||||||
import type { PropertiesHyphen } from 'csstype'
|
|
||||||
import { MDKatex } from './MDKatex'
|
|
||||||
import type { ExtendedProperties, IOpts, ThemeStyles } from '@/types'
|
import type { ExtendedProperties, IOpts, ThemeStyles } from '@/types'
|
||||||
|
import type { PropertiesHyphen } from 'csstype'
|
||||||
|
import type { Renderer, RendererObject, Tokens } from 'marked'
|
||||||
|
import { toMerged } from 'es-toolkit'
|
||||||
|
import hljs from 'highlight.js'
|
||||||
|
|
||||||
|
import { marked } from 'marked'
|
||||||
|
import mermaid from 'mermaid'
|
||||||
|
import { MDKatex } from './MDKatex'
|
||||||
|
|
||||||
marked.use(MDKatex({ nonStandard: true }))
|
marked.use(MDKatex({ nonStandard: true }))
|
||||||
|
|
||||||
|
@ -1,18 +1,11 @@
|
|||||||
<script setup>
|
<script setup lang="ts">
|
||||||
import { onMounted, ref, toRaw, watch } from 'vue'
|
import type { ComponentPublicInstance } from 'vue'
|
||||||
import { storeToRefs } from 'pinia'
|
import CssEditor from '@/components/CodemirrorEditor/CssEditor.vue'
|
||||||
import { ElMessage } from 'element-plus'
|
|
||||||
import CodeMirror from 'codemirror'
|
|
||||||
|
|
||||||
import fileApi from '@/utils/file'
|
|
||||||
import { useStore } from '@/stores'
|
|
||||||
|
|
||||||
import EditorHeader from '@/components/CodemirrorEditor/EditorHeader/index.vue'
|
import EditorHeader from '@/components/CodemirrorEditor/EditorHeader/index.vue'
|
||||||
import InsertFormDialog from '@/components/CodemirrorEditor/InsertFormDialog.vue'
|
import InsertFormDialog from '@/components/CodemirrorEditor/InsertFormDialog.vue'
|
||||||
import UploadImgDialog from '@/components/CodemirrorEditor/UploadImgDialog.vue'
|
import UploadImgDialog from '@/components/CodemirrorEditor/UploadImgDialog.vue'
|
||||||
import CssEditor from '@/components/CodemirrorEditor/CssEditor.vue'
|
|
||||||
import RunLoading from '@/components/RunLoading.vue'
|
|
||||||
|
|
||||||
|
import RunLoading from '@/components/RunLoading.vue'
|
||||||
import {
|
import {
|
||||||
ContextMenu,
|
ContextMenu,
|
||||||
ContextMenuContent,
|
ContextMenuContent,
|
||||||
@ -23,15 +16,25 @@ import {
|
|||||||
} from '@/components/ui/context-menu'
|
} from '@/components/ui/context-menu'
|
||||||
|
|
||||||
import { altKey, altSign, ctrlKey, shiftKey, shiftSign } from '@/config'
|
import { altKey, altSign, ctrlKey, shiftKey, shiftSign } from '@/config'
|
||||||
|
import { useDisplayStore, useStore } from '@/stores'
|
||||||
import {
|
import {
|
||||||
checkImage,
|
checkImage,
|
||||||
formatDoc,
|
formatDoc,
|
||||||
toBase64,
|
toBase64,
|
||||||
} from '@/utils'
|
} from '@/utils'
|
||||||
|
import fileApi from '@/utils/file'
|
||||||
|
import CodeMirror from 'codemirror'
|
||||||
|
|
||||||
|
import { ElCol, ElMessage } from 'element-plus'
|
||||||
|
|
||||||
|
import { storeToRefs } from 'pinia'
|
||||||
|
|
||||||
|
import { onMounted, ref, toRaw, watch } from 'vue'
|
||||||
|
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
const { isDark, output, editor, editorContent, isShowCssEditor } = storeToRefs(store)
|
const displayStore = useDisplayStore()
|
||||||
|
const { isDark, output, editor, editorContent } = storeToRefs(store)
|
||||||
|
const { isShowCssEditor } = storeToRefs(displayStore)
|
||||||
|
|
||||||
const {
|
const {
|
||||||
editorRefresh,
|
editorRefresh,
|
||||||
@ -40,33 +43,37 @@ const {
|
|||||||
formatContent,
|
formatContent,
|
||||||
importMarkdownContent,
|
importMarkdownContent,
|
||||||
resetStyleConfirm,
|
resetStyleConfirm,
|
||||||
toggleShowInsertFormDialog,
|
|
||||||
toggleShowUploadImgDialog,
|
|
||||||
} = store
|
} = store
|
||||||
|
|
||||||
const isImgLoading = ref(false)
|
const {
|
||||||
const timeout = ref(0)
|
toggleShowInsertFormDialog,
|
||||||
|
toggleShowUploadImgDialog,
|
||||||
|
} = displayStore
|
||||||
|
|
||||||
const preview = ref(null)
|
const isImgLoading = ref(false)
|
||||||
|
const timeout = ref<NodeJS.Timeout>()
|
||||||
|
|
||||||
|
const preview = ref<typeof ElCol | null>(null)
|
||||||
|
|
||||||
// 使浏览区与编辑区滚动条建立同步联系
|
// 使浏览区与编辑区滚动条建立同步联系
|
||||||
function leftAndRightScroll() {
|
function leftAndRightScroll() {
|
||||||
const scrollCB = (text) => {
|
const scrollCB = (text: string) => {
|
||||||
let source, target
|
let source: HTMLElement
|
||||||
|
let target: HTMLElement
|
||||||
|
|
||||||
clearTimeout(timeout.value)
|
clearTimeout(timeout.value)
|
||||||
if (text === `preview`) {
|
if (text === `preview`) {
|
||||||
source = preview.value.$el
|
source = preview.value!.$el
|
||||||
target = document.querySelector(`.CodeMirror-scroll`)
|
target = document.querySelector<HTMLElement>(`.CodeMirror-scroll`)!
|
||||||
|
|
||||||
editor.value.off(`scroll`, editorScrollCB)
|
editor.value!.off(`scroll`, editorScrollCB)
|
||||||
timeout.value = setTimeout(() => {
|
timeout.value = setTimeout(() => {
|
||||||
editor.value.on(`scroll`, editorScrollCB)
|
editor.value!.on(`scroll`, editorScrollCB)
|
||||||
}, 300)
|
}, 300)
|
||||||
}
|
}
|
||||||
else if (text === `editor`) {
|
else {
|
||||||
source = document.querySelector(`.CodeMirror-scroll`)
|
source = document.querySelector<HTMLElement>(`.CodeMirror-scroll`)!
|
||||||
target = preview.value.$el
|
target = preview.value!.$el
|
||||||
|
|
||||||
target.removeEventListener(`scroll`, previewScrollCB, false)
|
target.removeEventListener(`scroll`, previewScrollCB, false)
|
||||||
timeout.value = setTimeout(() => {
|
timeout.value = setTimeout(() => {
|
||||||
@ -89,8 +96,8 @@ function leftAndRightScroll() {
|
|||||||
scrollCB(`preview`)
|
scrollCB(`preview`)
|
||||||
}
|
}
|
||||||
|
|
||||||
preview.value.$el.addEventListener(`scroll`, previewScrollCB, false)
|
(preview.value!.$el).addEventListener(`scroll`, previewScrollCB, false)
|
||||||
editor.value.on(`scroll`, editorScrollCB)
|
editor.value!.on(`scroll`, editorScrollCB)
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
@ -120,7 +127,7 @@ function endCopy() {
|
|||||||
}, 800)
|
}, 800)
|
||||||
}
|
}
|
||||||
|
|
||||||
function beforeUpload(file) {
|
function beforeUpload(file: File) {
|
||||||
// validate image
|
// validate image
|
||||||
const checkResult = checkImage(file)
|
const checkResult = checkImage(file)
|
||||||
if (!checkResult.ok) {
|
if (!checkResult.ok) {
|
||||||
@ -142,20 +149,20 @@ function beforeUpload(file) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 图片上传结束
|
// 图片上传结束
|
||||||
function uploaded(imageUrl) {
|
function uploaded(imageUrl: string) {
|
||||||
if (!imageUrl) {
|
if (!imageUrl) {
|
||||||
ElMessage.error(`上传图片未知异常`)
|
ElMessage.error(`上传图片未知异常`)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
toggleShowUploadImgDialog(false)
|
toggleShowUploadImgDialog(false)
|
||||||
// 上传成功,获取光标
|
// 上传成功,获取光标
|
||||||
const cursor = editor.value.getCursor()
|
const cursor = editor.value!.getCursor()
|
||||||
const markdownImage = `![](${imageUrl})`
|
const markdownImage = `![](${imageUrl})`
|
||||||
// 将 Markdown 形式的 URL 插入编辑框光标所在位置
|
// 将 Markdown 形式的 URL 插入编辑框光标所在位置
|
||||||
toRaw(store.editor).replaceSelection(`\n${markdownImage}\n`, cursor)
|
toRaw(store.editor!).replaceSelection(`\n${markdownImage}\n`, cursor as any)
|
||||||
ElMessage.success(`图片上传成功`)
|
ElMessage.success(`图片上传成功`)
|
||||||
}
|
}
|
||||||
function uploadImage(file, cb) {
|
function uploadImage(file: File, cb?: { (url: any): void, (arg0: unknown): void } | undefined) {
|
||||||
isImgLoading.value = true
|
isImgLoading.value = true
|
||||||
|
|
||||||
toBase64(file)
|
toBase64(file)
|
||||||
@ -176,7 +183,7 @@ function uploadImage(file, cb) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const changeTimer = ref(0)
|
const changeTimer = ref<NodeJS.Timeout>()
|
||||||
|
|
||||||
// 监听暗色模式并更新编辑器
|
// 监听暗色模式并更新编辑器
|
||||||
watch(isDark, () => {
|
watch(isDark, () => {
|
||||||
@ -186,7 +193,7 @@ watch(isDark, () => {
|
|||||||
|
|
||||||
// 初始化编辑器
|
// 初始化编辑器
|
||||||
function initEditor() {
|
function initEditor() {
|
||||||
const editorDom = document.querySelector(`#editor`)
|
const editorDom = document.querySelector<HTMLTextAreaElement>(`#editor`)!
|
||||||
|
|
||||||
if (!editorDom.value) {
|
if (!editorDom.value) {
|
||||||
editorDom.value = editorContent.value
|
editorDom.value = editorContent.value
|
||||||
@ -200,7 +207,7 @@ function initEditor() {
|
|||||||
autoCloseBrackets: true,
|
autoCloseBrackets: true,
|
||||||
extraKeys: {
|
extraKeys: {
|
||||||
[`${shiftKey}-${altKey}-F`]: function autoFormat(editor) {
|
[`${shiftKey}-${altKey}-F`]: function autoFormat(editor) {
|
||||||
formatDoc(editor.getValue(0)).then((doc) => {
|
formatDoc(editor.getValue()).then((doc) => {
|
||||||
editor.setValue(doc)
|
editor.setValue(doc)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@ -241,7 +248,7 @@ function initEditor() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// 粘贴上传图片并插入
|
// 粘贴上传图片并插入
|
||||||
editor.value.on(`paste`, (cm, e) => {
|
editor.value.on(`paste`, (_cm, e) => {
|
||||||
if (!(e.clipboardData && e.clipboardData.items) || isImgLoading.value) {
|
if (!(e.clipboardData && e.clipboardData.items) || isImgLoading.value) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -249,7 +256,7 @@ function initEditor() {
|
|||||||
const item = e.clipboardData.items[i]
|
const item = e.clipboardData.items[i]
|
||||||
if (item.kind === `file`) {
|
if (item.kind === `file`) {
|
||||||
// 校验图床参数
|
// 校验图床参数
|
||||||
const pasteFile = item.getAsFile()
|
const pasteFile = item.getAsFile()!
|
||||||
const isValid = beforeUpload(pasteFile)
|
const isValid = beforeUpload(pasteFile)
|
||||||
if (!isValid) {
|
if (!isValid) {
|
||||||
continue
|
continue
|
||||||
@ -263,33 +270,33 @@ function initEditor() {
|
|||||||
const container = ref(null)
|
const container = ref(null)
|
||||||
|
|
||||||
// 工具函数,添加格式
|
// 工具函数,添加格式
|
||||||
function addFormat(cmd) {
|
function addFormat(cmd: string | number) {
|
||||||
editor.value.options.extraKeys[cmd](editor.value)
|
(editor.value as any).options.extraKeys[cmd](editor.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
const codeMirrorWrapper = ref(null)
|
const codeMirrorWrapper = ref<ComponentPublicInstance<typeof ElCol> | null>(null)
|
||||||
|
|
||||||
// 转换 markdown 中的本地图片为线上图片
|
// 转换 markdown 中的本地图片为线上图片
|
||||||
// todo 处理事件覆盖
|
// todo 处理事件覆盖
|
||||||
function mdLocalToRemote() {
|
function mdLocalToRemote() {
|
||||||
const dom = codeMirrorWrapper.value.$el
|
const dom = codeMirrorWrapper.value!.$el as HTMLElement
|
||||||
|
|
||||||
// 上传 md 中的图片
|
// 上传 md 中的图片
|
||||||
const uploadMdImg = async ({ md, list }) => {
|
const uploadMdImg = async ({ md, list }: { md: { str: string, path: string, file: File }, list: { path: string, file: File }[] }) => {
|
||||||
const mdImgList = [
|
const mdImgList = [
|
||||||
...(md.str.matchAll(/!\[(.*?)\]\((.*?)\)/g) || []),
|
...(md.str.matchAll(/!\[(.*?)\]\((.*?)\)/g) || []),
|
||||||
].filter((item) => {
|
].filter((item) => {
|
||||||
return item // 获取所有相对地址的图片
|
return item // 获取所有相对地址的图片
|
||||||
})
|
})
|
||||||
const root = md.path.match(/.+?\//)[0]
|
const root = md.path.match(/.+?\//)![0]
|
||||||
const resList = await Promise.all(
|
const resList = await Promise.all<{ matchStr: string, url: string }>(
|
||||||
mdImgList.map((item) => {
|
mdImgList.map((item) => {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
let [, , matchStr] = item
|
let [, , matchStr] = item
|
||||||
matchStr = matchStr.replace(/^.\//, ``) // 处理 ./img/ 为 img/ 统一相对路径风格
|
matchStr = matchStr.replace(/^.\//, ``) // 处理 ./img/ 为 img/ 统一相对路径风格
|
||||||
const { file }
|
const { file }
|
||||||
= list.find(f => f.path === `${root}${matchStr}`) || {}
|
= list.find(f => f.path === `${root}${matchStr}`) || {}
|
||||||
uploadImage(file, (url) => {
|
uploadImage(file!, (url) => {
|
||||||
resolve({ matchStr, url })
|
resolve({ matchStr, url })
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -300,16 +307,16 @@ function mdLocalToRemote() {
|
|||||||
.replace(`](./${item.matchStr})`, `](${item.url})`)
|
.replace(`](./${item.matchStr})`, `](${item.url})`)
|
||||||
.replace(`](${item.matchStr})`, `](${item.url})`)
|
.replace(`](${item.matchStr})`, `](${item.url})`)
|
||||||
})
|
})
|
||||||
editor.value.setValue(md.str)
|
editor.value!.setValue(md.str)
|
||||||
}
|
}
|
||||||
|
|
||||||
dom.ondragover = evt => evt.preventDefault()
|
dom.ondragover = evt => evt.preventDefault()
|
||||||
dom.ondrop = async (evt) => {
|
dom.ondrop = async (evt: any) => {
|
||||||
evt.preventDefault()
|
evt.preventDefault()
|
||||||
for (const item of evt.dataTransfer.items) {
|
for (const item of evt.dataTransfer.items) {
|
||||||
item.getAsFileSystemHandle().then(async (handle) => {
|
item.getAsFileSystemHandle().then(async (handle: { kind: string, getFile: () => any }) => {
|
||||||
if (handle.kind === `directory`) {
|
if (handle.kind === `directory`) {
|
||||||
const list = await showFileStructure(handle)
|
const list = await showFileStructure(handle) as { path: string, file: File }[]
|
||||||
const md = await getMd({ list })
|
const md = await getMd({ list })
|
||||||
uploadMdImg({ md, list })
|
uploadMdImg({ md, list })
|
||||||
}
|
}
|
||||||
@ -322,14 +329,14 @@ function mdLocalToRemote() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 从文件列表中查找一个 md 文件并解析
|
// 从文件列表中查找一个 md 文件并解析
|
||||||
async function getMd({ list }) {
|
async function getMd({ list }: { list: { path: string, file: File }[] }) {
|
||||||
return new Promise((resolve) => {
|
return new Promise<{ str: string, file: File, path: string }>((resolve) => {
|
||||||
const { path, file } = list.find(item => item.path.match(/\.md$/))
|
const { path, file } = list.find(item => item.path.match(/\.md$/))!
|
||||||
const reader = new FileReader()
|
const reader = new FileReader()
|
||||||
reader.readAsText(file, `UTF-8`)
|
reader.readAsText(file!, `UTF-8`)
|
||||||
reader.onload = (evt) => {
|
reader.onload = (evt) => {
|
||||||
resolve({
|
resolve({
|
||||||
str: evt.target.result,
|
str: evt.target!.result as string,
|
||||||
file,
|
file,
|
||||||
path,
|
path,
|
||||||
})
|
})
|
||||||
@ -338,7 +345,7 @@ function mdLocalToRemote() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 转换文件系统句柄中的文件为文件列表
|
// 转换文件系统句柄中的文件为文件列表
|
||||||
async function showFileStructure(root) {
|
async function showFileStructure(root: any) {
|
||||||
const result = []
|
const result = []
|
||||||
let cwd = ``
|
let cwd = ``
|
||||||
try {
|
try {
|
||||||
@ -385,7 +392,7 @@ onMounted(() => {
|
|||||||
/>
|
/>
|
||||||
<main class="container-main flex-1">
|
<main class="container-main flex-1">
|
||||||
<el-row class="container-main-section h-full border-1">
|
<el-row class="container-main-section h-full border-1">
|
||||||
<el-col
|
<ElCol
|
||||||
ref="codeMirrorWrapper"
|
ref="codeMirrorWrapper"
|
||||||
:span="isShowCssEditor ? 8 : 12"
|
:span="isShowCssEditor ? 8 : 12"
|
||||||
class="codeMirror-wrapper border-r-1"
|
class="codeMirror-wrapper border-r-1"
|
||||||
@ -427,8 +434,8 @@ onMounted(() => {
|
|||||||
</ContextMenuItem>
|
</ContextMenuItem>
|
||||||
</ContextMenuContent>
|
</ContextMenuContent>
|
||||||
</ContextMenu>
|
</ContextMenu>
|
||||||
</el-col>
|
</ElCol>
|
||||||
<el-col
|
<ElCol
|
||||||
id="preview"
|
id="preview"
|
||||||
ref="preview"
|
ref="preview"
|
||||||
:span="isShowCssEditor ? 8 : 12"
|
:span="isShowCssEditor ? 8 : 12"
|
||||||
@ -445,7 +452,7 @@ onMounted(() => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</ElCol>
|
||||||
<CssEditor />
|
<CssEditor />
|
||||||
</el-row>
|
</el-row>
|
||||||
</main>
|
</main>
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
import path from 'node:path'
|
import path from 'node:path'
|
||||||
import process from 'node:process'
|
import process from 'node:process'
|
||||||
|
|
||||||
import { defineConfig } from 'vite'
|
|
||||||
import vue from '@vitejs/plugin-vue'
|
import vue from '@vitejs/plugin-vue'
|
||||||
import UnoCSS from 'unocss/vite'
|
|
||||||
import vueDevTools from 'vite-plugin-vue-devtools'
|
|
||||||
import { nodePolyfills } from 'vite-plugin-node-polyfills'
|
|
||||||
import { visualizer } from 'rollup-plugin-visualizer'
|
import { visualizer } from 'rollup-plugin-visualizer'
|
||||||
|
import UnoCSS from 'unocss/vite'
|
||||||
import AutoImport from 'unplugin-auto-import/vite'
|
import AutoImport from 'unplugin-auto-import/vite'
|
||||||
import Components from 'unplugin-vue-components/vite'
|
|
||||||
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
|
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
|
||||||
|
import Components from 'unplugin-vue-components/vite'
|
||||||
|
import { defineConfig } from 'vite'
|
||||||
|
import { nodePolyfills } from 'vite-plugin-node-polyfills'
|
||||||
|
import vueDevTools from 'vite-plugin-vue-devtools'
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
|
Loading…
Reference in New Issue
Block a user