|
8 | 8 | formatDoc,
|
9 | 9 | toBase64,
|
10 | 10 | } from '@/utils'
|
| 11 | +import { toggleFormat } from '@/utils/editor' |
11 | 12 | import fileApi from '@/utils/file'
|
12 | 13 | import CodeMirror from 'codemirror'
|
13 | 14 | import { Eye, List, Pen } from 'lucide-vue-next'
|
@@ -215,52 +216,78 @@ function initEditor() {
|
215 | 216 | autoCloseBrackets: true,
|
216 | 217 | extraKeys: {
|
217 | 218 | [`${shiftKey}-${altKey}-F`]: function autoFormat(editor) {
|
218 |
| - formatDoc(editor.getValue()).then((doc) => { |
| 219 | + const value = editor.getValue() |
| 220 | + formatDoc(value).then((doc: string) => { |
219 | 221 | editor.setValue(doc)
|
220 | 222 | })
|
221 | 223 | },
|
| 224 | +
|
222 | 225 | [`${ctrlKey}-B`]: function bold(editor) {
|
223 |
| - const selected = editor.getSelection() |
224 |
| - editor.replaceSelection(`**${selected}**`) |
| 226 | + toggleFormat(editor, { |
| 227 | + prefix: `**`, |
| 228 | + suffix: `**`, |
| 229 | + check: s => s.startsWith(`**`) && s.endsWith(`**`), |
| 230 | + }) |
225 | 231 | },
|
| 232 | +
|
226 | 233 | [`${ctrlKey}-I`]: function italic(editor) {
|
227 |
| - const selected = editor.getSelection() |
228 |
| - editor.replaceSelection(`*${selected}*`) |
| 234 | + toggleFormat(editor, { |
| 235 | + prefix: `*`, |
| 236 | + suffix: `*`, |
| 237 | + check: s => s.startsWith(`*`) && s.endsWith(`*`), |
| 238 | + }) |
229 | 239 | },
|
| 240 | +
|
230 | 241 | [`${ctrlKey}-D`]: function del(editor) {
|
231 |
| - const selected = editor.getSelection() |
232 |
| - editor.replaceSelection(`~~${selected}~~`) |
| 242 | + toggleFormat(editor, { |
| 243 | + prefix: `~~`, |
| 244 | + suffix: `~~`, |
| 245 | + check: s => s.startsWith(`~~`) && s.endsWith(`~~`), |
| 246 | + }) |
233 | 247 | },
|
| 248 | +
|
234 | 249 | [`${ctrlKey}-K`]: function link(editor) {
|
235 |
| - const selected = editor.getSelection() |
236 |
| - editor.replaceSelection(`[${selected}]()`) |
237 |
| - // now will slightly move the cursor to the left to fill in the link |
238 |
| - const { line, ch } = editor.getCursor() |
239 |
| - editor.setCursor({ line, ch: ch - 1 }) |
| 250 | + toggleFormat(editor, { |
| 251 | + prefix: `[`, |
| 252 | + suffix: `]()`, |
| 253 | + check: s => s.startsWith(`[`) && s.endsWith(`]()`), |
| 254 | + afterInsertCursorOffset: -1, |
| 255 | + }) |
240 | 256 | },
|
| 257 | +
|
241 | 258 | [`${ctrlKey}-E`]: function code(editor) {
|
242 |
| - const selected = editor.getSelection() |
243 |
| - editor.replaceSelection(`\`${selected}\``) |
| 259 | + toggleFormat(editor, { |
| 260 | + prefix: `\``, |
| 261 | + suffix: `\``, |
| 262 | + check: s => s.startsWith(`\``) && s.endsWith(`\``), |
| 263 | + }) |
244 | 264 | },
|
| 265 | +
|
| 266 | + // 标题:单行逻辑,手动处理 |
245 | 267 | [`${ctrlKey}-H`]: function heading(editor) {
|
246 | 268 | const selected = editor.getSelection()
|
247 |
| - editor.replaceSelection(`# ${selected}`) |
| 269 | + const replaced = selected.startsWith(`# `) ? selected.slice(2) : `# ${selected}` |
| 270 | + editor.replaceSelection(replaced) |
248 | 271 | },
|
| 272 | +
|
249 | 273 | [`${ctrlKey}-U`]: function unorderedList(editor) {
|
250 | 274 | const selected = editor.getSelection()
|
251 |
| - const lines = selected.split(`\n`).map(line => `- ${line}`) |
252 |
| - editor.replaceSelection(lines.join(`\n`)) |
| 275 | + const lines = selected.split(`\n`) |
| 276 | + const isList = lines.every(line => line.trim().startsWith(`- `)) |
| 277 | + const updated = isList |
| 278 | + ? lines.map(line => line.replace(/^- +/, ``)).join(`\n`) |
| 279 | + : lines.map(line => `- ${line}`).join(`\n`) |
| 280 | + editor.replaceSelection(updated) |
253 | 281 | },
|
254 | 282 |
|
255 | 283 | [`${ctrlKey}-O`]: function orderedList(editor) {
|
256 | 284 | const selected = editor.getSelection()
|
257 |
| - const lines = selected.split(`\n`).map((line, i) => `${i + 1}. ${line}`) |
258 |
| - editor.replaceSelection(lines.join(`\n`)) |
259 |
| - }, |
260 |
| - // 预备弃用 |
261 |
| - [`${ctrlKey}-L`]: function code(editor) { |
262 |
| - const selected = editor.getSelection() |
263 |
| - editor.replaceSelection(`\`${selected}\``) |
| 285 | + const lines = selected.split(`\n`) |
| 286 | + const isList = lines.every(line => /^\d+\.\s/.test(line.trim())) |
| 287 | + const updated = isList |
| 288 | + ? lines.map(line => line.replace(/^\d+\.\s+/, ``)).join(`\n`) |
| 289 | + : lines.map((line, i) => `${i + 1}. ${line}`).join(`\n`) |
| 290 | + editor.replaceSelection(updated) |
264 | 291 | },
|
265 | 292 | },
|
266 | 293 | })
|
|
0 commit comments