Skip to content

Commit

Permalink
Merge enter fix
Browse files Browse the repository at this point in the history
  • Loading branch information
xdan committed Feb 11, 2023
2 parents 265d32e + c83ef38 commit d45058a
Show file tree
Hide file tree
Showing 27 changed files with 601 additions and 491 deletions.
11 changes: 6 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#### :bug: Bug Fix

- [Wrong new empty paragraph location when cursor is set after a table and <Enter> key is pressed #953](https://github.com/xdan/jodit/issues/953)
- The PluginSystem module has been refactored: now asynchronous plugins do not block the initialization of the editor and it is ready to work without them.

## 3.24.4

Expand Down Expand Up @@ -1983,11 +1984,11 @@ Related with https://github.com/xdan/jodit/issues/574. In some cases need to lim
- @property {IUIOption[]} link.selectOptionsClassName=[] The list of the option for the select (to use with
modeClassName="select")
- ex: [
- { value: "", text: "" },
- { value: "val1", text: "text1" },
- { value: "val2", text: "text2" },
- { value: "val3", text: "text3" }
- ]
- { value: "", text: "" },
- { value: "val1", text: "text1" },
- { value: "val2", text: "text2" },
- { value: "val3", text: "text3" }
- ]
PR: https://github.com/xdan/jodit/pull/577 Thanks @s-renier-taonix-fr
##### New option `statusbar: boolean = true`
Expand Down
2 changes: 2 additions & 0 deletions src/core/dom/dom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1006,6 +1006,8 @@ export class Dom {
static safeInsertNode(range: Range, node: Node): void {
range.collapsed || range.deleteContents();
range.insertNode(node);
range.setStartBefore(node);
range.collapse(true);

// https://developer.mozilla.org/en-US/docs/Web/API/Range/insertNode
// if the new node is to be added to a text Node, that Node is split at the
Expand Down
80 changes: 80 additions & 0 deletions src/core/plugin/helpers/init-instance.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*!
* Jodit Editor (https://xdsoft.net/jodit/)
* Released under MIT see LICENSE.txt in the project root for license information.
* Copyright (c) 2013-2023 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
*/

/**
* @module plugin
*/

import type { IDictionary, IJodit, IPlugin, PluginInstance } from 'jodit/types';
import { isInitable } from 'jodit/core/helpers/checker';
import { loadStyle } from './load'

/**
* Init plugin and try init waiting list
* @private
*/
export function initInstance(
jodit: IJodit,
pluginName: string,
instance: PluginInstance,
doneList: Set<string>,
waitingList: IDictionary<PluginInstance>
): void {
if (init(jodit, pluginName, instance, doneList, waitingList)) {
Object.keys(waitingList).forEach(name => {
const plugin = waitingList[name];
init(jodit, name, plugin, doneList, waitingList);
});
}
}

/**
* Init plugin if it has not dependencies in another case wait requires plugins will be init
* @private
*/
export function init(
jodit: IJodit,
pluginName: string,
instance: PluginInstance,
doneList: Set<string>,
waitingList: IDictionary<PluginInstance>
): boolean {
const req = (instance as IPlugin).requires;

if (req?.length && !req.every(name => doneList.has(name))) {
// @ts-ignore
if (!isProd && !isTest && !waitingList[pluginName]) {
console.log('Await plugin: ', pluginName);
}

waitingList[pluginName] = instance;
return false;
}

if (isInitable(instance)) {
try {
instance.init(jodit);
} catch (e) {
console.error(e);

// @ts-ignore
if (!isProd) {
throw e;
}
}
}

doneList.add(pluginName);
delete waitingList[pluginName];

if ((instance as IPlugin).hasStyle) {
loadStyle(jodit, pluginName).catch(e => {
!isProd && console.log(e);
});
}

return true;
}
98 changes: 98 additions & 0 deletions src/core/plugin/helpers/load.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/*!
* Jodit Editor (https://xdsoft.net/jodit/)
* Released under MIT see LICENSE.txt in the project root for license information.
* Copyright (c) 2013-2023 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
*/

/**
* @module plugin
*/

import type { IExtraPlugin, IJodit, PluginType } from 'jodit/types';
import {
appendScriptAsync,
appendStyleAsync
} from 'jodit/core/helpers/utils/append-script';
import { kebabCase } from 'jodit/core/helpers/string/kebab-case';
import { normalizeName } from 'jodit/core/plugin/helpers/utils';

const styles: Set<string> = new Set();

/**
* @private
*/
export async function loadStyle(
jodit: IJodit,
pluginName: string
): Promise<void> {
const url = getFullUrl(jodit, pluginName, false);

if (styles.has(url)) {
return;
}

styles.add(url);

return appendStyleAsync(jodit, url);
}

/**
* Call full url to the script or style file
* @private
*/
function getFullUrl(jodit: IJodit, name: string, js: boolean): string {
name = kebabCase(name);

return (
jodit.basePath +
'plugins/' +
name +
'/' +
name +
'.' +
(js ? 'js' : 'css')
);
}

/**
* @private
*/
export function loadExtras(
items: Map<string, PluginType>,
jodit: IJodit,
extrasList: IExtraPlugin[],
callback: () => void
): void {
try {
const needLoadExtras = extrasList.filter(
extra => !items.has(normalizeName(extra.name))
);

if (needLoadExtras.length) {
load(jodit, needLoadExtras, callback);
}
} catch (e) {
// @ts-ignore
if (!isProd) {
throw e;
}
}
}

/**
* Download plugins
* @private
*/
function load(
jodit: IJodit,
pluginList: IExtraPlugin[],
callback: () => void
): void {
pluginList.map(extra => {
const url = extra.url || getFullUrl(jodit, extra.name, true);

return appendScriptAsync(jodit, url)
.then(callback)
.catch(() => null);
});
}
40 changes: 40 additions & 0 deletions src/core/plugin/helpers/make-instance.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*!
* Jodit Editor (https://xdsoft.net/jodit/)
* Released under MIT see LICENSE.txt in the project root for license information.
* Copyright (c) 2013-2023 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
*/

/**
* @module plugin
*/

import type { IJodit, Nullable, PluginInstance, PluginType } from 'jodit/types';
import { isFunction } from 'jodit/core/helpers/checker';

/**
* Create instance of plugin
* @private
*/
export function makeInstance(
jodit: IJodit,
plugin: PluginType
): Nullable<PluginInstance> {
try {
try {
// @ts-ignore
return isFunction(plugin) ? new plugin(jodit) : plugin;
} catch (e) {
if (isFunction(plugin) && !plugin.prototype) {
return (plugin as Function)(jodit);
}
}
} catch (e) {
console.error(e);
// @ts-ignore
if (!isProd) {
throw e;
}
}

return null;
}
18 changes: 18 additions & 0 deletions src/core/plugin/helpers/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*!
* Jodit Editor (https://xdsoft.net/jodit/)
* Released under MIT see LICENSE.txt in the project root for license information.
* Copyright (c) 2013-2023 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
*/

/**
* @module plugin
*/

import { kebabCase } from 'jodit/core/helpers/string/kebab-case';

/**
* @private
*/
export function normalizeName(name: string): string {
return kebabCase(name).toLowerCase();
}
15 changes: 15 additions & 0 deletions src/core/plugin/interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*!
* Jodit Editor (https://xdsoft.net/jodit/)
* Released under MIT see LICENSE.txt in the project root for license information.
* Copyright (c) 2013-2023 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
*/

declare module 'jodit/types/events' {
interface IEventEmitter {
/**
* Emitted every time after the plugins have been initialized
* or a deferred plugin has been loaded and also initialized
*/
on(event: 'updatePlugins', callback: () => void): this;
}
}
Loading

0 comments on commit d45058a

Please sign in to comment.