mirror of
https://github.com/codex-team/editor.js
synced 2024-05-18 22:36:47 +02:00
[Refactor] ESLint fixed (#1100)
Co-authored-by: Peter Savchenko <specc.dev@gmail.com>
This commit is contained in:
parent
f5e9a6648e
commit
4c0d806a12
41
.eslintrc
41
.eslintrc
|
@ -6,13 +6,40 @@
|
|||
/**
|
||||
* Temporary suppress some errors. We need to fix them partially in next patches
|
||||
*/
|
||||
"@typescript-eslint/explicit-function-return-type": ["warn"],
|
||||
"@typescript-eslint/explicit-member-accessibility": ["warn"],
|
||||
"@typescript-eslint/member-ordering": ["warn"],
|
||||
"@typescript-eslint/no-empty-function": ["warn"],
|
||||
"no-prototype-builtins": ["warn"],
|
||||
"no-mixed-operators": ["warn"],
|
||||
"import/no-duplicates": ["warn"],
|
||||
"no-case-declarations": ["warn"]
|
||||
},
|
||||
"settings": {
|
||||
"jsdoc": {
|
||||
"mode": "typescript"
|
||||
}
|
||||
},
|
||||
"globals": {
|
||||
"Node": true,
|
||||
"Range": true,
|
||||
"HTMLElement": true,
|
||||
"HTMLDivElement": true,
|
||||
"Element": true,
|
||||
"Selection": true,
|
||||
"SVGElement": true,
|
||||
"Text": true,
|
||||
"InsertPosition": true,
|
||||
"PropertyKey": true,
|
||||
"MouseEvent": true,
|
||||
"TouchEvent": true,
|
||||
"KeyboardEvent": true,
|
||||
"ClipboardEvent": true,
|
||||
"DragEvent": true,
|
||||
"Event": true,
|
||||
"EventTarget": true,
|
||||
"Document": true,
|
||||
"NodeList": true,
|
||||
"File": true,
|
||||
"FileList": true,
|
||||
"MutationRecord": true,
|
||||
"AddEventListenerOptions": true,
|
||||
"DataTransfer": true,
|
||||
"DOMRect": true,
|
||||
"ClientRect": true,
|
||||
"ArrayLike": true
|
||||
}
|
||||
}
|
||||
|
|
2
dist/editor.js
vendored
2
dist/editor.js
vendored
File diff suppressed because one or more lines are too long
11
dist/editor.js.LICENSE
vendored
11
dist/editor.js.LICENSE
vendored
|
@ -1,7 +1,7 @@
|
|||
/*!
|
||||
* Editor.js
|
||||
*
|
||||
* @version 2.17.0
|
||||
* @version 2.18.0
|
||||
*
|
||||
* @licence Apache-2.0
|
||||
* @author CodeX <https://codex.so>
|
||||
|
@ -15,8 +15,9 @@
|
|||
* Or, sanitizing config can be defined globally in editors initialization. That config will be used everywhere
|
||||
* At least, if there is no config overrides, that API uses Default configuration
|
||||
*
|
||||
* @uses https://www.npmjs.com/package/html-janitor
|
||||
* @license https://github.com/guardian/html-janitor/blob/master/LICENSE
|
||||
* @see {@link https://www.npmjs.com/package/html-janitor}
|
||||
* @license Apache-2.0
|
||||
* @see {@link https://github.com/guardian/html-janitor/blob/master/LICENSE}
|
||||
*
|
||||
* @param {SanitizerConfig} config - sanitizer extension
|
||||
*/
|
||||
|
@ -26,9 +27,9 @@
|
|||
*
|
||||
* Short Description (눈_눈;)
|
||||
*
|
||||
* @version 2.0
|
||||
* @version 2.18.0
|
||||
*
|
||||
* @licence Apache-2.0
|
||||
* @license Apache-2.0
|
||||
* @author CodeX-Team <https://ifmo.su>
|
||||
*/
|
||||
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
### 2.18
|
||||
|
||||
- `Improvements` - Deprecated TSLint replaced with ESLint, old config changed to [CodeX ESLint Config](https://github.com/codex-team/eslint-config).
|
||||
- `Improvements` - TSLint (deprecated) replaced with ESLint, old config changed to [CodeX ESLint Config](https://github.com/codex-team/eslint-config).
|
||||
- `Improvements` - Fix many code-style issues, add missed annotations.
|
||||
- `Improvements` - Adjusted GitHub action for ESLint.
|
||||
|
||||
### 2.17
|
||||
|
|
|
@ -93,7 +93,8 @@ body {
|
|||
max-width: 180px;
|
||||
background: #4A9DF8;
|
||||
padding: 17px 30px;
|
||||
box-shadow: 0 6px 4px -4px rgba(137, 207, 255, 0.77);
|
||||
box-shadow: 0 22px 18px -4px rgba(137, 207, 255, 0.77);
|
||||
transition: all 150ms ease;
|
||||
cursor: pointer;
|
||||
border-radius: 31px;
|
||||
color: #fff;
|
||||
|
@ -103,6 +104,8 @@ body {
|
|||
|
||||
.ce-example__button:hover {
|
||||
background: #3D8DE5;
|
||||
transform: translateY(2px);
|
||||
box-shadow: 0 20px 15px -4px rgba(137, 207, 255, 0.77);
|
||||
}
|
||||
|
||||
.ce-example__output-footer {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@editorjs/editorjs",
|
||||
"version": "2.17.0",
|
||||
"version": "2.18.0",
|
||||
"description": "Editor.js — Native JS, based on API and Open Source",
|
||||
"main": "dist/editor.js",
|
||||
"types": "./types/index.d.ts",
|
||||
|
|
15
src/codex.ts
15
src/codex.ts
|
@ -17,9 +17,9 @@ declare const VERSION: string;
|
|||
*
|
||||
* Short Description (눈_눈;)
|
||||
*
|
||||
* @version 2.0
|
||||
* @version 2.18.0
|
||||
*
|
||||
* @licence Apache-2.0
|
||||
* @license Apache-2.0
|
||||
* @author CodeX-Team <https://ifmo.su>
|
||||
*/
|
||||
export default class EditorJS {
|
||||
|
@ -35,7 +35,7 @@ export default class EditorJS {
|
|||
public destroy: () => void;
|
||||
|
||||
/** Editor version */
|
||||
static get version(): string {
|
||||
public static get version(): string {
|
||||
return VERSION;
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,8 @@ export default class EditorJS {
|
|||
/**
|
||||
* Set default onReady function
|
||||
*/
|
||||
let onReady = () => {};
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
let onReady = (): void => {};
|
||||
|
||||
/**
|
||||
* If `onReady` was passed in `configuration` then redefine onReady function
|
||||
|
@ -75,18 +76,18 @@ export default class EditorJS {
|
|||
/**
|
||||
* Export external API methods
|
||||
*
|
||||
* @param editor
|
||||
* @param {Core} editor — Editor's instance
|
||||
*/
|
||||
public exportAPI(editor: Core): void {
|
||||
const fieldsToExport = [ 'configuration' ];
|
||||
const destroy = () => {
|
||||
const destroy = (): void => {
|
||||
editor.moduleInstances.Listeners.removeAll();
|
||||
editor.moduleInstances.UI.destroy();
|
||||
editor.moduleInstances.ModificationsObserver.destroy();
|
||||
editor = null;
|
||||
|
||||
for (const field in this) {
|
||||
if (this.hasOwnProperty(field)) {
|
||||
if (Object.prototype.hasOwnProperty.call(this, field)) {
|
||||
delete this[field];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ export default class Module {
|
|||
|
||||
/**
|
||||
* @class
|
||||
* @param {EditorConfig}
|
||||
* @param {EditorConfig} config - Editor's config
|
||||
*/
|
||||
constructor({ config }: ModuleConfig) {
|
||||
if (new.target === Module) {
|
||||
|
@ -41,9 +41,9 @@ export default class Module {
|
|||
/**
|
||||
* Editor modules setter
|
||||
*
|
||||
* @param {EditorModules} Editor
|
||||
* @param {EditorModules} Editor - Editor's Modules
|
||||
*/
|
||||
set state(Editor: EditorModules) {
|
||||
public set state(Editor: EditorModules) {
|
||||
this.Editor = Editor;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ export default class DeleteTune implements BlockTune {
|
|||
/**
|
||||
* Property that contains Editor.js API methods
|
||||
*
|
||||
* @see {docs/api.md}
|
||||
* @see {@link docs/api.md}
|
||||
*/
|
||||
private readonly api: API;
|
||||
|
||||
|
@ -35,7 +35,7 @@ export default class DeleteTune implements BlockTune {
|
|||
/**
|
||||
* set false confirmation state
|
||||
*/
|
||||
private resetConfirmation: () => void;
|
||||
private readonly resetConfirmation: () => void;
|
||||
|
||||
/**
|
||||
* Tune nodes
|
||||
|
@ -47,12 +47,12 @@ export default class DeleteTune implements BlockTune {
|
|||
/**
|
||||
* DeleteTune constructor
|
||||
*
|
||||
* @param {{api: API}} api
|
||||
* @param {API} api - Editor's API
|
||||
*/
|
||||
constructor({ api }) {
|
||||
this.api = api;
|
||||
|
||||
this.resetConfirmation = () => {
|
||||
this.resetConfirmation = (): void => {
|
||||
this.setConfirmation(false);
|
||||
};
|
||||
}
|
||||
|
@ -60,9 +60,9 @@ export default class DeleteTune implements BlockTune {
|
|||
/**
|
||||
* Create "Delete" button and add click event listener
|
||||
*
|
||||
* @returns [Element}
|
||||
* @returns {HTMLElement}
|
||||
*/
|
||||
public render() {
|
||||
public render(): HTMLElement {
|
||||
this.nodes.button = $.make('div', [this.CSS.button, this.CSS.buttonDelete], {});
|
||||
this.nodes.button.appendChild($.svg('cross', 12, 12));
|
||||
this.api.listeners.on(this.nodes.button, 'click', (event: MouseEvent) => this.handleClick(event), false);
|
||||
|
@ -78,7 +78,7 @@ export default class DeleteTune implements BlockTune {
|
|||
/**
|
||||
* Delete block conditions passed
|
||||
*
|
||||
* @param {MouseEvent} event
|
||||
* @param {MouseEvent} event - click event
|
||||
*/
|
||||
public handleClick(event: MouseEvent): void {
|
||||
/**
|
||||
|
@ -114,9 +114,9 @@ export default class DeleteTune implements BlockTune {
|
|||
/**
|
||||
* change tune state
|
||||
*
|
||||
* @param state
|
||||
* @param {boolean} state - delete confirmation state
|
||||
*/
|
||||
private setConfirmation(state): void {
|
||||
private setConfirmation(state: boolean): void {
|
||||
this.needConfirmation = state;
|
||||
this.nodes.button.classList.add(this.CSS.buttonConfirm);
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ export default class MoveDownTune implements BlockTune {
|
|||
/**
|
||||
* Property that contains Editor.js API methods
|
||||
*
|
||||
* @see {api.md}
|
||||
* @see {@link docs/api.md}
|
||||
*/
|
||||
private readonly api: API;
|
||||
|
||||
|
@ -33,7 +33,7 @@ export default class MoveDownTune implements BlockTune {
|
|||
/**
|
||||
* MoveDownTune constructor
|
||||
*
|
||||
* @param {{api: API}} api
|
||||
* @param {API} api — Editor's API
|
||||
*/
|
||||
constructor({ api }) {
|
||||
this.api = api;
|
||||
|
@ -41,8 +41,10 @@ export default class MoveDownTune implements BlockTune {
|
|||
|
||||
/**
|
||||
* Return 'move down' button
|
||||
*
|
||||
* @returns {HTMLElement}
|
||||
*/
|
||||
public render() {
|
||||
public render(): HTMLElement {
|
||||
const moveDownButton = $.make('div', [this.CSS.button, this.CSS.wrapper], {});
|
||||
|
||||
moveDownButton.appendChild($.svg('arrow-down', 14, 14));
|
||||
|
@ -64,10 +66,10 @@ export default class MoveDownTune implements BlockTune {
|
|||
/**
|
||||
* Handle clicks on 'move down' button
|
||||
*
|
||||
* @param {MouseEvent} event
|
||||
* @param {HTMLElement} button
|
||||
* @param {MouseEvent} event - click event
|
||||
* @param {HTMLElement} button - clicked button
|
||||
*/
|
||||
public handleClick(event: MouseEvent, button: HTMLElement) {
|
||||
public handleClick(event: MouseEvent, button: HTMLElement): void {
|
||||
const currentBlockIndex = this.api.blocks.getCurrentBlockIndex();
|
||||
|
||||
// If Block is last do nothing
|
||||
|
|
|
@ -14,7 +14,7 @@ export default class MoveUpTune implements BlockTune {
|
|||
/**
|
||||
* Property that contains Editor.js API methods
|
||||
*
|
||||
* @see {api.md}
|
||||
* @see {@link docs/api.md}
|
||||
*/
|
||||
private readonly api: API;
|
||||
|
||||
|
@ -32,7 +32,7 @@ export default class MoveUpTune implements BlockTune {
|
|||
/**
|
||||
* MoveUpTune constructor
|
||||
*
|
||||
* @param {{api: API}} api
|
||||
* @param {API} api - Editor's API
|
||||
*/
|
||||
constructor({ api }) {
|
||||
this.api = api;
|
||||
|
@ -41,7 +41,7 @@ export default class MoveUpTune implements BlockTune {
|
|||
/**
|
||||
* Create "MoveUp" button and add click event listener
|
||||
*
|
||||
* @returns [HTMLElement}
|
||||
* @returns {HTMLElement}
|
||||
*/
|
||||
public render(): HTMLElement {
|
||||
const moveUpButton = $.make('div', [this.CSS.button, this.CSS.wrapper], {});
|
||||
|
@ -65,8 +65,8 @@ export default class MoveUpTune implements BlockTune {
|
|||
/**
|
||||
* Move current block up
|
||||
*
|
||||
* @param {MouseEvent} event
|
||||
* @param {HTMLElement} button
|
||||
* @param {MouseEvent} event - click event
|
||||
* @param {HTMLElement} button - clicked button
|
||||
*/
|
||||
public handleClick(event: MouseEvent, button: HTMLElement): void {
|
||||
const currentBlockIndex = this.api.blocks.getCurrentBlockIndex();
|
||||
|
|
|
@ -47,10 +47,9 @@ export enum BlockToolAPI {
|
|||
/**
|
||||
* @classdesc Abstract Block class that contains Block information, Tool name and Tool class instance
|
||||
*
|
||||
* @property tool - Tool instance
|
||||
* @property html - Returns HTML content of plugin
|
||||
* @property holder - Div element that wraps block content with Tool's content. Has `ce-block` CSS class
|
||||
* @property pluginsContent - HTML content that returns by Tool's render function
|
||||
* @property {BlockTool} tool - Tool instance
|
||||
* @property {HTMLElement} holder - Div element that wraps block content with Tool's content. Has `ce-block` CSS class
|
||||
* @property {HTMLElement} pluginsContent - HTML content that returns by Tool's render function
|
||||
*/
|
||||
export default class Block {
|
||||
/**
|
||||
|
@ -58,7 +57,7 @@ export default class Block {
|
|||
*
|
||||
* @returns {{wrapper: string, content: string}}
|
||||
*/
|
||||
static get CSS() {
|
||||
public static get CSS(): {[name: string]: string} {
|
||||
return {
|
||||
wrapper: 'ce-block',
|
||||
wrapperStretched: 'ce-block--stretched',
|
||||
|
@ -69,259 +68,6 @@ export default class Block {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Find and return all editable elements (contenteditables and native inputs) in the Tool HTML
|
||||
*
|
||||
* @returns {HTMLElement[]}
|
||||
*/
|
||||
get inputs(): HTMLElement[] {
|
||||
/**
|
||||
* Return from cache if existed
|
||||
*/
|
||||
if (this.cachedInputs.length !== 0) {
|
||||
return this.cachedInputs;
|
||||
}
|
||||
|
||||
const content = this.holder;
|
||||
const allowedInputTypes = ['text', 'password', 'email', 'number', 'search', 'tel', 'url'];
|
||||
|
||||
const selector = '[contenteditable], textarea, input:not([type]), ' +
|
||||
allowedInputTypes.map((type) => `input[type="${type}"]`).join(', ');
|
||||
|
||||
let inputs = _.array(content.querySelectorAll(selector));
|
||||
|
||||
/**
|
||||
* If contenteditable element contains block elements, treat them as inputs.
|
||||
*/
|
||||
inputs = inputs.reduce((result, input) => {
|
||||
if ($.isNativeInput(input) || $.containsOnlyInlineElements(input)) {
|
||||
return [...result, input];
|
||||
}
|
||||
|
||||
return [...result, ...$.getDeepestBlockElements(input)];
|
||||
}, []);
|
||||
|
||||
/**
|
||||
* If inputs amount was changed we need to check if input index is bigger then inputs array length
|
||||
*/
|
||||
if (this.inputIndex > inputs.length - 1) {
|
||||
this.inputIndex = inputs.length - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cache inputs
|
||||
*/
|
||||
this.cachedInputs = inputs;
|
||||
|
||||
return inputs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return current Tool`s input
|
||||
*
|
||||
* @returns {HTMLElement}
|
||||
*/
|
||||
get currentInput(): HTMLElement | Node {
|
||||
return this.inputs[this.inputIndex];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set input index to the passed element
|
||||
*
|
||||
* @param {HTMLElement} element
|
||||
*/
|
||||
set currentInput(element: HTMLElement | Node) {
|
||||
const index = this.inputs.findIndex((input) => input === element || input.contains(element));
|
||||
|
||||
if (index !== -1) {
|
||||
this.inputIndex = index;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return first Tool`s input
|
||||
*
|
||||
* @returns {HTMLElement}
|
||||
*/
|
||||
get firstInput(): HTMLElement {
|
||||
return this.inputs[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return first Tool`s input
|
||||
*
|
||||
* @returns {HTMLElement}
|
||||
*/
|
||||
get lastInput(): HTMLElement {
|
||||
const inputs = this.inputs;
|
||||
|
||||
return inputs[inputs.length - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return next Tool`s input or undefined if it doesn't exist
|
||||
*
|
||||
* @returns {HTMLElement}
|
||||
*/
|
||||
get nextInput(): HTMLElement {
|
||||
return this.inputs[this.inputIndex + 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return previous Tool`s input or undefined if it doesn't exist
|
||||
*
|
||||
* @returns {HTMLElement}
|
||||
*/
|
||||
get previousInput(): HTMLElement {
|
||||
return this.inputs[this.inputIndex - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Plugins content
|
||||
*
|
||||
* @returns {HTMLElement}
|
||||
*/
|
||||
get pluginsContent(): HTMLElement {
|
||||
const blockContentNodes = this.holder.querySelector(`.${Block.CSS.content}`);
|
||||
|
||||
if (blockContentNodes && blockContentNodes.childNodes.length) {
|
||||
/**
|
||||
* Editors Block content can contain different Nodes from extensions
|
||||
* We use DOM isExtensionNode to ignore such Nodes and return first Block that does not match filtering list
|
||||
*/
|
||||
for (let child = blockContentNodes.childNodes.length - 1; child >= 0; child--) {
|
||||
const contentNode = blockContentNodes.childNodes[child];
|
||||
|
||||
if (!$.isExtensionNode(contentNode)) {
|
||||
return contentNode as HTMLElement;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Block's JSON data
|
||||
*
|
||||
* @returns {object}
|
||||
*/
|
||||
get data(): BlockToolData {
|
||||
return this.save().then((savedObject) => {
|
||||
if (savedObject && !_.isEmpty(savedObject.data)) {
|
||||
return savedObject.data;
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns tool's sanitizer config
|
||||
*
|
||||
* @returns {object}
|
||||
*/
|
||||
get sanitize(): SanitizerConfig {
|
||||
return this.tool.sanitize;
|
||||
}
|
||||
|
||||
/**
|
||||
* is block mergeable
|
||||
* We plugin have merge function then we call it mergable
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
get mergeable(): boolean {
|
||||
return typeof this.tool.merge === 'function';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check block for emptiness
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
get isEmpty(): boolean {
|
||||
const emptyText = $.isEmpty(this.pluginsContent);
|
||||
const emptyMedia = !this.hasMedia;
|
||||
|
||||
return emptyText && emptyMedia;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if block has a media content such as images, iframes and other
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
get hasMedia(): boolean {
|
||||
/**
|
||||
* This tags represents media-content
|
||||
*
|
||||
* @type {string[]}
|
||||
*/
|
||||
const mediaTags = [
|
||||
'img',
|
||||
'iframe',
|
||||
'video',
|
||||
'audio',
|
||||
'source',
|
||||
'input',
|
||||
'textarea',
|
||||
'twitterwidget',
|
||||
];
|
||||
|
||||
return !!this.holder.querySelector(mediaTags.join(','));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set focused state
|
||||
*
|
||||
* @param {boolean} state - 'true' to select, 'false' to remove selection
|
||||
*/
|
||||
set focused(state: boolean) {
|
||||
this.holder.classList.toggle(Block.CSS.focused, state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set selected state
|
||||
* We don't need to mark Block as Selected when it is empty
|
||||
*
|
||||
* @param {boolean} state - 'true' to select, 'false' to remove selection
|
||||
*/
|
||||
set selected(state: boolean) {
|
||||
if (state) {
|
||||
this.holder.classList.add(Block.CSS.selected);
|
||||
} else {
|
||||
this.holder.classList.remove(Block.CSS.selected);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns True if it is Selected
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
get selected(): boolean {
|
||||
return this.holder.classList.contains(Block.CSS.selected);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set stretched state
|
||||
*
|
||||
* @param {boolean} state - 'true' to enable, 'false' to disable stretched statte
|
||||
*/
|
||||
set stretched(state: boolean) {
|
||||
this.holder.classList.toggle(Block.CSS.wrapperStretched, state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle drop target state
|
||||
*
|
||||
* @param {boolean} state
|
||||
*/
|
||||
public set dropTarget(state) {
|
||||
this.holder.classList.toggle(Block.CSS.dropTarget, state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Block Tool`s name
|
||||
*/
|
||||
|
@ -432,15 +178,268 @@ export default class Block {
|
|||
this.tunes = this.makeTunes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find and return all editable elements (contenteditables and native inputs) in the Tool HTML
|
||||
*
|
||||
* @returns {HTMLElement[]}
|
||||
*/
|
||||
public get inputs(): HTMLElement[] {
|
||||
/**
|
||||
* Return from cache if existed
|
||||
*/
|
||||
if (this.cachedInputs.length !== 0) {
|
||||
return this.cachedInputs;
|
||||
}
|
||||
|
||||
const content = this.holder;
|
||||
const allowedInputTypes = ['text', 'password', 'email', 'number', 'search', 'tel', 'url'];
|
||||
|
||||
const selector = '[contenteditable], textarea, input:not([type]), ' +
|
||||
allowedInputTypes.map((type) => `input[type="${type}"]`).join(', ');
|
||||
|
||||
let inputs = _.array(content.querySelectorAll(selector));
|
||||
|
||||
/**
|
||||
* If contenteditable element contains block elements, treat them as inputs.
|
||||
*/
|
||||
inputs = inputs.reduce((result, input) => {
|
||||
if ($.isNativeInput(input) || $.containsOnlyInlineElements(input)) {
|
||||
return [...result, input];
|
||||
}
|
||||
|
||||
return [...result, ...$.getDeepestBlockElements(input)];
|
||||
}, []);
|
||||
|
||||
/**
|
||||
* If inputs amount was changed we need to check if input index is bigger then inputs array length
|
||||
*/
|
||||
if (this.inputIndex > inputs.length - 1) {
|
||||
this.inputIndex = inputs.length - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cache inputs
|
||||
*/
|
||||
this.cachedInputs = inputs;
|
||||
|
||||
return inputs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return current Tool`s input
|
||||
*
|
||||
* @returns {HTMLElement}
|
||||
*/
|
||||
public get currentInput(): HTMLElement | Node {
|
||||
return this.inputs[this.inputIndex];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set input index to the passed element
|
||||
*
|
||||
* @param {HTMLElement | Node} element - HTML Element to set as current input
|
||||
*/
|
||||
public set currentInput(element: HTMLElement | Node) {
|
||||
const index = this.inputs.findIndex((input) => input === element || input.contains(element));
|
||||
|
||||
if (index !== -1) {
|
||||
this.inputIndex = index;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return first Tool`s input
|
||||
*
|
||||
* @returns {HTMLElement}
|
||||
*/
|
||||
public get firstInput(): HTMLElement {
|
||||
return this.inputs[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return first Tool`s input
|
||||
*
|
||||
* @returns {HTMLElement}
|
||||
*/
|
||||
public get lastInput(): HTMLElement {
|
||||
const inputs = this.inputs;
|
||||
|
||||
return inputs[inputs.length - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return next Tool`s input or undefined if it doesn't exist
|
||||
*
|
||||
* @returns {HTMLElement}
|
||||
*/
|
||||
public get nextInput(): HTMLElement {
|
||||
return this.inputs[this.inputIndex + 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return previous Tool`s input or undefined if it doesn't exist
|
||||
*
|
||||
* @returns {HTMLElement}
|
||||
*/
|
||||
public get previousInput(): HTMLElement {
|
||||
return this.inputs[this.inputIndex - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Plugins content
|
||||
*
|
||||
* @returns {HTMLElement}
|
||||
*/
|
||||
public get pluginsContent(): HTMLElement {
|
||||
const blockContentNodes = this.holder.querySelector(`.${Block.CSS.content}`);
|
||||
|
||||
if (blockContentNodes && blockContentNodes.childNodes.length) {
|
||||
/**
|
||||
* Editors Block content can contain different Nodes from extensions
|
||||
* We use DOM isExtensionNode to ignore such Nodes and return first Block that does not match filtering list
|
||||
*/
|
||||
for (let child = blockContentNodes.childNodes.length - 1; child >= 0; child--) {
|
||||
const contentNode = blockContentNodes.childNodes[child];
|
||||
|
||||
if (!$.isExtensionNode(contentNode)) {
|
||||
return contentNode as HTMLElement;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Block's JSON data
|
||||
*
|
||||
* @returns {object}
|
||||
*/
|
||||
public get data(): BlockToolData {
|
||||
return this.save().then((savedObject) => {
|
||||
if (savedObject && !_.isEmpty(savedObject.data)) {
|
||||
return savedObject.data;
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns tool's sanitizer config
|
||||
*
|
||||
* @returns {object}
|
||||
*/
|
||||
public get sanitize(): SanitizerConfig {
|
||||
return this.tool.sanitize;
|
||||
}
|
||||
|
||||
/**
|
||||
* is block mergeable
|
||||
* We plugin have merge function then we call it mergable
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
public mergeable(): boolean {
|
||||
return typeof this.tool.merge === 'function';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check block for emptiness
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
public get isEmpty(): boolean {
|
||||
const emptyText = $.isEmpty(this.pluginsContent);
|
||||
const emptyMedia = !this.hasMedia;
|
||||
|
||||
return emptyText && emptyMedia;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if block has a media content such as images, iframes and other
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
public get hasMedia(): boolean {
|
||||
/**
|
||||
* This tags represents media-content
|
||||
*
|
||||
* @type {string[]}
|
||||
*/
|
||||
const mediaTags = [
|
||||
'img',
|
||||
'iframe',
|
||||
'video',
|
||||
'audio',
|
||||
'source',
|
||||
'input',
|
||||
'textarea',
|
||||
'twitterwidget',
|
||||
];
|
||||
|
||||
return !!this.holder.querySelector(mediaTags.join(','));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set focused state
|
||||
*
|
||||
* @param {boolean} state - 'true' to select, 'false' to remove selection
|
||||
*/
|
||||
public set focused(state: boolean) {
|
||||
this.holder.classList.toggle(Block.CSS.focused, state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set selected state
|
||||
* We don't need to mark Block as Selected when it is empty
|
||||
*
|
||||
* @param {boolean} state - 'true' to select, 'false' to remove selection
|
||||
*/
|
||||
public set selected(state: boolean) {
|
||||
if (state) {
|
||||
this.holder.classList.add(Block.CSS.selected);
|
||||
} else {
|
||||
this.holder.classList.remove(Block.CSS.selected);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns True if it is Selected
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
public get selected(): boolean {
|
||||
return this.holder.classList.contains(Block.CSS.selected);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set stretched state
|
||||
*
|
||||
* @param {boolean} state - 'true' to enable, 'false' to disable stretched statte
|
||||
*/
|
||||
public set stretched(state: boolean) {
|
||||
this.holder.classList.toggle(Block.CSS.wrapperStretched, state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle drop target state
|
||||
*
|
||||
* @param {boolean} state - 'true' if block is drop target, false otherwise
|
||||
*/
|
||||
public set dropTarget(state) {
|
||||
this.holder.classList.toggle(Block.CSS.dropTarget, state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls Tool's method
|
||||
*
|
||||
* Method checks tool property {MethodName}. Fires method with passes params If it is instance of Function
|
||||
*
|
||||
* @param {string} methodName
|
||||
* @param {object} params
|
||||
* @param {string} methodName - method to call
|
||||
* @param {object} params - method argument
|
||||
*/
|
||||
public call(methodName: string, params?: object) {
|
||||
public call(methodName: string, params?: object): void {
|
||||
/**
|
||||
* call Tool's method with the instance context
|
||||
*/
|
||||
|
@ -457,7 +456,7 @@ export default class Block {
|
|||
/**
|
||||
* Call plugins merge method
|
||||
*
|
||||
* @param {object} data
|
||||
* @param {BlockToolData} data - data to merge
|
||||
*/
|
||||
public async mergeWith(data: BlockToolData): Promise<void> {
|
||||
await this.tool.merge(data);
|
||||
|
@ -500,7 +499,7 @@ export default class Block {
|
|||
*
|
||||
* @description Method returns true|false whether data passed the validation or not
|
||||
*
|
||||
* @param {BlockToolData} data
|
||||
* @param {BlockToolData} data - data to validate
|
||||
* @returns {Promise<boolean>} valid
|
||||
*/
|
||||
public async validate(data: BlockToolData): Promise<boolean> {
|
||||
|
@ -574,7 +573,7 @@ export default class Block {
|
|||
/**
|
||||
* Is fired when Block will be unselected
|
||||
*/
|
||||
public willUnselect() {
|
||||
public willUnselect(): void {
|
||||
this.mutationObserver.disconnect();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import * as _ from './utils';
|
||||
import $ from './dom';
|
||||
import Block, { BlockToolAPI } from './block';
|
||||
import { MoveEvent, MoveEventDetail } from '../../types/tools';
|
||||
import { MoveEvent } from '../../types/tools';
|
||||
|
||||
/**
|
||||
* @class Blocks
|
||||
|
@ -13,6 +13,26 @@ import { MoveEvent, MoveEventDetail } from '../../types/tools';
|
|||
*
|
||||
*/
|
||||
export default class Blocks {
|
||||
/**
|
||||
* Array of Block instances in order of addition
|
||||
*/
|
||||
public blocks: Block[];
|
||||
|
||||
/**
|
||||
* Editor`s area where to add Block`s HTML
|
||||
*/
|
||||
public workingArea: HTMLElement;
|
||||
|
||||
/**
|
||||
* @class
|
||||
*
|
||||
* @param {HTMLElement} workingArea — editor`s working node
|
||||
*/
|
||||
constructor(workingArea: HTMLElement) {
|
||||
this.blocks = [];
|
||||
this.workingArea = workingArea;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get length of Block instances array
|
||||
*
|
||||
|
@ -47,11 +67,11 @@ export default class Blocks {
|
|||
* blocks[0] = new Block(...)
|
||||
*
|
||||
* @param {Blocks} instance — Blocks instance
|
||||
* @param {number|string} property — block index or any Blocks class property to set
|
||||
* @param {PropertyKey} property — block index or any Blocks class property key to set
|
||||
* @param {Block} value — value to set
|
||||
* @returns {boolean}
|
||||
*/
|
||||
public static set(instance: Blocks, property: number | string, value: Block | any) {
|
||||
public static set(instance: Blocks, property: PropertyKey, value: Block | unknown): boolean {
|
||||
/**
|
||||
* If property name is not a number (method or other property, access it via reflect
|
||||
*/
|
||||
|
@ -67,7 +87,7 @@ export default class Blocks {
|
|||
* @example
|
||||
* blocks[0] = new Block();
|
||||
*/
|
||||
instance.insert(+property, value);
|
||||
instance.insert(+(property as number), value as Block);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -76,10 +96,10 @@ export default class Blocks {
|
|||
* Proxy trap to implement array-like getter
|
||||
*
|
||||
* @param {Blocks} instance — Blocks instance
|
||||
* @param {number|string} property — Blocks class property
|
||||
* @param {PropertyKey} property — Blocks class property key
|
||||
* @returns {Block|*}
|
||||
*/
|
||||
public static get(instance: Blocks, property: any | number) {
|
||||
public static get(instance: Blocks, property: PropertyKey): Block | unknown {
|
||||
/**
|
||||
* If property is not a number, get it via Reflect object
|
||||
*/
|
||||
|
@ -90,33 +110,13 @@ export default class Blocks {
|
|||
/**
|
||||
* If property is a number (Block index) return Block by passed index
|
||||
*/
|
||||
return instance.get(+property);
|
||||
}
|
||||
|
||||
/**
|
||||
* Array of Block instances in order of addition
|
||||
*/
|
||||
public blocks: Block[];
|
||||
|
||||
/**
|
||||
* Editor`s area where to add Block`s HTML
|
||||
*/
|
||||
public workingArea: HTMLElement;
|
||||
|
||||
/**
|
||||
* @class
|
||||
*
|
||||
* @param {HTMLElement} workingArea — editor`s working node
|
||||
*/
|
||||
constructor(workingArea: HTMLElement) {
|
||||
this.blocks = [];
|
||||
this.workingArea = workingArea;
|
||||
return instance.get(+(property as number));
|
||||
}
|
||||
|
||||
/**
|
||||
* Push new Block to the blocks array and append it to working area
|
||||
*
|
||||
* @param {Block} block
|
||||
* @param {Block} block - Block to add
|
||||
*/
|
||||
public push(block: Block): void {
|
||||
this.blocks.push(block);
|
||||
|
@ -228,7 +228,7 @@ export default class Blocks {
|
|||
/**
|
||||
* Remove block
|
||||
*
|
||||
* @param {number|null} index
|
||||
* @param {number} index - index of Block to remove
|
||||
*/
|
||||
public remove(index: number): void {
|
||||
if (isNaN(index)) {
|
||||
|
@ -258,7 +258,7 @@ export default class Blocks {
|
|||
*
|
||||
* @todo decide if this method is necessary
|
||||
*
|
||||
* @param {Block} targetBlock — target after wich Block should be inserted
|
||||
* @param {Block} targetBlock — target after which Block should be inserted
|
||||
* @param {Block} newBlock — Block to insert
|
||||
*/
|
||||
public insertAfter(targetBlock: Block, newBlock: Block): void {
|
||||
|
@ -280,7 +280,7 @@ export default class Blocks {
|
|||
/**
|
||||
* Return index of passed Block
|
||||
*
|
||||
* @param {Block} block
|
||||
* @param {Block} block - Block to find
|
||||
* @returns {number}
|
||||
*/
|
||||
public indexOf(block: Block): number {
|
||||
|
@ -307,13 +307,12 @@ export default class Blocks {
|
|||
/**
|
||||
* Composes Block event with passed type and details
|
||||
*
|
||||
* @param {string} type
|
||||
* @param {MoveEventDetail} detail
|
||||
* @param {string} type - event type
|
||||
* @param {object} detail - event detail
|
||||
*/
|
||||
private composeBlockEvent(type: string, detail: MoveEventDetail): MoveEvent {
|
||||
private composeBlockEvent(type: string, detail: object): MoveEvent {
|
||||
return new CustomEvent(type, {
|
||||
detail,
|
||||
}
|
||||
) as MoveEvent;
|
||||
}) as MoveEvent;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
import $ from './dom';
|
||||
// eslint-disable-next-line import/no-duplicates
|
||||
import * as _ from './utils';
|
||||
// eslint-disable-next-line import/no-duplicates
|
||||
import { LogLevels } from './utils';
|
||||
import { EditorConfig, OutputData, SanitizerConfig } from '../../types';
|
||||
import { EditorModules } from '../types-internal/editor-modules';
|
||||
import { LogLevels } from './utils';
|
||||
|
||||
/**
|
||||
* @typedef {Core} Core - editor core class
|
||||
|
@ -31,8 +33,8 @@ contextRequire.keys().forEach((filename) => {
|
|||
*
|
||||
* @classdesc Editor.js core class
|
||||
*
|
||||
* @property this.config - all settings
|
||||
* @property this.moduleInstances - constructed editor components
|
||||
* @property {EditorConfig} config - all settings
|
||||
* @property {EditorModules} moduleInstances - constructed editor components
|
||||
*
|
||||
* @type {Core}
|
||||
*/
|
||||
|
@ -110,9 +112,9 @@ export default class Core {
|
|||
/**
|
||||
* Setting for configuration
|
||||
*
|
||||
* @param {EditorConfig|string|undefined} config
|
||||
* @param {EditorConfig|string} config - Editor's config to set
|
||||
*/
|
||||
set configuration(config: EditorConfig|string) {
|
||||
public set configuration(config: EditorConfig|string) {
|
||||
/**
|
||||
* Process zero-configuration or with only holderId
|
||||
* Make config object
|
||||
|
@ -185,8 +187,10 @@ export default class Core {
|
|||
this.config.hideToolbar = this.config.hideToolbar ? this.config.hideToolbar : false;
|
||||
this.config.tools = this.config.tools || {};
|
||||
this.config.data = this.config.data || {} as OutputData;
|
||||
this.config.onReady = this.config.onReady || (() => {});
|
||||
this.config.onChange = this.config.onChange || (() => {});
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
this.config.onReady = this.config.onReady || ((): void => {});
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
this.config.onChange = this.config.onChange || ((): void => {});
|
||||
|
||||
/**
|
||||
* Initialize Blocks to pass data to the Renderer
|
||||
|
@ -206,7 +210,7 @@ export default class Core {
|
|||
*
|
||||
* @returns {EditorConfig}
|
||||
*/
|
||||
get configuration(): EditorConfig|string {
|
||||
public get configuration(): EditorConfig|string {
|
||||
return this.config;
|
||||
}
|
||||
|
||||
|
@ -239,7 +243,7 @@ export default class Core {
|
|||
* - make and save instances
|
||||
* - configure
|
||||
*/
|
||||
public init() {
|
||||
public init(): void {
|
||||
/**
|
||||
* Make modules instances and save it to the @property this.moduleInstances
|
||||
*/
|
||||
|
@ -256,9 +260,9 @@ export default class Core {
|
|||
*
|
||||
* Get list of modules that needs to be prepared and return a sequence (Promise)
|
||||
*
|
||||
* @returns {Promise}
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public async start() {
|
||||
public async start(): Promise<void> {
|
||||
const modulesToPrepare = [
|
||||
'Tools',
|
||||
'UI',
|
||||
|
@ -327,7 +331,7 @@ export default class Core {
|
|||
*/
|
||||
private configureModules(): void {
|
||||
for (const name in this.moduleInstances) {
|
||||
if (this.moduleInstances.hasOwnProperty(name)) {
|
||||
if (Object.prototype.hasOwnProperty.call(this.moduleInstances, name)) {
|
||||
/**
|
||||
* Module does not need self-instance
|
||||
*/
|
||||
|
|
|
@ -5,7 +5,7 @@ export default class Dom {
|
|||
/**
|
||||
* Check if passed tag has no closed tag
|
||||
*
|
||||
* @param {HTMLElement} tag
|
||||
* @param {HTMLElement} tag - element to check
|
||||
* @returns {boolean}
|
||||
*/
|
||||
public static isSingleTag(tag: HTMLElement): boolean {
|
||||
|
@ -32,10 +32,10 @@ export default class Dom {
|
|||
/**
|
||||
* Check if element is BR or WBR
|
||||
*
|
||||
* @param {HTMLElement} element
|
||||
* @param {HTMLElement} element - element to check
|
||||
* @returns {boolean}
|
||||
*/
|
||||
public static isLineBreakTag(element: HTMLElement) {
|
||||
public static isLineBreakTag(element: HTMLElement): element is HTMLBRElement {
|
||||
return element && element.tagName && [
|
||||
'BR',
|
||||
'WBR',
|
||||
|
@ -45,9 +45,10 @@ export default class Dom {
|
|||
/**
|
||||
* Helper for making Elements with classname and attributes
|
||||
*
|
||||
* @param {string} tagName - new Element tag name
|
||||
* @param {Array|string} classNames - list or name of CSS classname(s)
|
||||
* @param {object} attributes - any attributes
|
||||
* @param {string} tagName - new Element tag name
|
||||
* @param {string[]|string} [classNames] - list or name of CSS classname(s)
|
||||
* @param {object} [attributes] - any attributes
|
||||
*
|
||||
* @returns {HTMLElement}
|
||||
*/
|
||||
public static make(tagName: string, classNames: string|string[] = null, attributes: object = {}): HTMLElement {
|
||||
|
@ -60,7 +61,7 @@ export default class Dom {
|
|||
}
|
||||
|
||||
for (const attrName in attributes) {
|
||||
if (attributes.hasOwnProperty(attrName)) {
|
||||
if (Object.prototype.hasOwnProperty.call(attributes, attrName)) {
|
||||
el[attrName] = attributes[attrName];
|
||||
}
|
||||
}
|
||||
|
@ -72,6 +73,7 @@ export default class Dom {
|
|||
* Creates Text Node with the passed content
|
||||
*
|
||||
* @param {string} content - text content
|
||||
*
|
||||
* @returns {Text}
|
||||
*/
|
||||
public static text(content: string): Text {
|
||||
|
@ -82,8 +84,9 @@ export default class Dom {
|
|||
* Creates SVG icon linked to the sprite
|
||||
*
|
||||
* @param {string} name - name (id) of icon from sprite
|
||||
* @param {number} width
|
||||
* @param {number} height
|
||||
* @param {number} [width] - icon width
|
||||
* @param {number} [height] - icon height
|
||||
*
|
||||
* @returns {SVGElement}
|
||||
*/
|
||||
public static svg(name: string, width = 14, height = 14): SVGElement {
|
||||
|
@ -100,8 +103,8 @@ export default class Dom {
|
|||
/**
|
||||
* Append one or several elements to the parent
|
||||
*
|
||||
* @param {Element|DocumentFragment} parent - where to append
|
||||
* @param {Element|Element[]|Text|Text[]} elements - element or elements list
|
||||
* @param {Element|DocumentFragment} parent - where to append
|
||||
* @param {Element|Element[]|DocumentFragment|Text|Text[]} elements - element or elements list
|
||||
*/
|
||||
public static append(
|
||||
parent: Element|DocumentFragment,
|
||||
|
@ -170,10 +173,10 @@ export default class Dom {
|
|||
/**
|
||||
* Get Element by Id
|
||||
*
|
||||
* @param {string} id
|
||||
* @param {string} id - id to find
|
||||
* @returns {HTMLElement | null}
|
||||
*/
|
||||
public static get(id: string): HTMLElement {
|
||||
public static get(id: string): HTMLElement | null {
|
||||
return document.getElementById(id);
|
||||
}
|
||||
|
||||
|
@ -182,8 +185,9 @@ export default class Dom {
|
|||
*
|
||||
* Returns all matches
|
||||
*
|
||||
* @param {Element} el - element we searching inside. Default - DOM Document
|
||||
* @param {Element|Document} el - element we searching inside. Default - DOM Document
|
||||
* @param {string} selector - searching string
|
||||
*
|
||||
* @returns {NodeList}
|
||||
*/
|
||||
public static findAll(el: Element|Document = document, selector: string): NodeList {
|
||||
|
@ -198,7 +202,8 @@ export default class Dom {
|
|||
*
|
||||
* @param {Node} node - root Node. From this vertex we start Deep-first search
|
||||
* {@link https://en.wikipedia.org/wiki/Depth-first_search}
|
||||
* @param {boolean} atLast - find last text node
|
||||
* @param {boolean} [atLast] - find last text node
|
||||
*
|
||||
* @returns {Node} - it can be text Node or Element Node, so that caret will able to work with it
|
||||
*/
|
||||
public static getDeepestNode(node: Node, atLast = false): Node {
|
||||
|
@ -250,9 +255,11 @@ export default class Dom {
|
|||
/**
|
||||
* Check if object is DOM node
|
||||
*
|
||||
* @param {object} node
|
||||
* @param {*} node - object to check
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
public static isElement(node: any): node is Element {
|
||||
return node && typeof node === 'object' && node.nodeType && node.nodeType === Node.ELEMENT_NODE;
|
||||
}
|
||||
|
@ -260,17 +267,19 @@ export default class Dom {
|
|||
/**
|
||||
* Check if object is DocumentFragmemt node
|
||||
*
|
||||
* @param {object} node
|
||||
* @param {object} node - object to check
|
||||
* @returns {boolean}
|
||||
*/
|
||||
public static isFragment(node: any): boolean {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
public static isFragment(node: any): node is DocumentFragment {
|
||||
return node && typeof node === 'object' && node.nodeType && node.nodeType === Node.DOCUMENT_FRAGMENT_NODE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if passed element is contenteditable
|
||||
*
|
||||
* @param {HTMLElement} element
|
||||
* @param {HTMLElement} element - html element to check
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
public static isContentEditable(element: HTMLElement): boolean {
|
||||
|
@ -280,10 +289,12 @@ export default class Dom {
|
|||
/**
|
||||
* Checks target if it is native input
|
||||
*
|
||||
* @param {Element|string|Node} target - HTML element or string
|
||||
* @param {*} target - HTML element or string
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
public static isNativeInput(target: any): boolean {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
public static isNativeInput(target: any): target is HTMLInputElement | HTMLTextAreaElement {
|
||||
const nativeInputs = [
|
||||
'INPUT',
|
||||
'TEXTAREA',
|
||||
|
@ -295,16 +306,15 @@ export default class Dom {
|
|||
/**
|
||||
* Checks if we can set caret
|
||||
*
|
||||
* @param {HTMLElement} target
|
||||
* @param {HTMLElement} target - target to check
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
public static canSetCaret(target: HTMLElement): boolean {
|
||||
let result = true;
|
||||
|
||||
if (Dom.isNativeInput(target)) {
|
||||
const inputElement = target as HTMLInputElement;
|
||||
|
||||
switch (inputElement.type) {
|
||||
switch (target.type) {
|
||||
case 'file':
|
||||
case 'checkbox':
|
||||
case 'radio':
|
||||
|
@ -329,7 +339,8 @@ export default class Dom {
|
|||
* @description Method checks simple Node without any childs for emptiness
|
||||
* If you have Node with 2 or more children id depth, you better use {@link Dom#isEmpty} method
|
||||
*
|
||||
* @param {Node} node
|
||||
* @param {Node} node - node to check
|
||||
*
|
||||
* @returns {boolean} true if it is empty
|
||||
*/
|
||||
public static isNodeEmpty(node: Node): boolean {
|
||||
|
@ -351,7 +362,8 @@ export default class Dom {
|
|||
/**
|
||||
* checks node if it is doesn't have any child nodes
|
||||
*
|
||||
* @param {Node} node
|
||||
* @param {Node} node - node to check
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
public static isLeaf(node: Node): boolean {
|
||||
|
@ -368,7 +380,7 @@ export default class Dom {
|
|||
*
|
||||
* @description Pushes to stack all DOM leafs and checks for emptiness
|
||||
*
|
||||
* @param {Node} node
|
||||
* @param {Node} node - node to check
|
||||
* @returns {boolean}
|
||||
*/
|
||||
public static isEmpty(node: Node): boolean {
|
||||
|
@ -414,7 +426,7 @@ export default class Dom {
|
|||
}
|
||||
|
||||
/**
|
||||
* If one of childs is not empty, checked Node is not empty too
|
||||
* If one of child is not empty, checked Node is not empty too
|
||||
*/
|
||||
if (node && !this.isNodeEmpty(node)) {
|
||||
return false;
|
||||
|
@ -427,8 +439,9 @@ export default class Dom {
|
|||
/**
|
||||
* Check if string contains html elements
|
||||
*
|
||||
* @param {string} str - string to check
|
||||
*
|
||||
* @returns {boolean}
|
||||
* @param {string} str
|
||||
*/
|
||||
public static isHTMLString(str: string): boolean {
|
||||
const wrapper = Dom.make('div');
|
||||
|
@ -441,7 +454,8 @@ export default class Dom {
|
|||
/**
|
||||
* Return length of node`s text content
|
||||
*
|
||||
* @param {Node} node
|
||||
* @param {Node} node - node with content
|
||||
*
|
||||
* @returns {number}
|
||||
*/
|
||||
public static getContentLength(node: Node): number {
|
||||
|
@ -461,7 +475,7 @@ export default class Dom {
|
|||
*
|
||||
* @returns {string[]}
|
||||
*/
|
||||
static get blockElements(): string[] {
|
||||
public static get blockElements(): string[] {
|
||||
return [
|
||||
'address',
|
||||
'article',
|
||||
|
@ -507,6 +521,7 @@ export default class Dom {
|
|||
* Check if passed content includes only inline elements
|
||||
*
|
||||
* @param {string|HTMLElement} data - element or html string
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
public static containsOnlyInlineElements(data: string | HTMLElement): boolean {
|
||||
|
@ -519,7 +534,7 @@ export default class Dom {
|
|||
wrapper = data;
|
||||
}
|
||||
|
||||
const check = (element: HTMLElement) => {
|
||||
const check = (element: HTMLElement): boolean => {
|
||||
return !Dom.blockElements.includes(element.tagName.toLowerCase()) &&
|
||||
Array.from(element.children).every(check);
|
||||
};
|
||||
|
@ -530,7 +545,7 @@ export default class Dom {
|
|||
/**
|
||||
* Find and return all block elements in the passed parent (including subtree)
|
||||
*
|
||||
* @param {HTMLElement} parent
|
||||
* @param {HTMLElement} parent - root element
|
||||
*
|
||||
* @returns {HTMLElement[]}
|
||||
*/
|
||||
|
@ -547,7 +562,9 @@ export default class Dom {
|
|||
/**
|
||||
* Helper for get holder from {string} or return HTMLElement
|
||||
*
|
||||
* @param element
|
||||
* @param {string | HTMLElement} element - holder's id or holder's HTML Element
|
||||
*
|
||||
* @returns {HTMLElement}
|
||||
*/
|
||||
public static getHolder(element: string | HTMLElement): HTMLElement {
|
||||
if (typeof element === 'string') {
|
||||
|
@ -561,6 +578,8 @@ export default class Dom {
|
|||
* Method checks passed Node if it is some extension Node
|
||||
*
|
||||
* @param {Node} node - any node
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
public static isExtensionNode(node: Node): boolean {
|
||||
const extensions = [
|
||||
|
@ -573,9 +592,11 @@ export default class Dom {
|
|||
/**
|
||||
* Returns true if element is anchor (is A tag)
|
||||
*
|
||||
* @param element
|
||||
* @param {Element} element - element to check
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
public static isAnchor(element: Element): boolean {
|
||||
public static isAnchor(element: Element): element is HTMLAnchorElement {
|
||||
return element.tagName.toLowerCase() === 'a';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,7 +61,7 @@ export default class DomIterator {
|
|||
/**
|
||||
* Sets items. Can be used when iterable items changed dynamically
|
||||
*
|
||||
* @param {HTMLElement[]} nodeList
|
||||
* @param {HTMLElement[]} nodeList - nodes to iterate
|
||||
*/
|
||||
public setItems(nodeList: HTMLElement[]): void {
|
||||
this.items = nodeList;
|
||||
|
|
|
@ -3,6 +3,8 @@ import * as _ from './utils';
|
|||
|
||||
/**
|
||||
* Flipper construction options
|
||||
*
|
||||
* @interface FlipperOptions
|
||||
*/
|
||||
export interface FlipperOptions {
|
||||
/**
|
||||
|
@ -66,7 +68,6 @@ export default class Flipper {
|
|||
* @class
|
||||
*
|
||||
* @param {FlipperOptions} options - different constructing settings
|
||||
* @
|
||||
*/
|
||||
constructor(options: FlipperOptions) {
|
||||
this.allowArrows = typeof options.allowArrows === 'boolean' ? options.allowArrows : true;
|
||||
|
@ -115,7 +116,7 @@ export default class Flipper {
|
|||
/**
|
||||
* Array of keys (codes) that is handled by Flipper
|
||||
* Used to:
|
||||
* - preventDefault only for this keys, not all keywdowns (@see constructor)
|
||||
* - preventDefault only for this keys, not all keydowns (@see constructor)
|
||||
* - to skip external behaviours only for these keys, when filler is activated (@see BlockEvents@arrowRightAndDown)
|
||||
*/
|
||||
public static get usedKeys(): number[] {
|
||||
|
@ -180,7 +181,7 @@ export default class Flipper {
|
|||
* This function is fired before handling flipper keycodes
|
||||
* The result of this function defines if it is need to be handled or not
|
||||
*
|
||||
* @param {KeyboardEvent} event
|
||||
* @param {KeyboardEvent} event - keydown keyboard event
|
||||
* @returns {boolean}
|
||||
*/
|
||||
private isEventReadyForHandling(event: KeyboardEvent): boolean {
|
||||
|
@ -208,7 +209,7 @@ export default class Flipper {
|
|||
/**
|
||||
* When flipper is activated tab press will leaf the items
|
||||
*
|
||||
* @param {KeyboardEvent} event
|
||||
* @param {KeyboardEvent} event - tab keydown event
|
||||
*/
|
||||
private handleTabPress(event: KeyboardEvent): void {
|
||||
/** this property defines leaf direction */
|
||||
|
@ -242,7 +243,7 @@ export default class Flipper {
|
|||
/**
|
||||
* Enter press will click current item if flipper is activated
|
||||
*
|
||||
* @param {KeyboardEvent} event
|
||||
* @param {KeyboardEvent} event - enter keydown event
|
||||
*/
|
||||
private handleEnterPress(event: KeyboardEvent): void {
|
||||
if (!this.activated) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import $ from '../dom';
|
||||
import { API, InlineTool, SanitizerConfig } from '../../../types';
|
||||
import { InlineTool, SanitizerConfig } from '../../../types';
|
||||
|
||||
/**
|
||||
* Bold Tool
|
||||
|
@ -27,7 +27,7 @@ export default class BoldInlineTool implements InlineTool {
|
|||
*
|
||||
* @returns {object}
|
||||
*/
|
||||
static get sanitize(): SanitizerConfig {
|
||||
public static get sanitize(): SanitizerConfig {
|
||||
return {
|
||||
b: {},
|
||||
} as SanitizerConfig;
|
||||
|
@ -69,7 +69,7 @@ export default class BoldInlineTool implements InlineTool {
|
|||
/**
|
||||
* Wrap range with <b> tag
|
||||
*
|
||||
* @param {Range} range
|
||||
* @param {Range} range - range to wrap
|
||||
*/
|
||||
public surround(range: Range): void {
|
||||
document.execCommand(this.commandName);
|
||||
|
@ -78,7 +78,9 @@ export default class BoldInlineTool implements InlineTool {
|
|||
/**
|
||||
* Check selection and set activated state to button if there are <b> tag
|
||||
*
|
||||
* @param {Selection} selection
|
||||
* @param {Selection} selection - selection to check
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
public checkState(selection: Selection): boolean {
|
||||
const isActive = document.queryCommandState(this.commandName);
|
||||
|
@ -90,6 +92,8 @@ export default class BoldInlineTool implements InlineTool {
|
|||
|
||||
/**
|
||||
* Set a shortcut
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
public get shortcut(): string {
|
||||
return 'CMD+B';
|
||||
|
|
|
@ -27,7 +27,7 @@ export default class ItalicInlineTool implements InlineTool {
|
|||
*
|
||||
* @returns {object}
|
||||
*/
|
||||
static get sanitize(): SanitizerConfig {
|
||||
public static get sanitize(): SanitizerConfig {
|
||||
return {
|
||||
i: {},
|
||||
} as SanitizerConfig;
|
||||
|
@ -69,7 +69,7 @@ export default class ItalicInlineTool implements InlineTool {
|
|||
/**
|
||||
* Wrap range with <i> tag
|
||||
*
|
||||
* @param {Range} range
|
||||
* @param {Range} range - range to wrap
|
||||
*/
|
||||
public surround(range: Range): void {
|
||||
document.execCommand(this.commandName);
|
||||
|
@ -78,7 +78,7 @@ export default class ItalicInlineTool implements InlineTool {
|
|||
/**
|
||||
* Check selection and set activated state to button if there are <i> tag
|
||||
*
|
||||
* @param {Selection} selection
|
||||
* @param {Selection} selection - selection to check
|
||||
*/
|
||||
public checkState(selection: Selection): boolean {
|
||||
const isActive = document.queryCommandState(this.commandName);
|
||||
|
|
|
@ -31,7 +31,7 @@ export default class LinkInlineTool implements InlineTool {
|
|||
*
|
||||
* @returns {object}
|
||||
*/
|
||||
static get sanitize(): SanitizerConfig {
|
||||
public static get sanitize(): SanitizerConfig {
|
||||
return {
|
||||
a: {
|
||||
href: true,
|
||||
|
@ -101,7 +101,7 @@ export default class LinkInlineTool implements InlineTool {
|
|||
private notifier: Notifier;
|
||||
|
||||
/**
|
||||
* @param {{api: API}} - Editor.js API
|
||||
* @param {API} api - Editor.js API
|
||||
*/
|
||||
constructor({ api }) {
|
||||
this.toolbar = api.toolbar;
|
||||
|
@ -142,7 +142,7 @@ export default class LinkInlineTool implements InlineTool {
|
|||
/**
|
||||
* Handle clicks on the Inline Toolbar icon
|
||||
*
|
||||
* @param {Range} range
|
||||
* @param {Range} range - range to wrap with link
|
||||
*/
|
||||
public surround(range: Range): void {
|
||||
/**
|
||||
|
@ -182,7 +182,7 @@ export default class LinkInlineTool implements InlineTool {
|
|||
/**
|
||||
* Check selection and set activated state to button if there are <a> tag
|
||||
*
|
||||
* @param {Selection} selection
|
||||
* @param {Selection} selection - selection to check
|
||||
*/
|
||||
public checkState(selection?: Selection): boolean {
|
||||
const anchorTag = this.selection.findParentTag('A');
|
||||
|
@ -275,7 +275,7 @@ export default class LinkInlineTool implements InlineTool {
|
|||
/**
|
||||
* Enter pressed on input
|
||||
*
|
||||
* @param {KeyboardEvent} event
|
||||
* @param {KeyboardEvent} event - enter keydown event
|
||||
*/
|
||||
private enterPressed(event: KeyboardEvent): void {
|
||||
let value = this.nodes.input.value || '';
|
||||
|
@ -318,7 +318,7 @@ export default class LinkInlineTool implements InlineTool {
|
|||
/**
|
||||
* Detects if passed string is URL
|
||||
*
|
||||
* @param {string} str
|
||||
* @param {string} str - string to validate
|
||||
* @returns {boolean}
|
||||
*/
|
||||
private validateURL(str: string): boolean {
|
||||
|
@ -345,7 +345,7 @@ export default class LinkInlineTool implements InlineTool {
|
|||
/**
|
||||
* Add 'http' protocol to the links like 'vc.ru', 'google.com'
|
||||
*
|
||||
* @param {string} link
|
||||
* @param {string} link - string to process
|
||||
*/
|
||||
private addProtocol(link: string): string {
|
||||
/**
|
||||
|
|
|
@ -14,19 +14,19 @@ export default class BlocksAPI extends Module {
|
|||
*
|
||||
* @returns {Blocks}
|
||||
*/
|
||||
get methods(): Blocks {
|
||||
public get methods(): Blocks {
|
||||
return {
|
||||
clear: () => this.clear(),
|
||||
render: (data: OutputData) => this.render(data),
|
||||
renderFromHTML: (data: string) => this.renderFromHTML(data),
|
||||
delete: () => this.delete(),
|
||||
swap: (fromIndex: number, toIndex: number) => this.swap(fromIndex, toIndex),
|
||||
move: (toIndex: number, fromIndex?: number) => this.move(toIndex, fromIndex),
|
||||
getBlockByIndex: (index: number) => this.getBlockByIndex(index),
|
||||
getCurrentBlockIndex: () => this.getCurrentBlockIndex(),
|
||||
getBlocksCount: () => this.getBlocksCount(),
|
||||
stretchBlock: (index: number, status = true) => this.stretchBlock(index, status),
|
||||
insertNewBlock: () => this.insertNewBlock(),
|
||||
clear: (): void => this.clear(),
|
||||
render: (data: OutputData): Promise<void> => this.render(data),
|
||||
renderFromHTML: (data: string): Promise<void> => this.renderFromHTML(data),
|
||||
delete: (): void => this.delete(),
|
||||
swap: (fromIndex: number, toIndex: number): void => this.swap(fromIndex, toIndex),
|
||||
move: (toIndex: number, fromIndex?: number): void => this.move(toIndex, fromIndex),
|
||||
getBlockByIndex: (index: number): HTMLElement => this.getBlockByIndex(index),
|
||||
getCurrentBlockIndex: (): number => this.getCurrentBlockIndex(),
|
||||
getBlocksCount: (): number => this.getBlocksCount(),
|
||||
stretchBlock: (index: number, status = true): void => this.stretchBlock(index, status),
|
||||
insertNewBlock: (): void => this.insertNewBlock(),
|
||||
insert: this.insert,
|
||||
};
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ export default class BlocksAPI extends Module {
|
|||
/**
|
||||
* Returns Block holder by Block index
|
||||
*
|
||||
* @param {number} index
|
||||
* @param {number} index - index to get
|
||||
*
|
||||
* @returns {HTMLElement}
|
||||
*/
|
||||
|
@ -82,8 +82,8 @@ export default class BlocksAPI extends Module {
|
|||
/**
|
||||
* Move block from one index to another
|
||||
*
|
||||
* @param {number} toIndex
|
||||
* @param {number} fromIndex
|
||||
* @param {number} toIndex - index to move to
|
||||
* @param {number} fromIndex - index to move from
|
||||
*/
|
||||
public move(toIndex: number, fromIndex?: number): void {
|
||||
this.Editor.BlockManager.move(toIndex, fromIndex);
|
||||
|
@ -98,7 +98,7 @@ export default class BlocksAPI extends Module {
|
|||
/**
|
||||
* Deletes Block
|
||||
*
|
||||
* @param blockIndex
|
||||
* @param {number} blockIndex - index of Block to delete
|
||||
*/
|
||||
public delete(blockIndex?: number): void {
|
||||
this.Editor.BlockManager.removeBlock(blockIndex);
|
||||
|
@ -141,7 +141,7 @@ export default class BlocksAPI extends Module {
|
|||
/**
|
||||
* Render passed HTML string
|
||||
*
|
||||
* @param {string} data
|
||||
* @param {string} data - HTML string to render
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public renderFromHTML(data: string): Promise<void> {
|
||||
|
@ -153,7 +153,7 @@ export default class BlocksAPI extends Module {
|
|||
/**
|
||||
* Stretch Block's content
|
||||
*
|
||||
* @param {number} index
|
||||
* @param {number} index - index of Block to stretch
|
||||
* @param {boolean} status - true to enable, false to disable
|
||||
*/
|
||||
public stretchBlock(index: number, status = true): void {
|
||||
|
@ -189,13 +189,13 @@ export default class BlocksAPI extends Module {
|
|||
index,
|
||||
needToFocus
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Insert new Block
|
||||
* After set caret to this Block
|
||||
*
|
||||
* @todo: remove in 3.0.0
|
||||
* @todo remove in 3.0.0
|
||||
*
|
||||
* @deprecated with insert() method
|
||||
*/
|
||||
|
|
|
@ -11,7 +11,7 @@ export default class CaretAPI extends Module {
|
|||
*
|
||||
* @returns {Caret}
|
||||
*/
|
||||
get methods(): Caret {
|
||||
public get methods(): Caret {
|
||||
return {
|
||||
setToFirstBlock: this.setToFirstBlock,
|
||||
setToLastBlock: this.setToLastBlock,
|
||||
|
@ -127,7 +127,7 @@ export default class CaretAPI extends Module {
|
|||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
private focus = (atEnd = false) => {
|
||||
private focus = (atEnd = false): boolean => {
|
||||
if (atEnd) {
|
||||
return this.setToLastBlock(this.Editor.Caret.positions.END);
|
||||
}
|
||||
|
|
|
@ -11,19 +11,19 @@ export default class EventsAPI extends Module {
|
|||
*
|
||||
* @returns {Events}
|
||||
*/
|
||||
get methods(): Events {
|
||||
public get methods(): Events {
|
||||
return {
|
||||
emit: (eventName: string, data: object) => this.emit(eventName, data),
|
||||
off: (eventName: string, callback: () => void) => this.off(eventName, callback),
|
||||
on: (eventName: string, callback: () => void) => this.on(eventName, callback),
|
||||
emit: (eventName: string, data: object): void => this.emit(eventName, data),
|
||||
off: (eventName: string, callback: () => void): void => this.off(eventName, callback),
|
||||
on: (eventName: string, callback: () => void): void => this.on(eventName, callback),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscribe on Events
|
||||
*
|
||||
* @param {string} eventName
|
||||
* @param {Function} callback
|
||||
* @param {string} eventName - event name to subscribe
|
||||
* @param {Function} callback - event handler
|
||||
*/
|
||||
public on(eventName, callback): void {
|
||||
this.Editor.Events.on(eventName, callback);
|
||||
|
@ -32,8 +32,8 @@ export default class EventsAPI extends Module {
|
|||
/**
|
||||
* Emit event with data
|
||||
*
|
||||
* @param {string} eventName
|
||||
* @param {object} data
|
||||
* @param {string} eventName - event to emit
|
||||
* @param {object} data - event's data
|
||||
*/
|
||||
public emit(eventName, data): void {
|
||||
this.Editor.Events.emit(eventName, data);
|
||||
|
@ -42,8 +42,8 @@ export default class EventsAPI extends Module {
|
|||
/**
|
||||
* Unsubscribe from Event
|
||||
*
|
||||
* @param {string} eventName
|
||||
* @param {Function} callback
|
||||
* @param {string} eventName - event to unsubscribe
|
||||
* @param {Function} callback - event handler
|
||||
*/
|
||||
public off(eventName, callback): void {
|
||||
this.Editor.Events.off(eventName, callback);
|
||||
|
|
|
@ -11,10 +11,10 @@ export default class InlineToolbarAPI extends Module {
|
|||
*
|
||||
* @returns {InlineToolbar}
|
||||
*/
|
||||
get methods(): InlineToolbar {
|
||||
public get methods(): InlineToolbar {
|
||||
return {
|
||||
close: () => this.close(),
|
||||
open: () => this.open(),
|
||||
close: (): void => this.close(),
|
||||
open: (): void => this.open(),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -11,20 +11,20 @@ export default class ListenersAPI extends Module {
|
|||
*
|
||||
* @returns {Listeners}
|
||||
*/
|
||||
get methods(): Listeners {
|
||||
public get methods(): Listeners {
|
||||
return {
|
||||
on: (element: HTMLElement, eventType, handler, useCapture) => this.on(element, eventType, handler, useCapture),
|
||||
off: (element, eventType, handler) => this.off(element, eventType, handler),
|
||||
on: (element: HTMLElement, eventType, handler, useCapture): void => this.on(element, eventType, handler, useCapture),
|
||||
off: (element, eventType, handler, useCapture): void => this.off(element, eventType, handler, useCapture),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* adds DOM event listener
|
||||
*
|
||||
* @param {HTMLElement} element
|
||||
* @param {string} eventType
|
||||
* @param {() => void} handler
|
||||
* @param {boolean} useCapture
|
||||
* @param {HTMLElement} element - Element to set handler to
|
||||
* @param {string} eventType - event type
|
||||
* @param {() => void} handler - event handler
|
||||
* @param {boolean} useCapture - capture event or not
|
||||
*/
|
||||
public on(element: HTMLElement, eventType: string, handler: () => void, useCapture?: boolean): void {
|
||||
this.Editor.Listeners.on(element, eventType, handler, useCapture);
|
||||
|
@ -33,11 +33,12 @@ export default class ListenersAPI extends Module {
|
|||
/**
|
||||
* Removes DOM listener from element
|
||||
*
|
||||
* @param element
|
||||
* @param eventType
|
||||
* @param handler
|
||||
* @param {Element} element - Element to remove handler from
|
||||
* @param eventType - event type
|
||||
* @param handler - event handler
|
||||
* @param {boolean} useCapture - capture event or not
|
||||
*/
|
||||
public off(element, eventType, handler): void {
|
||||
this.Editor.Listeners.off(element, eventType, handler);
|
||||
public off(element: Element, eventType: string, handler: () => void, useCapture?: boolean): void {
|
||||
this.Editor.Listeners.off(element, eventType, handler, useCapture);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,15 +9,16 @@ export default class NotifierAPI extends Module {
|
|||
/**
|
||||
* Available methods
|
||||
*/
|
||||
get methods(): Notifier {
|
||||
public get methods(): Notifier {
|
||||
return {
|
||||
show: (options: NotifierOptions | ConfirmNotifierOptions | PromptNotifierOptions) => this.show(options),
|
||||
show: (options: NotifierOptions | ConfirmNotifierOptions | PromptNotifierOptions): void => this.show(options),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Show notification
|
||||
* @param options
|
||||
*
|
||||
* @param {NotifierOptions} options - message option
|
||||
*/
|
||||
public show(options: NotifierOptions | ConfirmNotifierOptions | PromptNotifierOptions): void {
|
||||
return this.Editor.Notifier.show(options);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import Module from '../../__module';
|
||||
import { Sanitizer } from '../../../../types/api';
|
||||
import { SanitizerConfig } from '../../../../types/configs';
|
||||
|
||||
/**
|
||||
* @class SanitizerAPI
|
||||
|
@ -11,18 +12,21 @@ export default class SanitizerAPI extends Module {
|
|||
*
|
||||
* @returns {Sanitizer}
|
||||
*/
|
||||
get methods(): Sanitizer {
|
||||
public get methods(): Sanitizer {
|
||||
return {
|
||||
clean: (taintString, config) => this.clean(taintString, config),
|
||||
clean: (taintString, config): string => this.clean(taintString, config),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform sanitizing of a string
|
||||
* @param taintString - what to sanitize
|
||||
* @param config - sanitizer config
|
||||
*
|
||||
* @param {string} taintString - what to sanitize
|
||||
* @param {SanitizerConfig} config - sanitizer config
|
||||
*
|
||||
* @returns {string}
|
||||
*/
|
||||
public clean(taintString, config) {
|
||||
public clean(taintString: string, config: SanitizerConfig): string {
|
||||
return this.Editor.Sanitizer.clean(taintString, config);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,9 +12,9 @@ export default class SaverAPI extends Module {
|
|||
*
|
||||
* @returns {Saver}
|
||||
*/
|
||||
get methods(): Saver {
|
||||
public get methods(): Saver {
|
||||
return {
|
||||
save: () => this.save(),
|
||||
save: (): Promise<OutputData> => this.save(),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -14,8 +14,8 @@ export default class SelectionAPI extends Module {
|
|||
*/
|
||||
public get methods(): SelectionAPIInterface {
|
||||
return {
|
||||
findParentTag: (tagName: string, className?: string) => this.findParentTag(tagName, className),
|
||||
expandToTag: (node: HTMLElement) => this.expandToTag(node),
|
||||
findParentTag: (tagName: string, className?: string): HTMLElement | null => this.findParentTag(tagName, className),
|
||||
expandToTag: (node: HTMLElement): void => this.expandToTag(node),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -24,9 +24,10 @@ export default class SelectionAPI extends Module {
|
|||
*
|
||||
* @param {string} tagName - tag to find
|
||||
* @param {string} className - tag's class name
|
||||
*
|
||||
* @returns {HTMLElement|null}
|
||||
*/
|
||||
public findParentTag(tagName: string, className?: string): HTMLElement|null {
|
||||
public findParentTag(tagName: string, className?: string): HTMLElement | null {
|
||||
return new SelectionUtils().findParentTag(tagName, className);
|
||||
}
|
||||
|
||||
|
|
|
@ -11,10 +11,10 @@ export default class ToolbarAPI extends Module {
|
|||
*
|
||||
* @returns {Toolbar}
|
||||
*/
|
||||
get methods(): Toolbar {
|
||||
public get methods(): Toolbar {
|
||||
return {
|
||||
close: () => this.close(),
|
||||
open: () => this.open(),
|
||||
close: (): void => this.close(),
|
||||
open: (): void => this.open(),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -10,46 +10,46 @@ export default class TooltipAPI extends Module {
|
|||
/**
|
||||
* Available methods
|
||||
*/
|
||||
get methods(): Tooltip {
|
||||
public get methods(): Tooltip {
|
||||
return {
|
||||
show: (element: HTMLElement,
|
||||
content: TooltipContent,
|
||||
options?: TooltipOptions
|
||||
) => this.show(element, content, options),
|
||||
hide: () => this.hide(),
|
||||
): void => this.show(element, content, options),
|
||||
hide: (): void => this.hide(),
|
||||
onHover: (element: HTMLElement,
|
||||
content: TooltipContent,
|
||||
options?: TooltipOptions
|
||||
) => this.onHover(element, content, options),
|
||||
): void => this.onHover(element, content, options),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Method show tooltip on element with passed HTML content
|
||||
*
|
||||
* @param {HTMLElement} element
|
||||
* @param {TooltipContent} content
|
||||
* @param {TooltipOptions} options
|
||||
* @param {HTMLElement} element - element on which tooltip should be shown
|
||||
* @param {TooltipContent} content - tooltip content
|
||||
* @param {TooltipOptions} options - tooltip options
|
||||
*/
|
||||
public show(element: HTMLElement, content: TooltipContent, options?: TooltipOptions) {
|
||||
public show(element: HTMLElement, content: TooltipContent, options?: TooltipOptions): void {
|
||||
this.Editor.Tooltip.show(element, content, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method hides tooltip on HTML page
|
||||
*/
|
||||
public hide() {
|
||||
public hide(): void {
|
||||
this.Editor.Tooltip.hide();
|
||||
}
|
||||
|
||||
/**
|
||||
* Decorator for showing Tooltip by mouseenter/mouseleave
|
||||
*
|
||||
* @param {HTMLElement} element
|
||||
* @param {TooltipContent} content
|
||||
* @param {TooltipOptions} options
|
||||
* @param {HTMLElement} element - element on which tooltip should be shown
|
||||
* @param {TooltipContent} content - tooltip content
|
||||
* @param {TooltipOptions} options - tooltip options
|
||||
*/
|
||||
public onHover(element: HTMLElement, content: TooltipContent, options?: TooltipOptions) {
|
||||
public onHover(element: HTMLElement, content: TooltipContent, options?: TooltipOptions): void {
|
||||
this.Editor.Tooltip.onHover(element, content, options);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -95,7 +95,7 @@ export default class BlockEvents extends Module {
|
|||
* - shows Inline Toolbar if something selected
|
||||
* - shows conversion toolbar with 85% of block selection
|
||||
*
|
||||
* @param event
|
||||
* @param {KeyboardEvent} event - keyup event
|
||||
*/
|
||||
public keyup(event): void {
|
||||
/**
|
||||
|
@ -114,7 +114,7 @@ export default class BlockEvents extends Module {
|
|||
/**
|
||||
* Set up mouse selection handlers
|
||||
*
|
||||
* @param {MouseEvent} event
|
||||
* @param {MouseEvent} event - mouse down event
|
||||
*/
|
||||
public mouseDown(event: MouseEvent): void {
|
||||
/**
|
||||
|
@ -129,7 +129,7 @@ export default class BlockEvents extends Module {
|
|||
/**
|
||||
* Open Toolbox to leaf Tools
|
||||
*
|
||||
* @param {KeyboardEvent} event
|
||||
* @param {KeyboardEvent} event - tab keydown event
|
||||
*/
|
||||
public tabPressed(event): void {
|
||||
/**
|
||||
|
@ -162,7 +162,7 @@ export default class BlockEvents extends Module {
|
|||
* Escape pressed
|
||||
* If some of Toolbar components are opened, then close it otherwise close Toolbar
|
||||
*
|
||||
* @param {Event} event
|
||||
* @param {Event} event - escape keydown event
|
||||
*/
|
||||
public escapePressed(event): void {
|
||||
/**
|
||||
|
@ -186,9 +186,9 @@ export default class BlockEvents extends Module {
|
|||
/**
|
||||
* Add drop target styles
|
||||
*
|
||||
* @param {DragEvent} e
|
||||
* @param {DragEvent} e - drag over event
|
||||
*/
|
||||
public dragOver(e: DragEvent) {
|
||||
public dragOver(e: DragEvent): void {
|
||||
const block = this.Editor.BlockManager.getBlockByChildNode(e.target as Node);
|
||||
|
||||
block.dropTarget = true;
|
||||
|
@ -197,9 +197,9 @@ export default class BlockEvents extends Module {
|
|||
/**
|
||||
* Remove drop target style
|
||||
*
|
||||
* @param {DragEvent} e
|
||||
* @param {DragEvent} e - drag leave event
|
||||
*/
|
||||
public dragLeave(e: DragEvent) {
|
||||
public dragLeave(e: DragEvent): void {
|
||||
const block = this.Editor.BlockManager.getBlockByChildNode(e.target as Node);
|
||||
|
||||
block.dropTarget = false;
|
||||
|
@ -209,7 +209,7 @@ export default class BlockEvents extends Module {
|
|||
* Copying selected blocks
|
||||
* Before putting to the clipboard we sanitize all blocks and then copy to the clipboard
|
||||
*
|
||||
* @param {ClipboardEvent} event
|
||||
* @param {ClipboardEvent} event - clipboard event
|
||||
*/
|
||||
public handleCommandC(event: ClipboardEvent): void {
|
||||
const { BlockSelection } = this.Editor;
|
||||
|
@ -225,7 +225,7 @@ export default class BlockEvents extends Module {
|
|||
/**
|
||||
* Copy and Delete selected Blocks
|
||||
*
|
||||
* @param {ClipboardEvent} event
|
||||
* @param {ClipboardEvent} event - clipboard event
|
||||
*/
|
||||
public handleCommandX(event: ClipboardEvent): void {
|
||||
const { BlockSelection, BlockManager, Caret } = this.Editor;
|
||||
|
@ -325,7 +325,7 @@ export default class BlockEvents extends Module {
|
|||
/**
|
||||
* Check if Block should be removed by current Backspace keydown
|
||||
*/
|
||||
if (currentBlock.selected || currentBlock.isEmpty && currentBlock.currentInput === currentBlock.firstInput) {
|
||||
if (currentBlock.selected || (currentBlock.isEmpty && currentBlock.currentInput === currentBlock.firstInput)) {
|
||||
event.preventDefault();
|
||||
|
||||
const index = BlockManager.currentBlockIndex;
|
||||
|
@ -384,7 +384,7 @@ export default class BlockEvents extends Module {
|
|||
/**
|
||||
* Merge current and previous Blocks if they have the same type
|
||||
*/
|
||||
private mergeBlocks() {
|
||||
private mergeBlocks(): void {
|
||||
const { BlockManager, Caret, Toolbar } = this.Editor;
|
||||
const targetBlock = BlockManager.previousBlock;
|
||||
const blockToMerge = BlockManager.currentBlock;
|
||||
|
@ -427,7 +427,7 @@ export default class BlockEvents extends Module {
|
|||
/**
|
||||
* Handle right and down keyboard keys
|
||||
*
|
||||
* @param event
|
||||
* @param {KeyboardEvent} event - keyboard event
|
||||
*/
|
||||
private arrowRightAndDown(event: KeyboardEvent): void {
|
||||
const isFlipperCombination = Flipper.usedKeys.includes(event.keyCode) &&
|
||||
|
@ -481,7 +481,7 @@ export default class BlockEvents extends Module {
|
|||
/**
|
||||
* Handle left and up keyboard keys
|
||||
*
|
||||
* @param event
|
||||
* @param {KeyboardEvent} event - keyboard event
|
||||
*/
|
||||
private arrowLeftAndUp(event: KeyboardEvent): void {
|
||||
/**
|
||||
|
@ -536,9 +536,9 @@ export default class BlockEvents extends Module {
|
|||
/**
|
||||
* Cases when we need to close Toolbar
|
||||
*
|
||||
* @param event
|
||||
* @param {KeyboardEvent} event - keyboard event
|
||||
*/
|
||||
private needToolbarClosing(event) {
|
||||
private needToolbarClosing(event: KeyboardEvent): boolean {
|
||||
const toolboxItemSelected = (event.keyCode === _.keyCodes.ENTER && this.Editor.Toolbox.opened),
|
||||
blockSettingsItemSelected = (event.keyCode === _.keyCodes.ENTER && this.Editor.BlockSettings.opened),
|
||||
inlineToolbarItemSelected = (event.keyCode === _.keyCodes.ENTER && this.Editor.InlineToolbar.opened),
|
||||
|
|
|
@ -31,7 +31,7 @@ export default class BlockManager extends Module {
|
|||
/**
|
||||
* Set current Block index and fire Block lifecycle callbacks
|
||||
*
|
||||
* @param newIndex
|
||||
* @param {number} newIndex - index of Block to set as current
|
||||
*/
|
||||
public set currentBlockIndex(newIndex: number) {
|
||||
if (this._blocks[this._currentBlockIndex]) {
|
||||
|
@ -163,7 +163,7 @@ export default class BlockManager extends Module {
|
|||
*
|
||||
* @returns {Promise}
|
||||
*/
|
||||
public async prepare() {
|
||||
public async prepare(): Promise<void> {
|
||||
const blocks = new Blocks(this.Editor.UI.nodes.redactor);
|
||||
const { BlockEvents, Listeners } = this.Editor;
|
||||
|
||||
|
@ -252,7 +252,7 @@ export default class BlockManager extends Module {
|
|||
/**
|
||||
* Insert pasted content. Call onPaste callback after insert.
|
||||
*
|
||||
* @param {string} toolName
|
||||
* @param {string} toolName - name of Tool to insert
|
||||
* @param {PasteEvent} pasteEvent - pasted data
|
||||
* @param {boolean} replace - should replace current block
|
||||
*/
|
||||
|
@ -288,7 +288,7 @@ export default class BlockManager extends Module {
|
|||
*
|
||||
* @returns {Block} inserted Block
|
||||
*/
|
||||
public insertInitialBlockAtIndex(index: number, needToFocus = false) {
|
||||
public insertInitialBlockAtIndex(index: number, needToFocus = false): Block {
|
||||
const block = this.composeBlock(this.config.initialBlock, {}, {});
|
||||
|
||||
this._blocks[index] = block;
|
||||
|
@ -347,7 +347,7 @@ export default class BlockManager extends Module {
|
|||
/**
|
||||
* Remove block with passed index or remove last
|
||||
*
|
||||
* @param {number|null} index
|
||||
* @param {number|null} index - index of Block to remove
|
||||
*/
|
||||
public removeBlock(index?: number): void {
|
||||
if (index === undefined) {
|
||||
|
@ -374,7 +374,7 @@ export default class BlockManager extends Module {
|
|||
* Remove only selected Blocks
|
||||
* and returns first Block index where started removing...
|
||||
*
|
||||
* @returns number|undefined
|
||||
* @returns {number|undefined}
|
||||
*/
|
||||
public removeSelectedBlocks(): number|undefined {
|
||||
let firstSelectedBlockIndex;
|
||||
|
@ -461,7 +461,8 @@ export default class BlockManager extends Module {
|
|||
/**
|
||||
* Returns Block by passed index
|
||||
*
|
||||
* @param {number} index
|
||||
* @param {number} index - index to get
|
||||
*
|
||||
* @returns {Block}
|
||||
*/
|
||||
public getBlockByIndex(index): Block {
|
||||
|
@ -471,7 +472,8 @@ export default class BlockManager extends Module {
|
|||
/**
|
||||
* Get Block instance by html element
|
||||
*
|
||||
* @param {Node} element
|
||||
* @param {Node} element - html element to get Block by
|
||||
*
|
||||
* @returns {Block}
|
||||
*/
|
||||
public getBlock(element: HTMLElement): Block {
|
||||
|
@ -519,7 +521,7 @@ export default class BlockManager extends Module {
|
|||
* 2) Mark it as current
|
||||
*
|
||||
* @param {Node} childNode - look ahead from this node.
|
||||
* @param {string} caretPosition - position where to set caret
|
||||
*
|
||||
* @throws Error - when passed Node is not included at the Block
|
||||
*/
|
||||
public setCurrentBlockByChildNode(childNode: Node): Block {
|
||||
|
@ -549,7 +551,8 @@ export default class BlockManager extends Module {
|
|||
/**
|
||||
* Return block which contents passed node
|
||||
*
|
||||
* @param {Node} childNode
|
||||
* @param {Node} childNode - node to get Block by
|
||||
*
|
||||
* @returns {Block}
|
||||
*/
|
||||
public getBlockByChildNode(childNode: Node): Block {
|
||||
|
@ -568,8 +571,9 @@ export default class BlockManager extends Module {
|
|||
/**
|
||||
* Swap Blocks Position
|
||||
*
|
||||
* @param {number} fromIndex
|
||||
* @param {number} toIndex
|
||||
* @param {number} fromIndex - index of first block
|
||||
* @param {number} toIndex - index of second block
|
||||
*
|
||||
* @deprecated — use 'move' instead
|
||||
*/
|
||||
public swap(fromIndex, toIndex): void {
|
||||
|
@ -583,8 +587,8 @@ export default class BlockManager extends Module {
|
|||
/**
|
||||
* Move a block to a new index
|
||||
*
|
||||
* @param {number} toIndex
|
||||
* @param {number} fromIndex
|
||||
* @param {number} toIndex - index where to move Block
|
||||
* @param {number} fromIndex - index of Block to move
|
||||
*/
|
||||
public move(toIndex, fromIndex = this.currentBlockIndex): void {
|
||||
// make sure indexes are valid and within a valid range
|
||||
|
@ -640,7 +644,7 @@ export default class BlockManager extends Module {
|
|||
/**
|
||||
* Bind Events
|
||||
*
|
||||
* @param {object} block
|
||||
* @param {Block} block - Block to which event should be bound
|
||||
*/
|
||||
private bindEvents(block: Block): void {
|
||||
const { BlockEvents, Listeners } = this.Editor;
|
||||
|
@ -656,12 +660,10 @@ export default class BlockManager extends Module {
|
|||
* Validates that the given index is not lower than 0 or higher than the amount of blocks
|
||||
*
|
||||
* @param {number} index - index of blocks array to validate
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
private validateIndex(index: number): boolean {
|
||||
if (index < 0 || index >= this._blocks.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return !(index < 0 || index >= this._blocks.length);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import * as _ from '../utils';
|
|||
import $ from '../dom';
|
||||
|
||||
import SelectionUtils from '../selection';
|
||||
import { SanitizerConfig } from '../../../types/configs';
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -21,7 +22,7 @@ export default class BlockSelection extends Module {
|
|||
*
|
||||
* @returns {SanitizerConfig}
|
||||
*/
|
||||
private get sanitizerConfig() {
|
||||
private get sanitizerConfig(): SanitizerConfig {
|
||||
return {
|
||||
p: {},
|
||||
h1: {},
|
||||
|
@ -62,7 +63,7 @@ export default class BlockSelection extends Module {
|
|||
/**
|
||||
* Set selected all blocks
|
||||
*
|
||||
* @param {boolean} state
|
||||
* @param {boolean} state - state to set
|
||||
*/
|
||||
public set allBlocksSelected(state: boolean) {
|
||||
const { BlockManager } = this.Editor;
|
||||
|
@ -160,7 +161,7 @@ export default class BlockSelection extends Module {
|
|||
*
|
||||
* @param {number?} index - Block index according to the BlockManager's indexes
|
||||
*/
|
||||
public unSelectBlockByIndex(index?) {
|
||||
public unSelectBlockByIndex(index?): void {
|
||||
const { BlockManager } = this.Editor;
|
||||
|
||||
let block;
|
||||
|
@ -180,7 +181,7 @@ export default class BlockSelection extends Module {
|
|||
* @param {Event} reason - event caused clear of selection
|
||||
* @param {boolean} restoreSelection - if true, restore saved selection
|
||||
*/
|
||||
public clearSelection(reason?: Event, restoreSelection = false) {
|
||||
public clearSelection(reason?: Event, restoreSelection = false): void {
|
||||
const { BlockManager, Caret, RectangleSelection } = this.Editor;
|
||||
|
||||
this.needToSelectAll = false;
|
||||
|
@ -226,7 +227,7 @@ export default class BlockSelection extends Module {
|
|||
*
|
||||
* @param {ClipboardEvent} e - copy/cut event
|
||||
*
|
||||
* @returns Promise<void>
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public async copySelectedBlocks(e: ClipboardEvent): Promise<void> {
|
||||
/**
|
||||
|
@ -263,7 +264,7 @@ export default class BlockSelection extends Module {
|
|||
*
|
||||
* @param {number?} index - Block index according to the BlockManager's indexes
|
||||
*/
|
||||
public selectBlockByIndex(index?) {
|
||||
public selectBlockByIndex(index?): void {
|
||||
const { BlockManager } = this.Editor;
|
||||
|
||||
/**
|
||||
|
@ -294,7 +295,7 @@ export default class BlockSelection extends Module {
|
|||
* First CMD+A selects all input content by native behaviour,
|
||||
* next CMD+A keypress selects all blocks
|
||||
*
|
||||
* @param {KeyboardEvent} event
|
||||
* @param {KeyboardEvent} event - keyboard event
|
||||
*/
|
||||
private handleCommandA(event: KeyboardEvent): void {
|
||||
this.Editor.RectangleSelection.clearSelection();
|
||||
|
@ -365,7 +366,7 @@ export default class BlockSelection extends Module {
|
|||
* Select All Blocks
|
||||
* Each Block has selected setter that makes Block copyable
|
||||
*/
|
||||
private selectAllBlocks() {
|
||||
private selectAllBlocks(): void {
|
||||
/**
|
||||
* Save selection
|
||||
* Will be restored when closeSelection fired
|
||||
|
|
|
@ -131,7 +131,7 @@ export default class Caret extends Module {
|
|||
* We use <= comparison for case:
|
||||
* "| Hello" <--- selection.anchorOffset is 0, but firstLetterPosition is 1
|
||||
*/
|
||||
return firstNode === null || focusNode === firstNode && focusOffset <= firstLetterPosition;
|
||||
return firstNode === null || (focusNode === firstNode && focusOffset <= firstLetterPosition);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -191,7 +191,7 @@ export default class Caret extends Module {
|
|||
*/
|
||||
const isLastBR = i === rightSiblings.length - 1 && $.isLineBreakTag(node as HTMLElement);
|
||||
|
||||
return (isLastBR) || $.isEmpty(node) && !$.isLineBreakTag(node);
|
||||
return isLastBR || ($.isEmpty(node) && !$.isLineBreakTag(node));
|
||||
});
|
||||
|
||||
if (nothingAtRight && focusOffset === focusNode.textContent.length) {
|
||||
|
@ -286,9 +286,7 @@ export default class Caret extends Module {
|
|||
break;
|
||||
|
||||
case this.positions.END:
|
||||
const contentLength = $.getContentLength(nodeToSet);
|
||||
|
||||
this.set(nodeToSet as HTMLElement, contentLength);
|
||||
this.set(nodeToSet as HTMLElement, $.getContentLength(nodeToSet));
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -459,19 +457,19 @@ export default class Caret extends Module {
|
|||
/**
|
||||
* Inserts shadow element after passed element where caret can be placed
|
||||
*
|
||||
* @param {Node} element
|
||||
* @param {Element} element - element after which shadow caret should be inserted
|
||||
*/
|
||||
public createShadow(element): void {
|
||||
public createShadow(element: Element): void {
|
||||
const shadowCaret = document.createElement('span');
|
||||
|
||||
shadowCaret.classList.add(Caret.CSS.shadowCaret);
|
||||
element.insertAdjacentElement('beforeEnd', shadowCaret);
|
||||
element.insertAdjacentElement('beforeend', shadowCaret);
|
||||
}
|
||||
|
||||
/**
|
||||
* Restores caret position
|
||||
*
|
||||
* @param {HTMLElement} element
|
||||
* @param {HTMLElement} element - element where caret should be restored
|
||||
*/
|
||||
public restoreCaret(element: HTMLElement): void {
|
||||
const shadowCaret = element.querySelector(`.${Caret.CSS.shadowCaret}`);
|
||||
|
@ -543,11 +541,13 @@ export default class Caret extends Module {
|
|||
* <p></p> | right first-level siblings
|
||||
* <p></p> |
|
||||
* </div>
|
||||
* @returns {Element[]}
|
||||
* @param from
|
||||
* @param direction
|
||||
*
|
||||
* @param {HTMLElement} from - element from which siblings should be searched
|
||||
* @param {'left' | 'right'} direction - direction of search
|
||||
*
|
||||
* @returns {HTMLElement[]}
|
||||
*/
|
||||
private getHigherLevelSiblings(from: HTMLElement, direction?: string): HTMLElement[] {
|
||||
private getHigherLevelSiblings(from: HTMLElement, direction?: 'left' | 'right'): HTMLElement[] {
|
||||
let current = from;
|
||||
const siblings = [];
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ export default class CrossBlockSelection extends Module {
|
|||
return;
|
||||
}
|
||||
|
||||
const { BlockManager, UI, Listeners } = this.Editor;
|
||||
const { BlockManager, Listeners } = this.Editor;
|
||||
|
||||
this.firstSelectedBlock = BlockManager.getBlock(event.target as HTMLElement);
|
||||
this.lastSelectedBlock = this.firstSelectedBlock;
|
||||
|
@ -86,7 +86,7 @@ export default class CrossBlockSelection extends Module {
|
|||
*
|
||||
* @param {Event} reason - event caused clear of selection
|
||||
*/
|
||||
public clear(reason?: Event) {
|
||||
public clear(reason?: Event): void {
|
||||
const { BlockManager, BlockSelection, Caret } = this.Editor;
|
||||
const fIndex = BlockManager.blocks.indexOf(this.firstSelectedBlock);
|
||||
const lIndex = BlockManager.blocks.indexOf(this.lastSelectedBlock);
|
||||
|
@ -135,7 +135,7 @@ export default class CrossBlockSelection extends Module {
|
|||
* Mouse over event handler
|
||||
* Gets target and related blocks and change selected state for blocks in between
|
||||
*
|
||||
* @param {MouseEvent} event
|
||||
* @param {MouseEvent} event - mouse over event
|
||||
*/
|
||||
private onMouseOver = (event: MouseEvent): void => {
|
||||
const { BlockManager } = this.Editor;
|
||||
|
@ -176,8 +176,8 @@ export default class CrossBlockSelection extends Module {
|
|||
/**
|
||||
* Change blocks selection state between passed two blocks.
|
||||
*
|
||||
* @param {Block} firstBlock
|
||||
* @param {Block} lastBlock
|
||||
* @param {Block} firstBlock - first block in range
|
||||
* @param {Block} lastBlock - last block in range
|
||||
*/
|
||||
private toggleBlocksSelectedState(firstBlock: Block, lastBlock: Block): void {
|
||||
const { BlockManager } = this.Editor;
|
||||
|
|
|
@ -8,15 +8,13 @@ export default class DragNDrop extends Module {
|
|||
/**
|
||||
* If drag has been started at editor, we save it
|
||||
*
|
||||
* @type Boolean
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
private isStartedAtEditor = false;
|
||||
|
||||
/**
|
||||
* Bind events
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
public prepare(): void {
|
||||
this.bindEvents();
|
||||
|
@ -45,7 +43,7 @@ export default class DragNDrop extends Module {
|
|||
/**
|
||||
* Handle drop event
|
||||
*
|
||||
* @param {DragEvent} dropEvent
|
||||
* @param {DragEvent} dropEvent - drop event
|
||||
*/
|
||||
private processDrop = async (dropEvent: DragEvent): Promise<void> => {
|
||||
const {
|
||||
|
|
|
@ -19,7 +19,7 @@ export default class Events extends Module {
|
|||
*
|
||||
* @type {{}}
|
||||
*/
|
||||
private subscribers: {[name: string]: Array<(data?: any) => any>} = {};
|
||||
private subscribers: {[name: string]: Array<(data?: object) => object>} = {};
|
||||
|
||||
/**
|
||||
* Subscribe any event on callback
|
||||
|
@ -27,7 +27,7 @@ export default class Events extends Module {
|
|||
* @param {string} eventName - event name
|
||||
* @param {Function} callback - subscriber
|
||||
*/
|
||||
public on(eventName: string, callback: (data: any) => any) {
|
||||
public on(eventName: string, callback: (data: object) => object): void {
|
||||
if (!(eventName in this.subscribers)) {
|
||||
this.subscribers[eventName] = [];
|
||||
}
|
||||
|
@ -42,12 +42,12 @@ export default class Events extends Module {
|
|||
* @param {string} eventName - event name
|
||||
* @param {Function} callback - subscriber
|
||||
*/
|
||||
public once(eventName: string, callback: (data: any) => any) {
|
||||
public once(eventName: string, callback: (data: object) => object): void {
|
||||
if (!(eventName in this.subscribers)) {
|
||||
this.subscribers[eventName] = [];
|
||||
}
|
||||
|
||||
const wrappedCallback = (data: any) => {
|
||||
const wrappedCallback = (data: object): object => {
|
||||
const result = callback(data);
|
||||
|
||||
const indexOfHandler = this.subscribers[eventName].indexOf(wrappedCallback);
|
||||
|
@ -69,7 +69,7 @@ export default class Events extends Module {
|
|||
* @param {string} eventName - event name
|
||||
* @param {object} data - subscribers get this data when they were fired
|
||||
*/
|
||||
public emit(eventName: string, data?: any): void {
|
||||
public emit(eventName: string, data?: object): void {
|
||||
if (!this.subscribers[eventName]) {
|
||||
return;
|
||||
}
|
||||
|
@ -82,12 +82,12 @@ export default class Events extends Module {
|
|||
}
|
||||
|
||||
/**
|
||||
* Unsubsribe callback from event
|
||||
* Unsubscribe callback from event
|
||||
*
|
||||
* @param eventName
|
||||
* @param callback
|
||||
* @param {string} eventName - event name
|
||||
* @param {Function} callback - event handler
|
||||
*/
|
||||
public off(eventName: string, callback: (data: any) => void): void {
|
||||
public off(eventName: string, callback: (data: object) => object): void {
|
||||
for (let i = 0; i < this.subscribers[eventName].length; i++) {
|
||||
if (this.subscribers[eventName][i] === callback) {
|
||||
delete this.subscribers[eventName][i];
|
||||
|
|
|
@ -2,6 +2,8 @@ import Module from '../__module';
|
|||
|
||||
/**
|
||||
* Event listener information
|
||||
*
|
||||
* @interface ListenerData
|
||||
*/
|
||||
export interface ListenerData {
|
||||
/**
|
||||
|
@ -17,7 +19,7 @@ export interface ListenerData {
|
|||
/**
|
||||
* Event handler
|
||||
*
|
||||
* @param {Event} event
|
||||
* @param {Event} event - event object
|
||||
*/
|
||||
handler: (event: Event) => void;
|
||||
|
||||
|
@ -40,7 +42,7 @@ export interface ListenerData {
|
|||
|
||||
/**
|
||||
* @typedef {Listeners} Listeners
|
||||
* @property {Array} allListeners
|
||||
* @property {ListenerData[]} allListeners - listeners store
|
||||
*/
|
||||
export default class Listeners extends Module {
|
||||
/**
|
||||
|
@ -109,9 +111,12 @@ export default class Listeners extends Module {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param {EventTarget} element
|
||||
* @param {string} eventType
|
||||
* @param {Function} handler
|
||||
* Finds and returns first listener by passed params
|
||||
*
|
||||
* @param {EventTarget} element - event target
|
||||
* @param {string} [eventType] - event type
|
||||
* @param {Function} [handler] - event handler
|
||||
*
|
||||
* @returns {ListenerData|null}
|
||||
*/
|
||||
public findOne(element: EventTarget, eventType?: string, handler?: (event: Event) => void): ListenerData {
|
||||
|
@ -121,9 +126,12 @@ export default class Listeners extends Module {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param {EventTarget} element
|
||||
* @param {string} eventType
|
||||
* @param {Function} handler
|
||||
* Return all stored listeners by passed params
|
||||
*
|
||||
* @param {EventTarget} element - event target
|
||||
* @param {string} eventType - event type
|
||||
* @param {Function} handler - event handler
|
||||
*
|
||||
* @returns {ListenerData[]}
|
||||
*/
|
||||
public findAll(element: EventTarget, eventType?: string, handler?: (event: Event) => void): ListenerData[] {
|
||||
|
@ -156,6 +164,7 @@ export default class Listeners extends Module {
|
|||
* Search method: looks for listener by passed element
|
||||
*
|
||||
* @param {EventTarget} element - searching element
|
||||
*
|
||||
* @returns {Array} listeners that found on element
|
||||
*/
|
||||
private findByEventTarget(element: EventTarget): ListenerData[] {
|
||||
|
@ -169,8 +178,9 @@ export default class Listeners extends Module {
|
|||
/**
|
||||
* Search method: looks for listener by passed event type
|
||||
*
|
||||
* @param {string} eventType
|
||||
* @returns {Array} listeners that found on element
|
||||
* @param {string} eventType - event type
|
||||
*
|
||||
* @returns {ListenerData[]} listeners that found on element
|
||||
*/
|
||||
private findByType(eventType: string): ListenerData[] {
|
||||
return this.allListeners.filter((listener) => {
|
||||
|
@ -183,8 +193,9 @@ export default class Listeners extends Module {
|
|||
/**
|
||||
* Search method: looks for listener by passed handler
|
||||
*
|
||||
* @param {Function} handler
|
||||
* @returns {Array} listeners that found on element
|
||||
* @param {Function} handler - event handler
|
||||
*
|
||||
* @returns {ListenerData[]} listeners that found on element
|
||||
*/
|
||||
private findByHandler(handler: (event: Event) => void): ListenerData[] {
|
||||
return this.allListeners.filter((listener) => {
|
||||
|
|
|
@ -49,7 +49,7 @@ export default class ModificationsObserver extends Module {
|
|||
/**
|
||||
* Clear timeout and set null to mutationDebouncer property
|
||||
*/
|
||||
public destroy() {
|
||||
public destroy(): void {
|
||||
this.mutationDebouncer = null;
|
||||
if (this.observer) {
|
||||
this.observer.disconnect();
|
||||
|
@ -76,7 +76,7 @@ export default class ModificationsObserver extends Module {
|
|||
* Allows to disable observer,
|
||||
* for example when Editor wants to stealthy mutate DOM
|
||||
*/
|
||||
public disable() {
|
||||
public disable(): void {
|
||||
this.disabled = true;
|
||||
}
|
||||
|
||||
|
@ -84,7 +84,7 @@ export default class ModificationsObserver extends Module {
|
|||
* Enables mutation handling
|
||||
* Should be called after .disable()
|
||||
*/
|
||||
public enable() {
|
||||
public enable(): void {
|
||||
this.disabled = false;
|
||||
}
|
||||
|
||||
|
@ -113,10 +113,10 @@ export default class ModificationsObserver extends Module {
|
|||
/**
|
||||
* MutationObserver events handler
|
||||
*
|
||||
* @param mutationList
|
||||
* @param observer
|
||||
* @param {MutationRecord[]} mutationList - list of mutations
|
||||
* @param {MutationObserver} observer - observer instance
|
||||
*/
|
||||
private mutationHandler(mutationList, observer) {
|
||||
private mutationHandler(mutationList: MutationRecord[], observer): void {
|
||||
/**
|
||||
* Skip mutations in stealth mode
|
||||
*/
|
||||
|
@ -134,18 +134,14 @@ export default class ModificationsObserver extends Module {
|
|||
mutationList.forEach((mutation) => {
|
||||
switch (mutation.type) {
|
||||
case 'childList':
|
||||
case 'subtree':
|
||||
case 'characterData':
|
||||
case 'characterDataOldValue':
|
||||
contentMutated = true;
|
||||
break;
|
||||
case 'attributes':
|
||||
const mutatedTarget = mutation.target as Element;
|
||||
|
||||
/**
|
||||
* Changes on Element.ce-block usually is functional
|
||||
*/
|
||||
if (!mutatedTarget.classList.contains(Block.CSS.wrapper)) {
|
||||
if (!(mutation.target as Element).classList.contains(Block.CSS.wrapper)) {
|
||||
contentMutated = true;
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -14,9 +14,9 @@ export default class Notifier extends Module {
|
|||
/**
|
||||
* Show web notification
|
||||
*
|
||||
* @param {NotifierOptions | ConfirmNotifierOptions | PromptNotifierOptions} options
|
||||
* @param {NotifierOptions | ConfirmNotifierOptions | PromptNotifierOptions} options - notification options
|
||||
*/
|
||||
public show(options: NotifierOptions | ConfirmNotifierOptions | PromptNotifierOptions) {
|
||||
public show(options: NotifierOptions | ConfirmNotifierOptions | PromptNotifierOptions): void {
|
||||
notifier.show(options);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,6 +70,8 @@ interface FilesSubstitution {
|
|||
|
||||
/**
|
||||
* Processed paste data object.
|
||||
*
|
||||
* @interface PasteData
|
||||
*/
|
||||
interface PasteData {
|
||||
/**
|
||||
|
@ -151,7 +153,7 @@ export default class Paste extends Module {
|
|||
* Handle pasted or dropped data transfer object
|
||||
*
|
||||
* @param {DataTransfer} dataTransfer - pasted or dropped data transfer object
|
||||
* @param {boolean} isDragNDrop
|
||||
* @param {boolean} isDragNDrop - true if data transfer comes from drag'n'drop events
|
||||
*/
|
||||
public async processDataTransfer(dataTransfer: DataTransfer, isDragNDrop = false): Promise<void> {
|
||||
const { Sanitizer } = this.Editor;
|
||||
|
@ -161,6 +163,7 @@ export default class Paste extends Module {
|
|||
/**
|
||||
* In Microsoft Edge types is DOMStringList. So 'contains' is used to check if 'Files' type included
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const includesFiles = types.includes ? types.includes('Files') : (types as any).contains('Files');
|
||||
|
||||
if (includesFiles) {
|
||||
|
@ -216,7 +219,7 @@ export default class Paste extends Module {
|
|||
* @param {string} data - text to process. Can be HTML or plain.
|
||||
* @param {boolean} isHTML - if passed string is HTML, this parameter should be true
|
||||
*/
|
||||
public async processText(data: string, isHTML = false) {
|
||||
public async processText(data: string, isHTML = false): Promise<void> {
|
||||
const { Caret, BlockManager, Tools } = this.Editor;
|
||||
const dataToInsert = isHTML ? this.processHTML(data) : this.processPlain(data);
|
||||
|
||||
|
@ -266,9 +269,6 @@ export default class Paste extends Module {
|
|||
|
||||
/**
|
||||
* Process paste config for each tool
|
||||
*
|
||||
* @param {string} name
|
||||
* @param {Tool} tool
|
||||
*/
|
||||
private processTool = ([name, tool]: [string, BlockToolConstructable]): void => {
|
||||
try {
|
||||
|
@ -312,7 +312,7 @@ export default class Paste extends Module {
|
|||
const tags = toolPasteConfig.tags || [];
|
||||
|
||||
tags.forEach((tag) => {
|
||||
if (this.toolsTags.hasOwnProperty(tag)) {
|
||||
if (Object.prototype.hasOwnProperty.call(this.toolsTags, tag)) {
|
||||
_.log(
|
||||
`Paste handler for «${name}» Tool on «${tag}» tag is skipped ` +
|
||||
`because it is already used by «${this.toolsTags[tag].tool}» Tool.`,
|
||||
|
@ -404,6 +404,7 @@ export default class Paste extends Module {
|
|||
* Check if browser behavior suits better
|
||||
*
|
||||
* @param {EventTarget} element - element where content has been pasted
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
private isNativeBehaviour(element: EventTarget): boolean {
|
||||
|
@ -413,14 +414,14 @@ export default class Paste extends Module {
|
|||
/**
|
||||
* Check if Editor should process pasted data and pass data transfer object to handler
|
||||
*
|
||||
* @param {ClipboardEvent} event
|
||||
* @param {ClipboardEvent} event - clipboard event
|
||||
*/
|
||||
private handlePasteEvent = async (event: ClipboardEvent): Promise<void> => {
|
||||
const { BlockManager, Toolbar } = this.Editor;
|
||||
|
||||
/** If target is native input or is not Block, use browser behaviour */
|
||||
if (
|
||||
!BlockManager.currentBlock || this.isNativeBehaviour(event.target) && !event.clipboardData.types.includes('Files')
|
||||
!BlockManager.currentBlock || (this.isNativeBehaviour(event.target) && !event.clipboardData.types.includes('Files'))
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
@ -444,7 +445,7 @@ export default class Paste extends Module {
|
|||
*
|
||||
* @param {FileList} items - pasted or dropped items
|
||||
*/
|
||||
private async processFiles(items: FileList) {
|
||||
private async processFiles(items: FileList): Promise<void> {
|
||||
const { BlockManager, Tools } = this.Editor;
|
||||
|
||||
let dataToInsert: Array<{type: string; event: PasteEvent}>;
|
||||
|
@ -469,9 +470,9 @@ export default class Paste extends Module {
|
|||
/**
|
||||
* Get information about file and find Tool to handle it
|
||||
*
|
||||
* @param {File} file
|
||||
* @param {File} file - file to process
|
||||
*/
|
||||
private async processFile(file: File) {
|
||||
private async processFile(file: File): Promise<{event: PasteEvent; type: string}> {
|
||||
const extension = _.getFileExtension(file);
|
||||
|
||||
const foundConfig = Object
|
||||
|
@ -507,7 +508,8 @@ export default class Paste extends Module {
|
|||
/**
|
||||
* Split HTML string to blocks and return it as array of Block data
|
||||
*
|
||||
* @param {string} innerHTML
|
||||
* @param {string} innerHTML - html string to process
|
||||
*
|
||||
* @returns {PasteData[]}
|
||||
*/
|
||||
private processHTML(innerHTML: string): PasteData[] {
|
||||
|
@ -569,12 +571,12 @@ export default class Paste extends Module {
|
|||
/**
|
||||
* Split plain text by new line symbols and return it as array of Block data
|
||||
*
|
||||
* @param {string} plain
|
||||
* @param {string} plain - string to process
|
||||
*
|
||||
* @returns {PasteData[]}
|
||||
*/
|
||||
private processPlain(plain: string): PasteData[] {
|
||||
const { initialBlock } = this.config as {initialBlock: string},
|
||||
{ Tools } = this.Editor;
|
||||
const { initialBlock } = this.config as {initialBlock: string};
|
||||
|
||||
if (!plain) {
|
||||
return [];
|
||||
|
@ -606,7 +608,7 @@ export default class Paste extends Module {
|
|||
/**
|
||||
* Process paste of single Block tool content
|
||||
*
|
||||
* @param {PasteData} dataToInsert
|
||||
* @param {PasteData} dataToInsert - data of Block to inseret
|
||||
*/
|
||||
private async processSingleBlock(dataToInsert: PasteData): Promise<void> {
|
||||
const { Caret, BlockManager, Tools } = this.Editor;
|
||||
|
@ -634,11 +636,11 @@ export default class Paste extends Module {
|
|||
* 2. Insert new block if it is not the same type as current one
|
||||
* 3. Just insert text if there is no substitutions
|
||||
*
|
||||
* @param {PasteData} dataToInsert
|
||||
* @param {PasteData} dataToInsert - data of Block to insert
|
||||
*/
|
||||
private async processInlinePaste(dataToInsert: PasteData): Promise<void> {
|
||||
const { BlockManager, Caret, Sanitizer, Tools } = this.Editor;
|
||||
const { content, tool } = dataToInsert;
|
||||
const { content } = dataToInsert;
|
||||
|
||||
const currentBlockIsInitial = BlockManager.currentBlock && Tools.isInitial(BlockManager.currentBlock.tool);
|
||||
|
||||
|
@ -675,8 +677,9 @@ export default class Paste extends Module {
|
|||
/**
|
||||
* Get patterns` matches
|
||||
*
|
||||
* @param {string} text
|
||||
* @returns Promise<{data: BlockToolData, tool: string}>
|
||||
* @param {string} text - text to process
|
||||
*
|
||||
* @returns {Promise<{event: PasteEvent, tool: string}>}
|
||||
*/
|
||||
private async processPattern(text: string): Promise<{event: PasteEvent; tool: string}> {
|
||||
const pattern = this.toolsPatterns.find((substitute) => {
|
||||
|
@ -707,8 +710,9 @@ export default class Paste extends Module {
|
|||
/**
|
||||
* Insert pasted Block content to Editor
|
||||
*
|
||||
* @param {PasteData} data
|
||||
* @param {PasteData} data - data to insert
|
||||
* @param {boolean} canReplaceCurrentBlock - if true and is current Block is empty, will replace current Block
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
private insertBlock(data: PasteData, canReplaceCurrentBlock = false): void {
|
||||
|
@ -757,17 +761,62 @@ export default class Paste extends Module {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch nodes from Element node
|
||||
*
|
||||
* @param {Node} node - current node
|
||||
* @param {Node[]} nodes - processed nodes
|
||||
* @param {Node} destNode - destination node
|
||||
*
|
||||
* @returns {Node[]}
|
||||
*/
|
||||
private processElementNode(node: Node, nodes: Node[], destNode: Node): Node[] | void {
|
||||
const tags = Object.keys(this.toolsTags);
|
||||
|
||||
const element = node as HTMLElement;
|
||||
|
||||
const { tool = '' } = this.toolsTags[element.tagName] || {};
|
||||
const toolTags = this.tagsByTool[tool] || [];
|
||||
|
||||
const isSubstitutable = tags.includes(element.tagName);
|
||||
const isBlockElement = $.blockElements.includes(element.tagName.toLowerCase());
|
||||
const containsAnotherToolTags = Array
|
||||
.from(element.children)
|
||||
.some(
|
||||
({ tagName }) => tags.includes(tagName) && !toolTags.includes(tagName)
|
||||
);
|
||||
|
||||
const containsBlockElements = Array.from(element.children).some(
|
||||
({ tagName }) => $.blockElements.includes(tagName.toLowerCase())
|
||||
);
|
||||
|
||||
/** Append inline elements to previous fragment */
|
||||
if (!isBlockElement && !isSubstitutable && !containsAnotherToolTags) {
|
||||
destNode.appendChild(element);
|
||||
|
||||
return [...nodes, destNode];
|
||||
}
|
||||
|
||||
if (
|
||||
(isSubstitutable && !containsAnotherToolTags) ||
|
||||
(isBlockElement && !containsBlockElements && !containsAnotherToolTags)
|
||||
) {
|
||||
return [...nodes, destNode, element];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively divide HTML string to two types of nodes:
|
||||
* 1. Block element
|
||||
* 2. Document Fragments contained text and markup tags like a, b, i etc.
|
||||
*
|
||||
* @param {Node} wrapper
|
||||
* @param {Node} wrapper - wrapper of paster HTML content
|
||||
*
|
||||
* @returns {Node[]}
|
||||
*/
|
||||
private getNodes(wrapper: Node): Node[] {
|
||||
const children = Array.from(wrapper.childNodes),
|
||||
tags = Object.keys(this.toolsTags);
|
||||
const children = Array.from(wrapper.childNodes);
|
||||
let elementNodeProcessingResult: Node[] | void;
|
||||
|
||||
const reducer = (nodes: Node[], node: Node): Node[] => {
|
||||
if ($.isEmpty(node) && !$.isSingleTag(node as HTMLElement)) {
|
||||
|
@ -789,35 +838,10 @@ export default class Paste extends Module {
|
|||
* 2. Check if it contains another block or substitutable elements
|
||||
*/
|
||||
case Node.ELEMENT_NODE:
|
||||
const element = node as HTMLElement;
|
||||
elementNodeProcessingResult = this.processElementNode(node, nodes, destNode);
|
||||
|
||||
const { tool = '' } = this.toolsTags[element.tagName] || {};
|
||||
const toolTags = this.tagsByTool[tool] || [];
|
||||
|
||||
const isSubstitutable = tags.includes(element.tagName);
|
||||
const isBlockElement = $.blockElements.includes(element.tagName.toLowerCase());
|
||||
const containsAnotherToolTags = Array
|
||||
.from(element.children)
|
||||
.some(
|
||||
({ tagName }) => tags.includes(tagName) && !toolTags.includes(tagName)
|
||||
);
|
||||
|
||||
const containsBlockElements = Array.from(element.children).some(
|
||||
({ tagName }) => $.blockElements.includes(tagName.toLowerCase())
|
||||
);
|
||||
|
||||
/** Append inline elements to previous fragment */
|
||||
if (!isBlockElement && !isSubstitutable && !containsAnotherToolTags) {
|
||||
destNode.appendChild(element);
|
||||
|
||||
return [...nodes, destNode];
|
||||
}
|
||||
|
||||
if (
|
||||
(isSubstitutable && !containsAnotherToolTags) ||
|
||||
(isBlockElement && !containsBlockElements && !containsAnotherToolTags)
|
||||
) {
|
||||
return [...nodes, destNode, element];
|
||||
if (elementNodeProcessingResult) {
|
||||
return elementNodeProcessingResult;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -842,8 +866,8 @@ export default class Paste extends Module {
|
|||
/**
|
||||
* Compose paste event with passed type and detail
|
||||
*
|
||||
* @param {string} type
|
||||
* @param {PasteEventDetail} detail
|
||||
* @param {string} type - event type
|
||||
* @param {PasteEventDetail} detail - event detail
|
||||
*/
|
||||
private composePasteEvent(type: string, detail: PasteEventDetail): PasteEvent {
|
||||
return new CustomEvent(type, {
|
||||
|
|
|
@ -20,7 +20,7 @@ export default class RectangleSelection extends Module {
|
|||
*
|
||||
* @returns {{wrapper: string, content: string}}
|
||||
*/
|
||||
static get CSS() {
|
||||
public static get CSS(): {[name: string]: string} {
|
||||
return {
|
||||
overlay: 'codex-editor-overlay',
|
||||
overlayContainer: 'codex-editor-overlay__container',
|
||||
|
@ -136,7 +136,7 @@ export default class RectangleSelection extends Module {
|
|||
* @param {number} pageX - X coord of mouse
|
||||
* @param {number} pageY - Y coord of mouse
|
||||
*/
|
||||
public startSelection(pageX, pageY) {
|
||||
public startSelection(pageX, pageY): void {
|
||||
const elemWhereSelectionStart = document.elementFromPoint(pageX - window.pageXOffset, pageY - window.pageYOffset);
|
||||
|
||||
/**
|
||||
|
@ -175,7 +175,7 @@ export default class RectangleSelection extends Module {
|
|||
/**
|
||||
* Clear all params to end selection
|
||||
*/
|
||||
public endSelection() {
|
||||
public endSelection(): void {
|
||||
this.mousedown = false;
|
||||
this.startX = 0;
|
||||
this.startY = 0;
|
||||
|
@ -185,14 +185,14 @@ export default class RectangleSelection extends Module {
|
|||
/**
|
||||
* is RectSelection Activated
|
||||
*/
|
||||
public isRectActivated() {
|
||||
public isRectActivated(): boolean {
|
||||
return this.isRectSelectionActivated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark that selection is end
|
||||
*/
|
||||
public clearSelection() {
|
||||
public clearSelection(): void {
|
||||
this.isRectSelectionActivated = false;
|
||||
}
|
||||
|
||||
|
@ -201,7 +201,7 @@ export default class RectangleSelection extends Module {
|
|||
*
|
||||
* @param {number} clientY - Y coord of mouse
|
||||
*/
|
||||
private scrollByZones(clientY) {
|
||||
private scrollByZones(clientY): void {
|
||||
this.inScrollZone = null;
|
||||
if (clientY <= this.HEIGHT_OF_SCROLL_ZONE) {
|
||||
this.inScrollZone = this.TOP_SCROLL_ZONE;
|
||||
|
@ -223,9 +223,11 @@ export default class RectangleSelection extends Module {
|
|||
}
|
||||
|
||||
/**
|
||||
* Generates required HTML elements
|
||||
*
|
||||
* @returns {object<string, Element>}
|
||||
*/
|
||||
private genHTML() {
|
||||
private genHTML(): {container: Element; overlay: Element} {
|
||||
const { UI } = this.Editor;
|
||||
|
||||
const container = UI.nodes.holder.querySelector('.' + UI.CSS.editorWrapper);
|
||||
|
@ -250,7 +252,7 @@ export default class RectangleSelection extends Module {
|
|||
*
|
||||
* @param {number} speed - speed of scrolling
|
||||
*/
|
||||
private scrollVertical(speed) {
|
||||
private scrollVertical(speed): void {
|
||||
if (!(this.inScrollZone && this.mousedown)) {
|
||||
return;
|
||||
}
|
||||
|
@ -266,9 +268,9 @@ export default class RectangleSelection extends Module {
|
|||
/**
|
||||
* Handles the change in the rectangle and its effect
|
||||
*
|
||||
* @param {MouseEvent} event
|
||||
* @param {MouseEvent} event - mouse event
|
||||
*/
|
||||
private changingRectangle(event) {
|
||||
private changingRectangle(event): void {
|
||||
if (!this.mousedown) {
|
||||
return;
|
||||
}
|
||||
|
@ -310,7 +312,7 @@ export default class RectangleSelection extends Module {
|
|||
/**
|
||||
* Shrink rect to singular point
|
||||
*/
|
||||
private shrinkRectangleToPoint() {
|
||||
private shrinkRectangleToPoint(): void {
|
||||
this.overlayRectangle.style.left = `${this.startX - window.pageXOffset}px`;
|
||||
this.overlayRectangle.style.top = `${this.startY - window.pageYOffset}px`;
|
||||
this.overlayRectangle.style.bottom = `calc(100% - ${this.startY - window.pageYOffset}px`;
|
||||
|
@ -320,17 +322,17 @@ export default class RectangleSelection extends Module {
|
|||
/**
|
||||
* Select or unselect all of blocks in array if rect is out or in selectable area
|
||||
*/
|
||||
private inverseSelection() {
|
||||
private inverseSelection(): void {
|
||||
const firstBlockInStack = this.Editor.BlockManager.getBlockByIndex(this.stackOfSelected[0]);
|
||||
const isSelecteMode = firstBlockInStack.selected;
|
||||
const isSelectedMode = firstBlockInStack.selected;
|
||||
|
||||
if (this.rectCrossesBlocks && !isSelecteMode) {
|
||||
if (this.rectCrossesBlocks && !isSelectedMode) {
|
||||
for (const it of this.stackOfSelected) {
|
||||
this.Editor.BlockSelection.selectBlockByIndex(it);
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.rectCrossesBlocks && isSelecteMode) {
|
||||
if (!this.rectCrossesBlocks && isSelectedMode) {
|
||||
for (const it of this.stackOfSelected) {
|
||||
this.Editor.BlockSelection.unSelectBlockByIndex(it);
|
||||
}
|
||||
|
@ -340,7 +342,7 @@ export default class RectangleSelection extends Module {
|
|||
/**
|
||||
* Updates size of rectangle
|
||||
*/
|
||||
private updateRectangleSize() {
|
||||
private updateRectangleSize(): void {
|
||||
// Depending on the position of the mouse relative to the starting point,
|
||||
// change this.e distance from the desired edge of the screen*/
|
||||
if (this.mouseY >= this.startY) {
|
||||
|
@ -363,9 +365,9 @@ export default class RectangleSelection extends Module {
|
|||
/**
|
||||
* Collects information needed to determine the behavior of the rectangle
|
||||
*
|
||||
* @returns {number} index - index next Block, leftPos - start of left border of Block, rightPos - right border
|
||||
* @returns {object} index - index next Block, leftPos - start of left border of Block, rightPos - right border
|
||||
*/
|
||||
private genInfoForMouseSelection() {
|
||||
private genInfoForMouseSelection(): {index: number; leftPos: number; rightPos: number} {
|
||||
const widthOfRedactor = document.body.offsetWidth;
|
||||
const centerOfRedactor = widthOfRedactor / 2;
|
||||
const Y = this.mouseY - window.pageYOffset;
|
||||
|
@ -393,7 +395,7 @@ export default class RectangleSelection extends Module {
|
|||
*
|
||||
* @param index - index of block in redactor
|
||||
*/
|
||||
private addBlockInSelection(index) {
|
||||
private addBlockInSelection(index): void {
|
||||
if (this.rectCrossesBlocks) {
|
||||
this.Editor.BlockSelection.selectBlockByIndex(index);
|
||||
}
|
||||
|
@ -405,7 +407,7 @@ export default class RectangleSelection extends Module {
|
|||
*
|
||||
* @param {object} index - index of new block in the reactor
|
||||
*/
|
||||
private trySelectNextBlock(index) {
|
||||
private trySelectNextBlock(index): void {
|
||||
const sameBlock = this.stackOfSelected[this.stackOfSelected.length - 1] === index;
|
||||
const sizeStack = this.stackOfSelected.length;
|
||||
const down = 1, up = -1, undef = 0;
|
||||
|
@ -415,10 +417,16 @@ export default class RectangleSelection extends Module {
|
|||
}
|
||||
|
||||
const blockNumbersIncrease = this.stackOfSelected[sizeStack - 1] - this.stackOfSelected[sizeStack - 2] > 0;
|
||||
const direction = sizeStack <= 1 ? undef : blockNumbersIncrease ? down : up;
|
||||
const selectionInDownDurection = index > this.stackOfSelected[sizeStack - 1] && direction === down;
|
||||
|
||||
let direction = undef;
|
||||
|
||||
if (sizeStack > 1) {
|
||||
direction = blockNumbersIncrease ? down : up;
|
||||
}
|
||||
|
||||
const selectionInDownDirection = index > this.stackOfSelected[sizeStack - 1] && direction === down;
|
||||
const selectionInUpDirection = index < this.stackOfSelected[sizeStack - 1] && direction === up;
|
||||
const generalSelection = selectionInDownDurection || selectionInUpDirection || direction === undef;
|
||||
const generalSelection = selectionInDownDirection || selectionInUpDirection || direction === undef;
|
||||
const reduction = !generalSelection;
|
||||
|
||||
// When the selection is too fast, some blocks do not have time to be noticed. Fix it.
|
||||
|
@ -451,9 +459,9 @@ export default class RectangleSelection extends Module {
|
|||
|
||||
// cmp for different directions
|
||||
if (index > this.stackOfSelected[sizeStack - 1]) {
|
||||
cmp = () => index > this.stackOfSelected[i];
|
||||
cmp = (): boolean => index > this.stackOfSelected[i];
|
||||
} else {
|
||||
cmp = () => index < this.stackOfSelected[i];
|
||||
cmp = (): boolean => index < this.stackOfSelected[i];
|
||||
}
|
||||
|
||||
// Remove blocks missed due to speed.
|
||||
|
|
|
@ -43,10 +43,10 @@ export default class Renderer extends Module {
|
|||
/**
|
||||
* Make plugin blocks from array of plugin`s data
|
||||
*
|
||||
* @param {RendererBlocks[]} blocks
|
||||
* @param {BlockToolData[]} blocks - blocks to render
|
||||
*/
|
||||
public async render(blocks: BlockToolData[]): Promise<void> {
|
||||
const chainData = blocks.map((block) => ({ function: () => this.insertBlock(block) }));
|
||||
const chainData = blocks.map((block) => ({ function: (): Promise<void> => this.insertBlock(block) }));
|
||||
|
||||
const sequence = await _.sequence(chainData as ChainData[]);
|
||||
|
||||
|
@ -60,9 +60,8 @@ export default class Renderer extends Module {
|
|||
* Add plugin instance to BlockManager
|
||||
* Insert block to working zone
|
||||
*
|
||||
* @param {object} item
|
||||
* @param {object} item - Block data to insert
|
||||
* @returns {Promise<void>}
|
||||
* @private
|
||||
*/
|
||||
public async insertBlock(item): Promise<void> {
|
||||
const { Tools, BlockManager } = this.Editor;
|
||||
|
|
|
@ -57,8 +57,7 @@ export default class Sanitizer extends Module {
|
|||
*
|
||||
* Enumerate blocks and clean data
|
||||
*
|
||||
* @param blocksData
|
||||
* @param {{tool, data: BlockToolData}[]} blocksData[]
|
||||
* @param {Array<{tool, data: BlockToolData}>} blocksData - blocks' data to sanitize
|
||||
*/
|
||||
public sanitizeBlocks(
|
||||
blocksData: Array<{tool: string; data: BlockToolData}>
|
||||
|
@ -70,7 +69,7 @@ export default class Sanitizer extends Module {
|
|||
return block;
|
||||
}
|
||||
|
||||
block.data = this.deepSanitize(block.data, toolConfig);
|
||||
block.data = this.deepSanitize(block.data, toolConfig) as BlockToolData;
|
||||
|
||||
return block;
|
||||
});
|
||||
|
@ -82,7 +81,7 @@ export default class Sanitizer extends Module {
|
|||
* @param {BlockToolData|object|*} dataToSanitize - taint string or object/array that contains taint string
|
||||
* @param {SanitizerConfig} rules - object with sanitizer rules
|
||||
*/
|
||||
public deepSanitize(dataToSanitize: any, rules: SanitizerConfig): any {
|
||||
public deepSanitize(dataToSanitize: object | string, rules: SanitizerConfig): object | string {
|
||||
/**
|
||||
* BlockData It may contain 3 types:
|
||||
* - Array
|
||||
|
@ -138,8 +137,8 @@ export default class Sanitizer extends Module {
|
|||
/**
|
||||
* Merge with inline tool config
|
||||
*
|
||||
* @param {string} toolName
|
||||
* @param {SanitizerConfig} toolRules
|
||||
* @param {string} toolName - tool name
|
||||
*
|
||||
* @returns {SanitizerConfig}
|
||||
*/
|
||||
public composeToolConfig(toolName: string): SanitizerConfig {
|
||||
|
@ -166,7 +165,7 @@ export default class Sanitizer extends Module {
|
|||
const toolConfig = {} as SanitizerConfig;
|
||||
|
||||
for (const fieldName in toolRules) {
|
||||
if (toolRules.hasOwnProperty(fieldName)) {
|
||||
if (Object.prototype.hasOwnProperty.call(toolRules, fieldName)) {
|
||||
const rule = toolRules[fieldName];
|
||||
|
||||
if (typeof rule === 'object') {
|
||||
|
@ -186,7 +185,7 @@ export default class Sanitizer extends Module {
|
|||
* When Tool's "inlineToolbar" value is True, get all sanitizer rules from all tools,
|
||||
* otherwise get only enabled
|
||||
*
|
||||
* @param name
|
||||
* @param {string} name - Inline Tool name
|
||||
*/
|
||||
public getInlineToolsConfig(name: string): SanitizerConfig {
|
||||
const { Tools } = this.Editor;
|
||||
|
@ -234,7 +233,7 @@ export default class Sanitizer extends Module {
|
|||
const config: SanitizerConfig = {} as SanitizerConfig;
|
||||
|
||||
Object.entries(Tools.inline)
|
||||
.forEach(([name, inlineTool]: [string, InlineToolConstructable]) => {
|
||||
.forEach(([, inlineTool]: [string, InlineToolConstructable]) => {
|
||||
Object.assign(config, inlineTool[Tools.INTERNAL_SETTINGS.SANITIZE_CONFIG]);
|
||||
});
|
||||
|
||||
|
@ -247,9 +246,9 @@ export default class Sanitizer extends Module {
|
|||
* Clean array
|
||||
*
|
||||
* @param {Array} array - [1, 2, {}, []]
|
||||
* @param {object} ruleForItem
|
||||
* @param {SanitizerConfig} ruleForItem - sanitizer config for array
|
||||
*/
|
||||
private cleanArray(array: any[], ruleForItem: SanitizerConfig): any[] {
|
||||
private cleanArray(array: Array<object | string>, ruleForItem: SanitizerConfig): Array<object | string> {
|
||||
return array.map((arrayItem) => this.deepSanitize(arrayItem, ruleForItem));
|
||||
}
|
||||
|
||||
|
@ -260,11 +259,11 @@ export default class Sanitizer extends Module {
|
|||
* @param {object} rules - { b: true } or true|false
|
||||
* @returns {object}
|
||||
*/
|
||||
private cleanObject(object: any, rules: SanitizerConfig|{[field: string]: SanitizerConfig}): any {
|
||||
private cleanObject(object: object, rules: SanitizerConfig|{[field: string]: SanitizerConfig}): object {
|
||||
const cleanData = {};
|
||||
|
||||
for (const fieldName in object) {
|
||||
if (!object.hasOwnProperty(fieldName)) {
|
||||
if (!Object.prototype.hasOwnProperty.call(object, fieldName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -284,8 +283,11 @@ export default class Sanitizer extends Module {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param {string} taintString
|
||||
* @param {SanitizerConfig|boolean} rule
|
||||
* Clean primitive value
|
||||
*
|
||||
* @param {string} taintString - string to clean
|
||||
* @param {SanitizerConfig|boolean} rule - sanitizer rule
|
||||
*
|
||||
* @returns {string}
|
||||
*/
|
||||
private cleanOneItem(taintString: string, rule: SanitizerConfig|boolean): string {
|
||||
|
@ -303,7 +305,7 @@ export default class Sanitizer extends Module {
|
|||
* { a : true }, {}, false, true, function(){} — correct rules
|
||||
* undefined, null, 0, 1, 2 — not a rules
|
||||
*
|
||||
* @param config
|
||||
* @param {SanitizerConfig} config - config to check
|
||||
*/
|
||||
private isRule(config: SanitizerConfig): boolean {
|
||||
return typeof config === 'object' || typeof config === 'boolean' || typeof config === 'function';
|
||||
|
@ -314,8 +316,9 @@ export default class Sanitizer extends Module {
|
|||
* Or, sanitizing config can be defined globally in editors initialization. That config will be used everywhere
|
||||
* At least, if there is no config overrides, that API uses Default configuration
|
||||
*
|
||||
* @uses https://www.npmjs.com/package/html-janitor
|
||||
* @license https://github.com/guardian/html-janitor/blob/master/LICENSE
|
||||
* @see {@link https://www.npmjs.com/package/html-janitor}
|
||||
* @license Apache-2.0
|
||||
* @see {@link https://github.com/guardian/html-janitor/blob/master/LICENSE}
|
||||
*
|
||||
* @param {SanitizerConfig} config - sanitizer extension
|
||||
*/
|
||||
|
|
|
@ -67,7 +67,7 @@ export default class Saver extends Module {
|
|||
/**
|
||||
* Creates output object with saved data, time and version of editor
|
||||
*
|
||||
* @param {ValidatedData} allExtractedData
|
||||
* @param {ValidatedData} allExtractedData - data extracted from Blocks
|
||||
* @returns {OutputData}
|
||||
*/
|
||||
private makeOutput(allExtractedData): OutputData {
|
||||
|
|
|
@ -10,6 +10,8 @@ import Module from '../__module';
|
|||
* Each shortcut must have name and handler
|
||||
* `name` is a shortcut, like 'CMD+K', 'CMD+B' etc
|
||||
* `handler` is a callback
|
||||
*
|
||||
* @interface ShortcutData
|
||||
*/
|
||||
export interface ShortcutData {
|
||||
|
||||
|
@ -42,7 +44,7 @@ export default class Shortcuts extends Module {
|
|||
/**
|
||||
* Register shortcut
|
||||
*
|
||||
* @param {ShortcutData} shortcut
|
||||
* @param {ShortcutData} shortcut - shortcut options
|
||||
*/
|
||||
public add(shortcut: ShortcutData): void {
|
||||
const newShortcut = new Shortcut({
|
||||
|
@ -57,7 +59,7 @@ export default class Shortcuts extends Module {
|
|||
/**
|
||||
* Remove shortcut
|
||||
*
|
||||
* @param {ShortcutData} shortcut
|
||||
* @param {string} shortcut - shortcut name
|
||||
*/
|
||||
public remove(shortcut: string): void {
|
||||
const index = this.registeredShortcuts.findIndex((shc) => shc.name === shortcut);
|
||||
|
|
|
@ -32,7 +32,7 @@ export default class BlockSettings extends Module {
|
|||
*
|
||||
* @returns {{wrapper, wrapperOpened, toolSettings, defaultSettings, button}}
|
||||
*/
|
||||
public get CSS() {
|
||||
public get CSS(): {[name: string]: string} {
|
||||
return {
|
||||
// Settings Panel
|
||||
wrapper: 'ce-settings',
|
||||
|
@ -81,8 +81,6 @@ export default class BlockSettings extends Module {
|
|||
* Panel with block settings with 2 sections:
|
||||
* - Tool's Settings
|
||||
* - Default Settings [Move, Remove, etc]
|
||||
*
|
||||
* @returns {Element}
|
||||
*/
|
||||
public make(): void {
|
||||
this.nodes.wrapper = $.make('div', this.CSS.wrapper);
|
||||
|
|
|
@ -3,7 +3,6 @@ import $ from '../../dom';
|
|||
import { BlockToolConstructable } from '../../../../types';
|
||||
import * as _ from '../../utils';
|
||||
import { SavedData } from '../../../types-internal/block-data';
|
||||
import Block from '../../block';
|
||||
import Flipper from '../../flipper';
|
||||
|
||||
/**
|
||||
|
@ -155,7 +154,7 @@ export default class ConversionToolbar extends Module {
|
|||
* Replaces one Block with another
|
||||
* For that Tools must provide import/export methods
|
||||
*
|
||||
* @param {string} replacingToolName
|
||||
* @param {string} replacingToolName - name of Tool which replaces current
|
||||
*/
|
||||
public async replaceWithBlock(replacingToolName: string): Promise <void> {
|
||||
/**
|
||||
|
@ -251,7 +250,7 @@ export default class ConversionToolbar extends Module {
|
|||
const tools = this.Editor.Tools.blockTools;
|
||||
|
||||
for (const toolName in tools) {
|
||||
if (!tools.hasOwnProperty(toolName)) {
|
||||
if (!Object.prototype.hasOwnProperty.call(tools, toolName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -281,9 +280,9 @@ export default class ConversionToolbar extends Module {
|
|||
/**
|
||||
* Add tool to the Conversion Toolbar
|
||||
*
|
||||
* @param toolName
|
||||
* @param toolIcon
|
||||
* @param title
|
||||
* @param {string} toolName - name of Tool to add
|
||||
* @param {string} toolIcon - Tool icon
|
||||
* @param {string} title - button title
|
||||
*/
|
||||
private addTool(toolName: string, toolIcon: string, title: string): void {
|
||||
const tool = $.make('div', [ ConversionToolbar.CSS.conversionTool ]);
|
||||
|
|
|
@ -42,7 +42,7 @@ import * as _ from '../../utils';
|
|||
* @classdesc Toolbar module
|
||||
*
|
||||
* @typedef {Toolbar} Toolbar
|
||||
* @property {object} nodes
|
||||
* @property {object} nodes - Toolbar nodes
|
||||
* @property {Element} nodes.wrapper - Toolbar main element
|
||||
* @property {Element} nodes.content - Zone with Plus button and toolbox.
|
||||
* @property {Element} nodes.actions - Zone with Block Settings and Remove Button
|
||||
|
@ -76,7 +76,7 @@ export default class Toolbar extends Module {
|
|||
*
|
||||
* @returns {object}
|
||||
*/
|
||||
public get CSS() {
|
||||
public get CSS(): {[name: string]: string} {
|
||||
return {
|
||||
toolbar: 'ce-toolbar',
|
||||
content: 'ce-toolbar__content',
|
||||
|
@ -273,8 +273,8 @@ export default class Toolbar extends Module {
|
|||
*/
|
||||
public get plusButton(): {hide: () => void; show: () => void} {
|
||||
return {
|
||||
hide: () => this.nodes.plusButton.classList.add(this.CSS.plusButtonHidden),
|
||||
show: () => {
|
||||
hide: (): void => this.nodes.plusButton.classList.add(this.CSS.plusButtonHidden),
|
||||
show: (): void => {
|
||||
if (this.Editor.Toolbox.isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
@ -290,10 +290,10 @@ export default class Toolbar extends Module {
|
|||
*/
|
||||
private get blockActions(): {hide: () => void; show: () => void} {
|
||||
return {
|
||||
hide: () => {
|
||||
hide: (): void => {
|
||||
this.nodes.actions.classList.remove(this.CSS.actionsOpened);
|
||||
},
|
||||
show: () => {
|
||||
show: (): void => {
|
||||
this.nodes.actions.classList.add(this.CSS.actionsOpened);
|
||||
},
|
||||
};
|
||||
|
@ -301,8 +301,6 @@ export default class Toolbar extends Module {
|
|||
|
||||
/**
|
||||
* Handler for Plus Button
|
||||
*
|
||||
* @param {MouseEvent} event
|
||||
*/
|
||||
private plusButtonClicked(): void {
|
||||
this.Editor.Toolbox.toggle();
|
||||
|
|
|
@ -94,15 +94,15 @@ export default class InlineToolbar extends Module {
|
|||
/**
|
||||
* Inline Toolbar Tools
|
||||
*
|
||||
* @returns Map<string, InlineTool>
|
||||
* @returns {Map<string, InlineTool>}
|
||||
*/
|
||||
get tools(): Map<string, InlineTool> {
|
||||
public get tools(): Map<string, InlineTool> {
|
||||
if (!this.toolsInstances || this.toolsInstances.size === 0) {
|
||||
const allTools = this.inlineTools;
|
||||
|
||||
this.toolsInstances = new Map();
|
||||
for (const tool in allTools) {
|
||||
if (allTools.hasOwnProperty(tool)) {
|
||||
if (Object.prototype.hasOwnProperty.call(allTools, tool)) {
|
||||
this.toolsInstances.set(tool, allTools[tool]);
|
||||
}
|
||||
}
|
||||
|
@ -114,7 +114,7 @@ export default class InlineToolbar extends Module {
|
|||
/**
|
||||
* Making DOM
|
||||
*/
|
||||
public make() {
|
||||
public make(): void {
|
||||
this.nodes.wrapper = $.make('div', this.CSS.inlineToolbar);
|
||||
this.nodes.buttons = $.make('div', this.CSS.buttonsWrapper);
|
||||
this.nodes.actions = $.make('div', this.CSS.actionsWrapper);
|
||||
|
@ -516,8 +516,8 @@ export default class InlineToolbar extends Module {
|
|||
/**
|
||||
* Add tool button and activate clicks
|
||||
*
|
||||
* @param toolName
|
||||
* @param tool
|
||||
* @param {string} toolName - name of Tool to add
|
||||
* @param {InlineTool} tool - Tool class instance
|
||||
*/
|
||||
private addTool(toolName: string, tool: InlineTool): void {
|
||||
const {
|
||||
|
@ -561,7 +561,7 @@ export default class InlineToolbar extends Module {
|
|||
*/
|
||||
const internalTools: string[] = Object
|
||||
.entries(Tools.internalTools)
|
||||
.filter(([name, toolClass]: [string, ToolConstructable | ToolSettings]) => {
|
||||
.filter(([, toolClass]: [string, ToolConstructable | ToolSettings]) => {
|
||||
if (_.isFunction(toolClass)) {
|
||||
return toolClass[Tools.INTERNAL_SETTINGS.IS_INLINE];
|
||||
}
|
||||
|
@ -671,7 +671,7 @@ export default class InlineToolbar extends Module {
|
|||
const result = {};
|
||||
|
||||
for (const tool in this.Editor.Tools.inline) {
|
||||
if (this.Editor.Tools.inline.hasOwnProperty(tool)) {
|
||||
if (Object.prototype.hasOwnProperty.call(this.Editor.Tools.inline, tool)) {
|
||||
const toolSettings = this.Editor.Tools.getToolSettings(tool);
|
||||
|
||||
result[tool] = this.Editor.Tools.constructInline(this.Editor.Tools.inline[tool], toolSettings);
|
||||
|
|
|
@ -19,10 +19,9 @@ export default class Toolbox extends Module {
|
|||
/**
|
||||
* CSS styles
|
||||
*
|
||||
* @returns {{toolbox: string, toolboxButton string, toolboxButtonActive: string,
|
||||
* toolboxOpened: string, tooltip: string, tooltipShown: string, tooltipShortcut: string}}
|
||||
* @returns {object.<string, string>}
|
||||
*/
|
||||
get CSS() {
|
||||
public get CSS(): {[name: string]: string} {
|
||||
return {
|
||||
toolbox: 'ce-toolbox',
|
||||
toolboxButton: 'ce-toolbox__button',
|
||||
|
@ -90,8 +89,8 @@ export default class Toolbox extends Module {
|
|||
/**
|
||||
* Toolbox Tool's button click handler
|
||||
*
|
||||
* @param {MouseEvent|KeyboardEvent} event
|
||||
* @param {string} toolName
|
||||
* @param {MouseEvent|KeyboardEvent} event - event that activates toolbox button
|
||||
* @param {string} toolName - button to activate
|
||||
*/
|
||||
public toolButtonActivate(event: MouseEvent|KeyboardEvent, toolName: string): void {
|
||||
const tool = this.Editor.Tools.toolsClasses[toolName] as BlockToolConstructable;
|
||||
|
@ -143,7 +142,7 @@ export default class Toolbox extends Module {
|
|||
const tools = this.Editor.Tools.available;
|
||||
|
||||
for (const toolName in tools) {
|
||||
if (tools.hasOwnProperty(toolName)) {
|
||||
if (Object.prototype.hasOwnProperty.call(tools, toolName)) {
|
||||
this.addTool(toolName, tools[toolName] as BlockToolConstructable);
|
||||
}
|
||||
}
|
||||
|
@ -228,7 +227,7 @@ export default class Toolbox extends Module {
|
|||
* Draw tooltip for toolbox tools
|
||||
*
|
||||
* @param {string} toolName - toolbox tool name
|
||||
* @returns { HTMLElement }
|
||||
* @returns {HTMLElement}
|
||||
*/
|
||||
private drawTooltip(toolName: string): HTMLElement {
|
||||
const toolSettings = this.Editor.Tools.getToolSettings(toolName);
|
||||
|
@ -261,7 +260,7 @@ export default class Toolbox extends Module {
|
|||
* @param {string} toolName - Tool name
|
||||
* @param {string} shortcut - shortcut according to the ShortcutData Module format
|
||||
*/
|
||||
private enableShortcut(tool: BlockToolConstructable, toolName: string, shortcut: string) {
|
||||
private enableShortcut(tool: BlockToolConstructable, toolName: string, shortcut: string): void {
|
||||
this.Editor.Shortcuts.add({
|
||||
name: shortcut,
|
||||
handler: (event: KeyboardEvent) => {
|
||||
|
@ -290,11 +289,8 @@ export default class Toolbox extends Module {
|
|||
* @param {BlockToolConstructable} tool - Tool Class
|
||||
* @param {string} toolName - Tool name
|
||||
*/
|
||||
private insertNewBlock(tool: BlockToolConstructable, toolName: string) {
|
||||
private insertNewBlock(tool: BlockToolConstructable, toolName: string): void {
|
||||
const { BlockManager, Caret } = this.Editor;
|
||||
/**
|
||||
* @type {Block}
|
||||
*/
|
||||
const { currentBlock } = BlockManager;
|
||||
|
||||
let newBlock;
|
||||
|
|
|
@ -2,7 +2,8 @@ import Paragraph from '../tools/paragraph/dist/bundle';
|
|||
import Module from '../__module';
|
||||
import * as _ from '../utils';
|
||||
import {
|
||||
BlockToolConstructable,
|
||||
BlockTool,
|
||||
BlockToolConstructable, BlockToolData, EditorConfig,
|
||||
InlineTool,
|
||||
InlineToolConstructable, Tool,
|
||||
ToolConfig,
|
||||
|
@ -67,7 +68,7 @@ export default class Tools extends Module {
|
|||
return this._inlineTools;
|
||||
}
|
||||
|
||||
const tools = Object.entries(this.available).filter(([name, tool]) => {
|
||||
const tools = Object.entries(this.available).filter(([, tool]) => {
|
||||
if (!tool[this.INTERNAL_SETTINGS.IS_INLINE]) {
|
||||
return false;
|
||||
}
|
||||
|
@ -112,8 +113,7 @@ export default class Tools extends Module {
|
|||
* Return editor block tools
|
||||
*/
|
||||
public get blockTools(): {[name: string]: BlockToolConstructable} {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const tools = Object.entries(this.available).filter(([name, tool]) => {
|
||||
const tools = Object.entries(this.available).filter(([, tool]) => {
|
||||
return !tool[this.INTERNAL_SETTINGS.IS_INLINE];
|
||||
});
|
||||
|
||||
|
@ -134,7 +134,7 @@ export default class Tools extends Module {
|
|||
*
|
||||
* @returns {object}
|
||||
*/
|
||||
public get INTERNAL_SETTINGS() {
|
||||
public get INTERNAL_SETTINGS(): {[name: string]: string} {
|
||||
return {
|
||||
IS_ENABLED_LINE_BREAKS: 'enableLineBreaks',
|
||||
IS_INLINE: 'isInline',
|
||||
|
@ -151,7 +151,7 @@ export default class Tools extends Module {
|
|||
*
|
||||
* return {object}
|
||||
*/
|
||||
public get USER_SETTINGS() {
|
||||
public get USER_SETTINGS(): {[name: string]: string} {
|
||||
return {
|
||||
SHORTCUT: 'shortcut',
|
||||
TOOLBOX: 'toolbox',
|
||||
|
@ -196,7 +196,7 @@ export default class Tools extends Module {
|
|||
/**
|
||||
* @class
|
||||
*
|
||||
* @param {EditorConfig} config
|
||||
* @param {EditorConfig} config - Editor's configuration
|
||||
*/
|
||||
constructor({ config }) {
|
||||
super({ config });
|
||||
|
@ -227,9 +227,9 @@ export default class Tools extends Module {
|
|||
/**
|
||||
* Creates instances via passed or default configuration
|
||||
*
|
||||
* @returns {Promise}
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public prepare() {
|
||||
public prepare(): Promise<void> {
|
||||
this.validateTools();
|
||||
|
||||
/**
|
||||
|
@ -237,7 +237,7 @@ export default class Tools extends Module {
|
|||
*/
|
||||
this.config.tools = _.deepMerge({}, this.internalTools, this.config.tools);
|
||||
|
||||
if (!this.config.hasOwnProperty('tools') || Object.keys(this.config.tools).length === 0) {
|
||||
if (!Object.prototype.hasOwnProperty.call(this.config, 'tools') || Object.keys(this.config.tools).length === 0) {
|
||||
throw Error('Can\'t start without tools');
|
||||
}
|
||||
|
||||
|
@ -298,26 +298,30 @@ export default class Tools extends Module {
|
|||
}
|
||||
|
||||
/**
|
||||
* to see how it works {@link Util#sequence}
|
||||
* to see how it works {@link '../utils.ts#sequence'}
|
||||
*/
|
||||
return _.sequence(sequenceData, (data: any) => {
|
||||
return _.sequence(sequenceData, (data: {toolName: string}) => {
|
||||
this.success(data);
|
||||
}, (data) => {
|
||||
}, (data: {toolName: string}) => {
|
||||
this.fallback(data);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ChainData.data} data - append tool to available list
|
||||
* Success callback
|
||||
*
|
||||
* @param {object} data - append tool to available list
|
||||
*/
|
||||
public success(data) {
|
||||
public success(data: {toolName: string}): void {
|
||||
this.toolsAvailable[data.toolName] = this.toolsClasses[data.toolName];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ChainData.data} data - append tool to unavailable list
|
||||
* Fail callback
|
||||
*
|
||||
* @param {object} data - append tool to unavailable list
|
||||
*/
|
||||
public fallback(data) {
|
||||
public fallback(data: {toolName: string}): void {
|
||||
this.toolsUnavailable[data.toolName] = this.toolsClasses[data.toolName];
|
||||
}
|
||||
|
||||
|
@ -325,11 +329,12 @@ export default class Tools extends Module {
|
|||
* Return Tool`s instance
|
||||
*
|
||||
* @param {string} tool — tool name
|
||||
* @param {BlockToolData} data — initial data
|
||||
* @param {object} data — initial data
|
||||
*
|
||||
* @returns {BlockTool}
|
||||
*/
|
||||
public construct(tool, data) {
|
||||
const Plugin = this.toolsClasses[tool];
|
||||
public construct(tool: string, data: BlockToolData): BlockTool {
|
||||
const Plugin = this.toolsClasses[tool] as BlockToolConstructable;
|
||||
|
||||
/**
|
||||
* Configuration to be passed to the Tool's constructor
|
||||
|
@ -341,9 +346,6 @@ export default class Tools extends Module {
|
|||
config.placeholder = this.config.placeholder;
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {{api: API, config: ({}), data: BlockToolData}}
|
||||
*/
|
||||
const constructorOptions = {
|
||||
api: this.Editor.API.methods,
|
||||
config,
|
||||
|
@ -356,14 +358,12 @@ export default class Tools extends Module {
|
|||
/**
|
||||
* Return Inline Tool's instance
|
||||
*
|
||||
* @param {InlineTool} tool
|
||||
* @param {ToolSettings} toolSettings
|
||||
* @param {InlineTool} tool - Inline Tool instance
|
||||
* @param {ToolSettings} toolSettings - tool settings
|
||||
*
|
||||
* @returns {InlineTool} — instance
|
||||
*/
|
||||
public constructInline(tool: InlineToolConstructable, toolSettings: ToolSettings = {} as ToolSettings): InlineTool {
|
||||
/**
|
||||
* @type {{api: API}}
|
||||
*/
|
||||
const constructorOptions = {
|
||||
api: this.Editor.API.methods,
|
||||
config: (toolSettings[this.USER_SETTINGS.CONFIG] || {}) as ToolSettings,
|
||||
|
@ -377,22 +377,41 @@ export default class Tools extends Module {
|
|||
* Check if passed Tool is an instance of Initial Block Tool
|
||||
*
|
||||
* @param {Tool} tool - Tool to check
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
public isInitial(tool) {
|
||||
public isInitial(tool): boolean {
|
||||
return tool instanceof this.available[this.config.initialBlock];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return Tool's config by name
|
||||
*
|
||||
* @param {string} toolName
|
||||
* @param {string} toolName - name of tool
|
||||
*
|
||||
* @returns {ToolSettings}
|
||||
*/
|
||||
public getToolSettings(toolName): ToolSettings {
|
||||
return this.toolsSettings[toolName];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns internal tools
|
||||
* Includes Bold, Italic, Link and Paragraph
|
||||
*/
|
||||
public get internalTools(): {[toolName: string]: ToolConstructable|ToolSettings} {
|
||||
return {
|
||||
bold: { class: BoldInlineTool },
|
||||
italic: { class: ItalicInlineTool },
|
||||
link: { class: LinkInlineTool },
|
||||
paragraph: {
|
||||
class: Paragraph,
|
||||
inlineToolbar: true,
|
||||
},
|
||||
stub: { class: Stub },
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds prepare function of plugins with user or default config
|
||||
*
|
||||
|
@ -408,7 +427,7 @@ export default class Tools extends Module {
|
|||
> = [];
|
||||
|
||||
for (const toolName in this.toolsClasses) {
|
||||
if (this.toolsClasses.hasOwnProperty(toolName)) {
|
||||
if (Object.prototype.hasOwnProperty.call(this.toolsClasses, toolName)) {
|
||||
const toolClass = this.toolsClasses[toolName];
|
||||
|
||||
if (typeof toolClass.prepare === 'function') {
|
||||
|
@ -434,12 +453,12 @@ export default class Tools extends Module {
|
|||
/**
|
||||
* Validate Tools configuration objects and throw Error for user if it is invalid
|
||||
*/
|
||||
private validateTools() {
|
||||
private validateTools(): void {
|
||||
/**
|
||||
* Check Tools for a class containing
|
||||
*/
|
||||
for (const toolName in this.config.tools) {
|
||||
if (this.config.tools.hasOwnProperty(toolName)) {
|
||||
if (Object.prototype.hasOwnProperty.call(this.config.tools, toolName)) {
|
||||
if (toolName in this.internalTools) {
|
||||
return;
|
||||
}
|
||||
|
@ -454,21 +473,4 @@ export default class Tools extends Module {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns internal tools
|
||||
* Includes Bold, Italic, Link and Paragraph
|
||||
*/
|
||||
get internalTools() {
|
||||
return {
|
||||
bold: { class: BoldInlineTool },
|
||||
italic: { class: ItalicInlineTool },
|
||||
link: { class: LinkInlineTool },
|
||||
paragraph: {
|
||||
class: Paragraph,
|
||||
inlineToolbar: true,
|
||||
},
|
||||
stub: { class: Stub },
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* eslint-disable jsdoc/no-undefined-types */
|
||||
import Module from '../__module';
|
||||
|
||||
/**
|
||||
|
@ -21,7 +22,7 @@ export default class Tooltip extends Module {
|
|||
|
||||
/**
|
||||
* @class
|
||||
* @param {EditorConfig}
|
||||
* @param {EditorConfig} - Editor's config
|
||||
*/
|
||||
constructor({ config }: ModuleConfig) {
|
||||
super({ config });
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* eslint-disable jsdoc/no-undefined-types */
|
||||
/**
|
||||
* Prebuilded sprite of SVG icons
|
||||
*/
|
||||
|
@ -28,8 +29,8 @@ import Flipper from '../flipper';
|
|||
*
|
||||
* @typedef {UI} UI
|
||||
* @property {EditorConfig} config - editor configuration {@link EditorJS#configuration}
|
||||
* @property {Object} Editor - available editor modules {@link EditorJS#moduleInstances}
|
||||
* @property {Object} nodes -
|
||||
* @property {object} Editor - available editor modules {@link EditorJS#moduleInstances}
|
||||
* @property {object} nodes -
|
||||
* @property {Element} nodes.holder - element where we need to append redactor
|
||||
* @property {Element} nodes.wrapper - <codex-editor>
|
||||
* @property {Element} nodes.redactor - <ce-redactor>
|
||||
|
@ -37,7 +38,8 @@ import Flipper from '../flipper';
|
|||
export default class UI extends Module {
|
||||
/**
|
||||
* Editor.js UI CSS class names
|
||||
* @return {{editorWrapper: string, editorZone: string}}
|
||||
*
|
||||
* @returns {{editorWrapper: string, editorZone: string}}
|
||||
*/
|
||||
public get CSS(): {
|
||||
editorWrapper: string; editorWrapperNarrow: string; editorZone: string; editorZoneHidden: string;
|
||||
|
@ -55,7 +57,8 @@ export default class UI extends Module {
|
|||
|
||||
/**
|
||||
* Return Width of center column of Editor
|
||||
* @return {DOMRect}
|
||||
*
|
||||
* @returns {DOMRect}
|
||||
*/
|
||||
public get contentRect(): DOMRect {
|
||||
if (this.contentRectCache) {
|
||||
|
@ -82,6 +85,7 @@ export default class UI extends Module {
|
|||
|
||||
/**
|
||||
* Flag that became true on mobile viewport
|
||||
*
|
||||
* @type {boolean}
|
||||
*/
|
||||
public isMobile = false;
|
||||
|
@ -98,12 +102,14 @@ export default class UI extends Module {
|
|||
/**
|
||||
* Cache for center column rectangle info
|
||||
* Invalidates on window resize
|
||||
*
|
||||
* @type {DOMRect}
|
||||
*/
|
||||
private contentRectCache: DOMRect = undefined;
|
||||
|
||||
/**
|
||||
* Handle window resize only when it finished
|
||||
*
|
||||
* @type {() => void}
|
||||
*/
|
||||
private resizeDebouncer: () => void = _.debounce(() => {
|
||||
|
@ -184,7 +190,8 @@ export default class UI extends Module {
|
|||
/**
|
||||
* Check if one of Toolbar is opened
|
||||
* Used to prevent global keydowns (for example, Enter) conflicts with Enter-on-toolbar
|
||||
* @return {boolean}
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
public get someToolbarOpened(): boolean {
|
||||
const { Toolbox, BlockSettings, InlineToolbar, ConversionToolbar } = this.Editor;
|
||||
|
@ -226,17 +233,19 @@ export default class UI extends Module {
|
|||
/**
|
||||
* Check for mobile mode and cache a result
|
||||
*/
|
||||
private checkIsMobile() {
|
||||
private checkIsMobile(): void {
|
||||
this.isMobile = window.innerWidth < 650;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes Editor.js interface
|
||||
* @return {Promise<void>}
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
private async make(): Promise<void> {
|
||||
/**
|
||||
* Element where we need to append Editor.js
|
||||
*
|
||||
* @type {Element}
|
||||
*/
|
||||
this.nodes.holder = $.getHolder(this.config.holder);
|
||||
|
@ -270,6 +279,7 @@ export default class UI extends Module {
|
|||
/**
|
||||
* Load CSS
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const styles = require('../../styles/main.css');
|
||||
|
||||
/**
|
||||
|
@ -340,7 +350,8 @@ export default class UI extends Module {
|
|||
|
||||
/**
|
||||
* All keydowns on document
|
||||
* @param {Event} event
|
||||
*
|
||||
* @param {KeyboardEvent} event - keyboard event
|
||||
*/
|
||||
private documentKeydown(event: KeyboardEvent): void {
|
||||
switch (event.keyCode) {
|
||||
|
@ -358,7 +369,8 @@ export default class UI extends Module {
|
|||
|
||||
/**
|
||||
* Ignore all other document's keydown events
|
||||
* @param {KeyboardEvent} event
|
||||
*
|
||||
* @param {KeyboardEvent} event - keyboard event
|
||||
*/
|
||||
private defaultBehaviour(event: KeyboardEvent): void {
|
||||
const keyDownOnEditor = (event.target as HTMLElement).closest(`.${this.CSS.editorWrapper}`);
|
||||
|
@ -384,7 +396,7 @@ export default class UI extends Module {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param {KeyboardEvent} event
|
||||
* @param {KeyboardEvent} event - keyboard event
|
||||
*/
|
||||
private backspacePressed(event: KeyboardEvent): void {
|
||||
const { BlockManager, BlockSelection, Caret } = this.Editor;
|
||||
|
@ -410,7 +422,8 @@ export default class UI extends Module {
|
|||
|
||||
/**
|
||||
* Enter pressed on document
|
||||
* @param event
|
||||
*
|
||||
* @param {KeyboardEvent} event - keyboard event
|
||||
*/
|
||||
private enterPressed(event: KeyboardEvent): void {
|
||||
const { BlockManager, BlockSelection, Caret } = this.Editor;
|
||||
|
@ -468,7 +481,8 @@ export default class UI extends Module {
|
|||
|
||||
/**
|
||||
* All clicks on document
|
||||
* @param {MouseEvent} event - Click
|
||||
*
|
||||
* @param {MouseEvent} event - Click event
|
||||
*/
|
||||
private documentClicked(event: MouseEvent): void {
|
||||
/**
|
||||
|
@ -521,6 +535,8 @@ export default class UI extends Module {
|
|||
* Also:
|
||||
* - Move and show the Toolbar
|
||||
* - Set a Caret
|
||||
*
|
||||
* @param {MouseEvent | TouchEvent} event - touch or mouse event
|
||||
*/
|
||||
private documentTouched(event: MouseEvent | TouchEvent): void {
|
||||
let clickedNode = event.target as HTMLElement;
|
||||
|
@ -571,7 +587,7 @@ export default class UI extends Module {
|
|||
/**
|
||||
* All clicks on the redactor zone
|
||||
*
|
||||
* @param {MouseEvent} event
|
||||
* @param {MouseEvent} event - click event
|
||||
*
|
||||
* @description
|
||||
* - By clicks on the Editor's bottom zone:
|
||||
|
@ -628,7 +644,8 @@ export default class UI extends Module {
|
|||
/**
|
||||
* Handle selection changes on mobile devices
|
||||
* Uses for showing the Inline Toolbar
|
||||
* @param {Event} event
|
||||
*
|
||||
* @param {Event} event - selection event
|
||||
*/
|
||||
private selectionChanged(event: Event): void {
|
||||
const focusedElement = Selection.anchorElement as Element;
|
||||
|
|
|
@ -18,7 +18,9 @@ interface Element {
|
|||
* would be selected by the specified selector string;
|
||||
* otherwise, returns false.
|
||||
*
|
||||
* {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/matches#Polyfill}
|
||||
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/matches#Polyfill}
|
||||
*
|
||||
* @param {string} s - selector
|
||||
*/
|
||||
if (!Element.prototype.matches) {
|
||||
Element.prototype.matches = Element.prototype.matchesSelector ||
|
||||
|
@ -26,7 +28,7 @@ if (!Element.prototype.matches) {
|
|||
Element.prototype.msMatchesSelector ||
|
||||
Element.prototype.oMatchesSelector ||
|
||||
Element.prototype.webkitMatchesSelector ||
|
||||
function (s) {
|
||||
function (s): boolean {
|
||||
const matches = (this.document || this.ownerDocument).querySelectorAll(s);
|
||||
let i = matches.length;
|
||||
|
||||
|
@ -43,10 +45,12 @@ if (!Element.prototype.matches) {
|
|||
* matches the selectors given in parameter.
|
||||
* If there isn't such an ancestor, it returns null.
|
||||
*
|
||||
* {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/closest#Polyfill}
|
||||
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/closest#Polyfill}
|
||||
*
|
||||
* @param {string} s - selector
|
||||
*/
|
||||
if (!Element.prototype.closest) {
|
||||
Element.prototype.closest = function (s) {
|
||||
Element.prototype.closest = function (s): Element | null {
|
||||
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
||||
let el = this;
|
||||
|
||||
|
@ -71,20 +75,22 @@ if (!Element.prototype.closest) {
|
|||
* or DOMString objects before the first child of the ParentNode.
|
||||
* DOMString objects are inserted as equivalent Text nodes.
|
||||
*
|
||||
* {@link https://developer.mozilla.org/en-US/docs/Web/API/ParentNode/prepend#Polyfill}
|
||||
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/ParentNode/prepend#Polyfill}
|
||||
*
|
||||
* @param {Node | Node[] | string | string[]} nodes - nodes to prepend
|
||||
*/
|
||||
if (!Element.prototype.prepend) {
|
||||
Element.prototype.prepend = function prepend(nodes: Node|Node[]|any) {
|
||||
Element.prototype.prepend = function prepend(nodes: Array<Node | string> | Node | string): void {
|
||||
const docFrag = document.createDocumentFragment();
|
||||
|
||||
if (!Array.isArray(nodes)) {
|
||||
nodes = [ nodes ];
|
||||
}
|
||||
|
||||
nodes.forEach((node: Node|any) => {
|
||||
nodes.forEach((node: Node | string) => {
|
||||
const isNode = node instanceof Node;
|
||||
|
||||
docFrag.appendChild(isNode ? node : document.createTextNode(String(node)));
|
||||
docFrag.appendChild(isNode ? node as Node : document.createTextNode(node as string));
|
||||
});
|
||||
|
||||
this.insertBefore(docFrag, this.firstChild);
|
||||
|
|
|
@ -39,7 +39,7 @@ export default class SelectionUtils {
|
|||
*
|
||||
* @returns {{editorWrapper: string, editorZone: string}}
|
||||
*/
|
||||
static get CSS(): { editorWrapper: string; editorZone: string } {
|
||||
public static get CSS(): { editorWrapper: string; editorZone: string } {
|
||||
return {
|
||||
editorWrapper: 'codex-editor',
|
||||
editorZone: 'codex-editor__redactor',
|
||||
|
@ -52,7 +52,7 @@ export default class SelectionUtils {
|
|||
*
|
||||
* @returns {Node|null}
|
||||
*/
|
||||
static get anchorNode(): Node | null {
|
||||
public static get anchorNode(): Node | null {
|
||||
const selection = window.getSelection();
|
||||
|
||||
return selection ? selection.anchorNode : null;
|
||||
|
@ -63,7 +63,7 @@ export default class SelectionUtils {
|
|||
*
|
||||
* @returns {Element|null}
|
||||
*/
|
||||
static get anchorElement(): Element | null {
|
||||
public static get anchorElement(): Element | null {
|
||||
const selection = window.getSelection();
|
||||
|
||||
if (!selection) {
|
||||
|
@ -89,7 +89,7 @@ export default class SelectionUtils {
|
|||
*
|
||||
* @returns {number|null}
|
||||
*/
|
||||
static get anchorOffset(): number | null {
|
||||
public static get anchorOffset(): number | null {
|
||||
const selection = window.getSelection();
|
||||
|
||||
return selection ? selection.anchorOffset : null;
|
||||
|
@ -100,7 +100,7 @@ export default class SelectionUtils {
|
|||
*
|
||||
* @returns {boolean|null}
|
||||
*/
|
||||
static get isCollapsed(): boolean | null {
|
||||
public static get isCollapsed(): boolean | null {
|
||||
const selection = window.getSelection();
|
||||
|
||||
return selection ? selection.isCollapsed : null;
|
||||
|
@ -111,7 +111,7 @@ export default class SelectionUtils {
|
|||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
static get isAtEditor(): boolean {
|
||||
public static get isAtEditor(): boolean {
|
||||
const selection = SelectionUtils.get();
|
||||
|
||||
/**
|
||||
|
@ -140,7 +140,7 @@ export default class SelectionUtils {
|
|||
*
|
||||
* @returns {Range|null}
|
||||
*/
|
||||
static get range(): Range {
|
||||
public static get range(): Range | null {
|
||||
const selection = window.getSelection();
|
||||
|
||||
return selection && selection.rangeCount ? selection.getRangeAt(0) : null;
|
||||
|
@ -149,9 +149,9 @@ export default class SelectionUtils {
|
|||
/**
|
||||
* Calculates position and size of selected text
|
||||
*
|
||||
* @returns {{x, y, width, height, top?, left?, bottom?, right?}}
|
||||
* @returns {DOMRect | ClientRect}
|
||||
*/
|
||||
static get rect(): DOMRect | ClientRect {
|
||||
public static get rect(): DOMRect | ClientRect {
|
||||
let sel: Selection | MSSelection = (document as Document).selection,
|
||||
range: TextRange | Range;
|
||||
|
||||
|
@ -224,20 +224,15 @@ export default class SelectionUtils {
|
|||
*
|
||||
* @returns {string}
|
||||
*/
|
||||
static get text(): string {
|
||||
public static get text(): string {
|
||||
return window.getSelection ? window.getSelection().toString() : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns window SelectionUtils
|
||||
* {@link https://developer.mozilla.org/ru/docs/Web/API/Window/getSelection}
|
||||
* Selection instances
|
||||
*
|
||||
* @returns {Selection}
|
||||
* @todo Check if this is still relevant
|
||||
*/
|
||||
public static get(): Selection {
|
||||
return window.getSelection();
|
||||
}
|
||||
|
||||
public instance: Selection = null;
|
||||
public selection: Selection = null;
|
||||
|
||||
|
@ -261,10 +256,20 @@ export default class SelectionUtils {
|
|||
private readonly commandBackground: string = 'backColor';
|
||||
private readonly commandRemoveFormat: string = 'removeFormat';
|
||||
|
||||
/**
|
||||
* Returns window SelectionUtils
|
||||
* {@link https://developer.mozilla.org/ru/docs/Web/API/Window/getSelection}
|
||||
*
|
||||
* @returns {Selection}
|
||||
*/
|
||||
public static get(): Selection {
|
||||
return window.getSelection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes fake background
|
||||
*/
|
||||
public removeFakeBackground() {
|
||||
public removeFakeBackground(): void {
|
||||
if (!this.isFakeBackgroundEnabled) {
|
||||
return;
|
||||
}
|
||||
|
@ -276,7 +281,7 @@ export default class SelectionUtils {
|
|||
/**
|
||||
* Sets fake background
|
||||
*/
|
||||
public setFakeBackground() {
|
||||
public setFakeBackground(): void {
|
||||
document.execCommand(this.commandBackground, false, '#a8d6ff');
|
||||
|
||||
this.isFakeBackgroundEnabled = true;
|
||||
|
@ -329,6 +334,7 @@ export default class SelectionUtils {
|
|||
* @param {string} tagName - tag to found
|
||||
* @param {string} [className] - tag's class name
|
||||
* @param {number} [searchDepth] - count of tags that can be included. For better performance.
|
||||
*
|
||||
* @returns {HTMLElement|null}
|
||||
*/
|
||||
public findParentTag(tagName: string, className?: string, searchDepth = 10): HTMLElement | null {
|
||||
|
@ -402,7 +408,7 @@ export default class SelectionUtils {
|
|||
/**
|
||||
* Expands selection range to the passed parent node
|
||||
*
|
||||
* @param {HTMLElement} element
|
||||
* @param {HTMLElement} element - element which contents should be selcted
|
||||
*/
|
||||
public expandToTag(element: HTMLElement): void {
|
||||
const selection = window.getSelection();
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
import $ from '../../dom';
|
||||
import { BlockTool, BlockToolData } from '../../../../types';
|
||||
|
||||
export interface StubData extends BlockToolData{
|
||||
title: string;
|
||||
savedData: BlockToolData;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -38,11 +43,9 @@ export default class Stub implements BlockTool {
|
|||
private readonly savedData: BlockToolData;
|
||||
|
||||
/**
|
||||
* @param data
|
||||
* @param config
|
||||
* @param api
|
||||
* @param {BlockToolData} data - stub tool data
|
||||
*/
|
||||
constructor({ data, config, api }) {
|
||||
constructor({ data }: {data: StubData}) {
|
||||
this.title = data.title || 'Error';
|
||||
this.subtitle = 'The block can not be displayed correctly.';
|
||||
this.savedData = data.savedData;
|
||||
|
|
|
@ -22,10 +22,13 @@ declare const VERSION: string;
|
|||
/**
|
||||
* @typedef {object} ChainData
|
||||
* @property {object} data - data that will be passed to the success or fallback
|
||||
* @property {Function} function - function's that must be called asynchronically
|
||||
* @property {Function} function - function's that must be called asynchronously
|
||||
*
|
||||
* @interface ChainData
|
||||
*/
|
||||
export interface ChainData {
|
||||
data?: any;
|
||||
data?: object;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
function: (...args: any[]) => any;
|
||||
}
|
||||
|
||||
|
@ -79,6 +82,7 @@ function _log(
|
|||
labeled: boolean,
|
||||
msg: string,
|
||||
type = 'log',
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
args?: any,
|
||||
style = 'color: inherit'
|
||||
): void {
|
||||
|
@ -172,7 +176,8 @@ export const logLabeled = _log.bind(window, true);
|
|||
/**
|
||||
* Returns true if passed key code is printable (a-Z, 0-9, etc) character.
|
||||
*
|
||||
* @param {number} keyCode
|
||||
* @param {number} keyCode - key code
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isPrintableKey(keyCode: number): boolean {
|
||||
|
@ -196,24 +201,24 @@ export function isPrintableKey(keyCode: number): boolean {
|
|||
export async function sequence(
|
||||
chains: ChainData[],
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
success: (data: any) => void = (): void => {},
|
||||
success: (data: object) => void = (): void => {},
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
fallback: (data: any) => void = (): void => {},
|
||||
fallback: (data: object) => void = (): void => {}
|
||||
): Promise<void> {
|
||||
/**
|
||||
* Decorator
|
||||
*
|
||||
* @param {ChainData} chainData
|
||||
* @param {ChainData} chainData - Chain data
|
||||
*
|
||||
* @param {Function} successCallback
|
||||
* @param {Function} fallbackCallback
|
||||
* @param {Function} successCallback - success callback
|
||||
* @param {Function} fallbackCallback - fail callback
|
||||
*
|
||||
* @returns {Promise}
|
||||
*/
|
||||
async function waitNextBlock(
|
||||
chainData: ChainData,
|
||||
successCallback: (data: any) => void,
|
||||
fallbackCallback: (data: any) => void
|
||||
successCallback: (data: object) => void,
|
||||
fallbackCallback: (data: object) => void
|
||||
): Promise<void> {
|
||||
try {
|
||||
await chainData.function(chainData.data);
|
||||
|
@ -240,10 +245,11 @@ export async function sequence(
|
|||
/**
|
||||
* Make array from array-like collection
|
||||
*
|
||||
* @param {ArrayLike} collection
|
||||
* @param {ArrayLike} collection - collection to convert to array
|
||||
*
|
||||
* @returns {Array}
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export function array(collection: ArrayLike<any>): any[] {
|
||||
return Array.prototype.slice.call(collection);
|
||||
}
|
||||
|
@ -251,19 +257,23 @@ export function array(collection: ArrayLike<any>): any[] {
|
|||
/**
|
||||
* Check if passed variable is a function
|
||||
*
|
||||
* @param {*} fn
|
||||
* @param {*} fn - function to check
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isFunction(fn: any): boolean {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export function isFunction(fn: any): fn is Function {
|
||||
return typeof fn === 'function';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if passed function is a class
|
||||
*
|
||||
* @param {Function} fn
|
||||
* @param {Function} fn - function to check
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
// 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());
|
||||
}
|
||||
|
@ -271,7 +281,8 @@ export function isClass(fn: any): boolean {
|
|||
/**
|
||||
* Checks if object is empty
|
||||
*
|
||||
* @param {object} object
|
||||
* @param {object} object - object to check
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isEmpty(object: object): boolean {
|
||||
|
@ -288,18 +299,20 @@ export function isEmpty(object: object): boolean {
|
|||
* @param {*} object - object to check
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isPromise(object: any): boolean {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export function isPromise(object: any): object is Promise<any> {
|
||||
return Promise.resolve(object) === object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delays method execution
|
||||
*
|
||||
* @param {Function} method
|
||||
* @param {number} timeout
|
||||
* @param {Function} method - method to execute
|
||||
* @param {number} timeout - timeout in ms
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export function delay(method: (...args: any[]) => any, timeout: number) {
|
||||
return function() {
|
||||
return function (): void {
|
||||
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
||||
const context = this,
|
||||
// eslint-disable-next-line prefer-rest-params
|
||||
|
@ -312,8 +325,9 @@ export function delay(method: (...args: any[]) => any, timeout: number) {
|
|||
/**
|
||||
* Get file extension
|
||||
*
|
||||
* @param {File} file
|
||||
* @returns string
|
||||
* @param {File} file - file
|
||||
*
|
||||
* @returns {string}
|
||||
*/
|
||||
export function getFileExtension(file: File): string {
|
||||
return file.name.split('.').pop();
|
||||
|
@ -322,8 +336,9 @@ export function getFileExtension(file: File): string {
|
|||
/**
|
||||
* Check if string is MIME type
|
||||
*
|
||||
* @param {string} type
|
||||
* @returns boolean
|
||||
* @param {string} type - string to check
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isValidMimeType(type: string): boolean {
|
||||
return /^[-\w]+\/([-+\w]+|\*)$/.test(type);
|
||||
|
@ -416,22 +431,35 @@ export function getUserOS(): {[key: string]: boolean} {
|
|||
/**
|
||||
* Capitalizes first letter of the string
|
||||
*
|
||||
* @param {string} text
|
||||
* @param {string} text - text to capitalize
|
||||
*
|
||||
* @returns {string}
|
||||
*/
|
||||
export function capitalize(text: string): string {
|
||||
return text[0].toUpperCase() + text.slice(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return string representation of the object type
|
||||
*
|
||||
* @param {*} object - object to get type
|
||||
*
|
||||
* @returns {string}
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export function typeOf(object: any): string {
|
||||
return Object.prototype.toString.call(object).match(/\s([a-zA-Z]+)/)[1].toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge to objects recursively
|
||||
*
|
||||
* @param {object} target
|
||||
* @param {object[]} sources
|
||||
* @param {object} target - merge target
|
||||
* @param {object[]} sources - merge sources
|
||||
* @returns {object}
|
||||
*/
|
||||
export function deepMerge(target, ...sources): {[key: string]: any} {
|
||||
const isObject = (item) => item && typeOf(item) === 'object';
|
||||
export function deepMerge<T extends object>(target, ...sources): T {
|
||||
const isObject = (item): item is object => item && typeOf(item) === 'object';
|
||||
|
||||
if (!sources.length) {
|
||||
return target;
|
||||
|
@ -467,15 +495,6 @@ export function deepMerge(target, ...sources): {[key: string]: any} {
|
|||
*/
|
||||
export const isTouchSupported: boolean = 'ontouchstart' in document.documentElement;
|
||||
|
||||
/**
|
||||
* Return string representation of the object type
|
||||
*
|
||||
* @param {any} object
|
||||
*/
|
||||
export function typeOf(object: any): string {
|
||||
return Object.prototype.toString.call(object).match(/\s([a-zA-Z]+)/)[1].toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make shortcut command more human-readable
|
||||
*
|
||||
|
@ -511,7 +530,7 @@ export function beautifyShortcut(shortcut: string): string {
|
|||
* If url has `one slash`, then it concatenates with window location origin
|
||||
* or when url has `two lack` it appends only protocol
|
||||
*
|
||||
* @param {string} url
|
||||
* @param {string} url - url to prettify
|
||||
*/
|
||||
export function getValidUrl(url: string): string {
|
||||
try {
|
||||
|
|
2
types/tools/block-tool-data.d.ts
vendored
2
types/tools/block-tool-data.d.ts
vendored
|
@ -2,4 +2,4 @@
|
|||
* Object returned by Tool's {@link BlockTool#save} method
|
||||
* Specified by Tool developer, so leave it as object
|
||||
*/
|
||||
export type BlockToolData = object;
|
||||
export type BlockToolData<T extends object = any> = T;
|
||||
|
|
17
types/tools/block-tool.d.ts
vendored
17
types/tools/block-tool.d.ts
vendored
|
@ -1,10 +1,11 @@
|
|||
import { ConversionConfig, PasteConfig, SanitizerConfig } from '../configs';
|
||||
import { BlockToolData } from './block-tool-data';
|
||||
import { BaseTool, BaseToolConstructable } from './tool';
|
||||
import {BaseTool, BaseToolConstructable, BaseToolConstructorOptions} from './tool';
|
||||
import { ToolConfig } from './tool-config';
|
||||
import { API } from '../index';
|
||||
import { PasteEvent } from './paste-events';
|
||||
import { MoveEvent } from './hook-events';
|
||||
|
||||
/**
|
||||
* Describe Block Tool object
|
||||
* @see {@link docs/tools.md}
|
||||
|
@ -73,6 +74,15 @@ export interface BlockTool extends BaseTool {
|
|||
moved?(event: MoveEvent): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe constructor parameters
|
||||
*/
|
||||
export interface BlockToolConstructorOptions extends BaseToolConstructorOptions {
|
||||
api: API;
|
||||
data: BlockToolData;
|
||||
config?: ToolConfig;
|
||||
}
|
||||
|
||||
export interface BlockToolConstructable extends BaseToolConstructable {
|
||||
/**
|
||||
* Tool's Toolbox settings
|
||||
|
@ -101,7 +111,10 @@ export interface BlockToolConstructable extends BaseToolConstructable {
|
|||
|
||||
/**
|
||||
* @constructor
|
||||
*
|
||||
* @param {BlockToolConstructorOptions} config - constructor parameters
|
||||
*
|
||||
* @return {BlockTool}
|
||||
*/
|
||||
new(config: { api: API, config: ToolConfig, data: BlockToolData }): BlockTool;
|
||||
new(config: BlockToolConstructorOptions): BlockTool;
|
||||
}
|
||||
|
|
2
types/tools/index.d.ts
vendored
2
types/tools/index.d.ts
vendored
|
@ -12,4 +12,4 @@ export * from './paste-events';
|
|||
export * from './hook-events';
|
||||
|
||||
export type Tool = BaseTool | BlockTool | InlineTool;
|
||||
export type ToolConstructable = BaseToolConstructable | BlockToolConstructable | InlineToolConstructable;
|
||||
export type ToolConstructable = BlockToolConstructable | InlineToolConstructable;
|
||||
|
|
19
types/tools/inline-tool.d.ts
vendored
19
types/tools/inline-tool.d.ts
vendored
|
@ -1,4 +1,5 @@
|
|||
import {BaseTool, BaseToolConstructable} from './tool';
|
||||
import {API, ToolConfig} from "../index";
|
||||
/**
|
||||
* Base structure for the Inline Toolbar Tool
|
||||
*/
|
||||
|
@ -34,4 +35,20 @@ export interface InlineTool extends BaseTool {
|
|||
clear?(): void;
|
||||
}
|
||||
|
||||
export interface InlineToolConstructable extends BaseToolConstructable {}
|
||||
|
||||
/**
|
||||
* Describe constructor parameters
|
||||
*/
|
||||
export interface InlineToolConstructorOptions {
|
||||
api: API;
|
||||
config?: ToolConfig;
|
||||
}
|
||||
|
||||
export interface InlineToolConstructable extends BaseToolConstructable {
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param {InlineToolConstructorOptions} config - constructor parameters
|
||||
*/
|
||||
new(config: InlineToolConstructorOptions): BaseTool;
|
||||
}
|
||||
|
|
7
types/tools/tool.d.ts
vendored
7
types/tools/tool.d.ts
vendored
|
@ -1,4 +1,4 @@
|
|||
import {API, ToolSettings} from '../index';
|
||||
import {API, BlockToolData, ToolSettings} from '../index';
|
||||
import {ToolConfig} from './tool-config';
|
||||
import {SanitizerConfig} from '../configs';
|
||||
|
||||
|
@ -30,11 +30,6 @@ export interface BaseToolConstructable {
|
|||
*/
|
||||
title?: string;
|
||||
|
||||
/**
|
||||
* Describe constructor parameters
|
||||
*/
|
||||
new (config: {api: API, config?: ToolSettings}): BaseTool;
|
||||
|
||||
/**
|
||||
* Tool`s prepare method. Can be async
|
||||
* @param data
|
||||
|
|
Loading…
Reference in a new issue