Skip to content

Commit

Permalink
Pass configuration to internal tools (codex-team#648)
Browse files Browse the repository at this point in the history
* Pass configuration to internal tools

* Bump version
Add changelog

* Move tools validation to Tools module
Add class for wrapper when toolbox is opened

* Add emptiness check

* Update submodule
  • Loading branch information
gohabereg authored Mar 18, 2019
1 parent 1178a2f commit 6bd857d
Show file tree
Hide file tree
Showing 13 changed files with 110 additions and 35 deletions.
10 changes: 5 additions & 5 deletions dist/editor.js

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

### 2.11.11

- `New` — Add ability to pass configuration for internal Tools

### 2.11.10

- `Fix` - Fix editor view on mobile devices
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@editorjs/editorjs",
"version": "2.11.10",
"version": "2.11.11",
"description": "Editor.js — Native JS, based on API and Open Source",
"main": "dist/editor.js",
"types": "./types/index.d.ts",
Expand Down
15 changes: 0 additions & 15 deletions src/components/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -200,21 +200,6 @@ export default class Core {
if (!$.get(this.config.holderId)) {
throw Error(`element with ID «${this.config.holderId}» is missing. Pass correct holder's ID.`);
}

/**
* Check Tools for a class containing
*/
for (const toolName in this.config.tools) {
if (this.config.tools.hasOwnProperty(toolName)) {
const tool = this.config.tools[toolName];

if (!_.isFunction(tool) && !_.isFunction((tool as ToolSettings).class)) {
throw Error(
`Tool «${toolName}» must be a constructor function or an object with function in the «class» property`,
);
}
}
}
}

/**
Expand Down
9 changes: 9 additions & 0 deletions src/components/modules/blockManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,15 @@ export default class BlockManager extends Module {
return this._blocks.array;
}

/**
* Check if each Block is empty
*
* @returns {boolean}
*/
public get isEditorEmpty(): boolean {
return this.blocks.every((block) => block.isEmpty);
}

/**
* Index of current working block
*
Expand Down
10 changes: 10 additions & 0 deletions src/components/modules/modificationsObserver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export default class ModificationsObserver extends Module {
* @type {Function}
*/
private mutationDebouncer = _.debounce( () => {
this.checkEmptiness();
this.config.onChange();
}, ModificationsObserver.DebounceTimer);

Expand Down Expand Up @@ -142,4 +143,13 @@ export default class ModificationsObserver extends Module {
this.mutationDebouncer();
}
}

/**
* Check if Editor is empty and set CSS class to wrapper
*/
private checkEmptiness(): void {
const {BlockManager, UI} = this.Editor;

UI.nodes.wrapper.classList.toggle(UI.CSS.editorEmpty, BlockManager.isEditorEmpty);
}
}
7 changes: 4 additions & 3 deletions src/components/modules/rectangleSelection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import $ from '../dom';

import SelectionUtils from '../selection';
import Block from '../block';
import UI from './ui';
import Timeout = NodeJS.Timeout;

export default class RectangleSelection extends Module {
Expand Down Expand Up @@ -138,7 +137,7 @@ export default class RectangleSelection extends Module {
this.stackOfSelected = [];

const elemWhereSelectionStart = document.elementFromPoint(pageX - window.pageXOffset, pageY - window.pageYOffset);
if (!(elemWhereSelectionStart.closest('.' + UI.CSS.editorWrapper) &&
if (!(elemWhereSelectionStart.closest('.' + this.Editor.UI.CSS.editorWrapper) &&
!elemWhereSelectionStart.closest('.' + Block.CSS.content))) {
return;
}
Expand Down Expand Up @@ -197,7 +196,9 @@ export default class RectangleSelection extends Module {
}

private genHTML() {
const container = this.Editor.UI.nodes.holder.querySelector('.' + UI.CSS.editorWrapper);
const {UI} = this.Editor;

const container = UI.nodes.holder.querySelector('.' + UI.CSS.editorWrapper);
const overlay = $.make('div', RectangleSelection.CSS.overlay, {});
const overlayContainer = $.make('div', RectangleSelection.CSS.overlayContainer, {});
const overlayRectangle = $.make('div', RectangleSelection.CSS.rect, {});
Expand Down
5 changes: 5 additions & 0 deletions src/components/modules/toolbar/toolbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export default class Toolbox extends Module {
tooltip: 'ce-toolbox__tooltip',
tooltipShown: 'ce-toolbox__tooltip--shown',
tooltipShortcut: 'ce-toolbox__tooltip-shortcut',
openedToolbarHolderModifier: 'codex-editor--toolbox-opened',
};
}

Expand Down Expand Up @@ -124,7 +125,9 @@ export default class Toolbox extends Module {
return;
}

this.Editor.UI.nodes.wrapper.classList.add(this.CSS.openedToolbarHolderModifier);
this.nodes.toolbox.classList.add(this.CSS.toolboxOpened);

this.opened = true;
}

Expand All @@ -135,6 +138,8 @@ export default class Toolbox extends Module {
this.hideTooltip();

this.nodes.toolbox.classList.remove(this.CSS.toolboxOpened);
this.Editor.UI.nodes.wrapper.classList.remove(this.CSS.openedToolbarHolderModifier);

this.opened = false;

/** remove active item pointer */
Expand Down
28 changes: 27 additions & 1 deletion src/components/modules/tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,10 +195,12 @@ export default class Tools extends Module {
* @return {Promise}
*/
public prepare() {
this.validateTools();

/**
* Assign internal tools
*/
Object.assign(this.config.tools, this.internalTools);
_.deepMerge(this.config.tools, this.internalTools);

if (!this.config.hasOwnProperty('tools') || Object.keys(this.config.tools).length === 0) {
throw Error('Can\'t start without tools');
Expand Down Expand Up @@ -379,6 +381,30 @@ export default class Tools extends Module {
return toolPreparationList;
}

/**
* Validate Tools configuration objects and throw Error for user if it is invalid
*/
private validateTools() {
/**
* Check Tools for a class containing
*/
for (const toolName in this.config.tools) {
if (this.config.tools.hasOwnProperty(toolName)) {
if (toolName in this.internalTools) {
return;
}

const tool = this.config.tools[toolName];

if (!_.isFunction(tool) && !_.isFunction((tool as ToolSettings).class)) {
throw Error(
`Tool «${toolName}» must be a constructor function or an object with function in the «class» property`,
);
}
}
}
}

/**
* Returns internal tools
* Includes Bold, Italic, Link and Paragraph
Expand Down
19 changes: 10 additions & 9 deletions src/components/modules/ui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,17 @@ export default class UI extends Module {
* Editor.js UI CSS class names
* @return {{editorWrapper: string, editorZone: string}}
*/
public static get CSS(): {
public get CSS(): {
editorWrapper: string, editorWrapperNarrow: string, editorZone: string, editorZoneHidden: string,
editorLoader: string,
editorLoader: string, editorEmpty: string,
} {
return {
editorWrapper : 'codex-editor',
editorWrapperNarrow : 'codex-editor--narrow',
editorZone : 'codex-editor__redactor',
editorZoneHidden : 'codex-editor__redactor--hidden',
editorLoader : 'codex-editor__loader',
editorEmpty : 'codex-editor--empty',
};
}

Expand All @@ -70,17 +71,17 @@ export default class UI extends Module {
* Adds loader to editor while content is not ready
*/
public addLoader(): void {
this.nodes.loader = $.make('div', UI.CSS.editorLoader);
this.nodes.loader = $.make('div', this.CSS.editorLoader);
this.nodes.wrapper.prepend(this.nodes.loader);
this.nodes.redactor.classList.add(UI.CSS.editorZoneHidden);
this.nodes.redactor.classList.add(this.CSS.editorZoneHidden);
}

/**
* Removes loader when content has loaded
*/
public removeLoader(): void {
this.nodes.loader.remove();
this.nodes.redactor.classList.remove(UI.CSS.editorZoneHidden);
this.nodes.redactor.classList.remove(this.CSS.editorZoneHidden);
}

/**
Expand Down Expand Up @@ -142,14 +143,14 @@ export default class UI extends Module {
/**
* Create and save main UI elements
*/
this.nodes.wrapper = $.make('div', UI.CSS.editorWrapper);
this.nodes.redactor = $.make('div', UI.CSS.editorZone);
this.nodes.wrapper = $.make('div', this.CSS.editorWrapper);
this.nodes.redactor = $.make('div', this.CSS.editorZone);

/**
* If Editor has injected into the narrow container, enable Narrow Mode
*/
if (this.nodes.holder.offsetWidth < this.contentWidth) {
this.nodes.wrapper.classList.add(UI.CSS.editorWrapperNarrow);
this.nodes.wrapper.classList.add(this.CSS.editorWrapperNarrow);
}

this.nodes.wrapper.appendChild(this.nodes.redactor);
Expand Down Expand Up @@ -216,7 +217,7 @@ export default class UI extends Module {
* @param {KeyboardEvent} event
*/
private defaultBehaviour(event: KeyboardEvent): void {
const keyDownOnEditor = (event.target as HTMLElement).closest(`.${UI.CSS.editorWrapper}`);
const keyDownOnEditor = (event.target as HTMLElement).closest(`.${this.CSS.editorWrapper}`);
const {currentBlock} = this.Editor.BlockManager;
const isMetaKey = event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;

Expand Down
2 changes: 1 addition & 1 deletion src/components/tools/paragraph
30 changes: 30 additions & 0 deletions src/components/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -308,4 +308,34 @@ export default class Util {
public static capitalize(text: string): string {
return text[0].toUpperCase() + text.slice(1);
}

/**
* Merge to objects recursively
* @param {object} target
* @param {object[]} sources
* @return {object}
*/
public static deepMerge(target, ...sources) {
const isObject = (item) => item && typeof item === 'object' && !Array.isArray(item);

if (!sources.length) { return target; }
const source = sources.shift();

if (isObject(target) && isObject(source)) {
for (const key in source) {
if (isObject(source[key])) {
if (!target[key]) {
Object.assign(target, { [key]: {} });
}

Util.deepMerge(target[key], source[key]);
} else {
Object.assign(target, { [key]: source[key] });
}
}
}

return Util.deepMerge(target, ...sources);
}

}
4 changes: 4 additions & 0 deletions src/styles/ui.css
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,10 @@
opacity: 0.3;
}

.codex-editor--toolbox-opened [contentEditable=true][data-placeholder]:focus::before {
opacity: 0;
}

@keyframes editor-loader-spin {
0% {
transform: rotate(0deg);
Expand Down

0 comments on commit 6bd857d

Please sign in to comment.