dragon-editor 2.1.2 → 3.0.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/README.md +82 -96
- package/dist/module.json +1 -1
- package/dist/module.mjs +10 -12
- package/dist/runtime/components/DragonEditor.vue +457 -0
- package/dist/runtime/components/DragonEditorViewer.vue +228 -0
- package/dist/runtime/plugin.d.ts +2 -0
- package/dist/runtime/plugin.mjs +10 -0
- package/dist/runtime/scss/editor.css +261 -0
- package/dist/runtime/scss/viewer.css +198 -0
- package/dist/runtime/store.d.ts +7 -0
- package/dist/runtime/store.mjs +27 -0
- package/dist/runtime/type.d.ts +24 -0
- package/dist/runtime/utils/block.d.ts +9 -0
- package/dist/runtime/utils/block.mjs +70 -0
- package/dist/runtime/utils/convertor.d.ts +2 -0
- package/dist/runtime/utils/convertor.mjs +86 -0
- package/dist/runtime/utils/cursor.d.ts +6 -0
- package/dist/runtime/utils/cursor.mjs +132 -0
- package/dist/runtime/utils/element.d.ts +3 -0
- package/dist/runtime/utils/element.mjs +39 -0
- package/dist/runtime/utils/keyboardEvent.d.ts +10 -0
- package/dist/runtime/utils/keyboardEvent.mjs +781 -0
- package/dist/runtime/utils/style.d.ts +1 -0
- package/dist/runtime/utils/style.mjs +330 -0
- package/dist/runtime/utils/ui.d.ts +1 -0
- package/dist/runtime/utils/ui.mjs +35 -0
- package/package.json +10 -4
- package/README_en.md +0 -30
- package/dist/runtime/core/components/SvgIcon.d.ts +0 -10
- package/dist/runtime/core/components/SvgIcon.mjs +0 -98
- package/dist/runtime/core/components/editor/ImageBlock.vue +0 -175
- package/dist/runtime/core/components/editor/OlBlock.vue +0 -162
- package/dist/runtime/core/components/editor/TextBlock.vue +0 -172
- package/dist/runtime/core/components/editor/UlBlock.vue +0 -162
- package/dist/runtime/core/style/common.css +0 -496
- package/dist/runtime/core/style/viewer.css +0 -205
- package/dist/runtime/core/utils/converter.d.ts +0 -2
- package/dist/runtime/core/utils/converter.mjs +0 -90
- package/dist/runtime/core/utils/cursor.d.ts +0 -4
- package/dist/runtime/core/utils/cursor.mjs +0 -84
- package/dist/runtime/core/utils/element.d.ts +0 -3
- package/dist/runtime/core/utils/element.mjs +0 -40
- package/dist/runtime/core/utils/global.d.ts +0 -3
- package/dist/runtime/core/utils/global.mjs +0 -81
- package/dist/runtime/core/utils/index.d.ts +0 -7
- package/dist/runtime/core/utils/index.mjs +0 -7
- package/dist/runtime/core/utils/keyboard.d.ts +0 -6
- package/dist/runtime/core/utils/keyboard.mjs +0 -565
- package/dist/runtime/core/utils/style.d.ts +0 -6
- package/dist/runtime/core/utils/style.mjs +0 -374
- package/dist/runtime/core/utils/ui.d.ts +0 -4
- package/dist/runtime/core/utils/ui.mjs +0 -13
- package/dist/runtime/shared/components/DragonEditor.vue +0 -695
- package/dist/runtime/shared/components/DragonEditorComment.vue +0 -172
- package/dist/runtime/shared/components/DragonEditorNew.d.ts +0 -16
- package/dist/runtime/shared/components/DragonEditorNew.mjs +0 -62
- package/dist/runtime/shared/components/DragonEditorViewer.d.ts +0 -14
- package/dist/runtime/shared/components/DragonEditorViewer.mjs +0 -15
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div class="dragon-editor --comment">
|
|
3
|
-
<p class="d-text-block" :class="data.classList" contenteditable v-html="data.content" @keydown="textKeyboardEvent" @paste="pasteEvent" ref="$block"></p>
|
|
4
|
-
</div>
|
|
5
|
-
</template>
|
|
6
|
-
|
|
7
|
-
<script setup lang="ts">
|
|
8
|
-
// @ts-ignore
|
|
9
|
-
import { ref, unref } from "#imports";
|
|
10
|
-
import { keyboardEvent, setCursor, pasteText, styleSettings, getArrangementCursorData, getClipboardData, getCursor, findEditableElement } from "../../core/utils/index";
|
|
11
|
-
import { commentBlock, cursorSelection } from "../../../types/index";
|
|
12
|
-
|
|
13
|
-
const $block = ref();
|
|
14
|
-
const data = ref<commentBlock>({
|
|
15
|
-
classList: [],
|
|
16
|
-
content: "",
|
|
17
|
-
});
|
|
18
|
-
const props = defineProps<{ modelValue: commentBlock }>();
|
|
19
|
-
const emit = defineEmits<{
|
|
20
|
-
(e: "update:modelValue", modelValue: commentBlock): void;
|
|
21
|
-
}>();
|
|
22
|
-
const blockCursorData = ref<cursorSelection>({
|
|
23
|
-
type: "",
|
|
24
|
-
startNode: null,
|
|
25
|
-
startOffset: null,
|
|
26
|
-
endNode: null,
|
|
27
|
-
endOffset: null,
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
data.value = unref(props.modelValue) as commentBlock;
|
|
31
|
-
|
|
32
|
-
function textKeyboardEvent(e: KeyboardEvent) {
|
|
33
|
-
keyboardEvent("comment", e, emit, updateBlockData);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function pasteEvent(e: ClipboardEvent) {
|
|
37
|
-
e.preventDefault();
|
|
38
|
-
const data = getClipboardData(e.clipboardData as DataTransfer);
|
|
39
|
-
|
|
40
|
-
if (data.type === "text") {
|
|
41
|
-
pasteText("text", data.value as string);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// export event
|
|
46
|
-
function updateBlockData() {
|
|
47
|
-
// 데이터 정규화 및 검수
|
|
48
|
-
const blockClassList = [...$block.value.classList];
|
|
49
|
-
blockClassList.splice(0, 1);
|
|
50
|
-
const pushList = blockClassList.filter((item) => data.value.classList.indexOf(item) === -1);
|
|
51
|
-
|
|
52
|
-
data.value.classList = data.value.classList.concat(pushList);
|
|
53
|
-
|
|
54
|
-
// 커서위치 재지정
|
|
55
|
-
if ($block.value.innerHTML.length > 0) {
|
|
56
|
-
const preCursorData = getCursor();
|
|
57
|
-
|
|
58
|
-
if (preCursorData.startNode !== null) {
|
|
59
|
-
const cursorData = getArrangementCursorData(blockCursorData.value);
|
|
60
|
-
|
|
61
|
-
data.value.content = $block.value.innerHTML;
|
|
62
|
-
emit("update:modelValue", data.value);
|
|
63
|
-
|
|
64
|
-
setTimeout(() => {
|
|
65
|
-
if ($block.value) {
|
|
66
|
-
setCursor($block.value.childNodes[cursorData.childCount], cursorData.length);
|
|
67
|
-
|
|
68
|
-
// 구조 검수
|
|
69
|
-
$block.value.childNodes.forEach((child: ChildNode) => {
|
|
70
|
-
const $child = child as HTMLElement;
|
|
71
|
-
|
|
72
|
-
if (child.constructor.name !== "Text") {
|
|
73
|
-
// 텍스트가 아닐경우
|
|
74
|
-
if (child.constructor.name !== "HTMLBRElement") {
|
|
75
|
-
// br 태그 유지
|
|
76
|
-
if (child.textContent === "") {
|
|
77
|
-
// 빈 태그 삭제
|
|
78
|
-
child.remove();
|
|
79
|
-
} else if ($child.classList.length === 0) {
|
|
80
|
-
// 클레스 없는 엘리먼트 처리
|
|
81
|
-
$child.insertAdjacentHTML("afterend", $child.innerHTML);
|
|
82
|
-
child.remove();
|
|
83
|
-
}
|
|
84
|
-
} else {
|
|
85
|
-
$child.removeAttribute("class");
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
}, 100);
|
|
91
|
-
} else {
|
|
92
|
-
if ($block.value) {
|
|
93
|
-
$block.value.childNodes.forEach((child: ChildNode) => {
|
|
94
|
-
const $child = child as HTMLElement;
|
|
95
|
-
|
|
96
|
-
if (child.constructor.name !== "Text") {
|
|
97
|
-
// 텍스트가 아닐경우
|
|
98
|
-
if (child.constructor.name !== "HTMLBRElement") {
|
|
99
|
-
// br 태그 유지
|
|
100
|
-
if (child.textContent === "") {
|
|
101
|
-
// 빈 태그 삭제
|
|
102
|
-
child.remove();
|
|
103
|
-
} else if ($child.classList.length === 0) {
|
|
104
|
-
// 클레스 없는 엘리먼트 처리
|
|
105
|
-
$child.insertAdjacentHTML("afterend", $child.innerHTML);
|
|
106
|
-
child.remove();
|
|
107
|
-
}
|
|
108
|
-
} else {
|
|
109
|
-
$child.removeAttribute("class");
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
data.value.content = $block.value.innerHTML;
|
|
115
|
-
emit("update:modelValue", data.value);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
} else {
|
|
119
|
-
emit("update:modelValue", data.value);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
function focus() {
|
|
124
|
-
setCursor($block.value, 0);
|
|
125
|
-
blockCursorData.value = getCursor();
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
function setStyles(kind: string, url?: string) {
|
|
129
|
-
data.value = styleSettings({
|
|
130
|
-
kind: kind,
|
|
131
|
-
blockData: data.value,
|
|
132
|
-
$target: $block.value,
|
|
133
|
-
url: url,
|
|
134
|
-
cursorData: blockCursorData.value,
|
|
135
|
-
});
|
|
136
|
-
setTimeout(() => {
|
|
137
|
-
updateBlockData();
|
|
138
|
-
}, 250);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
function getCursorClassList(className: string) {
|
|
142
|
-
const cursorData = getCursor();
|
|
143
|
-
let value: string[] = [];
|
|
144
|
-
|
|
145
|
-
if (cursorData.type === "Caret") {
|
|
146
|
-
const type = (cursorData.startNode as Node).constructor.name;
|
|
147
|
-
const editableElement = findEditableElement(cursorData.startNode as Node);
|
|
148
|
-
let $target = cursorData.startNode as HTMLElement;
|
|
149
|
-
|
|
150
|
-
if (type === "Text") {
|
|
151
|
-
$target = (cursorData.startNode as HTMLElement).parentNode as HTMLElement;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
if ($target !== editableElement) {
|
|
155
|
-
value = [...$target.classList];
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
return value;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
defineExpose({
|
|
163
|
-
updateBlockData,
|
|
164
|
-
focus,
|
|
165
|
-
setStyles,
|
|
166
|
-
getCursorClassList,
|
|
167
|
-
});
|
|
168
|
-
</script>
|
|
169
|
-
|
|
170
|
-
<style>
|
|
171
|
-
@import "../../core/style/common.css";
|
|
172
|
-
</style>
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import "../../core/style/common.css";
|
|
2
|
-
declare const _default: import("vue").DefineComponent<Readonly<{
|
|
3
|
-
option?: any;
|
|
4
|
-
modelValue?: any;
|
|
5
|
-
}>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
6
|
-
[key: string]: any;
|
|
7
|
-
}>, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, "update:modelValue"[], "update:modelValue", import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<Readonly<{
|
|
8
|
-
option?: any;
|
|
9
|
-
modelValue?: any;
|
|
10
|
-
}>>> & {
|
|
11
|
-
"onUpdate:modelValue"?: ((...args: any[]) => any) | undefined;
|
|
12
|
-
}, {
|
|
13
|
-
readonly option?: any;
|
|
14
|
-
readonly modelValue?: any;
|
|
15
|
-
}, {}>;
|
|
16
|
-
export default _default;
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { h, defineComponent, ref, unref, watch } from "vue";
|
|
2
|
-
import { createLeftMenu } from "../../core/utils/index.mjs";
|
|
3
|
-
import "../../core/style/common.css";
|
|
4
|
-
export default defineComponent({
|
|
5
|
-
name: "DragonEditor",
|
|
6
|
-
props: ["modelValue", "option"],
|
|
7
|
-
emits: ["update:modelValue"],
|
|
8
|
-
setup: (props, ctx) => {
|
|
9
|
-
const modelValue = ref([]);
|
|
10
|
-
const option = ref({
|
|
11
|
-
blockMenu: ["text", "ol", "ul"]
|
|
12
|
-
// TODO : 다른 블럭 만들기 "table", "quotation"
|
|
13
|
-
});
|
|
14
|
-
if (props.modelValue) {
|
|
15
|
-
modelValue.value = props.modelValue;
|
|
16
|
-
}
|
|
17
|
-
if (props.option !== void 0) {
|
|
18
|
-
option.value = Object.assign(option.value, props.option);
|
|
19
|
-
}
|
|
20
|
-
const activeLeftMenu = ref(false);
|
|
21
|
-
const leftMenuPosition = ref(0);
|
|
22
|
-
const leftMenuStructure = createLeftMenu(modelValue.value, leftMenuPosition.value, activeLeftMenu.value);
|
|
23
|
-
const customStyleMenu = ref([]);
|
|
24
|
-
if (option.value.customStyleMenu) {
|
|
25
|
-
customStyleMenu.value = unref(option.value.customStyleMenu);
|
|
26
|
-
}
|
|
27
|
-
init(modelValue.value);
|
|
28
|
-
function init(targetData) {
|
|
29
|
-
if (targetData && Array.isArray(targetData)) {
|
|
30
|
-
if (targetData.length == 0) {
|
|
31
|
-
}
|
|
32
|
-
} else {
|
|
33
|
-
throw new Error("[DragonEditor] : You must set 'v-model' attribute and 'v-mode' type is must be Array(EditorContentType).");
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
function addImageBlock({ src, width, height, caption = "" }) {
|
|
37
|
-
console.log("addImage");
|
|
38
|
-
}
|
|
39
|
-
watch(
|
|
40
|
-
() => props.modelValue,
|
|
41
|
-
(newData, oldData) => {
|
|
42
|
-
init(newData);
|
|
43
|
-
}
|
|
44
|
-
);
|
|
45
|
-
ctx.expose({ addImageBlock });
|
|
46
|
-
return () => {
|
|
47
|
-
return h(
|
|
48
|
-
"div",
|
|
49
|
-
{
|
|
50
|
-
class: ["dragon-editor"],
|
|
51
|
-
onPaste: () => {
|
|
52
|
-
console.log("paste");
|
|
53
|
-
},
|
|
54
|
-
onCopy: () => {
|
|
55
|
-
console.log("copy");
|
|
56
|
-
}
|
|
57
|
-
},
|
|
58
|
-
[leftMenuStructure]
|
|
59
|
-
);
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
});
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import "../../core/style/viewer.css";
|
|
2
|
-
declare const _default: import("vue").DefineComponent<Readonly<{
|
|
3
|
-
content?: any;
|
|
4
|
-
mediaUrl?: any;
|
|
5
|
-
}>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
6
|
-
[key: string]: any;
|
|
7
|
-
}>, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<Readonly<{
|
|
8
|
-
content?: any;
|
|
9
|
-
mediaUrl?: any;
|
|
10
|
-
}>>>, {
|
|
11
|
-
readonly content?: any;
|
|
12
|
-
readonly mediaUrl?: any;
|
|
13
|
-
}, {}>;
|
|
14
|
-
export default _default;
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { h, defineComponent } from "vue";
|
|
2
|
-
import { convertViewBlock } from "../../core/utils/index.mjs";
|
|
3
|
-
import "../../core/style/viewer.css";
|
|
4
|
-
export default defineComponent({
|
|
5
|
-
name: "DragonEditorViewer",
|
|
6
|
-
props: ["content", "mediaUrl"],
|
|
7
|
-
setup: (props, ctx) => {
|
|
8
|
-
if (props.content === void 0 || Array.isArray(props.content) === false) {
|
|
9
|
-
throw new Error("[DragonEditor] Type error : 'content' props is must be Array.");
|
|
10
|
-
}
|
|
11
|
-
return () => {
|
|
12
|
-
return h("div", { class: ["dragon-editor-viewer"] }, convertViewBlock(props.content, props.mediaUrl));
|
|
13
|
-
};
|
|
14
|
-
}
|
|
15
|
-
});
|