dragon-editor 3.8.7 → 4.0.1
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/README.md +10 -9
- package/dist/module.json +1 -1
- package/dist/module.mjs +9 -7
- package/dist/runtime/components/Block/Code.d.vue.ts +13 -0
- package/dist/runtime/components/Block/Code.vue +193 -0
- package/dist/runtime/components/Block/Code.vue.d.ts +13 -0
- package/dist/runtime/components/Block/Custom.d.vue.ts +9 -0
- package/dist/runtime/components/Block/Custom.vue +28 -0
- package/dist/runtime/components/Block/Custom.vue.d.ts +9 -0
- package/dist/runtime/components/Block/Divider.d.vue.ts +9 -0
- package/dist/runtime/components/Block/Divider.vue +27 -0
- package/dist/runtime/components/Block/Divider.vue.d.ts +9 -0
- package/dist/runtime/components/Block/Heading.d.vue.ts +13 -0
- package/dist/runtime/components/Block/Heading.vue +84 -0
- package/dist/runtime/components/Block/Heading.vue.d.ts +13 -0
- package/dist/runtime/components/Block/Image.d.vue.ts +13 -0
- package/dist/runtime/components/Block/Image.vue +146 -0
- package/dist/runtime/components/Block/Image.vue.d.ts +13 -0
- package/dist/runtime/components/Block/List.d.vue.ts +13 -0
- package/dist/runtime/components/Block/List.vue +170 -0
- package/dist/runtime/components/Block/List.vue.d.ts +13 -0
- package/dist/runtime/components/Block/Text.d.vue.ts +13 -0
- package/dist/runtime/components/Block/Text.vue +84 -0
- package/dist/runtime/components/Block/Text.vue.d.ts +13 -0
- package/dist/runtime/components/DragonEditor.d.vue.ts +27 -22
- package/dist/runtime/components/DragonEditor.vue +311 -474
- package/dist/runtime/components/DragonEditor.vue.d.ts +27 -22
- package/dist/runtime/components/DragonEditorViewer.d.vue.ts +12 -5
- package/dist/runtime/components/DragonEditorViewer.vue +200 -227
- package/dist/runtime/components/DragonEditorViewer.vue.d.ts +12 -5
- package/dist/runtime/components/MenuBar.d.vue.ts +3 -0
- package/dist/runtime/components/MenuBar.vue +385 -0
- package/dist/runtime/components/MenuBar.vue.d.ts +3 -0
- package/dist/runtime/scss/editor.css +237 -283
- package/dist/runtime/scss/viewer.css +184 -210
- package/dist/runtime/store/editor.d.ts +2 -0
- package/dist/runtime/store/editor.js +59 -0
- package/dist/runtime/type.d.mts +101 -124
- package/dist/runtime/utils/data/block.d.ts +20 -0
- package/dist/runtime/utils/data/block.js +663 -0
- package/dist/runtime/utils/data/cursor.d.ts +9 -0
- package/dist/runtime/utils/data/cursor.js +137 -0
- package/dist/runtime/utils/data/index.d.ts +5 -0
- package/dist/runtime/utils/data/index.js +17 -0
- package/dist/runtime/utils/data/node.d.ts +9 -0
- package/dist/runtime/utils/data/node.js +101 -0
- package/dist/runtime/utils/event/cursor.d.ts +3 -6
- package/dist/runtime/utils/event/cursor.js +52 -105
- package/dist/runtime/utils/event/index.d.ts +2 -6
- package/dist/runtime/utils/event/index.js +48 -6
- package/dist/runtime/utils/event/keyboard.d.ts +22 -7
- package/dist/runtime/utils/event/keyboard.js +910 -1406
- package/dist/runtime/utils/layout/body.d.ts +3 -4
- package/dist/runtime/utils/layout/body.js +83 -51
- package/dist/runtime/utils/layout/icon.d.ts +1 -2
- package/dist/runtime/utils/layout/icon.js +64 -67
- package/dist/runtime/utils/layout/index.d.ts +0 -3
- package/dist/runtime/utils/layout/index.js +0 -3
- package/dist/runtime/utils/node/element.d.ts +4 -6
- package/dist/runtime/utils/node/element.js +58 -71
- package/dist/runtime/utils/node/index.d.ts +1 -1
- package/dist/runtime/utils/node/index.js +1 -1
- package/dist/runtime/utils/node/style.d.ts +5 -0
- package/dist/runtime/utils/node/style.js +702 -0
- package/package.json +32 -18
- package/dist/runtime/utils/event/block.d.ts +0 -7
- package/dist/runtime/utils/event/block.js +0 -110
- package/dist/runtime/utils/event/data.d.ts +0 -8
- package/dist/runtime/utils/event/data.js +0 -379
- package/dist/runtime/utils/event/mouse.d.ts +0 -11
- package/dist/runtime/utils/event/mouse.js +0 -85
- package/dist/runtime/utils/event/scroll.d.ts +0 -3
- package/dist/runtime/utils/event/scroll.js +0 -29
- package/dist/runtime/utils/event/touch.d.ts +0 -5
- package/dist/runtime/utils/event/touch.js +0 -10
- package/dist/runtime/utils/event/window.d.ts +0 -5
- package/dist/runtime/utils/event/window.js +0 -47
- package/dist/runtime/utils/layout/block.d.ts +0 -7
- package/dist/runtime/utils/layout/block.js +0 -123
- package/dist/runtime/utils/layout/controlbar.d.ts +0 -3
- package/dist/runtime/utils/layout/controlbar.js +0 -99
- package/dist/runtime/utils/layout/menuBar.d.ts +0 -3
- package/dist/runtime/utils/layout/menuBar.js +0 -408
- package/dist/runtime/utils/node/block.d.ts +0 -19
- package/dist/runtime/utils/node/block.js +0 -256
- package/dist/runtime/utils/style/anchor.d.ts +0 -5
- package/dist/runtime/utils/style/anchor.js +0 -245
- package/dist/runtime/utils/style/decoration.d.ts +0 -4
- package/dist/runtime/utils/style/decoration.js +0 -378
- package/dist/runtime/utils/style/index.d.ts +0 -2
- package/dist/runtime/utils/style/index.js +0 -2
package/README.md
CHANGED
|
@@ -46,7 +46,7 @@ yarn add dragon-editor
|
|
|
46
46
|
bun add dragon-editor
|
|
47
47
|
```
|
|
48
48
|
|
|
49
|
-
##
|
|
49
|
+
## How To Use
|
|
50
50
|
|
|
51
51
|
First. Set module
|
|
52
52
|
|
|
@@ -66,12 +66,10 @@ Second. Use Component
|
|
|
66
66
|
</template>
|
|
67
67
|
|
|
68
68
|
<script setup lang="ts">
|
|
69
|
-
const contentData = ref<DEContentData>([]);
|
|
69
|
+
const contentData = ref<DEContentData>([]);
|
|
70
70
|
</script>
|
|
71
71
|
```
|
|
72
72
|
|
|
73
|
-
Done!
|
|
74
|
-
|
|
75
73
|
## View Page
|
|
76
74
|
|
|
77
75
|
```html
|
|
@@ -86,14 +84,17 @@ Done!
|
|
|
86
84
|
</script>
|
|
87
85
|
```
|
|
88
86
|
|
|
89
|
-
|
|
87
|
+
## Link
|
|
88
|
+
|
|
89
|
+
- [Document](https://lovefields.github.io/dragonEditor-doc/)
|
|
90
|
+
- [Demo](https://lovefields.github.io/dragonEditor-doc/demo)
|
|
90
91
|
|
|
91
92
|
# Sponsors
|
|
92
93
|
|
|
93
94
|
Support this project by becoming a sponsor. [GitHub Sponsors](https://github.com/sponsors/lovefields)
|
|
94
95
|
|
|
95
|
-
<div align="center">
|
|
96
|
-
<a href="https://github.com/
|
|
97
|
-
<img src="https://github.com/
|
|
96
|
+
<!-- <div align="center">
|
|
97
|
+
<a href="https://github.com/{id}">
|
|
98
|
+
<img src="https://github.com/{id}.png" width="50" title="{id}" />
|
|
98
99
|
</a>
|
|
99
|
-
</div>
|
|
100
|
+
</div> -->
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defineNuxtModule, createResolver, addComponent, addTypeTemplate } from '@nuxt/kit';
|
|
1
|
+
import { defineNuxtModule, createResolver, importModule, addComponent, addTypeTemplate } from '@nuxt/kit';
|
|
2
2
|
|
|
3
3
|
const module$1 = defineNuxtModule({
|
|
4
4
|
meta: {
|
|
@@ -7,22 +7,24 @@ const module$1 = defineNuxtModule({
|
|
|
7
7
|
nuxt: ">=3.0.0"
|
|
8
8
|
}
|
|
9
9
|
},
|
|
10
|
-
async setup(
|
|
11
|
-
const
|
|
12
|
-
const typeContent = await readFile(
|
|
10
|
+
async setup() {
|
|
11
|
+
const { resolve } = createResolver(import.meta.url);
|
|
12
|
+
const typeContent = await readFile(resolve("./runtime/type.d.mts"));
|
|
13
|
+
await importModule("@pinia/nuxt");
|
|
14
|
+
await importModule("@vueuse/nuxt");
|
|
13
15
|
addComponent({
|
|
14
16
|
name: "DragonEditor",
|
|
15
|
-
filePath:
|
|
17
|
+
filePath: resolve("./runtime/components/DragonEditor")
|
|
16
18
|
});
|
|
17
19
|
addComponent({
|
|
18
20
|
name: "DragonEditorViewer",
|
|
19
|
-
filePath:
|
|
21
|
+
filePath: resolve("./runtime/components/DragonEditorViewer")
|
|
20
22
|
});
|
|
21
23
|
addTypeTemplate({
|
|
22
24
|
filename: "types/dragon-editor.d.ts",
|
|
23
25
|
getContents: () => `
|
|
24
26
|
declare global {
|
|
25
|
-
${typeContent}
|
|
27
|
+
${typeContent.replaceAll(new RegExp("^export", "gm"), "")}
|
|
26
28
|
}
|
|
27
29
|
|
|
28
30
|
export {}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { DECodeBlock } from "../../type.d.mts.js";
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
data: DECodeBlock;
|
|
4
|
+
isEdit: boolean;
|
|
5
|
+
index: number;
|
|
6
|
+
};
|
|
7
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
8
|
+
update: (data: DECodeBlock) => any;
|
|
9
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
10
|
+
onUpdate?: ((data: DECodeBlock) => any) | undefined;
|
|
11
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
12
|
+
declare const _default: typeof __VLS_export;
|
|
13
|
+
export default _default;
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
class="de-block de-code-block"
|
|
4
|
+
@click="setEdit"
|
|
5
|
+
>
|
|
6
|
+
<p
|
|
7
|
+
v-memo="memoData"
|
|
8
|
+
v-html="props.data.filename"
|
|
9
|
+
class="de-filename"
|
|
10
|
+
:contenteditable="props.isEdit === true"
|
|
11
|
+
ref="$fileName"
|
|
12
|
+
@focus="setEdit"
|
|
13
|
+
@keydown="fileNameKeydownEvent"
|
|
14
|
+
@input="updateFilename"
|
|
15
|
+
@paste="_normalPasteEvent($event, setEdit, abortEdit)"
|
|
16
|
+
></p>
|
|
17
|
+
|
|
18
|
+
<p
|
|
19
|
+
v-if="props.isEdit === false"
|
|
20
|
+
class="de-language"
|
|
21
|
+
>{{ editorStore.codeBlockLnaguageList[props.data.language] }}</p
|
|
22
|
+
>
|
|
23
|
+
|
|
24
|
+
<div
|
|
25
|
+
v-else
|
|
26
|
+
class="de-language"
|
|
27
|
+
>
|
|
28
|
+
<button
|
|
29
|
+
class="de-btn-language"
|
|
30
|
+
@click="isLanguageListActive = !isLanguageListActive"
|
|
31
|
+
ref="$btnLanguageList"
|
|
32
|
+
>{{ editorStore.codeBlockLnaguageList[props.data.language] }}</button
|
|
33
|
+
>
|
|
34
|
+
|
|
35
|
+
<div
|
|
36
|
+
class="de-list-language"
|
|
37
|
+
:class="{ '--active': isLanguageListActive === true }"
|
|
38
|
+
ref="$languageList"
|
|
39
|
+
>
|
|
40
|
+
<button
|
|
41
|
+
v-for="[name, value] in Object.entries(editorStore.codeBlockLnaguageList)"
|
|
42
|
+
class="de-lang"
|
|
43
|
+
@click="setLanguageEvent(name)"
|
|
44
|
+
>
|
|
45
|
+
{{ value }}
|
|
46
|
+
</button>
|
|
47
|
+
</div>
|
|
48
|
+
</div>
|
|
49
|
+
|
|
50
|
+
<div class="de-pre-wrap">
|
|
51
|
+
<div class="de-number">
|
|
52
|
+
<p
|
|
53
|
+
v-for="i in lineNumber"
|
|
54
|
+
class="de-number-item"
|
|
55
|
+
>
|
|
56
|
+
{{ i }}
|
|
57
|
+
</p>
|
|
58
|
+
</div>
|
|
59
|
+
|
|
60
|
+
<pre class="de-pre"><code v-memo="memoData" v-html="props.data.textContent" class="de-code-content" :contenteditable="props.isEdit === true" ref="$content" @focus="setEdit" @keydown="contentKeydownEvent" @input="updateContent" @blur="setStyleEvent" @paste="_normalPasteEvent($event, setEdit, abortEdit)"></code></pre>
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
</template>
|
|
64
|
+
|
|
65
|
+
<script setup>
|
|
66
|
+
import hljs from "highlight.js";
|
|
67
|
+
import { useEditorStore } from "../../store/editor";
|
|
68
|
+
import { ref, computed, nextTick } from "vue";
|
|
69
|
+
import { onClickOutside } from "@vueuse/core";
|
|
70
|
+
import { _moveCodeBlockEvent, _codeBlockShiftEnterEvent, _codeBlockTabEvent, _normalPasteEvent } from "../../utils/event";
|
|
71
|
+
const editorStore = useEditorStore();
|
|
72
|
+
const props = defineProps({
|
|
73
|
+
data: { type: null, required: true },
|
|
74
|
+
isEdit: { type: Boolean, required: true },
|
|
75
|
+
index: { type: Number, required: true }
|
|
76
|
+
});
|
|
77
|
+
const emit = defineEmits(["update"]);
|
|
78
|
+
const isLanguageListActive = ref(false);
|
|
79
|
+
const $fileName = ref(null);
|
|
80
|
+
const $content = ref(null);
|
|
81
|
+
const $languageList = ref(null);
|
|
82
|
+
const $btnLanguageList = ref(null);
|
|
83
|
+
const lineNumber = computed(() => {
|
|
84
|
+
const match = props.data.textContent.match(/\n/g);
|
|
85
|
+
const matchEmptyLast = props.data.textContent.match(/\n\n$/g);
|
|
86
|
+
let number = match === null ? 1 : match.length + 1;
|
|
87
|
+
if (matchEmptyLast !== null) {
|
|
88
|
+
number -= 1;
|
|
89
|
+
}
|
|
90
|
+
return number;
|
|
91
|
+
});
|
|
92
|
+
const memoData = computed(() => {
|
|
93
|
+
const isFrozen = props.isEdit === true && editorStore.selectedBlockId === props.data.id;
|
|
94
|
+
const memoKey = isFrozen ? "frozen" : JSON.stringify(props.data);
|
|
95
|
+
return [memoKey];
|
|
96
|
+
});
|
|
97
|
+
function setEdit() {
|
|
98
|
+
editorStore.selectedBlockId = props.data.id;
|
|
99
|
+
editorStore.selectedBlockIndex = props.index;
|
|
100
|
+
}
|
|
101
|
+
function abortEdit() {
|
|
102
|
+
editorStore.selectedBlockId = "";
|
|
103
|
+
editorStore.selectedBlockIndex = -1;
|
|
104
|
+
}
|
|
105
|
+
function updateFilename(event) {
|
|
106
|
+
const newData = JSON.parse(JSON.stringify(props.data));
|
|
107
|
+
newData.filename = event.target.innerHTML;
|
|
108
|
+
emit("update", newData);
|
|
109
|
+
}
|
|
110
|
+
function fileNameKeydownEvent(event) {
|
|
111
|
+
if ($content.value !== null) {
|
|
112
|
+
if (event.isComposing === false) {
|
|
113
|
+
switch (event.key) {
|
|
114
|
+
case "Enter":
|
|
115
|
+
_moveCodeBlockEvent(event, "down", "filename", $content.value);
|
|
116
|
+
break;
|
|
117
|
+
case "Tab":
|
|
118
|
+
_moveCodeBlockEvent(event, "down", "filename", $content.value);
|
|
119
|
+
break;
|
|
120
|
+
case "ArrowUp":
|
|
121
|
+
_moveCodeBlockEvent(event, "up", "filename", $content.value);
|
|
122
|
+
break;
|
|
123
|
+
case "ArrowDown":
|
|
124
|
+
_moveCodeBlockEvent(event, "down", "filename", $content.value);
|
|
125
|
+
break;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
} else {
|
|
129
|
+
event.preventDefault();
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
function updateContent(event) {
|
|
133
|
+
const newData = JSON.parse(JSON.stringify(props.data));
|
|
134
|
+
newData.textContent = event.target.innerHTML;
|
|
135
|
+
emit("update", newData);
|
|
136
|
+
}
|
|
137
|
+
function contentKeydownEvent(event) {
|
|
138
|
+
if ($fileName.value !== null) {
|
|
139
|
+
if (event.isComposing === false) {
|
|
140
|
+
switch (event.key) {
|
|
141
|
+
case "Enter":
|
|
142
|
+
if (event.shiftKey === true) {
|
|
143
|
+
_codeBlockShiftEnterEvent(event, props.index);
|
|
144
|
+
}
|
|
145
|
+
break;
|
|
146
|
+
case "Tab":
|
|
147
|
+
_codeBlockTabEvent(event);
|
|
148
|
+
break;
|
|
149
|
+
case "ArrowUp":
|
|
150
|
+
_moveCodeBlockEvent(event, "up", "content", $fileName.value);
|
|
151
|
+
break;
|
|
152
|
+
case "ArrowDown":
|
|
153
|
+
_moveCodeBlockEvent(event, "down", "content", $fileName.value);
|
|
154
|
+
break;
|
|
155
|
+
}
|
|
156
|
+
} else {
|
|
157
|
+
event.preventDefault();
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
async function setLanguageEvent(lang) {
|
|
162
|
+
if ($content.value !== null) {
|
|
163
|
+
const textContent = $content.value.textContent;
|
|
164
|
+
const highlights = hljs.highlight(textContent, { language: lang });
|
|
165
|
+
const newData = JSON.parse(JSON.stringify(props.data));
|
|
166
|
+
isLanguageListActive.value = false;
|
|
167
|
+
abortEdit();
|
|
168
|
+
newData.language = lang;
|
|
169
|
+
newData.textContent = highlights.value;
|
|
170
|
+
emit("update", newData);
|
|
171
|
+
await nextTick();
|
|
172
|
+
setEdit();
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
function setStyleEvent() {
|
|
176
|
+
if ($content.value !== null) {
|
|
177
|
+
const textContent = $content.value.textContent;
|
|
178
|
+
const highlights = hljs.highlight(textContent, { language: props.data.language });
|
|
179
|
+
const newData = JSON.parse(JSON.stringify(props.data));
|
|
180
|
+
newData.textContent = highlights.value;
|
|
181
|
+
emit("update", newData);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
onClickOutside(
|
|
185
|
+
$languageList,
|
|
186
|
+
() => {
|
|
187
|
+
isLanguageListActive.value = false;
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
ignore: [$btnLanguageList]
|
|
191
|
+
}
|
|
192
|
+
);
|
|
193
|
+
</script>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { DECodeBlock } from "../../type.d.mts.js";
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
data: DECodeBlock;
|
|
4
|
+
isEdit: boolean;
|
|
5
|
+
index: number;
|
|
6
|
+
};
|
|
7
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
8
|
+
update: (data: DECodeBlock) => any;
|
|
9
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
10
|
+
onUpdate?: ((data: DECodeBlock) => any) | undefined;
|
|
11
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
12
|
+
declare const _default: typeof __VLS_export;
|
|
13
|
+
export default _default;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { DECustomBlock } from "../../type.d.mts.js";
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
data: DECustomBlock;
|
|
4
|
+
isEdit: boolean;
|
|
5
|
+
index: number;
|
|
6
|
+
};
|
|
7
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
8
|
+
declare const _default: typeof __VLS_export;
|
|
9
|
+
export default _default;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
v-memo="memoData"
|
|
4
|
+
v-html="props.data.textContent"
|
|
5
|
+
class="de-block de-custom-block"
|
|
6
|
+
@click="setEdit"
|
|
7
|
+
></div>
|
|
8
|
+
</template>
|
|
9
|
+
|
|
10
|
+
<script setup>
|
|
11
|
+
import { computed } from "vue";
|
|
12
|
+
import { useEditorStore } from "../../store/editor";
|
|
13
|
+
const editorStore = useEditorStore();
|
|
14
|
+
const props = defineProps({
|
|
15
|
+
data: { type: null, required: true },
|
|
16
|
+
isEdit: { type: Boolean, required: true },
|
|
17
|
+
index: { type: Number, required: true }
|
|
18
|
+
});
|
|
19
|
+
const memoData = computed(() => {
|
|
20
|
+
const isFrozen = props.isEdit === true && editorStore.selectedBlockId === props.data.id;
|
|
21
|
+
const memoKey = isFrozen ? "frozen" : JSON.stringify(props.data);
|
|
22
|
+
return [memoKey];
|
|
23
|
+
});
|
|
24
|
+
function setEdit() {
|
|
25
|
+
editorStore.selectedBlockId = props.data.id;
|
|
26
|
+
editorStore.selectedBlockIndex = props.index;
|
|
27
|
+
}
|
|
28
|
+
</script>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { DECustomBlock } from "../../type.d.mts.js";
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
data: DECustomBlock;
|
|
4
|
+
isEdit: boolean;
|
|
5
|
+
index: number;
|
|
6
|
+
};
|
|
7
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
8
|
+
declare const _default: typeof __VLS_export;
|
|
9
|
+
export default _default;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { DEDividerBlock } from "../../type.d.mts.js";
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
data: DEDividerBlock;
|
|
4
|
+
isEdit: boolean;
|
|
5
|
+
index: number;
|
|
6
|
+
};
|
|
7
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
8
|
+
declare const _default: typeof __VLS_export;
|
|
9
|
+
export default _default;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
v-memo="memoData"
|
|
4
|
+
class="de-block de-divider-block"
|
|
5
|
+
@click="setEdit"
|
|
6
|
+
></div>
|
|
7
|
+
</template>
|
|
8
|
+
|
|
9
|
+
<script setup>
|
|
10
|
+
import { computed } from "vue";
|
|
11
|
+
import { useEditorStore } from "../../store/editor";
|
|
12
|
+
const editorStore = useEditorStore();
|
|
13
|
+
const props = defineProps({
|
|
14
|
+
data: { type: null, required: true },
|
|
15
|
+
isEdit: { type: Boolean, required: true },
|
|
16
|
+
index: { type: Number, required: true }
|
|
17
|
+
});
|
|
18
|
+
const memoData = computed(() => {
|
|
19
|
+
const isFrozen = props.isEdit === true && editorStore.selectedBlockId === props.data.id;
|
|
20
|
+
const memoKey = isFrozen ? "frozen" : JSON.stringify(props.data);
|
|
21
|
+
return [memoKey];
|
|
22
|
+
});
|
|
23
|
+
function setEdit() {
|
|
24
|
+
editorStore.selectedBlockId = props.data.id;
|
|
25
|
+
editorStore.selectedBlockIndex = props.index;
|
|
26
|
+
}
|
|
27
|
+
</script>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { DEDividerBlock } from "../../type.d.mts.js";
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
data: DEDividerBlock;
|
|
4
|
+
isEdit: boolean;
|
|
5
|
+
index: number;
|
|
6
|
+
};
|
|
7
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
8
|
+
declare const _default: typeof __VLS_export;
|
|
9
|
+
export default _default;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { DEHeadingBlock } from "../../type.d.mts.js";
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
data: DEHeadingBlock;
|
|
4
|
+
isEdit: boolean;
|
|
5
|
+
index: number;
|
|
6
|
+
};
|
|
7
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
8
|
+
update: (data: DEHeadingBlock) => any;
|
|
9
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
10
|
+
onUpdate?: ((data: DEHeadingBlock) => any) | undefined;
|
|
11
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
12
|
+
declare const _default: typeof __VLS_export;
|
|
13
|
+
export default _default;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<component :is="renderHeading()" />
|
|
3
|
+
</template>
|
|
4
|
+
|
|
5
|
+
<script setup>
|
|
6
|
+
import { useEditorStore } from "../../store/editor";
|
|
7
|
+
import { h, withMemo } from "vue";
|
|
8
|
+
import { _sliceAndNewTextBlock, _blockTabEvent, _moveBlockDefaultEvent, _defaultBackspaceEvent, _defaultDeleteEvent, _allDataPasteEvent, _convertHeadingBlockType, _updateCursorData } from "../../utils/event";
|
|
9
|
+
const editorStore = useEditorStore();
|
|
10
|
+
const props = defineProps({
|
|
11
|
+
data: { type: null, required: true },
|
|
12
|
+
isEdit: { type: Boolean, required: true },
|
|
13
|
+
index: { type: Number, required: true }
|
|
14
|
+
});
|
|
15
|
+
const emit = defineEmits(["update"]);
|
|
16
|
+
const memoCache = [];
|
|
17
|
+
function setEdit() {
|
|
18
|
+
editorStore.selectedBlockId = props.data.id;
|
|
19
|
+
editorStore.selectedBlockIndex = props.index;
|
|
20
|
+
_updateCursorData();
|
|
21
|
+
}
|
|
22
|
+
function abortEdit() {
|
|
23
|
+
editorStore.selectedBlockId = "";
|
|
24
|
+
editorStore.selectedBlockIndex = -1;
|
|
25
|
+
}
|
|
26
|
+
function keydownEvent(event) {
|
|
27
|
+
if (event.isComposing === false) {
|
|
28
|
+
switch (event.key) {
|
|
29
|
+
case "Enter":
|
|
30
|
+
if (event.shiftKey === false) {
|
|
31
|
+
_sliceAndNewTextBlock(event, props.data, props.index);
|
|
32
|
+
} else {
|
|
33
|
+
}
|
|
34
|
+
break;
|
|
35
|
+
case "Tab":
|
|
36
|
+
_blockTabEvent(event, props.data, props.index, setEdit, abortEdit);
|
|
37
|
+
break;
|
|
38
|
+
case "ArrowUp":
|
|
39
|
+
_moveBlockDefaultEvent(event, "up");
|
|
40
|
+
break;
|
|
41
|
+
case "ArrowDown":
|
|
42
|
+
_moveBlockDefaultEvent(event, "down");
|
|
43
|
+
break;
|
|
44
|
+
case "Backspace":
|
|
45
|
+
_defaultBackspaceEvent(event);
|
|
46
|
+
break;
|
|
47
|
+
case "Delete":
|
|
48
|
+
_defaultDeleteEvent(event, setEdit, abortEdit);
|
|
49
|
+
break;
|
|
50
|
+
case " ":
|
|
51
|
+
_convertHeadingBlockType(event, props.data, props.index, setEdit, abortEdit);
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
} else {
|
|
55
|
+
event.preventDefault();
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function updateData(event) {
|
|
59
|
+
const newData = JSON.parse(JSON.stringify(props.data));
|
|
60
|
+
newData.textContent = event.target.innerHTML;
|
|
61
|
+
emit("update", newData);
|
|
62
|
+
}
|
|
63
|
+
function renderHeading() {
|
|
64
|
+
const isFrozen = props.isEdit === true && editorStore.selectedBlockId === props.data.id;
|
|
65
|
+
const memoKey = isFrozen ? "frozen" : JSON.stringify(props.data);
|
|
66
|
+
return withMemo(
|
|
67
|
+
[memoKey],
|
|
68
|
+
() => h(`h${props.data.level}`, {
|
|
69
|
+
class: ["de-block", "de-heading-block", ...props.data.classList],
|
|
70
|
+
id: props.data.id,
|
|
71
|
+
contenteditable: props.isEdit === true,
|
|
72
|
+
"data-depth": props.data.depth,
|
|
73
|
+
"data-level": props.data.level,
|
|
74
|
+
innerHTML: props.data.textContent,
|
|
75
|
+
onFocus: setEdit,
|
|
76
|
+
onInput: updateData,
|
|
77
|
+
onkeydown: keydownEvent,
|
|
78
|
+
onPaste: (event) => _allDataPasteEvent(event, setEdit, abortEdit)
|
|
79
|
+
}),
|
|
80
|
+
memoCache,
|
|
81
|
+
0
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
</script>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { DEHeadingBlock } from "../../type.d.mts.js";
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
data: DEHeadingBlock;
|
|
4
|
+
isEdit: boolean;
|
|
5
|
+
index: number;
|
|
6
|
+
};
|
|
7
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
8
|
+
update: (data: DEHeadingBlock) => any;
|
|
9
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
10
|
+
onUpdate?: ((data: DEHeadingBlock) => any) | undefined;
|
|
11
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
12
|
+
declare const _default: typeof __VLS_export;
|
|
13
|
+
export default _default;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { DEImageBlock } from "../../type.d.mts.js";
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
data: DEImageBlock;
|
|
4
|
+
isEdit: boolean;
|
|
5
|
+
index: number;
|
|
6
|
+
};
|
|
7
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
8
|
+
update: (data: DEImageBlock) => any;
|
|
9
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
10
|
+
onUpdate?: ((data: DEImageBlock) => any) | undefined;
|
|
11
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
12
|
+
declare const _default: typeof __VLS_export;
|
|
13
|
+
export default _default;
|