@kungal/editor-nuxt 0.25.2 → 0.26.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.
- package/CHANGELOG.md +33 -0
- package/package.json +3 -3
- package/runtime/KunEditorToolbar.vue +57 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
# @kungal/editor-nuxt
|
|
2
2
|
|
|
3
|
+
## 0.26.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 945708d: Add an insert-link feature (click to add a URL).
|
|
8
|
+
|
|
9
|
+
The `link` mark already existed (so `[text](url)` round-trips and pasted URLs
|
|
10
|
+
autolink), but there was no click-to-insert UI. Now there is:
|
|
11
|
+
|
|
12
|
+
- **editor-core**: `insertLinkCommand` (`{ href, text? }`) — applies the link mark
|
|
13
|
+
to the selection, or inserts linked text on an empty selection; clears the
|
|
14
|
+
stored mark afterwards. Re-exported from `@kungal/editor-core/preset`.
|
|
15
|
+
- **editor-vue**: `KunEditorToolbarApi.insertLink(payload)`; a `link` button in the
|
|
16
|
+
default toolbar and the selection bubble (both default-on); `'link'` added to
|
|
17
|
+
`KunToolbarItem` and `KunSelectionItem`. Headless UI prompts for the URL.
|
|
18
|
+
- **editor-nuxt**: `<KunEditorToolbar>` gains a `link` button — a KunPopover with a
|
|
19
|
+
KunInput for the URL.
|
|
20
|
+
|
|
21
|
+
A link is a **mark** (`[text](url)`), deliberately distinct from the custom-NODE
|
|
22
|
+
embeds (mention / quote). A future "article card" or custom component would be a
|
|
23
|
+
node like those (schema + toUrl/fromUrl), not this — a separate mechanism.
|
|
24
|
+
|
|
25
|
+
Verified in the docs production build: the KunUI toolbar popover wraps a selection
|
|
26
|
+
(`[…](https://example.com)`); the selection bubble does too
|
|
27
|
+
(`[linktext](https://kun.com)`); 4 new core tests (wrap / insert / autolink
|
|
28
|
+
fallback / blank-href no-op) pass; 0 console errors.
|
|
29
|
+
|
|
30
|
+
### Patch Changes
|
|
31
|
+
|
|
32
|
+
- Updated dependencies [945708d]
|
|
33
|
+
- @kungal/editor-core@0.26.0
|
|
34
|
+
- @kungal/editor-vue@0.26.0
|
|
35
|
+
|
|
3
36
|
## 0.25.2
|
|
4
37
|
|
|
5
38
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kungal/editor-nuxt",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.26.0",
|
|
4
4
|
"description": "KunEditor Nuxt Layer — wraps @kungal/editor-vue and auto-imports <KunEditor> so an existing Nuxt app keeps its exact DX (no import needed).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
"nuxt.config.ts"
|
|
32
32
|
],
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@kungal/editor-core": "0.
|
|
35
|
-
"@kungal/editor-vue": "0.
|
|
34
|
+
"@kungal/editor-core": "0.26.0",
|
|
35
|
+
"@kungal/editor-vue": "0.26.0"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
38
|
"@kungal/ui-vue": "^2.7.0",
|
|
@@ -58,6 +58,7 @@ const DEFAULT_ITEMS: KunToolbarItem[] = [
|
|
|
58
58
|
'italic',
|
|
59
59
|
'strike',
|
|
60
60
|
'code',
|
|
61
|
+
'link',
|
|
61
62
|
'|',
|
|
62
63
|
'bulletList',
|
|
63
64
|
'orderedList',
|
|
@@ -79,6 +80,9 @@ const t = computed(() => ({
|
|
|
79
80
|
italic: en.value ? 'Italic' : '斜体',
|
|
80
81
|
strike: en.value ? 'Strikethrough' : '删除线',
|
|
81
82
|
code: en.value ? 'Inline code' : '行内代码',
|
|
83
|
+
link: en.value ? 'Link' : '链接',
|
|
84
|
+
linkPlaceholder: en.value ? 'https://…' : 'https://…',
|
|
85
|
+
linkApply: en.value ? 'Apply' : '确定',
|
|
82
86
|
bulletList: en.value ? 'Bullet list' : '无序列表',
|
|
83
87
|
orderedList: en.value ? 'Ordered list' : '有序列表',
|
|
84
88
|
quote: en.value ? 'Blockquote' : '引用块',
|
|
@@ -117,6 +121,7 @@ const commandButtons = computed<Record<string, Tool>>(() => ({
|
|
|
117
121
|
type RenderItem =
|
|
118
122
|
| { kind: 'divider' }
|
|
119
123
|
| { kind: 'heading' }
|
|
124
|
+
| { kind: 'link' }
|
|
120
125
|
| { kind: 'image' }
|
|
121
126
|
| { kind: 'picker' }
|
|
122
127
|
| { kind: 'button'; tool: Tool }
|
|
@@ -133,6 +138,7 @@ const resolvedItems = computed<RenderItem[]>(() => {
|
|
|
133
138
|
.map<RenderItem | null>((it) => {
|
|
134
139
|
if (it === '|') return { kind: 'divider' }
|
|
135
140
|
if (it === 'heading') return { kind: 'heading' }
|
|
141
|
+
if (it === 'link') return { kind: 'link' }
|
|
136
142
|
if (it === 'image') return { kind: 'image' }
|
|
137
143
|
if (it === 'picker') return { kind: 'picker' }
|
|
138
144
|
const tool = buttons[it]
|
|
@@ -172,6 +178,23 @@ const setHeading = (level: number) => {
|
|
|
172
178
|
headingPopoverEl?.close()
|
|
173
179
|
}
|
|
174
180
|
|
|
181
|
+
// Link — a KunPopover with a URL input. Applies to the current selection (or
|
|
182
|
+
// inserts the URL as linked text when nothing is selected). The editor keeps its
|
|
183
|
+
// selection while the popover input is focused, so api.insertLink wraps it.
|
|
184
|
+
const linkUrl = ref('')
|
|
185
|
+
let linkPopoverEl: { close: () => void } | null = null
|
|
186
|
+
const setLinkPopover = (el: unknown) => {
|
|
187
|
+
linkPopoverEl = el as { close: () => void } | null
|
|
188
|
+
}
|
|
189
|
+
const applyLink = () => {
|
|
190
|
+
const href = linkUrl.value.trim()
|
|
191
|
+
if (href) {
|
|
192
|
+
props.insertLink({ href })
|
|
193
|
+
}
|
|
194
|
+
linkUrl.value = ''
|
|
195
|
+
linkPopoverEl?.close()
|
|
196
|
+
}
|
|
197
|
+
|
|
175
198
|
// Image upload — via api.uploadImage (shows the in-document "uploading…"
|
|
176
199
|
// placeholder). Only rendered when the host supplies uploadImage.
|
|
177
200
|
const canUpload = computed(() => !!props.adapters.uploadImage)
|
|
@@ -245,6 +268,40 @@ const insertSticker = (src: string, name: string) =>
|
|
|
245
268
|
</button>
|
|
246
269
|
</KunPopover>
|
|
247
270
|
|
|
271
|
+
<KunPopover
|
|
272
|
+
v-else-if="item.kind === 'link'"
|
|
273
|
+
:ref="setLinkPopover"
|
|
274
|
+
position="bottom-start"
|
|
275
|
+
:opaque="true"
|
|
276
|
+
inner-class="w-64 p-2"
|
|
277
|
+
>
|
|
278
|
+
<template #trigger>
|
|
279
|
+
<KunTooltip :text="t.link" :delay-show="300">
|
|
280
|
+
<KunButton
|
|
281
|
+
variant="light"
|
|
282
|
+
size="sm"
|
|
283
|
+
:is-icon-only="true"
|
|
284
|
+
:aria-label="t.link"
|
|
285
|
+
>
|
|
286
|
+
<KunIcon name="lucide:link" />
|
|
287
|
+
</KunButton>
|
|
288
|
+
</KunTooltip>
|
|
289
|
+
</template>
|
|
290
|
+
<form class="flex items-center gap-1" @submit.prevent="applyLink">
|
|
291
|
+
<KunInput
|
|
292
|
+
v-model="linkUrl"
|
|
293
|
+
type="url"
|
|
294
|
+
size="sm"
|
|
295
|
+
:placeholder="t.linkPlaceholder"
|
|
296
|
+
:autofocus="true"
|
|
297
|
+
class="flex-1"
|
|
298
|
+
/>
|
|
299
|
+
<KunButton type="submit" variant="flat" color="primary" size="sm">
|
|
300
|
+
{{ t.linkApply }}
|
|
301
|
+
</KunButton>
|
|
302
|
+
</form>
|
|
303
|
+
</KunPopover>
|
|
304
|
+
|
|
248
305
|
<template v-else-if="item.kind === 'image'">
|
|
249
306
|
<KunTooltip :text="t.image" :delay-show="300">
|
|
250
307
|
<KunButton
|