@tnotesjs/ui 0.1.5 → 0.2.0

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.
Files changed (67) hide show
  1. package/README.md +30 -97
  2. package/dist/code/highlight.js +6 -15
  3. package/dist/components/Footprints/parse.js +1 -3
  4. package/dist/components/Mindmap/markdown.d.ts +1 -7
  5. package/dist/components/Mindmap/markdown.js +1 -15
  6. package/package.json +24 -8
  7. package/src/browser/clipboard.ts +16 -19
  8. package/src/browser/theme.ts +10 -15
  9. package/src/code/highlight.test.ts +23 -6
  10. package/src/code/highlight.ts +89 -105
  11. package/src/components/Badge/Badge.vue +4 -4
  12. package/src/components/CodeBlock/CodeBlock.vue +43 -53
  13. package/src/components/CodeGroup/CodeGroup.vue +32 -35
  14. package/src/components/Footprints/Footprints.vue +2 -14
  15. package/src/components/Footprints/parse.ts +1 -3
  16. package/src/components/ImagePreview/ImagePreview.vue +101 -126
  17. package/src/components/Mermaid/Mermaid.vue +9 -12
  18. package/src/components/Mindmap/FocusBreadcrumbs.test.ts +40 -30
  19. package/src/components/Mindmap/FocusBreadcrumbs.vue +31 -28
  20. package/src/components/Mindmap/InlineRuns.ts +25 -16
  21. package/src/components/Mindmap/Mindmap.vue +147 -81
  22. package/src/components/Mindmap/MindmapOutlineNode.vue +4 -1
  23. package/src/components/Mindmap/editor/AppIcon.vue +32 -11
  24. package/src/components/Mindmap/editor/CanvasContextMenu.vue +126 -49
  25. package/src/components/Mindmap/editor/LinkPopover.vue +101 -23
  26. package/src/components/Mindmap/editor/MarkdownView.vue +7 -4
  27. package/src/components/Mindmap/editor/MindmapView.vue +11 -3
  28. package/src/components/Mindmap/editor/OutlineView.vue +144 -58
  29. package/src/components/Mindmap/editor/RichInlineEditor.vue +93 -44
  30. package/src/components/Mindmap/editor/SelectionToolbar.vue +133 -41
  31. package/src/components/Mindmap/editor/canvasClipboard.ts +1 -5
  32. package/src/components/Mindmap/editor/imagePaste.ts +1 -1
  33. package/src/components/Mindmap/editor/mindmapClipboard.ts +17 -5
  34. package/src/components/Mindmap/editor/outlineDrag.ts +1 -1
  35. package/src/components/Mindmap/markdown.ts +10 -29
  36. package/src/components/WordList/RightClickMenu.vue +10 -35
  37. package/src/components/WordList/WordList.vue +19 -42
  38. package/src/components/sharedMedia.test.ts +94 -112
  39. package/src/entries/bilibili-video.ts +1 -1
  40. package/src/entries/excalidraw-editor.ts +20 -0
  41. package/src/entries/excalidraw-view.ts +15 -0
  42. package/src/entries/footprints.ts +1 -1
  43. package/src/entries/mermaid.ts +1 -1
  44. package/src/entries/mindmap.ts +1 -1
  45. package/src/entries/notes-table.ts +2 -2
  46. package/src/entries/word-list.ts +1 -1
  47. package/src/excalidraw/ExcalidrawSvg.vue +125 -0
  48. package/src/excalidraw/editorHost.ts +110 -0
  49. package/src/excalidraw/editorSession.test.ts +205 -0
  50. package/src/excalidraw/editorSession.ts +224 -0
  51. package/src/excalidraw/exporter.ts +50 -0
  52. package/src/excalidraw/focus.test.ts +60 -0
  53. package/src/excalidraw/focus.ts +33 -0
  54. package/src/excalidraw/fonts.test.ts +66 -0
  55. package/src/excalidraw/fonts.ts +92 -0
  56. package/src/excalidraw/renderer.test.ts +148 -0
  57. package/src/excalidraw/renderer.ts +105 -0
  58. package/src/excalidraw/scene.ts +93 -0
  59. package/src/index.ts +25 -33
  60. package/src/markdown/image.test.ts +1 -3
  61. package/src/markdown/image.ts +4 -13
  62. package/src/styles/code.css +5 -5
  63. package/src/styles/prose.css +1 -1
  64. package/src/styles/swiper.css +1 -1
  65. package/src/styles/tokens.css +5 -6
  66. package/src/swiper/hydrate.test.ts +37 -41
  67. package/src/swiper/hydrate.ts +91 -102
@@ -73,37 +73,40 @@ function forceExitPeerFullscreen(activeRoot: HTMLElement | null): void {
73
73
  syncBodyFullscreenAttr(activeRoot)
74
74
  }
75
75
 
76
- const props = withDefaults(defineProps<{
77
- content?: string
78
- /** Plain mindmap markdown (preferred over URI-encoded content). */
79
- source?: string
80
- initialExpandLevel?: number
81
- /** When true, canvas uses CanvasEditor and edits emit `change`. */
82
- editable?: boolean
83
- /** Show expand-level control on the chrome (Desk). */
84
- expandLevelControl?: boolean
85
- /** Explicit dark mode; omit to auto-detect html.dark / data-theme=dark. */
86
- isDark?: boolean
87
- /**
88
- * Resolve markdown image paths for canvas display (Desk: tnotes-asset protocol).
89
- * Defaults to identity.
90
- */
91
- resolveImageSrc?: (src: string) => string
92
- /**
93
- * Persist a pasted/dropped image blob and return the markdown-relative path
94
- * (e.g. `./assets/foo.png`). Required for editable paste-to-assets.
95
- */
96
- writeAsset?: (blob: Blob) => Promise<{ relativePath: string; alt?: string }>
97
- }>(), {
98
- content: '',
99
- source: '',
100
- initialExpandLevel: 3,
101
- editable: false,
102
- expandLevelControl: false,
103
- isDark: undefined,
104
- resolveImageSrc: undefined,
105
- writeAsset: undefined,
106
- })
76
+ const props = withDefaults(
77
+ defineProps<{
78
+ content?: string
79
+ /** Plain mindmap markdown (preferred over URI-encoded content). */
80
+ source?: string
81
+ initialExpandLevel?: number
82
+ /** When true, canvas uses CanvasEditor and edits emit `change`. */
83
+ editable?: boolean
84
+ /** Show expand-level control on the chrome (Desk). */
85
+ expandLevelControl?: boolean
86
+ /** Explicit dark mode; omit to auto-detect html.dark / data-theme=dark. */
87
+ isDark?: boolean
88
+ /**
89
+ * Resolve markdown image paths for canvas display (Desk: tnotes-asset protocol).
90
+ * Defaults to identity.
91
+ */
92
+ resolveImageSrc?: (src: string) => string
93
+ /**
94
+ * Persist a pasted/dropped image blob and return the markdown-relative path
95
+ * (e.g. `./assets/foo.png`). Required for editable paste-to-assets.
96
+ */
97
+ writeAsset?: (blob: Blob) => Promise<{ relativePath: string; alt?: string }>
98
+ }>(),
99
+ {
100
+ content: '',
101
+ source: '',
102
+ initialExpandLevel: 3,
103
+ editable: false,
104
+ expandLevelControl: false,
105
+ isDark: undefined,
106
+ resolveImageSrc: undefined,
107
+ writeAsset: undefined
108
+ }
109
+ )
107
110
 
108
111
  const emit = defineEmits<{
109
112
  change: [markdown: string]
@@ -148,7 +151,7 @@ const sessionEpoch = ref(0)
148
151
  const viewOptions = [
149
152
  { value: 'mindmap', label: '脑图' },
150
153
  { value: 'outline', label: '大纲' },
151
- { value: 'source', label: '源码' },
154
+ { value: 'source', label: '源码' }
152
155
  ] as const
153
156
 
154
157
  function decodeContent(value: string): string {
@@ -190,7 +193,7 @@ function createViewer(): void {
190
193
  const theme = dark.value ? 'dark' : 'light'
191
194
  viewer = new CanvasViewer(canvasHost.value, session.value, {
192
195
  theme,
193
- resolveImageSrc: (src) => props.resolveImageSrc?.(src) ?? src,
196
+ resolveImageSrc: (src) => props.resolveImageSrc?.(src) ?? src
194
197
  })
195
198
  }
196
199
 
@@ -212,10 +215,12 @@ function rebuildSession(): void {
212
215
  suppressChangeEmit = true
213
216
  const next = new MindmapSession({
214
217
  markdown: normalizedContent.value,
215
- fileName: 'mindmap-preview.tn-mindmap.md',
218
+ fileName: 'mindmap-preview.tn-mindmap.md'
216
219
  })
217
220
  applyInitialExpandLevel(next, expandLevel.value)
218
- const invalidate = () => { renderVersion.value += 1 }
221
+ const invalidate = () => {
222
+ renderVersion.value += 1
223
+ }
219
224
  next.on('collapseChange', invalidate)
220
225
  next.on('focusChange', invalidate)
221
226
  next.on('selectionChange', invalidate)
@@ -242,7 +247,7 @@ function onSourceMarkdown(value: string): void {
242
247
  async function onSourcePasteImage(
243
248
  blob: Blob,
244
249
  selectionStart: number,
245
- selectionEnd: number,
250
+ selectionEnd: number
246
251
  ): Promise<void> {
247
252
  if (!props.editable || !session.value || !props.writeAsset) return
248
253
  try {
@@ -252,7 +257,7 @@ async function onSourcePasteImage(
252
257
  selectionStart,
253
258
  selectionEnd,
254
259
  asset.relativePath,
255
- asset.alt ?? '截图',
260
+ asset.alt ?? '截图'
256
261
  )
257
262
  onSourceMarkdown(next)
258
263
  } catch {
@@ -346,7 +351,7 @@ async function toggleFullscreen(): Promise<void> {
346
351
  forceExitPeerFullscreen(root)
347
352
  void nextTick(() => zoomToFit())
348
353
 
349
- // Best-effort native fullscreen for browser / VitePress (non-blocking).
354
+ // Best-effort native fullscreen (non-blocking).
350
355
  if (!document.fullscreenEnabled || typeof root.requestFullscreen !== 'function') return
351
356
  if (/Electron/i.test(navigator.userAgent)) return
352
357
  try {
@@ -354,7 +359,7 @@ async function toggleFullscreen(): Promise<void> {
354
359
  root.requestFullscreen(),
355
360
  new Promise<never>((_, reject) => {
356
361
  window.setTimeout(() => reject(new Error('fullscreen-timeout')), 500)
357
- }),
362
+ })
358
363
  ])
359
364
  if (document.fullscreenElement === root) fullscreenMode = 'native'
360
365
  } catch {
@@ -398,7 +403,7 @@ function handleCanvasWheelCapture(event: WheelEvent): void {
398
403
  function handlePreviewPasteBubble(event: ClipboardEvent): void {
399
404
  if (!props.editable) return
400
405
  const hasImage = [...(event.clipboardData?.items ?? [])].some(
401
- (item) => item.kind === 'file' && item.type.startsWith('image/'),
406
+ (item) => item.kind === 'file' && item.type.startsWith('image/')
402
407
  )
403
408
  if (!hasImage) return
404
409
  event.stopPropagation()
@@ -468,7 +473,7 @@ function handleDocumentKeydown(event: KeyboardEvent): void {
468
473
  const inTextEdit =
469
474
  target instanceof Element
470
475
  ? target.closest(
471
- '.mm-edit-input, .rich-inline-editor, [contenteditable="true"], textarea, input',
476
+ '.mm-edit-input, .rich-inline-editor, [contenteditable="true"], textarea, input'
472
477
  )
473
478
  : null
474
479
  if (inTextEdit && root?.contains(inTextEdit)) return
@@ -524,15 +529,12 @@ function handleDocumentKeydown(event: KeyboardEvent): void {
524
529
  watch(
525
530
  normalizedContent,
526
531
  (value) => {
527
- if (
528
- session.value &&
529
- normalizeMindmapMarkdown(session.value.getMarkdown()) === value
530
- ) {
532
+ if (session.value && normalizeMindmapMarkdown(session.value.getMarkdown()) === value) {
531
533
  return
532
534
  }
533
535
  rebuildSession()
534
536
  },
535
- { immediate: true },
537
+ { immediate: true }
536
538
  )
537
539
  watch(
538
540
  () => props.initialExpandLevel,
@@ -544,7 +546,7 @@ watch(
544
546
  applyInitialExpandLevel(session.value, level)
545
547
  renderVersion.value += 1
546
548
  }
547
- },
549
+ }
548
550
  )
549
551
  watch(
550
552
  () => props.editable,
@@ -552,7 +554,7 @@ watch(
552
554
  destroyViewer()
553
555
  editorRef = null
554
556
  void nextTick(createViewer)
555
- },
557
+ }
556
558
  )
557
559
  watch(dark, (value) => {
558
560
  const theme = value ? 'dark' : 'light'
@@ -565,7 +567,10 @@ function observeTheme() {
565
567
  const next = detectDark()
566
568
  if (next !== dark.value) dark.value = next
567
569
  })
568
- observer.observe(document.documentElement, { attributes: true, attributeFilter: ['class', 'data-theme'] })
570
+ observer.observe(document.documentElement, {
571
+ attributes: true,
572
+ attributeFilter: ['class', 'data-theme']
573
+ })
569
574
  return observer
570
575
  }
571
576
  let themeObserver: MutationObserver | null = null
@@ -575,7 +580,7 @@ onMounted(() => {
575
580
  themeObserver = observeTheme()
576
581
  unregisterFullscreenOwner = registerMindmapFullscreenOwner(
577
582
  fullscreenOwnerId,
578
- exitFullscreenOverlay,
583
+ exitFullscreenOverlay
579
584
  )
580
585
  document.addEventListener('fullscreenchange', handleFullscreenChange)
581
586
  document.addEventListener('pointerdown', handleDocumentPointerDown, true)
@@ -608,7 +613,7 @@ onBeforeUnmount(() => {
608
613
  'is-dark': dark,
609
614
  'is-fullscreen': isFullscreen,
610
615
  'is-editable': editable,
611
- 'is-interaction-active': isCanvasActive,
616
+ 'is-interaction-active': isCanvasActive
612
617
  }"
613
618
  :data-view="activeView"
614
619
  :data-version="renderVersion"
@@ -632,11 +637,7 @@ onBeforeUnmount(() => {
632
637
  </button>
633
638
  </nav>
634
639
  <span class="mindmap-preview-action-divider" aria-hidden="true" />
635
- <label
636
- v-if="expandLevelControl"
637
- class="mindmap-preview-expand"
638
- title="默认展开层级"
639
- >
640
+ <label v-if="expandLevelControl" class="mindmap-preview-expand" title="默认展开层级">
640
641
  <span class="mindmap-preview-expand-label">层</span>
641
642
  <input
642
643
  class="mindmap-preview-expand-input"
@@ -776,13 +777,13 @@ onBeforeUnmount(() => {
776
777
  align-items: center;
777
778
  gap: 4px;
778
779
  padding: 2px;
779
- border: .1px solid var(--tn-c-divider);
780
+ border: 0.1px solid var(--tn-c-divider);
780
781
  border-radius: 7px;
781
782
  background-color: color-mix(in srgb, var(--tn-c-bg-elv) 92%, transparent);
782
783
  box-shadow: var(--tn-shadow-2);
783
784
  opacity: 0;
784
785
  pointer-events: none;
785
- transition: opacity .2s;
786
+ transition: opacity 0.2s;
786
787
  }
787
788
 
788
789
  /* Editable Desk island: chrome must stay hittable. */
@@ -816,7 +817,9 @@ onBeforeUnmount(() => {
816
817
  background: transparent;
817
818
  color: var(--tn-c-brand);
818
819
  cursor: pointer;
819
- transition: background-color .2s, transform .2s;
820
+ transition:
821
+ background-color 0.2s,
822
+ transform 0.2s;
820
823
 
821
824
  svg,
822
825
  img {
@@ -834,8 +837,12 @@ onBeforeUnmount(() => {
834
837
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--tn-c-brand) 55%, transparent);
835
838
  }
836
839
 
837
- &:hover { transform: scale(1.05); }
838
- &:active { transform: scale(.95); }
840
+ &:hover {
841
+ transform: scale(1.05);
842
+ }
843
+ &:active {
844
+ transform: scale(0.95);
845
+ }
839
846
  }
840
847
 
841
848
  .mindmap-preview-action-divider {
@@ -981,13 +988,19 @@ onBeforeUnmount(() => {
981
988
  color: #f0f0f2;
982
989
  }
983
990
 
984
- .mindmap-canvas-host:deep(.mm-edit-input .inline-run.bold) { font-weight: 700; }
985
- .mindmap-canvas-host:deep(.mm-edit-input .inline-run.italic) { font-style: italic; }
991
+ .mindmap-canvas-host:deep(.mm-edit-input .inline-run.bold) {
992
+ font-weight: 700;
993
+ }
994
+ .mindmap-canvas-host:deep(.mm-edit-input .inline-run.italic) {
995
+ font-style: italic;
996
+ }
986
997
  .mindmap-canvas-host:deep(.mm-edit-input .inline-run.underline) {
987
998
  text-decoration-line: underline;
988
999
  text-underline-offset: 3px;
989
1000
  }
990
- .mindmap-canvas-host:deep(.mm-edit-input .inline-run.strike) { text-decoration-line: line-through; }
1001
+ .mindmap-canvas-host:deep(.mm-edit-input .inline-run.strike) {
1002
+ text-decoration-line: line-through;
1003
+ }
991
1004
  .mindmap-canvas-host:deep(.mm-edit-input .inline-run.underline.strike) {
992
1005
  text-decoration-line: underline line-through;
993
1006
  }
@@ -1097,19 +1110,62 @@ onBeforeUnmount(() => {
1097
1110
  text-align: center;
1098
1111
  }
1099
1112
 
1100
- .mindmap-outline :deep(.mindmap-outline-toggle:hover) { color: var(--tn-c-brand); }
1101
- .mindmap-outline :deep(.mindmap-outline-checkbox) { margin-top: 5px; }
1102
- .mindmap-outline :deep(.mindmap-outline-label) { min-width: 0; overflow-wrap: anywhere; }
1103
- .mindmap-outline :deep(.mindmap-outline-node.is-root > .mindmap-outline-row) { font-size: 18px; font-weight: 700; }
1104
- .mindmap-outline :deep(.mindmap-outline-node.is-done > .mindmap-outline-row .mindmap-outline-label) { opacity: .58; text-decoration: line-through; }
1105
- .mindmap-outline :deep(.mindmap-outline-image) { display: block; max-width: min(100%, 560px); max-height: 360px; margin: 5px 0 12px 25px; border-radius: 6px; }
1106
- .mindmap-outline :deep(.is-bold) { font-weight: 700; }
1107
- .mindmap-outline :deep(.is-italic) { font-style: italic; }
1108
- .mindmap-outline :deep(.is-underline) { text-decoration: underline; }
1109
- .mindmap-outline :deep(.is-strike) { text-decoration: line-through; }
1110
- .mindmap-outline :deep(.is-highlight) { padding: 0 2px; border-radius: 2px; background: #ffe56b; color: #252525; }
1111
- .mindmap-outline :deep(.is-code) { padding: 1px 5px; border-radius: 4px; background: var(--tn-c-bg-soft); color: var(--tn-c-danger); font-family: var(--tn-font-mono); }
1112
- .mindmap-outline :deep(.is-link) { color: var(--tn-c-brand); text-decoration: underline; text-underline-offset: 3px; }
1113
+ .mindmap-outline :deep(.mindmap-outline-toggle:hover) {
1114
+ color: var(--tn-c-brand);
1115
+ }
1116
+ .mindmap-outline :deep(.mindmap-outline-checkbox) {
1117
+ margin-top: 5px;
1118
+ }
1119
+ .mindmap-outline :deep(.mindmap-outline-label) {
1120
+ min-width: 0;
1121
+ overflow-wrap: anywhere;
1122
+ }
1123
+ .mindmap-outline :deep(.mindmap-outline-node.is-root > .mindmap-outline-row) {
1124
+ font-size: 18px;
1125
+ font-weight: 700;
1126
+ }
1127
+ .mindmap-outline
1128
+ :deep(.mindmap-outline-node.is-done > .mindmap-outline-row .mindmap-outline-label) {
1129
+ opacity: 0.58;
1130
+ text-decoration: line-through;
1131
+ }
1132
+ .mindmap-outline :deep(.mindmap-outline-image) {
1133
+ display: block;
1134
+ max-width: min(100%, 560px);
1135
+ max-height: 360px;
1136
+ margin: 5px 0 12px 25px;
1137
+ border-radius: 6px;
1138
+ }
1139
+ .mindmap-outline :deep(.is-bold) {
1140
+ font-weight: 700;
1141
+ }
1142
+ .mindmap-outline :deep(.is-italic) {
1143
+ font-style: italic;
1144
+ }
1145
+ .mindmap-outline :deep(.is-underline) {
1146
+ text-decoration: underline;
1147
+ }
1148
+ .mindmap-outline :deep(.is-strike) {
1149
+ text-decoration: line-through;
1150
+ }
1151
+ .mindmap-outline :deep(.is-highlight) {
1152
+ padding: 0 2px;
1153
+ border-radius: 2px;
1154
+ background: #ffe56b;
1155
+ color: #252525;
1156
+ }
1157
+ .mindmap-outline :deep(.is-code) {
1158
+ padding: 1px 5px;
1159
+ border-radius: 4px;
1160
+ background: var(--tn-c-bg-soft);
1161
+ color: var(--tn-c-danger);
1162
+ font-family: var(--tn-font-mono);
1163
+ }
1164
+ .mindmap-outline :deep(.is-link) {
1165
+ color: var(--tn-c-brand);
1166
+ text-decoration: underline;
1167
+ text-underline-offset: 3px;
1168
+ }
1113
1169
 
1114
1170
  .mindmap-source {
1115
1171
  max-height: 560px;
@@ -1193,10 +1249,20 @@ onBeforeUnmount(() => {
1193
1249
  }
1194
1250
 
1195
1251
  @media (max-width: 768px) {
1196
- .mindmap-canvas-host { height: 360px; }
1197
- .mindmap-preview-actions { top: 6px; right: 6px; }
1198
- .mindmap-preview-action { width: 28px; height: 28px; }
1199
- .mindmap-outline { padding-inline: 12px; }
1252
+ .mindmap-canvas-host {
1253
+ height: 360px;
1254
+ }
1255
+ .mindmap-preview-actions {
1256
+ top: 6px;
1257
+ right: 6px;
1258
+ }
1259
+ .mindmap-preview-action {
1260
+ width: 28px;
1261
+ height: 28px;
1262
+ }
1263
+ .mindmap-outline {
1264
+ padding-inline: 12px;
1265
+ }
1200
1266
  }
1201
1267
  </style>
1202
1268
 
@@ -17,7 +17,10 @@ defineEmits<{
17
17
  </script>
18
18
 
19
19
  <template>
20
- <li class="mindmap-outline-node" :class="{ 'is-root': root, 'is-done': node.content.checked === true }">
20
+ <li
21
+ class="mindmap-outline-node"
22
+ :class="{ 'is-root': root, 'is-done': node.content.checked === true }"
23
+ >
21
24
  <div class="mindmap-outline-row">
22
25
  <button
23
26
  v-if="node.children.length > 0"
@@ -38,7 +38,8 @@ defineProps<{ name: string; size?: number }>()
38
38
  <path d="m15 7 5 5-5 5M20 12h-9a6 6 0 0 0-6 6" />
39
39
  </template>
40
40
  <template v-else-if="name === 'search'">
41
- <circle cx="10.5" cy="10.5" r="6.5" /><path d="m16 16 4.5 4.5" />
41
+ <circle cx="10.5" cy="10.5" r="6.5" />
42
+ <path d="m16 16 4.5 4.5" />
42
43
  </template>
43
44
  <template v-else-if="name === 'collapse'">
44
45
  <path d="M5 5h6v6H5zM13 13h6v6h-6zM8 11v5h5M15 3v7m-3-3 3 3 3-3" />
@@ -48,23 +49,30 @@ defineProps<{ name: string; size?: number }>()
48
49
  <circle cx="12" cy="12" r="3" />
49
50
  </template>
50
51
  <template v-else-if="name === 'zoomIn' || name === 'zoomOut'">
51
- <circle cx="10.5" cy="10.5" r="6.5" /><path d="m16 16 4.5 4.5M7.5 10.5h6" />
52
+ <circle cx="10.5" cy="10.5" r="6.5" />
53
+ <path d="m16 16 4.5 4.5M7.5 10.5h6" />
52
54
  <path v-if="name === 'zoomIn'" d="M10.5 7.5v6" />
53
55
  </template>
54
56
  <template v-else-if="name === 'fit'">
55
57
  <path d="M8 3H3v5M16 3h5v5M8 21H3v-5M16 21h5v-5M8 8h8v8H8z" />
56
58
  </template>
57
59
  <template v-else-if="name === 'more'">
58
- <circle cx="5" cy="12" r="1" fill="currentColor" /><circle cx="12" cy="12" r="1" fill="currentColor" /><circle cx="19" cy="12" r="1" fill="currentColor" />
60
+ <circle cx="5" cy="12" r="1" fill="currentColor" />
61
+ <circle cx="12" cy="12" r="1" fill="currentColor" />
62
+ <circle cx="19" cy="12" r="1" fill="currentColor" />
59
63
  </template>
60
64
  <template v-else-if="name === 'image'">
61
- <rect x="3" y="4" width="18" height="16" rx="2" /><circle cx="9" cy="9" r="2" /><path d="m4 17 5-5 3 3 2-2 6 6" />
65
+ <rect x="3" y="4" width="18" height="16" rx="2" />
66
+ <circle cx="9" cy="9" r="2" />
67
+ <path d="m4 17 5-5 3 3 2-2 6 6" />
62
68
  </template>
63
69
  <template v-else-if="name === 'highlight'">
64
70
  <path d="m14.5 4.5 5 5-8.2 8.2-5.6.6.6-5.6zM12.5 6.5l5 5M4 21h16" />
65
71
  </template>
66
72
  <template v-else-if="name === 'link'">
67
- <path d="M10 13a5 5 0 0 0 7.5.5l2-2a5 5 0 0 0-7-7l-1.2 1.2M14 11a5 5 0 0 0-7.5-.5l-2 2a5 5 0 0 0 7 7l1.2-1.2" />
73
+ <path
74
+ d="M10 13a5 5 0 0 0 7.5.5l2-2a5 5 0 0 0-7-7l-1.2 1.2M14 11a5 5 0 0 0-7.5-.5l-2 2a5 5 0 0 0 7 7l1.2-1.2"
75
+ />
68
76
  </template>
69
77
  <template v-else-if="name === 'code'">
70
78
  <path d="m8 5-5 7 5 7M16 5l5 7-5 7M14 3l-4 18" />
@@ -73,10 +81,12 @@ defineProps<{ name: string; size?: number }>()
73
81
  <path d="M4 7h16M9 7V4h6v3M6 7l1 14h10l1-14M10 11v6M14 11v6" />
74
82
  </template>
75
83
  <template v-else-if="name === 'copy'">
76
- <rect x="8" y="8" width="12" height="12" rx="2" /><path d="M16 8V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h3" />
84
+ <rect x="8" y="8" width="12" height="12" rx="2" />
85
+ <path d="M16 8V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h3" />
77
86
  </template>
78
87
  <template v-else-if="name === 'check'">
79
- <rect x="3" y="3" width="18" height="18" rx="3" /><path d="m7 12 3 3 7-7" />
88
+ <rect x="3" y="3" width="18" height="18" rx="3" />
89
+ <path d="m7 12 3 3 7-7" />
80
90
  </template>
81
91
  <template v-else-if="name === 'removeLink'">
82
92
  <path d="M9 15 7.5 16.5a5 5 0 0 1-7-7L3 7M15 9l1.5-1.5a5 5 0 0 1 7 7L21 17M3 3l18 18" />
@@ -85,16 +95,24 @@ defineProps<{ name: string; size?: number }>()
85
95
  <path d="m4 20 4.2-1 10.6-10.6a2.1 2.1 0 0 0-3-3L5.2 16zM14.8 6.2l3 3" />
86
96
  </template>
87
97
  <template v-else-if="name === 'clearFormat'">
88
- <path d="m4 17 7.5-11.5a2 2 0 0 1 2.8-.5l4.2 2.8a2 2 0 0 1 .5 2.8L12.2 21H7zM8.5 14.5l5.8 3.8M3 21h18" />
98
+ <path
99
+ d="m4 17 7.5-11.5a2 2 0 0 1 2.8-.5l4.2 2.8a2 2 0 0 1 .5 2.8L12.2 21H7zM8.5 14.5l5.8 3.8M3 21h18"
100
+ />
89
101
  </template>
90
102
  <template v-else-if="name === 'close'">
91
103
  <path d="M5 5l14 14M19 5 5 19" />
92
104
  </template>
93
105
  <template v-else-if="name === 'outline'">
94
- <circle cx="5" cy="6" r="1.2" fill="currentColor" /><circle cx="5" cy="12" r="1.2" fill="currentColor" /><circle cx="5" cy="18" r="1.2" fill="currentColor" /><path d="M9 6h11M9 12h8M9 18h10" />
106
+ <circle cx="5" cy="6" r="1.2" fill="currentColor" />
107
+ <circle cx="5" cy="12" r="1.2" fill="currentColor" />
108
+ <circle cx="5" cy="18" r="1.2" fill="currentColor" />
109
+ <path d="M9 6h11M9 12h8M9 18h10" />
95
110
  </template>
96
111
  <template v-else-if="name === 'mindmap'">
97
- <circle cx="12" cy="5" r="2.5" /><circle cx="5" cy="18" r="2.5" /><circle cx="19" cy="18" r="2.5" /><path d="M12 7.5V12M5 15.5V12h14v3.5" />
112
+ <circle cx="12" cy="5" r="2.5" />
113
+ <circle cx="5" cy="18" r="2.5" />
114
+ <circle cx="19" cy="18" r="2.5" />
115
+ <path d="M12 7.5V12M5 15.5V12h14v3.5" />
98
116
  </template>
99
117
  <template v-else-if="name === 'source'">
100
118
  <path d="m9 6-6 6 6 6M15 6l6 6-6 6M14 3l-4 18" />
@@ -103,5 +121,8 @@ defineProps<{ name: string; size?: number }>()
103
121
  </template>
104
122
 
105
123
  <style scoped>
106
- .app-icon { display: block; flex: none; }
124
+ .app-icon {
125
+ display: block;
126
+ flex: none;
127
+ }
107
128
  </style>