@nywqs/vue-markdown-editor 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +255 -221
- package/dist-lib/github-ClbBTCKO.js +1 -0
- package/dist-lib/vue-markdown-editor.css +1 -1
- package/dist-lib/vue-markdown-editor.es.js +21377 -17634
- package/dist-lib/vue-markdown-editor.umd.js +448 -49
- package/package.json +60 -38
package/README.md
CHANGED
|
@@ -1,221 +1,255 @@
|
|
|
1
|
-
# @nywqs/vue-markdown-editor
|
|
2
|
-
|
|
3
|
-
一个基于 Vue 3
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
|
77
|
-
|
|
78
|
-
| `
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
'
|
|
95
|
-
'
|
|
96
|
-
'
|
|
97
|
-
'
|
|
98
|
-
'
|
|
99
|
-
'
|
|
100
|
-
'
|
|
101
|
-
'
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
1
|
+
# @nywqs/vue-markdown-editor
|
|
2
|
+
|
|
3
|
+
一个基于 Vue 3 和 Canvas 的高性能 Markdown 编辑器组件,采用混合渲染架构(Canvas + DOM),支持大文件编辑、实时语法高亮、智能预测渲染等特性。
|
|
4
|
+
|
|
5
|
+
## ✨ 核心特性
|
|
6
|
+
|
|
7
|
+
- 🚀 **高性能渲染**:Canvas + DOM 混合渲染,支持大文件流畅编辑
|
|
8
|
+
- 🎨 **实时语法高亮**:支持 Markdown 语法高亮和主题切换
|
|
9
|
+
- 📝 **丰富的编辑功能**:工具栏快捷操作、键盘快捷键、搜索替换
|
|
10
|
+
- 🔌 **插件系统**:支持表格、待办列表、数学公式、流程图等扩展
|
|
11
|
+
- 💡 **智能优化**:视口裁剪、虚拟滚动、增量渲染、离屏缓存
|
|
12
|
+
- 🎯 **实时预览**:支持 Markdown 预览面板,双向滚动同步
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## 📦 安装
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install @nywqs/vue-markdown-editor
|
|
20
|
+
# 或
|
|
21
|
+
yarn add @nywqs/vue-markdown-editor
|
|
22
|
+
# 或
|
|
23
|
+
pnpm add @nywqs/vue-markdown-editor
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## 🚀 快速上手
|
|
29
|
+
|
|
30
|
+
### 全局注册组件
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
import { createApp } from 'vue'
|
|
34
|
+
import App from './App.vue'
|
|
35
|
+
import { CanvasEditor } from '@nywqs/vue-markdown-editor'
|
|
36
|
+
import '@nywqs/vue-markdown-editor/dist-lib/wqs_editor.css'
|
|
37
|
+
|
|
38
|
+
const app = createApp(App)
|
|
39
|
+
|
|
40
|
+
// 作为全局组件使用
|
|
41
|
+
app.component('CanvasEditor', CanvasEditor)
|
|
42
|
+
|
|
43
|
+
app.mount('#app')
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### 基本用法
|
|
47
|
+
|
|
48
|
+
```vue
|
|
49
|
+
<template>
|
|
50
|
+
<div style="height: 600px;">
|
|
51
|
+
<CanvasEditor
|
|
52
|
+
v-model="content"
|
|
53
|
+
:theme="theme"
|
|
54
|
+
:show-line-numbers="true"
|
|
55
|
+
:show-toolbar="true"
|
|
56
|
+
/>
|
|
57
|
+
</div>
|
|
58
|
+
</template>
|
|
59
|
+
|
|
60
|
+
<script setup lang="ts">
|
|
61
|
+
import { ref } from 'vue'
|
|
62
|
+
import { CanvasEditor } from '@nywqs/vue-markdown-editor'
|
|
63
|
+
import '@nywqs/vue-markdown-editor/dist-lib/wqs_editor.css'
|
|
64
|
+
|
|
65
|
+
const content = ref('# Hello Canvas Editor\n\n这是一个高性能的 Markdown 编辑器')
|
|
66
|
+
const theme = ref('light')
|
|
67
|
+
</script>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## 📖 组件属性(Props)
|
|
73
|
+
|
|
74
|
+
`CanvasEditor` 主要支持以下 props:
|
|
75
|
+
|
|
76
|
+
| Prop | 类型 | 默认值 | 说明 |
|
|
77
|
+
|-------------------------|---------------------|-----------|------|
|
|
78
|
+
| `modelValue` | `string` | `''` | 当前 Markdown 文本内容,支持 `v-model` |
|
|
79
|
+
| `theme` | `'light' \| 'dark'` | `'light'` | 编辑器主题 |
|
|
80
|
+
| `enableSyntaxHighlight` | `boolean` | `true` | 是否启用语法高亮 |
|
|
81
|
+
| `fontSize` | `number` | `15` | 字体大小(像素) |
|
|
82
|
+
| `lineHeight` | `number` | `26` | 行高(像素) |
|
|
83
|
+
| `showLineNumbers` | `boolean` | `true` | 是否显示行号 |
|
|
84
|
+
| `showToolbar` | `boolean` | `true` | 是否显示工具栏 |
|
|
85
|
+
| `scrollPercentage` | `number` | `0` | 外部控制的滚动位置(百分比,0-1) |
|
|
86
|
+
| `isSyncing` | `boolean` | `false` | 是否正在同步滚动(避免循环) |
|
|
87
|
+
|
|
88
|
+
### `toolbarItems` 默认值
|
|
89
|
+
|
|
90
|
+
默认工具栏包含主题切换、标题、加粗、斜体、列表、引用、代码块、分割线、链接、图片:
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
[
|
|
94
|
+
'theme-toggle',
|
|
95
|
+
'divider',
|
|
96
|
+
'h1',
|
|
97
|
+
'h2',
|
|
98
|
+
'divider',
|
|
99
|
+
'bold',
|
|
100
|
+
'italic',
|
|
101
|
+
'divider',
|
|
102
|
+
'unordered-list',
|
|
103
|
+
'ordered-list',
|
|
104
|
+
'blockquote',
|
|
105
|
+
'code-block',
|
|
106
|
+
'horizontal-rule',
|
|
107
|
+
'divider',
|
|
108
|
+
'link',
|
|
109
|
+
'image',
|
|
110
|
+
]
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## ⚡ 事件(Emits)
|
|
116
|
+
|
|
117
|
+
组件会触发以下事件:
|
|
118
|
+
|
|
119
|
+
| 事件名 | 参数 | 说明 |
|
|
120
|
+
|---------------------------|--------------------|------|
|
|
121
|
+
| `update:modelValue` | `(value: string)` | `v-model` 双向绑定事件 |
|
|
122
|
+
| `update:scrollPercentage` | `(value: number)` | 滚动位置变化时触发 |
|
|
123
|
+
| `scroll` | `(value: number)` | 滚动事件 |
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## 🎨 主题和样式
|
|
128
|
+
|
|
129
|
+
编辑器支持 `light` 和 `dark` 两种内置主题,可以通过 `theme` 属性切换:
|
|
130
|
+
|
|
131
|
+
```vue
|
|
132
|
+
<CanvasEditor v-model="content" theme="dark" />
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
你也可以通过 CSS 变量自定义样式(见源码 `style.css`)。
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## 🔧 配合预览面板使用
|
|
140
|
+
|
|
141
|
+
如果需要实时预览,可以配合 `MarkdownPreviewPanel` 组件使用:
|
|
142
|
+
|
|
143
|
+
```vue
|
|
144
|
+
<script setup lang="ts">
|
|
145
|
+
import { ref } from 'vue'
|
|
146
|
+
import { CanvasEditor, MarkdownPreviewPanel } from '@nywqs/vue-markdown-editor'
|
|
147
|
+
import '@nywqs/vue-markdown-editor/dist-lib/wqs_editor.css'
|
|
148
|
+
|
|
149
|
+
const content = ref('# Hello\n\n这是预览内容')
|
|
150
|
+
const theme = ref('light')
|
|
151
|
+
const editorScrollPercentage = ref(0)
|
|
152
|
+
const previewScrollPercentage = ref(0)
|
|
153
|
+
const isSyncingEditor = ref(false)
|
|
154
|
+
const isSyncingPreview = ref(false)
|
|
155
|
+
|
|
156
|
+
const handleEditorScroll = (percentage) => {
|
|
157
|
+
if (isSyncingPreview.value) return
|
|
158
|
+
isSyncingEditor.value = true
|
|
159
|
+
previewScrollPercentage.value = percentage
|
|
160
|
+
setTimeout(() => { isSyncingEditor.value = false }, 100)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const handlePreviewScroll = (percentage) => {
|
|
164
|
+
if (isSyncingEditor.value) return
|
|
165
|
+
isSyncingPreview.value = true
|
|
166
|
+
editorScrollPercentage.value = percentage
|
|
167
|
+
setTimeout(() => { isSyncingPreview.value = false }, 100)
|
|
168
|
+
}
|
|
169
|
+
</script>
|
|
170
|
+
|
|
171
|
+
<template>
|
|
172
|
+
<div style="display: flex; height: 600px;">
|
|
173
|
+
<div style="flex: 1;">
|
|
174
|
+
<CanvasEditor
|
|
175
|
+
v-model="content"
|
|
176
|
+
:theme="theme"
|
|
177
|
+
:scroll-percentage="editorScrollPercentage"
|
|
178
|
+
:is-syncing="isSyncingEditor"
|
|
179
|
+
@scroll="handleEditorScroll"
|
|
180
|
+
/>
|
|
181
|
+
</div>
|
|
182
|
+
<div style="flex: 1;">
|
|
183
|
+
<MarkdownPreviewPanel
|
|
184
|
+
:content="content"
|
|
185
|
+
:theme="theme"
|
|
186
|
+
:scroll-percentage="previewScrollPercentage"
|
|
187
|
+
:is-syncing="isSyncingPreview"
|
|
188
|
+
@scroll="handlePreviewScroll"
|
|
189
|
+
/>
|
|
190
|
+
</div>
|
|
191
|
+
</div>
|
|
192
|
+
</template>
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
> **注意**:`MarkdownPreviewPanel` 同时支持 `content` 和 `modelValue` 属性,推荐使用 `content`。
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## 🔌 插件系统
|
|
200
|
+
|
|
201
|
+
编辑器内置了丰富的插件:
|
|
202
|
+
|
|
203
|
+
- **TablePlugin**:表格插入和编辑(Ctrl+Shift+T)
|
|
204
|
+
- **TodoListPlugin**:待办列表支持
|
|
205
|
+
- **MathPlugin**:数学公式支持(Ctrl+M)
|
|
206
|
+
- **MermaidPlugin**:流程图支持(Ctrl+Shift+D)
|
|
207
|
+
- **AutoCompletePlugin**:自动补全
|
|
208
|
+
- **SyntaxCheckerPlugin**:语法检查
|
|
209
|
+
|
|
210
|
+
插件会自动激活,无需额外配置。
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
## ⚙️ 性能优化
|
|
215
|
+
|
|
216
|
+
编辑器采用了多项性能优化技术:
|
|
217
|
+
|
|
218
|
+
1. **视口裁剪**:只渲染可见区域,大文件性能提升 10-40 倍
|
|
219
|
+
2. **虚拟滚动**:缓冲区机制,避免滚动闪烁
|
|
220
|
+
3. **增量渲染**:只重绘变更的行,编辑时性能提升 3-5 倍
|
|
221
|
+
4. **离屏缓存**:静态内容(行号、背景)缓存到离屏 Canvas
|
|
222
|
+
5. **智能调度**:防抖优化 + 立即渲染混合策略
|
|
223
|
+
|
|
224
|
+
这些优化让编辑器可以流畅处理大型文档(10000+ 行)。
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
## 🛠️ 开发与构建
|
|
229
|
+
|
|
230
|
+
本仓库使用 Vite + Vue 3 进行开发和构建。
|
|
231
|
+
|
|
232
|
+
本地开发:
|
|
233
|
+
|
|
234
|
+
```bash
|
|
235
|
+
npm install
|
|
236
|
+
npm run dev
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
构建库:
|
|
240
|
+
|
|
241
|
+
```bash
|
|
242
|
+
npm run build:lib
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
类型检查:
|
|
246
|
+
|
|
247
|
+
```bash
|
|
248
|
+
npm run typecheck
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
## License
|
|
254
|
+
|
|
255
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/* empty css */
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
pre code.hljs{padding:1em;display:block;overflow-x:auto}code.hljs{padding:3px 5px}.hljs{color:#c9d1d9;background:#0d1117}.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable.language_{color:#ff7b72}.hljs-title,.hljs-title.class_,.hljs-title.class_.inherited__,.hljs-title.function_{color:#d2a8ff}.hljs-attr,.hljs-attribute,.hljs-literal,.hljs-meta,.hljs-number,.hljs-operator,.hljs-variable,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id{color:#79c0ff}.hljs-regexp,.hljs-string,.hljs-meta .hljs-string{color:#a5d6ff}.hljs-built_in,.hljs-symbol{color:#ffa657}.hljs-comment,.hljs-code,.hljs-formula{color:#8b949e}.hljs-name,.hljs-quote,.hljs-selector-tag,.hljs-selector-pseudo{color:#7ee787}.hljs-subst{color:#c9d1d9}.hljs-section{color:#1f6feb;font-weight:700}.hljs-bullet{color:#f2cc60}.hljs-emphasis{color:#c9d1d9;font-style:italic}.hljs-strong{color:#c9d1d9;font-weight:700}.hljs-addition{color:#aff5b4;background-color:#033a16}.hljs-deletion{color:#ffdcd7;background-color:#67060c}
|
|
1
|
+
.canvas-toolbar[data-v-46e06aed]{background:#f5f5f5;border-bottom:1px solid #ddd;flex-wrap:wrap;align-items:center;gap:4px;padding:8px 12px;display:flex}.toolbar-btn[data-v-46e06aed]{cursor:pointer;color:#666;white-space:nowrap;background:#fff;border:1px solid #ddd;border-radius:4px;justify-content:center;align-items:center;min-width:32px;height:32px;padding:0 8px;font-size:16px;transition:all .2s;display:flex}.toolbar-btn .icon[data-v-46e06aed]{justify-content:center;align-items:center;width:18px;height:18px;display:flex}.toolbar-btn[data-v-46e06aed]:hover{color:#333;background:#e9e9e9;border-color:#999;transform:translateY(-1px);box-shadow:0 2px 4px #0000001a}.toolbar-btn[data-v-46e06aed]:active{box-shadow:none;transform:translateY(0)}.toolbar-btn.divider[data-v-46e06aed]{cursor:default;background:#ddd;border:none;width:1px;min-width:1px;height:20px;margin:0 4px;padding:0}.toolbar-btn.divider[data-v-46e06aed]:hover{box-shadow:none;background:#ddd;transform:none}.search-panel[data-v-46382544]{z-index:1000;background:#fff;border:1px solid #e0e0e0;border-radius:8px;min-width:420px;padding:16px;position:absolute;top:8px;right:8px;box-shadow:0 4px 16px #0000001f}.search-row[data-v-46382544],.replace-row[data-v-46382544]{align-items:center;gap:8px;margin-bottom:10px;display:flex}.search-input[data-v-46382544]{border:1px solid #d0d0d0;border-radius:6px;outline:none;flex:1;padding:8px 12px;font-size:13px;transition:all .2s}.search-input[data-v-46382544]:focus{border-color:#4a90e2;box-shadow:0 0 0 3px #4a90e21a}.search-count[data-v-46382544]{color:#666;text-align:center;background:#f5f5f5;border-radius:4px;min-width:45px;padding:4px 8px;font-size:12px;font-weight:500}.search-btn[data-v-46382544],.action-btn[data-v-46382544]{cursor:pointer;color:#555;background:#fff;border:1px solid #d0d0d0;border-radius:6px;padding:8px 12px;font-size:13px;transition:all .2s}.search-btn[data-v-46382544]:hover,.action-btn[data-v-46382544]:hover{color:#4a90e2;background:#f8f8f8;border-color:#4a90e2}.search-btn[data-v-46382544]:active,.action-btn[data-v-46382544]:active{background:#e8e8e8}.close-btn[data-v-46382544]{color:#999;font-weight:700}.close-btn[data-v-46382544]:hover{color:#f44;background:#fff5f5;border-color:#f44}.action-btn[data-v-46382544]{color:#fff;background:#4a90e2;border-color:#4a90e2;padding:8px 16px;font-weight:500}.action-btn[data-v-46382544]:hover{color:#fff;background:#357abd;border-color:#357abd}.search-options[data-v-46382544]{border-top:1px solid #f0f0f0;gap:20px;padding-top:12px;display:flex}.search-options label[data-v-46382544]{color:#666;cursor:pointer;-webkit-user-select:none;user-select:none;align-items:center;gap:6px;font-size:12px;transition:color .2s;display:flex}.search-options label[data-v-46382544]:hover{color:#4a90e2}.search-options input[type=checkbox][data-v-46382544]{cursor:pointer;width:14px;height:14px}.canvas-editor-container[data-v-ddb360e3]{flex-direction:column;width:100%;height:100%;display:flex}.canvas-editor[data-v-ddb360e3]{flex:1;width:100%;position:relative;overflow:hidden}canvas[data-v-ddb360e3]{cursor:text;z-index:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-smooth:always;text-rendering:optimizeLegibility;display:block;position:absolute;top:0;left:0}.preview-panel[data-v-cef068b8]{background:#fff;width:100%;height:100%;transition:background-color .3s;overflow:hidden auto}.preview-panel[data-v-cef068b8]::-webkit-scrollbar{width:8px}.preview-panel[data-v-cef068b8]::-webkit-scrollbar-track{background:#f1f1f1}.preview-panel[data-v-cef068b8]::-webkit-scrollbar-thumb{background:#888;border-radius:4px}.preview-panel[data-v-cef068b8]::-webkit-scrollbar-thumb:hover{background:#555}.preview-content[data-v-cef068b8]{color:#333;max-width:900px;margin:0 auto;padding:20px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;font-size:16px;line-height:1.6}.preview-panel[data-theme=dark][data-v-cef068b8]{background:#1e1e1e}.preview-panel[data-theme=dark] .preview-content[data-v-cef068b8]{color:#ccc}.preview-content[data-v-cef068b8] h1,.preview-content[data-v-cef068b8] h2,.preview-content[data-v-cef068b8] h3,.preview-content[data-v-cef068b8] h4,.preview-content[data-v-cef068b8] h5,.preview-content[data-v-cef068b8] h6{margin-top:24px;margin-bottom:16px;font-weight:600;line-height:1.25}.preview-content[data-v-cef068b8] h1{border-bottom:1px solid #eaecef;padding-bottom:.3em;font-size:2em}.preview-content[data-v-cef068b8] h2{border-bottom:1px solid #eaecef;padding-bottom:.3em;font-size:1.5em}.preview-content[data-v-cef068b8] h3{font-size:1.25em}.preview-content[data-v-cef068b8] h4{font-size:1em}.preview-content[data-v-cef068b8] h5{font-size:.875em}.preview-content[data-v-cef068b8] h6{color:#6a737d;font-size:.85em}.preview-content[data-v-cef068b8] p{margin-top:0;margin-bottom:16px}.preview-content[data-v-cef068b8] a{color:#0366d6;text-decoration:none}.preview-content[data-v-cef068b8] a:hover{text-decoration:underline}.preview-content[data-v-cef068b8] strong{font-weight:600}.preview-content[data-v-cef068b8] em{font-style:italic}.preview-content[data-v-cef068b8] code{background-color:#1b1f230d;border-radius:3px;margin:0;padding:.2em .4em;font-family:SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;font-size:85%}.preview-content[data-v-cef068b8] pre{background-color:#f6f8fa;border-radius:6px;margin-bottom:16px;padding:16px;font-size:85%;line-height:1.45;overflow:auto}.preview-content[data-v-cef068b8] pre code{line-height:inherit;word-wrap:normal;background-color:#0000;border:0;margin:0;padding:0;display:inline;overflow:visible}.preview-content[data-v-cef068b8] blockquote{color:#6a737d;border-left:.25em solid #dfe2e5;margin:0 0 16px;padding:0 1em}.preview-content[data-v-cef068b8] ul,.preview-content[data-v-cef068b8] ol{margin-top:0;margin-bottom:16px;padding-left:2em}.preview-content[data-v-cef068b8] li{margin-bottom:.25em}.preview-content[data-v-cef068b8] li>p{margin-bottom:0}.preview-content[data-v-cef068b8] img{box-sizing:content-box;background-color:#fff;max-width:100%}.preview-content[data-v-cef068b8] hr{background-color:#e1e4e8;border:0;height:.25em;margin:24px 0;padding:0}.preview-content[data-v-cef068b8] table{border-spacing:0;border-collapse:collapse;width:100%;margin-bottom:16px;display:block;overflow:auto}.preview-content[data-v-cef068b8] table th{background-color:#f6f8fa;border:1px solid #dfe2e5;padding:6px 13px;font-weight:600}.preview-content[data-v-cef068b8] table td{border:1px solid #dfe2e5;padding:6px 13px}.preview-content[data-v-cef068b8] table tr{background-color:#fff;border-top:1px solid #c6cbd1}.preview-content[data-v-cef068b8] table tr:nth-child(2n){background-color:#f6f8fa}.preview-content[data-v-cef068b8] input[type=checkbox]{margin-right:.5em}.preview-panel[data-theme=dark] .preview-content[data-v-cef068b8] code{background-color:#6e768166}.preview-panel[data-theme=dark] .preview-content[data-v-cef068b8] pre{background-color:#2d2d2d}.preview-panel[data-theme=dark] .preview-content[data-v-cef068b8] table th{background-color:#2d2d2d;border-color:#444}.preview-panel[data-theme=dark] .preview-content[data-v-cef068b8] table td{border-color:#444}.preview-panel[data-theme=dark] .preview-content[data-v-cef068b8] table tr{background-color:#1e1e1e;border-color:#444}.preview-panel[data-theme=dark] .preview-content[data-v-cef068b8] table tr:nth-child(2n){background-color:#252525}.preview-panel[data-theme=dark] .preview-content[data-v-cef068b8] blockquote{color:#8b949e;border-left-color:#3b3b3b}.preview-panel[data-theme=dark] .preview-content[data-v-cef068b8] hr{background-color:#3b3b3b}.preview-panel[data-theme=dark] .preview-content[data-v-cef068b8] h1,.preview-panel[data-theme=dark] .preview-content[data-v-cef068b8] h2{border-bottom-color:#3b3b3b}pre code.hljs{padding:1em;display:block;overflow-x:auto}code.hljs{padding:3px 5px}.hljs{color:#c9d1d9;background:#0d1117}.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable.language_{color:#ff7b72}.hljs-title,.hljs-title.class_,.hljs-title.class_.inherited__,.hljs-title.function_{color:#d2a8ff}.hljs-attr,.hljs-attribute,.hljs-literal,.hljs-meta,.hljs-number,.hljs-operator,.hljs-variable,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id{color:#79c0ff}.hljs-regexp,.hljs-string,.hljs-meta .hljs-string{color:#a5d6ff}.hljs-built_in,.hljs-symbol{color:#ffa657}.hljs-comment,.hljs-code,.hljs-formula{color:#8b949e}.hljs-name,.hljs-quote,.hljs-selector-tag,.hljs-selector-pseudo{color:#7ee787}.hljs-subst{color:#c9d1d9}.hljs-section{color:#1f6feb;font-weight:700}.hljs-bullet{color:#f2cc60}.hljs-emphasis{color:#c9d1d9;font-style:italic}.hljs-strong{color:#c9d1d9;font-weight:700}.hljs-addition{color:#aff5b4;background-color:#033a16}.hljs-deletion{color:#ffdcd7;background-color:#67060c}.editor-config[data-v-2ff40722]{z-index:1000;background:#fff;border-radius:8px;width:600px;max-height:80vh;position:fixed;top:50%;left:50%;overflow:hidden;transform:translate(-50%,-50%);box-shadow:0 4px 24px #0003}.config-header[data-v-2ff40722]{background:#f9f9f9;border-bottom:1px solid #e5e5e5;justify-content:space-between;align-items:center;padding:16px 20px;display:flex}.config-header h3[data-v-2ff40722]{margin:0;font-size:18px;font-weight:600}.close-btn[data-v-2ff40722]{cursor:pointer;color:#666;background:0 0;border:none;border-radius:4px;justify-content:center;align-items:center;width:32px;height:32px;font-size:24px;transition:all .2s;display:flex}.close-btn[data-v-2ff40722]:hover{color:#333;background:#e5e5e5}.config-body[data-v-2ff40722]{max-height:calc(80vh - 140px);padding:20px;overflow-y:auto}.config-section[data-v-2ff40722]{margin-bottom:24px}.config-section h4[data-v-2ff40722]{color:#333;margin:0 0 12px;font-size:16px;font-weight:600}.hint[data-v-2ff40722]{color:#999;margin:0 0 12px;font-size:13px}.config-item[data-v-2ff40722]{align-items:center;gap:12px;margin-bottom:12px;display:flex}.config-item label[data-v-2ff40722]{color:#666;min-width:80px;font-size:14px}.config-item select[data-v-2ff40722],.config-item input[type=number][data-v-2ff40722]{border:1px solid #ddd;border-radius:4px;flex:1;padding:6px 10px;font-size:14px}.config-item input[type=checkbox][data-v-2ff40722]{cursor:pointer;margin:0}.unit[data-v-2ff40722]{color:#999;font-size:12px}.color-grid[data-v-2ff40722]{grid-template-columns:repeat(2,1fr);gap:12px;display:grid}.color-item[data-v-2ff40722]{background:#fafafa;border:1px solid #e5e5e5;border-radius:4px;align-items:center;gap:8px;padding:8px;display:flex}.color-item label[data-v-2ff40722]{color:#666;flex:1;font-size:13px}.color-item input[type=color][data-v-2ff40722]{cursor:pointer;border:none;border-radius:4px;width:36px;height:36px}.color-value[data-v-2ff40722]{color:#999;font-family:monospace;font-size:12px}.config-footer[data-v-2ff40722]{background:#f9f9f9;border-top:1px solid #e5e5e5;justify-content:flex-end;gap:8px;padding:16px 20px;display:flex}.btn[data-v-2ff40722]{cursor:pointer;border:1px solid #ddd;border-radius:4px;padding:8px 16px;font-size:14px;transition:all .2s}.btn-secondary[data-v-2ff40722]{color:#666;background:#fff}.btn-secondary[data-v-2ff40722]:hover{background:#f5f5f5}.btn-primary[data-v-2ff40722]{color:#fff;background:#4a90e2;border-color:#4a90e2}.btn-primary[data-v-2ff40722]:hover{background:#357abd}
|
|
2
2
|
/*$vite$:1*/
|