|
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