Skip to content

Commit

Permalink
Migrate to new installation methods
Browse files Browse the repository at this point in the history
  • Loading branch information
filipsobol committed May 31, 2024
1 parent 81e323b commit 4fbf432
Show file tree
Hide file tree
Showing 23 changed files with 1,815 additions and 1,072 deletions.
33 changes: 5 additions & 28 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,39 +20,24 @@
"dependencies": {
"prop-types": "^15.7.2"
},
"peerDependencies": {
"ckeditor5": ">=42.0.0 || ^0.0.0-nightly",
"react": "^16.13.1 || ^17.0.0 || ^18.0.0"
},
"devDependencies": {
"@babel/core": "^7.10.5",
"@babel/preset-react": "^7.10.4",
"@ckeditor/ckeditor5-autoformat": "^41.3.1",
"@ckeditor/ckeditor5-basic-styles": "^41.3.1",
"@ckeditor/ckeditor5-block-quote": "^41.3.1",
"@ckeditor/ckeditor5-build-classic": "^41.3.1",
"@ckeditor/ckeditor5-build-multi-root": "^41.3.1",
"@ckeditor/ckeditor5-cloud-services": "^41.3.1",
"@ckeditor/ckeditor5-dev-bump-year": "^38.0.0",
"@ckeditor/ckeditor5-dev-ci": "^38.0.0",
"@ckeditor/ckeditor5-dev-release-tools": "^38.0.0",
"@ckeditor/ckeditor5-dev-utils": "^38.0.0",
"@ckeditor/ckeditor5-editor-classic": "^41.3.1",
"@ckeditor/ckeditor5-editor-multi-root": "^41.3.1",
"@ckeditor/ckeditor5-essentials": "^41.3.1",
"@ckeditor/ckeditor5-heading": "^41.3.1",
"@ckeditor/ckeditor5-image": "^41.3.1",
"@ckeditor/ckeditor5-indent": "^41.3.1",
"@ckeditor/ckeditor5-link": "^41.3.1",
"@ckeditor/ckeditor5-list": "^41.3.1",
"@ckeditor/ckeditor5-media-embed": "^41.3.1",
"@ckeditor/ckeditor5-paste-from-office": "^41.3.1",
"@ckeditor/ckeditor5-table": "^41.3.1",
"@ckeditor/ckeditor5-utils": "^41.3.1",
"@ckeditor/ckeditor5-watchdog": "^41.3.1",
"@testing-library/react-hooks": "^8.0.1",
"@types/react": "^16.14.35",
"@types/react-dom": "^16.9.18",
"babel-loader": "^8.1.0",
"babel-plugin-istanbul": "^6.1.0",
"chai": "^4.2.0",
"ckeditor5": "^41.3.1",
"ckeditor5": "nightly",
"coveralls": "^3.1.1",
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.2",
Expand Down Expand Up @@ -87,14 +72,6 @@
"string-width": "^4.0.0",
"semver": "^7.0.0"
},
"peerDependencies": {
"@ckeditor/ckeditor5-core": ">=41.3.1",
"@ckeditor/ckeditor5-editor-multi-root": ">=41.3.1",
"@ckeditor/ckeditor5-engine": ">=41.3.1",
"@ckeditor/ckeditor5-utils": ">=41.3.1",
"@ckeditor/ckeditor5-watchdog": ">=41.3.1",
"react": "^16.13.1 || ^17.0.0 || ^18.0.0"
},
"engines": {
"node": ">=18.0.0"
},
Expand Down
3 changes: 0 additions & 3 deletions scripts/utils/getkarmaconfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,6 @@ module.exports = function getKarmaConfig() {
frameworks: [ 'mocha', 'chai', 'sinon', 'webpack' ],

files: [
// If the file below is imported in tests directly, it leads to an error related to CKEDITOR_VERSION collision.
// It may be related to presets that are required for *.jsx files.
path.resolve( __dirname, '..', '..', 'tests', '_utils', '_buildclassicdll.js' ),
'tests/**/*.js',
'tests/**/*.jsx'
],
Expand Down
63 changes: 36 additions & 27 deletions src/ckeditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,21 @@

import React from 'react';
import PropTypes, { type InferProps, type Validator } from 'prop-types';

import uid from '@ckeditor/ckeditor5-utils/src/uid';

import type { EventInfo } from '@ckeditor/ckeditor5-utils';
import type { Editor, EditorConfig } from '@ckeditor/ckeditor5-core';
import type { DocumentChangeEvent } from '@ckeditor/ckeditor5-engine';

import { EditorWatchdog, ContextWatchdog } from '@ckeditor/ckeditor5-watchdog';
import type { WatchdogConfig } from '@ckeditor/ckeditor5-watchdog/src/watchdog';
import type { EditorCreatorFunction } from '@ckeditor/ckeditor5-watchdog/src/editorwatchdog';

import type {
EventInfo,
Editor,
EditorConfig,
DocumentChangeEvent,
EditorWatchdog,
ContextWatchdog,
WatchdogConfig,
EditorCreatorFunction
} from 'ckeditor5';

import { uid } from './utils/uid';
import { ContextWatchdogContext } from './ckeditorcontext';

import type { EditorSemaphoreMountResult } from './lifecycle/LifeCycleEditorSemaphore';
import { LifeCycleElementSemaphore } from './lifecycle/LifeCycleElementSemaphore';
import type { EditorSemaphoreMountResult } from './lifecycle/LifeCycleEditorSemaphore';

const REACT_INTEGRATION_READ_ONLY_LOCK_ID = 'Lock from React integration (@ckeditor/ckeditor5-react)';

Expand All @@ -41,17 +41,26 @@ export default class CKEditor<TEditor extends Editor> extends React.Component<Pr
constructor( props: Props<TEditor> ) {
super( props );

this._checkVersion();
}

/**
* Checks if the CKEditor version used in the application is compatible with the component.
*/
private _checkVersion(): void {
const { CKEDITOR_VERSION } = window;

if ( CKEDITOR_VERSION ) {
const [ major ] = CKEDITOR_VERSION.split( '.' ).map( Number );
if ( !CKEDITOR_VERSION ) {
return console.warn( 'Cannot find the "CKEDITOR_VERSION" in the "window" scope.' );
}

if ( major < 37 ) {
console.warn( 'The <CKEditor> component requires using CKEditor 5 in version 37 or higher.' );
}
} else {
console.warn( 'Cannot find the "CKEDITOR_VERSION" in the "window" scope.' );
const [ major ] = CKEDITOR_VERSION.split( '.' ).map( Number );

if ( major >= 42 || CKEDITOR_VERSION.startsWith( '0.0.0' ) ) {
return;
}

console.warn( 'The <CKEditor> component requires using CKEditor 5 in version 42+ or nightly build.' );
}

private get _semaphoreValue(): EditorSemaphoreMountResult<TEditor> | null {
Expand Down Expand Up @@ -208,11 +217,11 @@ export default class CKEditor<TEditor extends Editor> extends React.Component<Pr
}

const watchdog = ( () => {
if ( this.context instanceof ContextWatchdog ) {
if ( this.context instanceof this.props.editor.ContextWatchdog ) {
return new EditorWatchdogAdapter( this.context );
}

return new CKEditor._EditorWatchdog( this.props.editor, this.props.watchdogConfig );
return new this.props.editor.EditorWatchdog( this.props.editor, this.props.watchdogConfig );
} )() as EditorWatchdogAdapter<TEditor>;

const totalRestartsRef = {
Expand Down Expand Up @@ -409,17 +418,17 @@ export default class CKEditor<TEditor extends Editor> extends React.Component<Pr
disabled: PropTypes.bool,
id: PropTypes.any
};

// Store the API in the static property to easily overwrite it in tests.
// Too bad dependency injection does not work in Webpack + ES 6 (const) + Babel.
public static _EditorWatchdog = EditorWatchdog;
}

/**
* TODO this is type space definition for props, the CKEditor.propTypes is a run-time props validation that should match.
*/
interface Props<TEditor extends Editor> extends InferProps<typeof CKEditor.propTypes> {
editor: { create( ...args: any ): Promise<TEditor> };
editor: {
create( ...args: any ): Promise<TEditor>;
EditorWatchdog: typeof EditorWatchdog;
ContextWatchdog: typeof ContextWatchdog;
};
config?: EditorConfig;
watchdogConfig?: WatchdogConfig;
disableWatchdog?: boolean;
Expand Down
14 changes: 9 additions & 5 deletions src/ckeditorcontext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@
import React, { type ReactNode } from 'react';
import PropTypes, { type InferProps, type Validator } from 'prop-types';

import { ContextWatchdog } from '@ckeditor/ckeditor5-watchdog';
import type { WatchdogConfig } from '@ckeditor/ckeditor5-watchdog/src/watchdog';

import type { Context, ContextConfig } from '@ckeditor/ckeditor5-core';
import type {
ContextWatchdog,
WatchdogConfig,
Context,
ContextConfig
} from 'ckeditor5';

export const ContextWatchdogContext = React.createContext<ContextWatchdog | 'contextWatchdog' | null>( 'contextWatchdog' );

Expand Down Expand Up @@ -67,7 +69,8 @@ export default class CKEditorContext<TContext extends Context = Context> extends
}

private async _initializeContextWatchdog( config?: ContextConfig ): Promise<void> {
this.contextWatchdog = new ContextWatchdog( this.props.context!, this.props.watchdogConfig );
// eslint-disable-next-line new-cap
this.contextWatchdog = new this.props.contextWatchdog( this.props.context!, this.props.watchdogConfig );

this.contextWatchdog.on( 'error', ( _, errorEvent ) => {
this.props.onError( errorEvent.error, {
Expand Down Expand Up @@ -116,6 +119,7 @@ export default class CKEditorContext<TContext extends Context = Context> extends

interface Props<TContext extends Context> extends InferProps<typeof CKEditorContext.propTypes> {
context?: { create( ...args: any ): Promise<TContext> };
contextWatchdog: typeof ContextWatchdog<TContext>;
watchdogConfig?: WatchdogConfig;
config?: ContextConfig;
onReady?: ( context: Context ) => void; // TODO this should accept TContext (after ContextWatchdog release).
Expand Down
3 changes: 1 addition & 2 deletions src/lifecycle/LifeCycleEditorSemaphore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
* For licensing, see LICENSE.md.
*/

import type { Editor } from '@ckeditor/ckeditor5-core';
import type { EditorWatchdog } from '@ckeditor/ckeditor5-watchdog';
import type { Editor, EditorWatchdog } from 'ckeditor5';

import type { EditorWatchdogAdapter } from '../ckeditor';
import type { LifeCycleElementSemaphore } from './LifeCycleElementSemaphore';
Expand Down
28 changes: 16 additions & 12 deletions src/useMultiRootEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,20 @@ import React, {
type Dispatch, type SetStateAction, type RefObject
} from 'react';

import type { InlineEditableUIView } from '@ckeditor/ckeditor5-ui';
import type { EditorConfig } from '@ckeditor/ckeditor5-core';
import type { DocumentChangeEvent, Writer, RootElement } from '@ckeditor/ckeditor5-engine';

import { ContextWatchdog, EditorWatchdog } from '@ckeditor/ckeditor5-watchdog';
import type { WatchdogConfig } from '@ckeditor/ckeditor5-watchdog/src/watchdog';

import type { AddRootEvent, DetachRootEvent } from '@ckeditor/ckeditor5-editor-multi-root/src/multirooteditor';
import type MultiRootEditor from '@ckeditor/ckeditor5-build-multi-root';
import type EventInfo from '@ckeditor/ckeditor5-utils/src/eventinfo';
import type {
InlineEditableUIView,
EditorConfig,
DocumentChangeEvent,
Writer,
RootElement,
ContextWatchdog,
EditorWatchdog,
WatchdogConfig,
AddRootEvent,
DetachRootEvent,
MultiRootEditor,
EventInfo
} from 'ckeditor5';

import { ContextWatchdogContext } from './ckeditorcontext';
import { EditorWatchdogAdapter } from './ckeditor';
Expand Down Expand Up @@ -332,11 +336,11 @@ const useMultiRootEditor = ( props: MultiRootHookProps ): MultiRootHookReturns =
}

const watchdog = ( () => {
if ( context instanceof ContextWatchdog ) {
if ( context instanceof props.editor.ContextWatchdog ) {
return new EditorWatchdogAdapter( context );
}

return new EditorWatchdog( props.editor, props.watchdogConfig );
return new props.editor.EditorWatchdog( props.editor, props.watchdogConfig );
} )() as EditorWatchdogAdapter<MultiRootEditor>;

const totalRestartsRef = {
Expand Down
57 changes: 57 additions & 0 deletions src/utils/uid.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/**
* @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md.
*/

/**
* A hash table of hex numbers to avoid using toString() in uid() which is costly.
* [ '00', '01', '02', ..., 'fe', 'ff' ]
*/
const HEX_NUMBERS = new Array( 256 ).fill( '' )
.map( ( _, index ) => ( '0' + ( index ).toString( 16 ) ).slice( -2 ) );

/**
* Returns a unique id. The id starts with an "e" character and a randomly generated string of
* 32 alphanumeric characters.
*
* **Note**: The characters the unique id is built from correspond to the hex number notation
* (from "0" to "9", from "a" to "f"). In other words, each id corresponds to an "e" followed
* by 16 8-bit numbers next to each other.
*
* @returns An unique id string.
*/
export function uid(): string {
// Let's create some positive random 32bit integers first.
//
// 1. Math.random() is a float between 0 and 1.
// 2. 0x100000000 is 2^32 = 4294967296.
// 3. >>> 0 enforces integer (in JS all numbers are floating point).
//
// For instance:
// Math.random() * 0x100000000 = 3366450031.853859
// but
// Math.random() * 0x100000000 >>> 0 = 3366450031.
const r1 = Math.random() * 0x100000000 >>> 0;
const r2 = Math.random() * 0x100000000 >>> 0;
const r3 = Math.random() * 0x100000000 >>> 0;
const r4 = Math.random() * 0x100000000 >>> 0;

// Make sure that id does not start with number.
return 'e' +
HEX_NUMBERS[ r1 >> 0 & 0xFF ] +
HEX_NUMBERS[ r1 >> 8 & 0xFF ] +
HEX_NUMBERS[ r1 >> 16 & 0xFF ] +
HEX_NUMBERS[ r1 >> 24 & 0xFF ] +
HEX_NUMBERS[ r2 >> 0 & 0xFF ] +
HEX_NUMBERS[ r2 >> 8 & 0xFF ] +
HEX_NUMBERS[ r2 >> 16 & 0xFF ] +
HEX_NUMBERS[ r2 >> 24 & 0xFF ] +
HEX_NUMBERS[ r3 >> 0 & 0xFF ] +
HEX_NUMBERS[ r3 >> 8 & 0xFF ] +
HEX_NUMBERS[ r3 >> 16 & 0xFF ] +
HEX_NUMBERS[ r3 >> 24 & 0xFF ] +
HEX_NUMBERS[ r4 >> 0 & 0xFF ] +
HEX_NUMBERS[ r4 >> 8 & 0xFF ] +
HEX_NUMBERS[ r4 >> 16 & 0xFF ] +
HEX_NUMBERS[ r4 >> 24 & 0xFF ];
}
Loading

0 comments on commit 4fbf432

Please sign in to comment.