@kungal/editor-nuxt 0.17.0 → 0.19.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 +70 -0
- package/package.json +3 -3
- package/runtime/KunEditorToolbar.vue +8 -12
- package/runtime/KunEditorViewSwitch.vue +31 -15
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,75 @@
|
|
|
1
1
|
# @kungal/editor-nuxt
|
|
2
2
|
|
|
3
|
+
## 0.19.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- f111b82: Add a desktop **split view** for long-form writing.
|
|
8
|
+
|
|
9
|
+
`<KunEditor>` now has a third view mode, `split`, alongside WYSIWYG and Markdown:
|
|
10
|
+
an editable markdown source pane + a live **read-only WYSIWYG preview**, side by
|
|
11
|
+
side and left/right swappable. The markdown string stays the single source of
|
|
12
|
+
truth and the preview is derived — the industry-standard model (VS Code /
|
|
13
|
+
StackEdit / Dillinger), so there's no two-editor bidirectional-sync problem.
|
|
14
|
+
|
|
15
|
+
- **editor-vue**: the view mode gains `'split'`; `KunEditorViewSwitchApi` gains
|
|
16
|
+
`swap()` / `swapped` and `labels.split` / `labels.swap`. The WYSIWYG becomes a
|
|
17
|
+
read-only preview in split (its editability now reacts to the `readonly` prop).
|
|
18
|
+
The default hand-rolled view switch gets a 分栏 tab + a ⇄ swap button.
|
|
19
|
+
- **editor-nuxt**: `<KunEditorViewSwitch>` gets the 分栏 KunTab + a KunUI swap
|
|
20
|
+
button (shown in split).
|
|
21
|
+
- **Headless**: the layout is class hooks only — `.kun-editor__panes` /
|
|
22
|
+
`.kun-editor__pane` under `[data-mode='split']` (+ `[data-swap]`). Styled by the
|
|
23
|
+
reference `kun-editor.css`: stacked on narrow screens, side-by-side (swappable)
|
|
24
|
+
from `md` up. editor-vue still ships zero CSS.
|
|
25
|
+
|
|
26
|
+
Verified in the docs production build (headless + KunUI view switches): 分栏 shows
|
|
27
|
+
both panes side by side, typing markdown in the source updates the preview live,
|
|
28
|
+
the WYSIWYG preview is `contenteditable=false`, swap reverses the panes; 0 console
|
|
29
|
+
errors. (Synced scrolling between panes is a possible follow-up.)
|
|
30
|
+
|
|
31
|
+
### Patch Changes
|
|
32
|
+
|
|
33
|
+
- Updated dependencies [f111b82]
|
|
34
|
+
- @kungal/editor-vue@0.19.0
|
|
35
|
+
- @kungal/editor-core@0.19.0
|
|
36
|
+
|
|
37
|
+
## 0.18.0
|
|
38
|
+
|
|
39
|
+
### Minor Changes
|
|
40
|
+
|
|
41
|
+
- 6545866: Toolbar image upload now shows an in-document "uploading…" placeholder.
|
|
42
|
+
|
|
43
|
+
Previously only paste/drop showed the in-flight placeholder (Milkdown's `upload`
|
|
44
|
+
plugin); the toolbar image button uploaded silently — the image just popped in
|
|
45
|
+
when the adapter resolved. Now the toolbar path uses the same placeholder UX
|
|
46
|
+
(ProseMirror's official upload-example pattern).
|
|
47
|
+
|
|
48
|
+
- **editor-core**: `startImageUpload(view, file, { uploadImage, notify, locale })`
|
|
49
|
+
- the `imageUploadPlaceholder` decoration plugin (exported from `/preset`;
|
|
50
|
+
wired by the preset when `uploadImage` is present). Inserts a
|
|
51
|
+
`.kun-editor__uploading` widget at the caret, uploads, then replaces it with the
|
|
52
|
+
image (or removes it + notifies on failure); not an undo step. The paste/drop
|
|
53
|
+
placeholder now uses the same `.kun-editor__uploading` class so both look
|
|
54
|
+
identical.
|
|
55
|
+
- **editor-vue**: `KunEditorToolbarApi` gains `uploadImage(file)`; both the
|
|
56
|
+
headless `EditorToolbar` and the `#toolbar` slot API route uploads through
|
|
57
|
+
`startImageUpload`.
|
|
58
|
+
- **editor-nuxt**: `<KunEditorToolbar>`'s image button uses it.
|
|
59
|
+
- **Headless kept**: the placeholder is a class + widget hook only; style it via
|
|
60
|
+
`.kun-editor__uploading` in the reference `kun-editor.css` (primary-colored).
|
|
61
|
+
|
|
62
|
+
Customizable: style the placeholder via `.kun-editor__uploading`; the text is
|
|
63
|
+
localized (zh/en). Verified in the docs production build: uploading via either
|
|
64
|
+
toolbar inserts the image; the unit tests confirm the placeholder shows during a
|
|
65
|
+
pending upload and is replaced on success / removed on failure.
|
|
66
|
+
|
|
67
|
+
### Patch Changes
|
|
68
|
+
|
|
69
|
+
- Updated dependencies [6545866]
|
|
70
|
+
- @kungal/editor-core@0.18.0
|
|
71
|
+
- @kungal/editor-vue@0.18.0
|
|
72
|
+
|
|
3
73
|
## 0.17.0
|
|
4
74
|
|
|
5
75
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kungal/editor-nuxt",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.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.19.0",
|
|
35
|
+
"@kungal/editor-vue": "0.19.0"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
38
|
"@kungal/ui-vue": "^2.7.0",
|
|
@@ -106,22 +106,18 @@ const groups = computed<Tool[][]>(() => [
|
|
|
106
106
|
]
|
|
107
107
|
])
|
|
108
108
|
|
|
109
|
-
// Image upload — only when the host supplies uploadImage.
|
|
110
|
-
//
|
|
111
|
-
|
|
109
|
+
// Image upload button — shown only when the host supplies uploadImage. The
|
|
110
|
+
// upload itself goes through api.uploadImage, which shows an in-document
|
|
111
|
+
// "uploading…" placeholder at the caret (same UX as paste/drop).
|
|
112
|
+
const canUpload = computed(() => !!props.adapters.uploadImage)
|
|
112
113
|
const fileInput = ref<HTMLInputElement | null>(null)
|
|
113
114
|
const pickImage = () => fileInput.value?.click()
|
|
114
|
-
const onFileChange =
|
|
115
|
+
const onFileChange = (e: Event) => {
|
|
115
116
|
const input = e.target as HTMLInputElement
|
|
116
117
|
const file = input.files?.[0]
|
|
117
118
|
input.value = ''
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
try {
|
|
121
|
-
const src = await upload(file)
|
|
122
|
-
props.run(insertImageCommand.key, { src, title: file.name, alt: file.name })
|
|
123
|
-
} catch {
|
|
124
|
-
props.adapters.notify?.(en.value ? 'Image upload failed' : '图片上传失败', 'error')
|
|
119
|
+
if (file) {
|
|
120
|
+
props.uploadImage(file)
|
|
125
121
|
}
|
|
126
122
|
}
|
|
127
123
|
|
|
@@ -183,7 +179,7 @@ const insertSticker = (src: string, name: string) =>
|
|
|
183
179
|
</KunTooltip>
|
|
184
180
|
</template>
|
|
185
181
|
|
|
186
|
-
<template v-if="
|
|
182
|
+
<template v-if="canUpload">
|
|
187
183
|
<span class="bg-default-200 mx-1 h-5 w-px" aria-hidden="true" />
|
|
188
184
|
<KunTooltip :text="t.image" :delay-show="300">
|
|
189
185
|
<KunButton
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
// KunUI view switch for <KunEditor>'s #view-switch slot —
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
// layer (not headless editor-vue) and is driven purely
|
|
2
|
+
// KunUI view switch for <KunEditor>'s #view-switch slot — 预览 / Markdown / 分栏
|
|
3
|
+
// as a real <KunTab variant="underlined"> (keyboard nav, sliding indicator, a11y),
|
|
4
|
+
// plus a swap button in split mode. Same pattern as <KunEditorToolbar>: it lives
|
|
5
|
+
// in this ui-nuxt-assuming layer (not headless editor-vue) and is driven purely
|
|
6
|
+
// by the slot API.
|
|
6
7
|
//
|
|
7
8
|
// <KunEditor v-model="md">
|
|
8
9
|
// <template #view-switch="s"><KunEditorViewSwitch v-bind="s" /></template>
|
|
9
10
|
// </KunEditor>
|
|
10
11
|
//
|
|
11
|
-
// KunTab
|
|
12
|
+
// KunTab / KunButton / KunIcon are auto-imported by @kungal/ui-nuxt.
|
|
12
13
|
import { computed } from 'vue'
|
|
13
14
|
import type { KunEditorViewSwitchApi } from '@kungal/editor-vue'
|
|
14
15
|
|
|
@@ -16,21 +17,36 @@ const props = defineProps<KunEditorViewSwitchApi>()
|
|
|
16
17
|
|
|
17
18
|
const items = computed(() => [
|
|
18
19
|
{ value: 'wysiwyg', textValue: props.labels.wysiwyg },
|
|
19
|
-
{ value: 'source', textValue: props.labels.source }
|
|
20
|
+
{ value: 'source', textValue: props.labels.source },
|
|
21
|
+
{ value: 'split', textValue: props.labels.split }
|
|
20
22
|
])
|
|
21
23
|
|
|
22
24
|
const onChange = (value: string) => {
|
|
23
|
-
props.setMode(
|
|
25
|
+
props.setMode(
|
|
26
|
+
value === 'source' ? 'source' : value === 'split' ? 'split' : 'wysiwyg'
|
|
27
|
+
)
|
|
24
28
|
}
|
|
25
29
|
</script>
|
|
26
30
|
|
|
27
31
|
<template>
|
|
28
|
-
<
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
<div class="flex items-center gap-1">
|
|
33
|
+
<KunTab
|
|
34
|
+
:model-value="mode"
|
|
35
|
+
:items="items"
|
|
36
|
+
variant="underlined"
|
|
37
|
+
color="primary"
|
|
38
|
+
size="sm"
|
|
39
|
+
@update:model-value="onChange"
|
|
40
|
+
/>
|
|
41
|
+
<KunButton
|
|
42
|
+
v-if="mode === 'split'"
|
|
43
|
+
variant="light"
|
|
44
|
+
size="sm"
|
|
45
|
+
:is-icon-only="true"
|
|
46
|
+
:aria-label="labels.swap"
|
|
47
|
+
@click="swap()"
|
|
48
|
+
>
|
|
49
|
+
<KunIcon name="lucide:arrow-left-right" />
|
|
50
|
+
</KunButton>
|
|
51
|
+
</div>
|
|
36
52
|
</template>
|