Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve narrowing of CKEditor CDN configuration type #523

Merged
merged 4 commits into from
Sep 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,9 @@ jobs:
- run:
name: Run build
command: yarn run build
- run:
name: Check types of tests
command: yarn run test:check:types
- run:
name: Run unit tests
command: yarn run test
Expand Down Expand Up @@ -205,7 +208,7 @@ jobs:
name: Verify if a releaser triggered the job
command: |
#!/bin/bash

# Do not fail if the Node script ends with non-zero exit code.
set +e

Expand Down
2 changes: 1 addition & 1 deletion demos/cdn-multiroot-react/ContextMultiRootEditorDemo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ const ContextEditorDemo = ( { editor }: { editor: any } ): JSX.Element => {
const withCKCloud = withCKEditorCloud( {
cloud: {
version: '43.0.0',
languages: [ 'en', 'de' ],
translations: [ 'es', 'de' ],
premium: true
}
} );
Expand Down
2 changes: 1 addition & 1 deletion demos/cdn-multiroot-react/MultiRootEditorDemo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ type EditorDemoProps = WithCKEditorCloudHocProps & {
const withCKCloud = withCKEditorCloud( {
cloud: {
version: '43.0.0',
languages: [ 'de' ],
translations: [ 'de' ],
premium: true
}
} );
Expand Down
2 changes: 1 addition & 1 deletion demos/cdn-multiroot-react/MultiRootEditorRichDemo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ type EditorDemoProps = WithCKEditorCloudHocProps & {
const withCKCloud = withCKEditorCloud( {
cloud: {
version: '43.0.0',
languages: [ 'de' ],
translations: [ 'de' ],
premium: true
}
} );
Expand Down
4 changes: 2 additions & 2 deletions demos/cdn-multiroot-react/useCKCdnMultiRootEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
*/

import type { MultiRootEditor } from 'https://cdn.ckeditor.com/typings/ckeditor5.d.ts';
import type { CKEditorCloudResult } from '../../src/index.js';
import type { CKEditorCloudConfig, CKEditorCloudResult } from '../../src/index.js';

export const useCKCdnMultiRootEditor = ( cloud: CKEditorCloudResult ): typeof MultiRootEditor => {
export const useCKCdnMultiRootEditor = ( cloud: CKEditorCloudResult<CKEditorCloudConfig> ): typeof MultiRootEditor => {
const {
MultiRootEditor: MultiRootEditorBase,
CloudServices,
Expand Down
2 changes: 1 addition & 1 deletion demos/cdn-react/CKEditorCloudPluginsDemo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ declare global {
export const CKEditorCloudPluginsDemo = ( { content }: CKEditorCloudPluginsDemoProps ): ReactNode => {
const cloud = useCKEditorCloud( {
version: '43.0.0',
languages: [ 'pl', 'de' ],
translations: [ 'pl', 'de' ],
premium: true,
plugins: {
Wiris: {
Expand Down
2 changes: 1 addition & 1 deletion demos/npm-multiroot-react/ContextMultiRootEditorDemo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import React from 'react';

import { useMultiRootEditor, type MultiRootHookProps, CKEditorContext } from '../../src/index.js';
import MultiRootEditor from './MultiRootEditor';
import MultiRootEditor from './MultiRootEditor.js';

export default function ContextMultiRootEditorDemo(): JSX.Element {
return (
Expand Down
2 changes: 1 addition & 1 deletion demos/npm-multiroot-react/MultiRootEditorDemo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import React from 'react';

import { useMultiRootEditor, type MultiRootHookProps } from '../../src/index.js';
import MultiRootEditor from './MultiRootEditor';
import MultiRootEditor from './MultiRootEditor.js';

type EditorDemoProps = {
data: Record<string, string>;
Expand Down
2 changes: 1 addition & 1 deletion demos/npm-multiroot-react/MultiRootEditorRichDemo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import React, { useState, type ChangeEvent } from 'react';

import { useMultiRootEditor, type MultiRootHookProps } from '../../src/index.js';
import MultiRootEditor from './MultiRootEditor';
import MultiRootEditor from './MultiRootEditor.js';

const SAMPLE_READ_ONLY_LOCK_ID = 'Integration Sample';

Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
},
"dependencies": {
"prop-types": "^15.7.2",
"@ckeditor/ckeditor5-integrations-common": "^1.0.0"
"@ckeditor/ckeditor5-integrations-common": "^2.0.0"
},
"peerDependencies": {
"ckeditor5": ">=42.0.0 || ^0.0.0-nightly",
Expand Down Expand Up @@ -91,6 +91,7 @@
"build": "vite build && tsc --emitDeclarationOnly",
"test": "vitest run --coverage",
"test:watch": "vitest --ui --watch",
"test:check:types": "tsc --noEmit -p ./tests/tsconfig.json",
"lint": "eslint --quiet \"**/*.{ts,tsx}\"",
"postinstall": "node ./scripts/postinstall.js",
"changelog": "node ./scripts/changelog.js",
Expand Down
23 changes: 11 additions & 12 deletions src/cloud/useCKEditorCloud.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,23 @@
import {
loadCKEditorCloud,
type CKEditorCloudConfig,
type CKEditorCloudResult,
type CdnPluginsPacks
type CKEditorCloudResult
} from '@ckeditor/ckeditor5-integrations-common';

import { useAsyncValue, type AsyncValueHookResult } from '../hooks/useAsyncValue';
import { useAsyncValue, type AsyncValueHookResult } from '../hooks/useAsyncValue.js';

/**
* Hook that loads CKEditor bundles from CDN.
*
* @template A The type of the additional resources to load.
* @template Config The type of the CKEditor Cloud configuration.
* @param config The configuration of the hook.
* @returns The state of async operation that resolves to the CKEditor bundles.
* @example
*
* ```ts
* const cloud = useCKEditorCloud( {
* version: '42.0.0',
* languages: [ 'en', 'de' ],
* translations: [ 'es', 'de' ],
* premium: true
* } );
*
Expand All @@ -33,15 +32,15 @@ import { useAsyncValue, type AsyncValueHookResult } from '../hooks/useAsyncValue
* }
* ```
*/
export default function useCKEditorCloud<A extends CdnPluginsPacks>(
config: CKEditorCloudConfig<A>
): CKEditorCloudHookResult<A> {
export default function useCKEditorCloud<Config extends CKEditorCloudConfig>(
config: Config
): CKEditorCloudHookResult<Config> {
// Serialize the config to a string to fast compare if there was a change and re-render is needed.
const serializedConfigKey = JSON.stringify( config );

// Fetch the CKEditor Cloud Services bundles on every modification of config.
const result = useAsyncValue(
async (): Promise<CKEditorCloudResult<A>> => loadCKEditorCloud( config ),
async (): Promise<CKEditorCloudResult<Config>> => loadCKEditorCloud( config ),
[ serializedConfigKey ]
);

Expand All @@ -59,6 +58,6 @@ export default function useCKEditorCloud<A extends CdnPluginsPacks>(
/**
* The result of the `useCKEditorCloud` hook. It changes success state to be more intuitive.
*/
type CKEditorCloudHookResult<A extends CdnPluginsPacks> =
| Exclude<AsyncValueHookResult<CKEditorCloudResult<A>>, { status: 'success' }>
| ( CKEditorCloudResult<A> & { status: 'success' } );
type CKEditorCloudHookResult<Config extends CKEditorCloudConfig> =
| Exclude<AsyncValueHookResult<CKEditorCloudResult<Config>>, { status: 'success' }>
| ( CKEditorCloudResult<Config> & { status: 'success' } );
27 changes: 13 additions & 14 deletions src/cloud/withCKEditorCloud.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@
import React, { type ReactNode, type ComponentType } from 'react';
import type {
CKEditorCloudConfig,
CKEditorCloudResult,
CdnPluginsPacks
CKEditorCloudResult
} from '@ckeditor/ckeditor5-integrations-common';

import useCKEditorCloud from './useCKEditorCloud';
import useCKEditorCloud from './useCKEditorCloud.js';

/**
* HOC that injects the CKEditor Cloud integration into a component.
Expand All @@ -24,7 +23,7 @@ import useCKEditorCloud from './useCKEditorCloud';
* const withCKCloud = withCKEditorCloud( {
* cloud: {
* version: '42.0.0',
* languages: [ 'en', 'de' ],
* translations: [ 'es', 'de' ],
* premium: true
* }
* } );
Expand All @@ -38,11 +37,11 @@ import useCKEditorCloud from './useCKEditorCloud';
* } );
* ```
*/
const withCKEditorCloud = <A extends CdnPluginsPacks>( config: CKEditorCloudHocConfig<A> ) =>
const withCKEditorCloud = <Config extends CKEditorCloudConfig>( config: CKEditorCloudHocConfig<Config> ) =>
<P extends object>(
WrappedComponent: ComponentType<WithCKEditorCloudHocProps<A> & P>
): ComponentType<Omit<P, keyof WithCKEditorCloudHocProps>> => {
const ComponentWithCKEditorCloud = ( props: Omit<P, keyof WithCKEditorCloudHocProps> ) => {
WrappedComponent: ComponentType<WithCKEditorCloudHocProps<Config> & P>
): ComponentType<Omit<P, keyof WithCKEditorCloudHocProps<Config>>> => {
const ComponentWithCKEditorCloud = ( props: Omit<P, keyof WithCKEditorCloudHocProps<Config>> ) => {
const ckeditorCloudResult = useCKEditorCloud( config.cloud );

switch ( ckeditorCloudResult.status ) {
Expand Down Expand Up @@ -74,27 +73,27 @@ export default withCKEditorCloud;
/**
* Props injected by the `withCKEditorCloud` HOC.
*
* @template A The type of the additional resources to load.
* @template Config The configuration of the CKEditor Cloud integration.
*/
export type WithCKEditorCloudHocProps<A extends CdnPluginsPacks = any> = {
export type WithCKEditorCloudHocProps<Config extends CKEditorCloudConfig = CKEditorCloudConfig> = {

/**
* The result of the CKEditor Cloud integration.
*/
cloud: CKEditorCloudResult<A>;
cloud: CKEditorCloudResult<Config>;
};

/**
* The configuration of the CKEditor Cloud integration.
*
* @template A The type of the additional resources to load.
* @template Config The configuration of the CKEditor Cloud integration.
*/
type CKEditorCloudHocConfig<A extends CdnPluginsPacks> = {
type CKEditorCloudHocConfig<Config extends CKEditorCloudConfig> = {

/**
* The configuration of the CKEditor Cloud integration.
*/
cloud: CKEditorCloudConfig<A>;
cloud: Config;

/**
* Component to render while the cloud information is being fetched.
Expand Down
6 changes: 3 additions & 3 deletions src/context/useInitializedCKEditorsMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
*/

import { useEffect } from 'react';
import { useRefSafeCallback } from '../hooks/useRefSafeCallback';
import { useRefSafeCallback } from '../hooks/useRefSafeCallback.js';

import type { CollectionAddEvent, Context, ContextWatchdog, Editor } from 'ckeditor5';
import type { ContextWatchdogValue } from './ckeditorcontext';
import type { ContextWatchdogValue } from './ckeditorcontext.js';

import {
tryExtractCKEditorReactContextMetadata,
type CKEditorConfigContextMetadata
} from './setCKEditorReactContextMetadata';
} from './setCKEditorReactContextMetadata.js';

/**
* A hook that listens for the editor initialization and destruction events and updates the editors map.
Expand Down
4 changes: 2 additions & 2 deletions src/hooks/useAsyncCallback.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
import { useState, useRef } from 'react';
import { uid, isSSR } from '@ckeditor/ckeditor5-integrations-common';

import { useIsUnmountedRef } from './useIsUnmountedRef';
import { useRefSafeCallback } from './useRefSafeCallback';
import { useIsUnmountedRef } from './useIsUnmountedRef.js';
import { useRefSafeCallback } from './useRefSafeCallback.js';

/**
* A hook that allows to execute an asynchronous function and provides the state of the execution.
Expand Down
4 changes: 2 additions & 2 deletions src/hooks/useAsyncValue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@

import type { DependencyList } from 'react';

import { useInstantEffect } from './useInstantEffect';
import { useAsyncCallback, type AsyncCallbackState } from './useAsyncCallback';
import { useInstantEffect } from './useInstantEffect.js';
import { useAsyncCallback, type AsyncCallbackState } from './useAsyncCallback.js';

/**
* A hook that allows to execute an asynchronous function and provides the state of the execution.
Expand Down
4 changes: 2 additions & 2 deletions src/hooks/useInstantEditorEffect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
*/

import type { DependencyList } from 'react';
import type { LifeCycleElementSemaphore } from '../lifecycle/LifeCycleElementSemaphore';
import type { LifeCycleElementSemaphore } from '../lifecycle/LifeCycleElementSemaphore.js';

import { useInstantEffect } from './useInstantEffect';
import { useInstantEffect } from './useInstantEffect.js';

/**
* `useEffect` alternative but executed after mounting of editor.
Expand Down
2 changes: 1 addition & 1 deletion src/lifecycle/LifeCycleEditorSemaphore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import type { Editor, EditorWatchdog } from 'ckeditor5';

import type { EditorWatchdogAdapter } from '../ckeditor';
import type { LifeCycleElementSemaphore } from './LifeCycleElementSemaphore';
import type { LifeCycleElementSemaphore } from './LifeCycleElementSemaphore.js';

export type EditorSemaphoreMountResult<TEditor extends Editor> = {

Expand Down
Loading