mirror of
https://github.com/codex-team/editor.js
synced 2024-06-26 17:30:48 +02:00
Add tools` titles for Toolbox (#540)
* Add tools` titles for Toolbox * Bump version * Use isEmpty method to check object emptiness * Improve isEmpty method * Override toolbox settings from editor config
This commit is contained in:
parent
8a53ba5aef
commit
c93ed2501b
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -53,8 +53,7 @@ Options that Tool can specify. All settings should be passed as static propertie
|
||||||
|
|
||||||
| Name | Type | Default Value | Description |
|
| Name | Type | Default Value | Description |
|
||||||
| -- | -- | -- | -- |
|
| -- | -- | -- | -- |
|
||||||
| `displayInToolbox` | _Boolean_ | `false` | Pass `true` to display this `Tool` in the Editor's `Toolbox` |
|
| `toolbox` | _Object_ | `undefined` | Pass here `icon` and `title` to display this `Tool` in the Editor's `Toolbox` <br /> `icon` - HTML string with icon for Toolbox <br /> `title` - optional title to display in Toolbox |
|
||||||
| `toolboxIcon` | _String_ | — | Icon for Toolbox HTML string |
|
|
||||||
| `enableLineBreaks` | _Boolean_ | `false` | With this option, CodeX Editor won't handle Enter keydowns. Can be helpful for Tools like `<code>` where line breaks should be handled by default behaviour. |
|
| `enableLineBreaks` | _Boolean_ | `false` | With this option, CodeX Editor won't handle Enter keydowns. Can be helpful for Tools like `<code>` where line breaks should be handled by default behaviour. |
|
||||||
| `isInline` | _Boolean_ | `false` | Describes Tool as a [Tool for the Inline Toolbar](tools-inline.md) |
|
| `isInline` | _Boolean_ | `false` | Describes Tool as a [Tool for the Inline Toolbar](tools-inline.md) |
|
||||||
|
|
||||||
|
@ -96,15 +95,15 @@ When user pastes content into Editor, pasted content will be splitted into block
|
||||||
|
|
||||||
Also Editor API allows you to define your own pasting scenario. You can either:
|
Also Editor API allows you to define your own pasting scenario. You can either:
|
||||||
|
|
||||||
1. Specify **HTML tags**, that can be represented by your Tool. For example, Image Tool can handle `<img>` tags.
|
1. Specify **HTML tags**, that can be represented by your Tool. For example, Image Tool can handle `<img>` tags.
|
||||||
If tags you specified will be found on content pasting, your Tool will be rendered.
|
If tags you specified will be found on content pasting, your Tool will be rendered.
|
||||||
2. Specify **RegExp** for pasted strings. If pattern has been matched, your Tool will be rendered.
|
2. Specify **RegExp** for pasted strings. If pattern has been matched, your Tool will be rendered.
|
||||||
3. Specify **MIME type** or **extensions** of files that can be handled by your Tool on pasting by drag-n-drop or from clipboard.
|
3. Specify **MIME type** or **extensions** of files that can be handled by your Tool on pasting by drag-n-drop or from clipboard.
|
||||||
|
|
||||||
For each scenario, you should do 2 next things:
|
For each scenario, you should do 2 next things:
|
||||||
|
|
||||||
1. Define static getter `pasteConfig` in Tool class. Specify handled patterns there.
|
1. Define static getter `pasteConfig` in Tool class. Specify handled patterns there.
|
||||||
2. Define public method `onPaste` that will handle PasteEvent to process pasted data.
|
2. Define public method `onPaste` that will handle PasteEvent to process pasted data.
|
||||||
|
|
||||||
### HTML tags handling
|
### HTML tags handling
|
||||||
|
|
||||||
|
@ -187,10 +186,10 @@ static get pasteConfig() {
|
||||||
If you registered some paste substitutions in `pasteConfig` property, you **should** provide `onPaste` callback in your Tool class.
|
If you registered some paste substitutions in `pasteConfig` property, you **should** provide `onPaste` callback in your Tool class.
|
||||||
`onPaste` should be public non-static method. It accepts custom _PasteEvent_ object as argument.
|
`onPaste` should be public non-static method. It accepts custom _PasteEvent_ object as argument.
|
||||||
|
|
||||||
PasteEvent is an alias for three types of events - `tag`, `pattern` and `file`. You can get the type from _PasteEvent_ object's `type` property.
|
PasteEvent is an alias for three types of events - `tag`, `pattern` and `file`. You can get the type from _PasteEvent_ object's `type` property.
|
||||||
Each of these events provide `detail` property with info about pasted content.
|
Each of these events provide `detail` property with info about pasted content.
|
||||||
|
|
||||||
| Type | Detail |
|
| Type | Detail |
|
||||||
| ----- | ------ |
|
| ----- | ------ |
|
||||||
| `tag` | `data` - pasted HTML element |
|
| `tag` | `data` - pasted HTML element |
|
||||||
| `pattern` | `key` - matched pattern key you specified in `pasteConfig` object <br /> `data` - pasted string |
|
| `pattern` | `key` - matched pattern key you specified in `pasteConfig` object <br /> `data` - pasted string |
|
||||||
|
@ -203,14 +202,14 @@ onPaste (event) {
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
case 'tag':
|
case 'tag':
|
||||||
const element = event.detail.data;
|
const element = event.detail.data;
|
||||||
|
|
||||||
this.handleHTMLPaste(element);
|
this.handleHTMLPaste(element);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'pattern':
|
case 'pattern':
|
||||||
const text = event.detail.data;
|
const text = event.detail.data;
|
||||||
const key = event.detail.key;
|
const key = event.detail.key;
|
||||||
|
|
||||||
this.handlePatternPaste(key, text);
|
this.handlePatternPaste(key, text);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -225,7 +224,7 @@ onPaste (event) {
|
||||||
|
|
||||||
## Sanitize
|
## Sanitize
|
||||||
|
|
||||||
CodeX Editor provides [API](sanitizer.md) to clean taint strings.
|
CodeX Editor provides [API](sanitizer.md) to clean taint strings.
|
||||||
Use it manually at the `save()` method or or pass `sanitizer` config to do it automatically.
|
Use it manually at the `save()` method or or pass `sanitizer` config to do it automatically.
|
||||||
|
|
||||||
### Sanitizer Configuration
|
### Sanitizer Configuration
|
||||||
|
@ -239,7 +238,7 @@ let sanitizerConfig = {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Keys of config object is tags and the values is a rules.
|
Keys of config object is tags and the values is a rules.
|
||||||
|
|
||||||
#### Rule
|
#### Rule
|
||||||
|
|
||||||
|
@ -251,7 +250,7 @@ but leave tag.
|
||||||
Also you can pass special attributes that you want to leave.
|
Also you can pass special attributes that you want to leave.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
a: {
|
a: {
|
||||||
href: true
|
href: true
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -290,11 +289,11 @@ Call API method `sanitizer.clean()` at the save method for each field in returne
|
||||||
```javascript
|
```javascript
|
||||||
save() {
|
save() {
|
||||||
return {
|
return {
|
||||||
text: this.api.sanitizer.clean(taintString, sanitizerConfig)
|
text: this.api.sanitizer.clean(taintString, sanitizerConfig)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Automatic sanitize
|
### Automatic sanitize
|
||||||
|
|
||||||
If you pass the sanitizer config as static getter, CodeX Editor will automatically sanitize your saved data.
|
If you pass the sanitizer config as static getter, CodeX Editor will automatically sanitize your saved data.
|
||||||
|
@ -318,7 +317,7 @@ static get sanitize() {
|
||||||
|
|
||||||
Don't forget to set the rule for each embedded subitems otherwise they will
|
Don't forget to set the rule for each embedded subitems otherwise they will
|
||||||
not be sanitized.
|
not be sanitized.
|
||||||
|
|
||||||
if you want to sanitize everything and get data without any tags, use `{}` or just
|
if you want to sanitize everything and get data without any tags, use `{}` or just
|
||||||
ignore field in case if you want to get pure HTML
|
ignore field in case if you want to get pure HTML
|
||||||
|
|
||||||
|
@ -332,7 +331,7 @@ static get sanitize() {
|
||||||
// other objects here won't be sanitized
|
// other objects here won't be sanitized
|
||||||
subitems: {
|
subitems: {
|
||||||
// leave <a> and <b> in subitems
|
// leave <a> and <b> in subitems
|
||||||
a: true,
|
a: true,
|
||||||
b: true,
|
b: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "codex.editor",
|
"name": "codex.editor",
|
||||||
"version": "2.6.2",
|
"version": "2.7.0",
|
||||||
"description": "Codex Editor. Native JS, based on API and Open Source",
|
"description": "Codex Editor. Native JS, based on API and Open Source",
|
||||||
"main": "build/codex-editor.js",
|
"main": "build/codex-editor.js",
|
||||||
"types": "./types/index.d.ts",
|
"types": "./types/index.d.ts",
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import Module from '../../__module';
|
import Module from '../../__module';
|
||||||
import $ from '../../dom';
|
import $ from '../../dom';
|
||||||
import _ from '../../utils';
|
import _ from '../../utils';
|
||||||
import {BlockToolConstructable} from '../../../../types';
|
import {BlockToolConstructable, ToolboxConfig} from '../../../../types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class Toolbox
|
* @class Toolbox
|
||||||
|
@ -196,7 +196,7 @@ export default class Toolbox extends Module {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (childNodes[this.activeButtonIndex] as HTMLElement).title;
|
return (childNodes[this.activeButtonIndex] as HTMLElement).dataset.tool;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -229,7 +229,16 @@ export default class Toolbox extends Module {
|
||||||
private addTool(toolName: string, tool: BlockToolConstructable): void {
|
private addTool(toolName: string, tool: BlockToolConstructable): void {
|
||||||
const api = this.Editor.Tools.apiSettings;
|
const api = this.Editor.Tools.apiSettings;
|
||||||
|
|
||||||
if (tool[api.IS_DISPLAYED_IN_TOOLBOX] && !tool[api.TOOLBAR_ICON]) {
|
const toolToolboxSettings = tool[api.TOOLBOX];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Skip tools that don't pass 'toolbox' property
|
||||||
|
*/
|
||||||
|
if (_.isEmpty(toolToolboxSettings)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toolToolboxSettings && !toolToolboxSettings.icon) {
|
||||||
_.log('Toolbar icon is missed. Tool %o skipped', 'warn', toolName);
|
_.log('Toolbar icon is missed. Tool %o skipped', 'warn', toolName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -242,18 +251,14 @@ export default class Toolbox extends Module {
|
||||||
// return;
|
// return;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
/**
|
const {toolbox: userToolboxSettings = {} as ToolboxConfig} = this.Editor.Tools.getToolSettings(toolName);
|
||||||
* Skip tools that pass 'displayInToolbox=false'
|
|
||||||
*/
|
|
||||||
if (!tool[api.IS_DISPLAYED_IN_TOOLBOX]) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const button = $.make('li', [ Toolbox.CSS.toolboxButton ], {
|
const button = $.make('li', [ Toolbox.CSS.toolboxButton ], {
|
||||||
title: toolName,
|
title: userToolboxSettings.title || toolToolboxSettings.title || toolName,
|
||||||
});
|
});
|
||||||
|
|
||||||
button.innerHTML = tool.toolboxIcon;
|
button.dataset.tool = toolName;
|
||||||
|
button.innerHTML = userToolboxSettings.icon || toolToolboxSettings.icon;
|
||||||
|
|
||||||
$.append(this.nodes.toolbox, button);
|
$.append(this.nodes.toolbox, button);
|
||||||
|
|
||||||
|
|
|
@ -113,13 +113,12 @@ export default class Tools extends Module {
|
||||||
public get apiSettings() {
|
public get apiSettings() {
|
||||||
return {
|
return {
|
||||||
CONFIG: 'config',
|
CONFIG: 'config',
|
||||||
IS_DISPLAYED_IN_TOOLBOX: 'displayInToolbox',
|
|
||||||
IS_ENABLED_INLINE_TOOLBAR: 'inlineToolbar',
|
IS_ENABLED_INLINE_TOOLBAR: 'inlineToolbar',
|
||||||
IS_ENABLED_LINE_BREAKS: 'enableLineBreaks',
|
IS_ENABLED_LINE_BREAKS: 'enableLineBreaks',
|
||||||
IS_INLINE: 'isInline',
|
IS_INLINE: 'isInline',
|
||||||
IS_PASTE_DISALLOWED: 'disallowPaste',
|
IS_PASTE_DISALLOWED: 'disallowPaste',
|
||||||
SHORTCUT: 'shortcut',
|
SHORTCUT: 'shortcut',
|
||||||
TOOLBAR_ICON: 'toolboxIcon',
|
TOOLBOX: 'toolbox',
|
||||||
SANITIZE_CONFIG: 'sanitize',
|
SANITIZE_CONFIG: 'sanitize',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -331,7 +330,7 @@ export default class Tools extends Module {
|
||||||
* @param {string} toolName
|
* @param {string} toolName
|
||||||
* @return {ToolSettings}
|
* @return {ToolSettings}
|
||||||
*/
|
*/
|
||||||
public getToolSettings(toolName) {
|
public getToolSettings(toolName): ToolSettings {
|
||||||
return this.toolsSettings[toolName];
|
return this.toolsSettings[toolName];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -169,6 +169,10 @@ export default class Util {
|
||||||
* @return {boolean}
|
* @return {boolean}
|
||||||
*/
|
*/
|
||||||
public static isEmpty(object: object): boolean {
|
public static isEmpty(object: object): boolean {
|
||||||
|
if (!object) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return Object.keys(object).length === 0 && object.constructor === Object;
|
return Object.keys(object).length === 0 && object.constructor === Object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
1
types/index.d.ts
vendored
1
types/index.d.ts
vendored
|
@ -18,6 +18,7 @@ export {
|
||||||
BlockToolConstructable,
|
BlockToolConstructable,
|
||||||
BlockTool,
|
BlockTool,
|
||||||
BlockToolData,
|
BlockToolData,
|
||||||
|
ToolboxConfig,
|
||||||
ToolSettings,
|
ToolSettings,
|
||||||
ToolConfig,
|
ToolConfig,
|
||||||
PasteEvent,
|
PasteEvent,
|
||||||
|
|
17
types/tools/block-tool.d.ts
vendored
17
types/tools/block-tool.d.ts
vendored
|
@ -57,14 +57,19 @@ export interface BlockTool extends Tool {
|
||||||
|
|
||||||
export interface BlockToolConstructable extends ToolConstructable {
|
export interface BlockToolConstructable extends ToolConstructable {
|
||||||
/**
|
/**
|
||||||
* Should this Tool be displayed in the Editor's Toolbox
|
* Tool's Toolbox settings
|
||||||
*/
|
*/
|
||||||
displayInToolbox?: boolean;
|
toolbox?: {
|
||||||
|
/**
|
||||||
|
* HTML string with an icon for Toolbox
|
||||||
|
*/
|
||||||
|
icon: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* String with an icon for Toolbox
|
* Tool title for Toolbox
|
||||||
*/
|
*/
|
||||||
toolboxIcon?: string;
|
title?: string;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Paste substitutions configuration
|
* Paste substitutions configuration
|
||||||
|
|
20
types/tools/tool-settings.d.ts
vendored
20
types/tools/tool-settings.d.ts
vendored
|
@ -1,6 +1,21 @@
|
||||||
import {ToolConfig} from './tool-config';
|
import {ToolConfig} from './tool-config';
|
||||||
import {ToolConstructable} from './tool';
|
import {ToolConstructable} from './tool';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tool's Toolbox settings
|
||||||
|
*/
|
||||||
|
export interface ToolboxConfig {
|
||||||
|
/**
|
||||||
|
* Tool title for Toolbox
|
||||||
|
*/
|
||||||
|
title?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HTML string with an icon for Toolbox
|
||||||
|
*/
|
||||||
|
icon?: string;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Object passed to the Tool's constructor by {@link EditorConfig#tools}
|
* Object passed to the Tool's constructor by {@link EditorConfig#tools}
|
||||||
*/
|
*/
|
||||||
|
@ -31,4 +46,9 @@ export interface ToolSettings {
|
||||||
* Define shortcut that will render Tool
|
* Define shortcut that will render Tool
|
||||||
*/
|
*/
|
||||||
shortcut?: string;
|
shortcut?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tool's Toolbox settings
|
||||||
|
*/
|
||||||
|
toolbox?: ToolboxConfig;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue