mirror of
https://github.com/codex-team/editor.js
synced 2024-06-01 21:42:26 +02:00
Handle paste to the same block (#578)
This commit is contained in:
parent
9d0d638d42
commit
7ca07c7999
6
dist/codex-editor.js
vendored
6
dist/codex-editor.js
vendored
File diff suppressed because one or more lines are too long
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "codex.editor",
|
||||
"version": "2.7.20",
|
||||
"version": "2.7.21",
|
||||
"description": "CodeX Editor. Native JS, based on API and Open Source",
|
||||
"main": "dist/codex-editor.js",
|
||||
"types": "./types/index.d.ts",
|
||||
|
|
|
@ -460,4 +460,27 @@ export default class Dom {
|
|||
'video',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if passed content includes only inline elements
|
||||
*
|
||||
* @param {string|HTMLElement} data - element or html string
|
||||
* @return {boolean}
|
||||
*/
|
||||
public static containsOnlyInlineElements(data: string | HTMLElement): boolean {
|
||||
const wrapper = document.createElement('template');
|
||||
|
||||
if (typeof data === 'string') {
|
||||
wrapper.innerHTML = data;
|
||||
} else {
|
||||
wrapper.appendChild(data);
|
||||
}
|
||||
|
||||
const check = (element: HTMLElement) => {
|
||||
return !Dom.blockElements.includes(element.tagName.toLowerCase())
|
||||
&& Array.from(element.children).every(check);
|
||||
};
|
||||
|
||||
return check(wrapper);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -433,6 +433,35 @@ export default class Caret extends Module {
|
|||
}, 50);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts passed content at caret position
|
||||
*
|
||||
* @param {string} content - content to insert
|
||||
*/
|
||||
public insertContentAtCaretPosition(content: string): void {
|
||||
const fragment = document.createDocumentFragment();
|
||||
const wrapper = document.createElement('div');
|
||||
const selection = Selection.get();
|
||||
const range = Selection.range;
|
||||
|
||||
wrapper.innerHTML = content;
|
||||
|
||||
Array.from(wrapper.childNodes).forEach((child: Node) => fragment.appendChild(child));
|
||||
|
||||
const lastChild = fragment.lastChild;
|
||||
|
||||
range.deleteContents();
|
||||
range.insertNode(fragment);
|
||||
|
||||
/** Cross-browser caret insertion */
|
||||
const newRange = document.createRange();
|
||||
|
||||
newRange.setStart(lastChild, lastChild.textContent.length);
|
||||
|
||||
selection.removeAllRanges();
|
||||
selection.addRange(newRange);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all first-level (first child of [contenteditabel]) siblings from passed node
|
||||
* Then you can check it for emptiness
|
||||
|
|
|
@ -1,10 +1,15 @@
|
|||
import CaretClass from './caret';
|
||||
import SelectionUtils from '../selection';
|
||||
|
||||
import Module from '../__module';
|
||||
import $ from '../dom';
|
||||
import _ from '../utils';
|
||||
import {BlockTool, BlockToolConstructable, PasteConfig, PasteEvent, PasteEventDetail} from '../../../types';
|
||||
import {
|
||||
BlockTool,
|
||||
BlockToolConstructable,
|
||||
PasteConfig,
|
||||
PasteEvent,
|
||||
PasteEventDetail,
|
||||
} from '../../../types';
|
||||
import Block from '../block';
|
||||
|
||||
/**
|
||||
* Tag substitute object.
|
||||
|
@ -432,8 +437,12 @@ export default class Paste extends Module {
|
|||
return;
|
||||
}
|
||||
|
||||
if (dataToInsert.length === 1 && !dataToInsert[0].isBlock) {
|
||||
this.processSingleBlock(dataToInsert.pop());
|
||||
if (dataToInsert.length === 1) {
|
||||
if (!dataToInsert[0].isBlock) {
|
||||
this.processInlinePaste(dataToInsert.pop());
|
||||
} else {
|
||||
this.processSingleBlock(dataToInsert.pop());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -536,6 +545,26 @@ export default class Paste extends Module {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Process paste of single Block tool content
|
||||
*
|
||||
* @param {PasteData} dataToInsert
|
||||
*/
|
||||
private async processSingleBlock(dataToInsert: PasteData): Promise<void> {
|
||||
const {Caret, BlockManager, Tools} = this.Editor;
|
||||
const {currentBlock} = BlockManager;
|
||||
|
||||
/**
|
||||
* If pasted tool isn`t equal current Block or if pasted content contains block elements, insert it as new Block
|
||||
*/
|
||||
if (dataToInsert.tool !== currentBlock.name || !$.containsOnlyInlineElements(dataToInsert.content.innerHTML)) {
|
||||
this.insertBlock(dataToInsert, Tools.isInitial(currentBlock.tool) && currentBlock.isEmpty);
|
||||
return;
|
||||
}
|
||||
|
||||
Caret.insertContentAtCaretPosition(dataToInsert.content.innerHTML);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process paste to single Block:
|
||||
* 1. Find patterns` matches
|
||||
|
@ -544,7 +573,7 @@ export default class Paste extends Module {
|
|||
*
|
||||
* @param {PasteData} dataToInsert
|
||||
*/
|
||||
private async processSingleBlock(dataToInsert: PasteData): Promise<void> {
|
||||
private async processInlinePaste(dataToInsert: PasteData): Promise<void> {
|
||||
const initialTool = this.config.initialBlock,
|
||||
{BlockManager, Caret, Sanitizer, Tools} = this.Editor,
|
||||
{content, tool} = dataToInsert;
|
||||
|
@ -613,15 +642,17 @@ export default class Paste extends Module {
|
|||
private async insertBlock(data: PasteData, canReplaceCurrentBlock: boolean = false): Promise<void> {
|
||||
const {BlockManager, Caret} = this.Editor;
|
||||
const {currentBlock} = BlockManager;
|
||||
let block: Block;
|
||||
|
||||
if (canReplaceCurrentBlock && currentBlock && currentBlock.isEmpty) {
|
||||
BlockManager.paste(data.tool, data.event, true);
|
||||
block = BlockManager.paste(data.tool, data.event, true);
|
||||
Caret.setToBlock(block, CaretClass.positions.END);
|
||||
return;
|
||||
}
|
||||
|
||||
const block = BlockManager.paste(data.tool, data.event);
|
||||
block = BlockManager.paste(data.tool, data.event);
|
||||
|
||||
Caret.setToBlock(block);
|
||||
Caret.setToBlock(block, CaretClass.positions.END);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -678,7 +709,7 @@ export default class Paste extends Module {
|
|||
);
|
||||
|
||||
/** Append inline elements to previous fragment */
|
||||
if (!isBlockElement && !isSubstitutable) {
|
||||
if (!isBlockElement && !isSubstitutable && !containsAnotherToolTags) {
|
||||
destNode.appendChild(element);
|
||||
return [...nodes, destNode];
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue