@ebl-vue/editor-full 1.0.8
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/.postcssrc.yml +33 -0
- package/LICENSE +21 -0
- package/README.md +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.mjs +2565 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +55 -0
- package/postcss.config.js +15 -0
- package/src/components/Editor/Editor.vue +209 -0
- package/src/components/index.ts +27 -0
- package/src/constants/index.ts +1 -0
- package/src/i18n/zh-cn.ts +151 -0
- package/src/icons/index.ts +78 -0
- package/src/index.ts +11 -0
- package/src/installer.ts +22 -0
- package/src/plugins/alert/index.css +150 -0
- package/src/plugins/alert/index.ts +463 -0
- package/src/plugins/block-alignment/index.css +9 -0
- package/src/plugins/block-alignment/index.ts +116 -0
- package/src/plugins/block-alignment/readme.md +1 -0
- package/src/plugins/code/LICENSE +21 -0
- package/src/plugins/code/index.css +120 -0
- package/src/plugins/code/index.ts +530 -0
- package/src/plugins/code/utils/string.ts +34 -0
- package/src/plugins/color-picker/index.ts +138 -0
- package/src/plugins/color-picker/styles.css +27 -0
- package/src/plugins/delimiter/index.css +14 -0
- package/src/plugins/delimiter/index.ts +122 -0
- package/src/plugins/drag-drop/index.css +19 -0
- package/src/plugins/drag-drop/index.ts +151 -0
- package/src/plugins/drag-drop/readme.md +1 -0
- package/src/plugins/header/H1.ts +405 -0
- package/src/plugins/header/H2.ts +403 -0
- package/src/plugins/header/H3.ts +404 -0
- package/src/plugins/header/H4.ts +405 -0
- package/src/plugins/header/H5.ts +405 -0
- package/src/plugins/header/H6.ts +406 -0
- package/src/plugins/header/index.css +20 -0
- package/src/plugins/header/index.ts +15 -0
- package/src/plugins/header/types.d.ts +46 -0
- package/src/plugins/indent/index.css +86 -0
- package/src/plugins/indent/index.ts +697 -0
- package/src/plugins/inline-code/index.css +11 -0
- package/src/plugins/inline-code/index.ts +205 -0
- package/src/plugins/list/ListRenderer/ChecklistRenderer.ts +211 -0
- package/src/plugins/list/ListRenderer/ListRenderer.ts +73 -0
- package/src/plugins/list/ListRenderer/OrderedListRenderer.ts +123 -0
- package/src/plugins/list/ListRenderer/UnorderedListRenderer.ts +123 -0
- package/src/plugins/list/ListRenderer/index.ts +6 -0
- package/src/plugins/list/ListTabulator/index.ts +1179 -0
- package/src/plugins/list/index.ts +502 -0
- package/src/plugins/list/styles/CssPrefix.ts +4 -0
- package/src/plugins/list/styles/icons/index.ts +10 -0
- package/src/plugins/list/styles/input.css +36 -0
- package/src/plugins/list/styles/list.css +165 -0
- package/src/plugins/list/types/Elements.ts +14 -0
- package/src/plugins/list/types/ItemMeta.ts +40 -0
- package/src/plugins/list/types/ListParams.ts +102 -0
- package/src/plugins/list/types/ListRenderer.ts +6 -0
- package/src/plugins/list/types/OlCounterType.ts +63 -0
- package/src/plugins/list/types/index.ts +14 -0
- package/src/plugins/list/utils/focusItem.ts +18 -0
- package/src/plugins/list/utils/getChildItems.ts +40 -0
- package/src/plugins/list/utils/getItemChildWrapper.ts +10 -0
- package/src/plugins/list/utils/getItemContentElement.ts +10 -0
- package/src/plugins/list/utils/getSiblings.ts +52 -0
- package/src/plugins/list/utils/isLastItem.ts +9 -0
- package/src/plugins/list/utils/itemHasSublist.ts +10 -0
- package/src/plugins/list/utils/normalizeData.ts +84 -0
- package/src/plugins/list/utils/removeChildWrapperIfEmpty.ts +31 -0
- package/src/plugins/list/utils/renderToolboxInput.ts +105 -0
- package/src/plugins/list/utils/stripNumbers.ts +7 -0
- package/src/plugins/list/utils/type-guards.ts +8 -0
- package/src/plugins/list.md +15 -0
- package/src/plugins/marker/index.css +4 -0
- package/src/plugins/marker/index.ts +187 -0
- package/src/plugins/paragraph/index.css +23 -0
- package/src/plugins/paragraph/index.ts +380 -0
- package/src/plugins/paragraph/types/icons.d.ts +4 -0
- package/src/plugins/paragraph/utils/makeFragment.ts +17 -0
- package/src/plugins/quote/index.css +26 -0
- package/src/plugins/quote/index.ts +206 -0
- package/src/plugins/table/index.ts +4 -0
- package/src/plugins/table/plugin.ts +254 -0
- package/src/plugins/table/style.css +388 -0
- package/src/plugins/table/table.ts +1192 -0
- package/src/plugins/table/toolbox.ts +165 -0
- package/src/plugins/table/utils/dom.ts +128 -0
- package/src/plugins/table/utils/popover.ts +172 -0
- package/src/plugins/table/utils/throttled.ts +22 -0
- package/src/plugins/underline/index.css +3 -0
- package/src/plugins/underline/index.ts +216 -0
- package/src/plugins/undo/index.ts +509 -0
- package/src/plugins/undo/observer.ts +101 -0
- package/src/style.css +89 -0
- package/src/utils/index.ts +15 -0
- package/src/utils/install.ts +19 -0
- package/tsconfig.json +37 -0
- package/types/index.d.ts +13 -0
- package/types/plugins/index.d.ts +0 -0
- package/vite.config.ts +79 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
.ce-popover--inline .ce-popover--nested .ce-popover__container {
|
|
2
|
+
width: min-content !important;
|
|
3
|
+
min-width: unset !important;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.ce-popover--inline .ce-popover--nested .ce-popover__items {
|
|
7
|
+
width: max-content;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.editorjs__color-selector-container {
|
|
11
|
+
display: grid;
|
|
12
|
+
gap: 10px;
|
|
13
|
+
padding: 4px;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.editorjs__color-selector__container-item {
|
|
17
|
+
width: 30px;
|
|
18
|
+
height: 30px;
|
|
19
|
+
display: block;
|
|
20
|
+
cursor: pointer;
|
|
21
|
+
border-radius: 100%;
|
|
22
|
+
transition: transform 0.2s ease;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.editorjs__color-selector__container-item:hover {
|
|
26
|
+
transform: scale(1.1);
|
|
27
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build styles
|
|
3
|
+
*/
|
|
4
|
+
import './index.css';
|
|
5
|
+
import {API, BlockTool, BlockToolConstructorOptions, BlockToolData, ToolboxConfig, PasteConfig, PasteEvent} from "@ebl-vue/editorjs";
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
const IconDelimiter = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
9
|
+
<line x1="6" y1="12" x2="10" y2="12" stroke="black" stroke-width="2" stroke-linecap="round"/>
|
|
10
|
+
<line x1="14" y1="12" x2="18" y2="12" stroke="black" stroke-width="2" stroke-linecap="round"/>
|
|
11
|
+
</svg>
|
|
12
|
+
`;
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
export default class Delimiter implements BlockTool {
|
|
16
|
+
|
|
17
|
+
static get isReadOnlySupported(): boolean {
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
static get contentless(): boolean {
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
private api: API
|
|
27
|
+
|
|
28
|
+
private _CSS: {
|
|
29
|
+
block: string
|
|
30
|
+
wrapper: string
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
private _element: HTMLDivElement
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
constructor({data, config, api}: BlockToolConstructorOptions) {
|
|
39
|
+
this.api = api;
|
|
40
|
+
|
|
41
|
+
this._CSS = {
|
|
42
|
+
block: this.api.styles.block,
|
|
43
|
+
wrapper: 'ce-delimiter'
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
this._element = this.drawView();
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Create Tool's view
|
|
53
|
+
* @return {HTMLDivElement}
|
|
54
|
+
* @private
|
|
55
|
+
*/
|
|
56
|
+
drawView(): HTMLDivElement {
|
|
57
|
+
let wrapper = document.createElement('div');
|
|
58
|
+
let lineWrapper = document.createElement('div');
|
|
59
|
+
let lineDiv = document.createElement('div');
|
|
60
|
+
|
|
61
|
+
wrapper.classList.add(this._CSS.wrapper, this._CSS.block);
|
|
62
|
+
lineWrapper.classList.add('ce-delimiter__line__wrapper');
|
|
63
|
+
lineDiv.classList.add('ce-delimiter__line');
|
|
64
|
+
|
|
65
|
+
lineWrapper.appendChild(lineDiv);
|
|
66
|
+
wrapper.appendChild(lineWrapper);
|
|
67
|
+
|
|
68
|
+
return wrapper;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Return Tool's view
|
|
73
|
+
* @returns {HTMLDivElement}
|
|
74
|
+
* @public
|
|
75
|
+
*/
|
|
76
|
+
render(): HTMLDivElement {
|
|
77
|
+
return this._element;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Extract Tool's data from the view
|
|
82
|
+
* @param {HTMLDivElement} toolsContent - Paragraph tools rendered view
|
|
83
|
+
* @returns {DelimiterData} - saved data
|
|
84
|
+
* @public
|
|
85
|
+
*/
|
|
86
|
+
save(toolsContent: HTMLElement): BlockToolData {
|
|
87
|
+
return {};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Get Tool toolbox settings
|
|
92
|
+
* icon - Tool icon's SVG
|
|
93
|
+
* title - title to show in toolbox
|
|
94
|
+
*
|
|
95
|
+
* @return {{icon: string, title: string}}
|
|
96
|
+
*/
|
|
97
|
+
static get toolbox(): ToolboxConfig {
|
|
98
|
+
return {
|
|
99
|
+
icon: IconDelimiter,
|
|
100
|
+
title: 'Delimiter'
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Delimiter onPaste configuration
|
|
106
|
+
*
|
|
107
|
+
* @public
|
|
108
|
+
*/
|
|
109
|
+
static get pasteConfig(): PasteConfig {
|
|
110
|
+
return { tags: ['HR'] };
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* On paste callback that is fired from Editor
|
|
115
|
+
*
|
|
116
|
+
* @param {PasteEvent} event - event with pasted data
|
|
117
|
+
*/
|
|
118
|
+
onPaste(event: PasteEvent): void {
|
|
119
|
+
this.data = {};
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
.ce-block--drop-target .ce-block__content:before {
|
|
2
|
+
content: "";
|
|
3
|
+
position: absolute;
|
|
4
|
+
top: 50%;
|
|
5
|
+
left: -20px;
|
|
6
|
+
margin-top: -1px;
|
|
7
|
+
height: 8px;
|
|
8
|
+
width: 8px;
|
|
9
|
+
border: solid #a0a0a0;
|
|
10
|
+
border-width: 1px 1px 0 0;
|
|
11
|
+
-webkit-transform-origin: right;
|
|
12
|
+
transform-origin: right;
|
|
13
|
+
-webkit-transform: rotate(45deg);
|
|
14
|
+
transform: rotate(45deg);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.ce-block--drop-target .ce-block__content:after {
|
|
18
|
+
background: none;
|
|
19
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import './index.css';
|
|
2
|
+
|
|
3
|
+
import type EditorJS from '@ebl-vue/editorjs/types';
|
|
4
|
+
|
|
5
|
+
export default class DragDrop {
|
|
6
|
+
private toolbar: any;
|
|
7
|
+
private borderStyle: string;
|
|
8
|
+
private api: any;
|
|
9
|
+
private holder: HTMLElement;
|
|
10
|
+
private readOnly: boolean | undefined;
|
|
11
|
+
private startBlock: number | null;
|
|
12
|
+
private endBlock: number | null;
|
|
13
|
+
|
|
14
|
+
constructor(
|
|
15
|
+
holderId: string,
|
|
16
|
+
readonly: boolean,
|
|
17
|
+
editor: EditorJS,
|
|
18
|
+
borderStyle: string) {
|
|
19
|
+
const {
|
|
20
|
+
blocks,
|
|
21
|
+
toolbar,
|
|
22
|
+
} = editor;
|
|
23
|
+
this.toolbar = toolbar;
|
|
24
|
+
this.borderStyle = borderStyle || '1px dashed #aaa';
|
|
25
|
+
this.api = blocks;
|
|
26
|
+
this.holder = document.getElementById(holderId) as HTMLElement;
|
|
27
|
+
this.readOnly =readonly;
|
|
28
|
+
this.startBlock = null;
|
|
29
|
+
this.endBlock = null;
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
this.setDragListener();
|
|
33
|
+
this.setDropListener();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
setElementCursor(element: HTMLElement|null) {
|
|
38
|
+
if (!element) return;
|
|
39
|
+
const range = document.createRange();
|
|
40
|
+
const selection = window.getSelection();
|
|
41
|
+
|
|
42
|
+
range.setStart(element.childNodes[0], 0);
|
|
43
|
+
range.collapse(true);
|
|
44
|
+
selection?.removeAllRanges();
|
|
45
|
+
selection?.addRange(range);
|
|
46
|
+
element.focus();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
setDragListener() {
|
|
51
|
+
if (!this.readOnly) {
|
|
52
|
+
const settingsButton = this.holder?.querySelector<HTMLElement>('.ce-toolbar__settings-btn');
|
|
53
|
+
if (settingsButton) {
|
|
54
|
+
this.initializeDragListener(settingsButton);
|
|
55
|
+
} else {
|
|
56
|
+
const observer = new MutationObserver((mutations, obs) => {
|
|
57
|
+
const settingsButton = this.holder?.querySelector<HTMLElement>(
|
|
58
|
+
".ce-toolbar__settings-btn"
|
|
59
|
+
);
|
|
60
|
+
if (settingsButton) {
|
|
61
|
+
this.initializeDragListener(settingsButton);
|
|
62
|
+
obs.disconnect();
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
observer.observe(this.holder, {
|
|
67
|
+
childList: true,
|
|
68
|
+
subtree: true,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
initializeDragListener(settingsButton: HTMLElement) {
|
|
75
|
+
settingsButton.setAttribute("draggable", "true");
|
|
76
|
+
settingsButton.addEventListener("dragstart", () => {
|
|
77
|
+
this.startBlock = this.api.getCurrentBlockIndex();
|
|
78
|
+
});
|
|
79
|
+
settingsButton.addEventListener('drag', () => {
|
|
80
|
+
this.toolbar.close();
|
|
81
|
+
if (!this.isTheOnlyBlock()) {
|
|
82
|
+
const allBlocks = this.holder.querySelectorAll('.ce-block') as NodeListOf<HTMLElement>;
|
|
83
|
+
const blockFocused = this.holder.querySelector<HTMLElement>('.ce-block--drop-target');
|
|
84
|
+
this.setElementCursor(blockFocused);
|
|
85
|
+
this.setBorderBlocks(allBlocks, blockFocused);
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
setBorderBlocks(allBlocks: NodeListOf<HTMLElement>, blockFocused: HTMLElement|null) {
|
|
93
|
+
Object.values(allBlocks).forEach((block: HTMLElement) => {
|
|
94
|
+
const blockContent = block.querySelector<HTMLElement>('.ce-block__content');
|
|
95
|
+
if (block !== blockFocused) {
|
|
96
|
+
blockContent?.style.removeProperty('border-top');
|
|
97
|
+
blockContent?.style.removeProperty('border-bottom');
|
|
98
|
+
} else {
|
|
99
|
+
const index = Object.keys(allBlocks).find((key) => allBlocks[Number(key)] === blockFocused);
|
|
100
|
+
if (index && Number(index) > this.startBlock!) blockContent!.style.borderBottom = this.borderStyle;
|
|
101
|
+
else blockContent!.style.borderTop = this.borderStyle;
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
setDropListener() {
|
|
108
|
+
document.addEventListener('drop', (event: DragEvent) => {
|
|
109
|
+
const { target } = event;
|
|
110
|
+
if (this.holder.contains(target as HTMLElement) && this.startBlock !== null) {
|
|
111
|
+
const dropTarget = this.getDropTarget(target as HTMLElement);
|
|
112
|
+
if (dropTarget) {
|
|
113
|
+
const blockContent = dropTarget.querySelector<HTMLElement>('.ce-block__content');
|
|
114
|
+
blockContent?.style.removeProperty('border-top');
|
|
115
|
+
blockContent?.style.removeProperty('border-bottom');
|
|
116
|
+
this.endBlock = this.getTargetPosition(dropTarget as HTMLElement);
|
|
117
|
+
this.moveBlocks();
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
this.startBlock = null;
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
static get isReadOnlySupported() {
|
|
126
|
+
return true;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
getDropTarget(target: HTMLElement) {
|
|
131
|
+
return target.classList.contains('ce-block')
|
|
132
|
+
? target
|
|
133
|
+
: target.closest('.ce-block');
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
getTargetPosition(target: HTMLElement) {
|
|
138
|
+
return Array.from(target.parentNode!.children).indexOf(target);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
isTheOnlyBlock() {
|
|
142
|
+
return this.api.getBlocksCount() === 1;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
moveBlocks() {
|
|
147
|
+
if (!this.isTheOnlyBlock()) {
|
|
148
|
+
this.api.move(this.endBlock, this.startBlock);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# 拖拽块插件
|