mirror of
https://github.com/codex-team/editor.js
synced 2024-06-10 09:52:36 +02:00
Fixes for 2.19 (#1356)
* Fixes * Update docs/CHANGELOG.md Co-authored-by: Peter Savchenko <specc.dev@gmail.com> * Fix RTL * Optimize tune down * Add explanation on focus events listeners Co-authored-by: Peter Savchenko <specc.dev@gmail.com>
This commit is contained in:
parent
0037a91051
commit
9581fc2dc9
2
dist/editor.js
vendored
2
dist/editor.js
vendored
File diff suppressed because one or more lines are too long
|
@ -21,6 +21,7 @@
|
|||
- `Fix` - Fixed the `Tab` key behavior when the caret is not set inside contenteditable element, but the block is selected [#1302](https://github.com/codex-team/editor.js/issues/1302).
|
||||
- `Fix` - Fixed the `onChange` callback issue. This method didn't be called for native inputs before some contentedtable element changed [#843](https://github.com/codex-team/editor.js/issues/843)
|
||||
- `Fix` - Fixed the `onChange` callback issue. This method didn't be called after the callback throws an exception [#1339](https://github.com/codex-team/editor.js/issues/1339)
|
||||
- `Deprecated` — The Inline Tool `clear()` method is deprecated because the new instance of Inline Tools will be created on every showing of the Inline Toolbar
|
||||
|
||||
### 2.18
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<!--
|
||||
Use this page for debugging purposes.
|
||||
Use this page for RTL mode debugging.
|
||||
Editor Tools are loaded as git-submodules.
|
||||
You can pull modules by running `yarn pull_tools` and start experimenting.
|
||||
-->
|
||||
|
@ -7,7 +7,7 @@
|
|||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Editor.js 🤩🧦🤨 example</title>
|
||||
<title>Editor.js RTL example</title>
|
||||
<link href="https://fonts.googleapis.com/css?family=PT+Mono" rel="stylesheet">
|
||||
<link href="assets/demo.css" rel="stylesheet">
|
||||
<script src="assets/json-preview.js"></script>
|
||||
|
|
|
@ -26,6 +26,16 @@
|
|||
<div class="ce-example__button" id="saveButton">
|
||||
editor.save()
|
||||
</div>
|
||||
|
||||
<div class="ce-example__statusbar">
|
||||
Readonly:
|
||||
<b id="readonly-state">
|
||||
Off
|
||||
</b>
|
||||
<div class="ce-example__statusbar-button" id="toggleReadOnlyButton">
|
||||
toggle
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ce-example__output">
|
||||
<pre class="ce-example__output-content" id="output"></pre>
|
||||
|
@ -65,21 +75,29 @@
|
|||
|
||||
<!-- Initialization -->
|
||||
<script>
|
||||
/**
|
||||
* Saving button
|
||||
*/
|
||||
const saveButton = document.getElementById('saveButton');
|
||||
|
||||
/**
|
||||
* To initialize the Editor, create a new instance with configuration object
|
||||
* @see docs/installation.md for mode details
|
||||
*/
|
||||
var editor = new EditorJS({
|
||||
/**
|
||||
* Enable/Disable the read only mode
|
||||
*/
|
||||
readOnly: false,
|
||||
|
||||
/**
|
||||
* Wrapper of Editor
|
||||
*/
|
||||
holder: 'editorjs',
|
||||
|
||||
/**
|
||||
* Common Inline Toolbar settings
|
||||
* - if true (or not specified), the order from 'tool' property will be used
|
||||
* - if an array of tool names, this order will be used
|
||||
*/
|
||||
// inlineToolbar: ['link', 'marker', 'bold', 'italic'],
|
||||
// inlineToolbar: true,
|
||||
|
||||
/**
|
||||
* Tools list
|
||||
*/
|
||||
|
@ -89,7 +107,7 @@
|
|||
*/
|
||||
header: {
|
||||
class: Header,
|
||||
inlineToolbar: ['link'],
|
||||
inlineToolbar: ['marker', 'link'],
|
||||
config: {
|
||||
placeholder: 'Header'
|
||||
},
|
||||
|
@ -268,13 +286,37 @@
|
|||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Saving button
|
||||
*/
|
||||
const saveButton = document.getElementById('saveButton');
|
||||
|
||||
/**
|
||||
* Toggle read-only button
|
||||
*/
|
||||
const toggleReadOnlyButton = document.getElementById('toggleReadOnlyButton');
|
||||
const readOnlyIndicator = document.getElementById('readonly-state');
|
||||
|
||||
/**
|
||||
* Saving example
|
||||
*/
|
||||
saveButton.addEventListener('click', function () {
|
||||
editor.save().then((savedData) => {
|
||||
cPreview.show(savedData, document.getElementById("output"));
|
||||
});
|
||||
editor.save()
|
||||
.then((savedData) => {
|
||||
cPreview.show(savedData, document.getElementById("output"));
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Saving error', error);
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Toggle read-only example
|
||||
*/
|
||||
toggleReadOnlyButton.addEventListener('click', async () => {
|
||||
const readOnlyState = await editor.readOnly.toggle();
|
||||
|
||||
readOnlyIndicator.textContent = readOnlyState ? 'On' : 'Off';
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
@ -53,7 +53,7 @@ export default class EditorJS {
|
|||
/**
|
||||
* If `onReady` was passed in `configuration` then redefine onReady function
|
||||
*/
|
||||
if (typeof configuration === 'object' && typeof configuration.onReady === 'function') {
|
||||
if (typeof configuration === 'object' && _.isFunction(configuration.onReady)) {
|
||||
onReady = configuration.onReady;
|
||||
}
|
||||
|
||||
|
|
|
@ -71,9 +71,10 @@ export default class MoveDownTune implements BlockTune {
|
|||
*/
|
||||
public handleClick(event: MouseEvent, button: HTMLElement): void {
|
||||
const currentBlockIndex = this.api.blocks.getCurrentBlockIndex();
|
||||
const nextBlock = this.api.blocks.getBlockByIndex(currentBlockIndex + 1);
|
||||
|
||||
// If Block is last do nothing
|
||||
if (currentBlockIndex === this.api.blocks.getBlocksCount() - 1) {
|
||||
if (!nextBlock) {
|
||||
button.classList.add(this.CSS.animation);
|
||||
|
||||
window.setTimeout(() => {
|
||||
|
@ -83,12 +84,6 @@ export default class MoveDownTune implements BlockTune {
|
|||
return;
|
||||
}
|
||||
|
||||
const nextBlock = this.api.blocks.getBlockByIndex(currentBlockIndex + 1);
|
||||
|
||||
if (!nextBlock) {
|
||||
return;
|
||||
}
|
||||
|
||||
const nextBlockElement = nextBlock.holder;
|
||||
const nextBlockCoords = nextBlockElement.getBoundingClientRect();
|
||||
|
||||
|
|
|
@ -228,7 +228,7 @@ export default class Block {
|
|||
config: this.config,
|
||||
api: this.api.getMethodsForTool(name, ToolType.Block),
|
||||
block: this.blockAPI,
|
||||
readOnly: readOnly,
|
||||
readOnly,
|
||||
});
|
||||
|
||||
this.holder = this.compose();
|
||||
|
@ -359,7 +359,7 @@ export default class Block {
|
|||
* @returns {boolean}
|
||||
*/
|
||||
public mergeable(): boolean {
|
||||
return typeof this.tool.merge === 'function';
|
||||
return _.isFunction(this.tool.merge);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -659,7 +659,7 @@ export default class Block {
|
|||
|
||||
/**
|
||||
* Mutation observer doesn't track changes in "<input>" and "<textarea>"
|
||||
* so we need to track focus events
|
||||
* so we need to track focus events to update current input and clear cache.
|
||||
*/
|
||||
this.addInputEvents();
|
||||
}
|
||||
|
|
|
@ -185,6 +185,7 @@ export default class Core {
|
|||
a: true,
|
||||
} as SanitizerConfig;
|
||||
|
||||
|
||||
this.config.hideToolbar = this.config.hideToolbar ? this.config.hideToolbar : false;
|
||||
this.config.tools = this.config.tools || {};
|
||||
this.config.i18n = this.config.i18n || {};
|
||||
|
@ -208,7 +209,6 @@ export default class Core {
|
|||
}
|
||||
|
||||
this.config.readOnly = this.config.readOnly as boolean || false;
|
||||
this.config.i18n = {};
|
||||
|
||||
/**
|
||||
* Adjust i18n
|
||||
|
@ -220,11 +220,7 @@ export default class Core {
|
|||
/**
|
||||
* Text direction. If not set, uses ltr
|
||||
*/
|
||||
if (config.i18n?.direction) {
|
||||
this.config.i18n = {
|
||||
direction: config.i18n?.direction || 'ltr',
|
||||
};
|
||||
}
|
||||
this.config.i18n.direction = config.i18n?.direction || 'ltr';
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -292,8 +288,6 @@ export default class Core {
|
|||
'InlineToolbar',
|
||||
'BlockManager',
|
||||
'Paste',
|
||||
'DragNDrop',
|
||||
'ModificationsObserver',
|
||||
'BlockSelection',
|
||||
'RectangleSelection',
|
||||
'CrossBlockSelection',
|
||||
|
@ -337,7 +331,7 @@ export default class Core {
|
|||
/**
|
||||
* If module has non-default exports, passed object contains them all and default export as 'default' property
|
||||
*/
|
||||
const Module = typeof module === 'function' ? module : module.default;
|
||||
const Module = _.isFunction(module) ? module : module.default;
|
||||
|
||||
try {
|
||||
/**
|
||||
|
|
|
@ -259,7 +259,7 @@ export default class Flipper {
|
|||
this.iterator.currentItem.click();
|
||||
}
|
||||
|
||||
if (typeof this.activateCallback === 'function') {
|
||||
if (_.isFunction(this.activateCallback)) {
|
||||
this.activateCallback(this.iterator.currentItem);
|
||||
}
|
||||
|
||||
|
|
|
@ -13,15 +13,6 @@ export default class DragNDrop extends Module {
|
|||
*/
|
||||
private isStartedAtEditor = false;
|
||||
|
||||
/**
|
||||
* Bind module. Enable all bindings if it is not read-only mode
|
||||
*/
|
||||
public prepare(): void {
|
||||
if (!this.Editor.ReadOnly.isEnabled) {
|
||||
this.enableModuleBindings();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle read-only state
|
||||
*
|
||||
|
|
|
@ -38,7 +38,7 @@ export default class ModificationsObserver extends Module {
|
|||
private mutationDebouncer = _.debounce(() => {
|
||||
this.updateNativeInputs();
|
||||
|
||||
if (typeof this.config.onChange === 'function') {
|
||||
if (_.isFunction(this.config.onChange)) {
|
||||
this.config.onChange(this.Editor.API.methods);
|
||||
}
|
||||
}, ModificationsObserver.DebounceTimer);
|
||||
|
@ -62,17 +62,6 @@ export default class ModificationsObserver extends Module {
|
|||
this.mutationDebouncer = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Preparation method
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public async prepare(): Promise<void> {
|
||||
if (!this.Editor.ReadOnly.isEnabled) {
|
||||
this.enableModule();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set read-only state
|
||||
*
|
||||
|
|
|
@ -144,9 +144,6 @@ export default class Paste extends Module {
|
|||
*/
|
||||
public async prepare(): Promise<void> {
|
||||
this.processTools();
|
||||
if (!this.Editor.ReadOnly.isEnabled) {
|
||||
this.setCallback();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -309,7 +309,7 @@ export default class Sanitizer extends Module {
|
|||
* @param {SanitizerConfig} config - config to check
|
||||
*/
|
||||
private isRule(config: SanitizerConfig): boolean {
|
||||
return typeof config === 'object' || typeof config === 'boolean' || typeof config === 'function';
|
||||
return typeof config === 'object' || typeof config === 'boolean' || _.isFunction(config);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -216,7 +216,7 @@ export default class BlockSettings extends Module<BlockSettingsNodes> {
|
|||
* Add Tool's settings
|
||||
*/
|
||||
private addToolSettings(): void {
|
||||
if (typeof this.Editor.BlockManager.currentBlock.tool.renderSettings === 'function') {
|
||||
if (_.isFunction(this.Editor.BlockManager.currentBlock.tool.renderSettings)) {
|
||||
$.append(this.nodes.toolSettings, this.Editor.BlockManager.currentBlock.tool.renderSettings());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -112,7 +112,7 @@ export default class ConversionToolbar extends Module<ConversionToolbarNodes> {
|
|||
this.close();
|
||||
}
|
||||
|
||||
if (typeof togglingCallback === 'function') {
|
||||
if (_.isFunction(togglingCallback)) {
|
||||
this.togglingCallback = togglingCallback;
|
||||
}
|
||||
}
|
||||
|
@ -136,7 +136,7 @@ export default class ConversionToolbar extends Module<ConversionToolbarNodes> {
|
|||
}));
|
||||
this.flipper.focusFirst();
|
||||
|
||||
if (typeof this.togglingCallback === 'function') {
|
||||
if (_.isFunction(this.togglingCallback)) {
|
||||
this.togglingCallback(true);
|
||||
}
|
||||
}, 50);
|
||||
|
@ -150,7 +150,7 @@ export default class ConversionToolbar extends Module<ConversionToolbarNodes> {
|
|||
this.flipper.deactivate();
|
||||
this.nodes.wrapper.classList.remove(ConversionToolbar.CSS.conversionToolbarShowed);
|
||||
|
||||
if (typeof this.togglingCallback === 'function') {
|
||||
if (_.isFunction(this.togglingCallback)) {
|
||||
this.togglingCallback(false);
|
||||
}
|
||||
}
|
||||
|
@ -207,7 +207,7 @@ export default class ConversionToolbar extends Module<ConversionToolbarNodes> {
|
|||
let exportData = '';
|
||||
const exportProp = currentBlockClass[INTERNAL_SETTINGS.CONVERSION_CONFIG].export;
|
||||
|
||||
if (typeof exportProp === 'function') {
|
||||
if (_.isFunction(exportProp)) {
|
||||
exportData = exportProp(blockData);
|
||||
} else if (typeof exportProp === 'string') {
|
||||
exportData = blockData[exportProp];
|
||||
|
@ -234,7 +234,7 @@ export default class ConversionToolbar extends Module<ConversionToolbarNodes> {
|
|||
let newBlockData = {};
|
||||
const importProp = replacingTool[INTERNAL_SETTINGS.CONVERSION_CONFIG].import;
|
||||
|
||||
if (typeof importProp === 'function') {
|
||||
if (_.isFunction(importProp)) {
|
||||
newBlockData = importProp(cleaned);
|
||||
} else if (typeof importProp === 'string') {
|
||||
newBlockData[importProp] = cleaned;
|
||||
|
|
|
@ -141,9 +141,6 @@ export default class Toolbar extends Module<ToolbarNodes> {
|
|||
|
||||
/**
|
||||
* Module preparation method
|
||||
* Steps:
|
||||
* - Make Toolbar dependent components like BlockSettings, Toolbox and so on
|
||||
* - Make itself and append dependent nodes to itself
|
||||
*/
|
||||
public async prepare(): Promise<void> {
|
||||
/**
|
||||
|
@ -369,6 +366,11 @@ export default class Toolbar extends Module<ToolbarNodes> {
|
|||
*
|
||||
* Toolbar contains BlockSettings and Toolbox.
|
||||
* Thats why at first we draw its components and then Toolbar itself
|
||||
*
|
||||
* Steps:
|
||||
* - Make Toolbar dependent components like BlockSettings, Toolbox and so on
|
||||
* - Make itself and append dependent nodes to itself
|
||||
*
|
||||
*/
|
||||
private drawUI(): void {
|
||||
/**
|
||||
|
|
|
@ -197,7 +197,7 @@ export default class InlineToolbar extends Module<InlineToolbarNodes> {
|
|||
/**
|
||||
* @todo replace 'clear' with 'destroy'
|
||||
*/
|
||||
if (typeof toolInstance.clear === 'function') {
|
||||
if (_.isFunction(toolInstance.clear)) {
|
||||
toolInstance.clear();
|
||||
}
|
||||
});
|
||||
|
@ -614,7 +614,7 @@ export default class InlineToolbar extends Module<InlineToolbarNodes> {
|
|||
this.nodes.buttons.appendChild(button);
|
||||
this.toolsInstances.set(toolName, tool);
|
||||
|
||||
if (typeof tool.renderActions === 'function') {
|
||||
if (_.isFunction(tool.renderActions)) {
|
||||
const actions = tool.renderActions();
|
||||
|
||||
this.nodes.actions.appendChild(actions);
|
||||
|
|
|
@ -444,7 +444,7 @@ export default class Tools extends Module {
|
|||
*/
|
||||
toolPreparationList.push({
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
function: typeof toolClass.prepare === 'function' ? toolClass.prepare : (): void => { },
|
||||
function: _.isFunction(toolClass.prepare) ? toolClass.prepare : (): void => { },
|
||||
data: {
|
||||
toolName,
|
||||
config: toolConfig,
|
||||
|
|
|
@ -163,13 +163,6 @@ export default class UI extends Module<UINodes> {
|
|||
* Load and append CSS
|
||||
*/
|
||||
this.loadStyles();
|
||||
|
||||
/**
|
||||
* Prepare with read-only state from config
|
||||
*/
|
||||
if (!this.Editor.ReadOnly.isEnabled) {
|
||||
this.enableModuleBindings();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -276,7 +276,7 @@ export function isFunction(fn: any): fn is Function {
|
|||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export function isClass(fn: any): boolean {
|
||||
return typeof fn === 'function' && /^\s*class\s+/.test(fn.toString());
|
||||
return isFunction(fn) && /^\s*class\s+/.test(fn.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
3
types/api/blocks.d.ts
vendored
3
types/api/blocks.d.ts
vendored
|
@ -15,11 +15,10 @@ export interface Blocks {
|
|||
* Render passed data
|
||||
*
|
||||
* @param {OutputData} data - saved Block data
|
||||
* @param {boolean} readOnly - the flag that should be used to render a block in the read-only mode
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
render(data: OutputData, readOnly: boolean): Promise<void>;
|
||||
render(data: OutputData): Promise<void>;
|
||||
|
||||
/**
|
||||
* Render passed HTML string
|
||||
|
|
6
types/tools/block-tool.d.ts
vendored
6
types/tools/block-tool.d.ts
vendored
|
@ -17,9 +17,9 @@ export interface BlockTool extends BaseTool {
|
|||
sanitize?: SanitizerConfig;
|
||||
|
||||
/**
|
||||
* @param {boolean} readOnly - render HTML on readonly mode
|
||||
* Creates and returns Tools HTML markup
|
||||
*/
|
||||
render(readOnly?: boolean): HTMLElement;
|
||||
render(): HTMLElement;
|
||||
|
||||
/**
|
||||
* Process Tool's element in DOM and return raw data
|
||||
|
@ -59,7 +59,7 @@ export interface BlockTool extends BaseTool {
|
|||
* Called when the editor is destroyed
|
||||
*/
|
||||
destroy?(): void;
|
||||
|
||||
|
||||
/**
|
||||
* Lifecycle hooks
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue