diff --git a/demos/cdn-multiroot-react/App.tsx b/demos/cdn-multiroot-react/App.tsx new file mode 100644 index 00000000..c016a5b4 --- /dev/null +++ b/demos/cdn-multiroot-react/App.tsx @@ -0,0 +1,79 @@ +/** + * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. + * For licensing, see LICENSE.md. + */ + +import React, { StrictMode, useState } from 'react'; +import MultiRootEditorDemo from './MultiRootEditorDemo'; +import MultiRootEditorRichDemo from './MultiRootEditorRichDemo'; +import ContextMultiRootEditorDemo from './ContextMultiRootEditorDemo'; + +type Demo = 'editor' | 'rich' | 'context'; + +const multiRootEditorContent = { + intro: '

Sample

This is an instance of the ' + + 'multi-root editor build.

', + content: '

It is the custom content

CKEditor 5 Sample image.
', + outro: '

You can use this sample to validate whether your ' + + 'custom build works fine.

' +}; + +const rootsAttributes = { + intro: { + row: '1', + order: 10 + }, + content: { + row: '1', + order: 20 + }, + outro: { + row: '2', + order: 10 + } +}; + +export default function App(): JSX.Element { + const [ demo, setDemo ] = useState( 'editor' ); + + const renderDemo = () => { + switch ( demo ) { + case 'context': + return ; + case 'editor': + return ; + case 'rich': + return ; + } + }; + + return ( + +

CKEditor 5 – useMultiRootEditor – CDN development sample

+ +
+ + + + + +
+ { renderDemo() } +
+ ); +} diff --git a/demos/cdn-multiroot-react/ContextMultiRootEditorDemo.tsx b/demos/cdn-multiroot-react/ContextMultiRootEditorDemo.tsx new file mode 100644 index 00000000..49cd45e2 --- /dev/null +++ b/demos/cdn-multiroot-react/ContextMultiRootEditorDemo.tsx @@ -0,0 +1,142 @@ +/** + * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. + * For licensing, see LICENSE.md. + */ + +import React from 'react'; + +import { useMultiRootEditor, type MultiRootHookProps, CKEditorContext, withCKEditorCloud } from '../../src/index.js'; +import { useCKCdnMultiRootEditor } from './useCKCdnMultiRootEditor.js'; + +const ContextEditorDemo = ( { editor }: { editor: any } ): JSX.Element => { + const editorProps: Partial = { + editor, + + onChange: ( event, editor ) => { + console.log( 'event: onChange', { event, editor } ); + }, + onBlur: ( event, editor ) => { + console.log( 'event: onBlur', { event, editor } ); + }, + onFocus: ( event, editor ) => { + console.log( 'event: onFocus', { event, editor } ); + } + }; + + // First editor initialization. + const { + editor: editor1, editableElements: editableElements1, toolbarElement: toolbarElement1 + } = useMultiRootEditor( { + ...editorProps, + data: { + intro: '

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

', + content: '

Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

' + }, + + onReady: editor => { + window.editor1 = editor; + + console.log( 'event: onChange', { editor } ); + } + } as MultiRootHookProps ); + + // Second editor initialization. + const { + editor: editor2, editableElements: editableElements2, toolbarElement: toolbarElement2 + } = useMultiRootEditor( { + ...editorProps, + data: { + notes: '

Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.

' + }, + + onReady: editor => { + window.editor2 = editor; + + console.log( 'event: onChange', { editor } ); + } + } as MultiRootHookProps ); + + // Function to simulate an error in the editor. + // It is used for testing purposes to trigger the Watchdog to restart the editor. + // Remove it in the actual integration. + const simulateError = ( editor: any ) => { + setTimeout( () => { + const err: any = new Error( 'foo' ); + + err.context = editor; + err.is = () => true; + + throw err; + } ); + }; + + return ( + <> +

Context Multi-root Editor Demo

+

+ This sample demonstrates integration with CKEditorContext.
+

+

Component's events are logged to the console.

+

+ +
+
+ +
+ + { toolbarElement1 } + +
+ { editableElements1 } +
+
+ +
+ +
+
+ +
+ + { toolbarElement2 } + +
+ { editableElements2 } +
+
+ + ); +}; + +const withCKCloud = withCKEditorCloud( { + cloud: { + version: '43.0.0', + languages: [ 'en', 'de' ], + premium: true + } +} ); + +const ContextMultiRootEditorDemo = withCKCloud( ( { cloud } ): JSX.Element => { + const MultiRootEditor = useCKCdnMultiRootEditor( cloud ); + + return ( + + + + ); +} ); + +export default ContextMultiRootEditorDemo; diff --git a/demos/cdn-multiroot-react/MultiRootEditorDemo.tsx b/demos/cdn-multiroot-react/MultiRootEditorDemo.tsx new file mode 100644 index 00000000..7f2ea3ee --- /dev/null +++ b/demos/cdn-multiroot-react/MultiRootEditorDemo.tsx @@ -0,0 +1,55 @@ +/** + * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. + * For licensing, see LICENSE.md. + */ + +import React, { type ReactNode } from 'react'; + +import { useCKCdnMultiRootEditor } from './useCKCdnMultiRootEditor.js'; +import { + useMultiRootEditor, withCKEditorCloud, + type MultiRootHookProps, + type WithCKEditorCloudHocProps +} from '../../src/index.js'; + +type EditorDemoProps = WithCKEditorCloudHocProps & { + data: Record; + rootsAttributes: Record>; +}; + +const withCKCloud = withCKEditorCloud( { + cloud: { + version: '43.0.0', + languages: [ 'de' ], + premium: true + } +} ); + +const MultiRootEditorDemo = withCKCloud( ( { data, cloud }: EditorDemoProps ): ReactNode => { + const MultiRootEditor = useCKCdnMultiRootEditor( cloud ); + const editorProps: MultiRootHookProps = { + editor: MultiRootEditor as any, + data + }; + + const { toolbarElement, editableElements } = useMultiRootEditor( editorProps ); + + return ( + <> +

Multi-root Editor Demo

+

+ This sample demonstrates the minimal React application that uses multi-root editor integration.
+ You may use it as a starting point for your application. +

+

+ +
+ { toolbarElement } + + { editableElements } +
+ + ); +} ); + +export default MultiRootEditorDemo; diff --git a/demos/cdn-multiroot-react/MultiRootEditorRichDemo.tsx b/demos/cdn-multiroot-react/MultiRootEditorRichDemo.tsx new file mode 100644 index 00000000..324656ed --- /dev/null +++ b/demos/cdn-multiroot-react/MultiRootEditorRichDemo.tsx @@ -0,0 +1,237 @@ +/** + * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. + * For licensing, see LICENSE.md. + */ + +import React, { useState, type ChangeEvent } from 'react'; + +import { + useMultiRootEditor, withCKEditorCloud, + type WithCKEditorCloudHocProps, type MultiRootHookProps +} from '../../src/index.js'; + +import { useCKCdnMultiRootEditor } from './useCKCdnMultiRootEditor.js'; + +const SAMPLE_READ_ONLY_LOCK_ID = 'Integration Sample'; + +type EditorDemoProps = WithCKEditorCloudHocProps & { + data: Record; + rootsAttributes: Record>; +}; + +const withCKCloud = withCKEditorCloud( { + cloud: { + version: '43.0.0', + languages: [ 'de' ], + premium: true + } +} ); + +const MultiRootEditorRichDemo = withCKCloud( ( props: EditorDemoProps ): JSX.Element => { + const MultiRootEditor = useCKCdnMultiRootEditor( props.cloud ); + const editorProps: MultiRootHookProps = { + editor: MultiRootEditor as any, + data: props.data, + rootsAttributes: props.rootsAttributes, + + onReady: editor => { + // @ts-expect-error: Caused by linking to parent project and conflicting react types + window.editor = editor; + + console.log( 'event: onChange', { editor } ); + }, + onChange: ( event, editor ) => { + console.log( 'event: onChange', { event, editor } ); + }, + onBlur: ( event, editor ) => { + console.log( 'event: onBlur', { event, editor } ); + }, + onFocus: ( event, editor ) => { + console.log( 'event: onFocus', { event, editor } ); + }, + + config: { + rootsAttributes: props.rootsAttributes + } + }; + + const { + editor, editableElements, toolbarElement, + data, setData, + attributes, setAttributes + } = useMultiRootEditor( editorProps ); + + // The element state with number of roots that should be added in one row. + // This is for demo purposes, and you may remove it in the actual integration or change accordingly to your needs. + const [ numberOfRoots, setNumberOfRoots ] = useState( 1 ); + + // A set with disabled roots. It is used to support read-only feature in multi root editor. + // This is for demo purposes, and you may remove it in the actual integration or change accordingly to your needs. + const [ disabledRoots, setDisabledRoots ] = useState>( new Set() ); + + // Function to toggle read-only mode for selected root. + const toggleReadOnly = () => { + const root = editor!.model.document.selection.getFirstRange()!.root; + + if ( !root || !root.rootName ) { + return; + } + + const isReadOnly = disabledRoots.has( root.rootName ); + + if ( isReadOnly ) { + disabledRoots.delete( root.rootName ); + editor!.enableRoot( root.rootName, SAMPLE_READ_ONLY_LOCK_ID ); + } else { + disabledRoots.add( root.rootName ); + editor!.disableRoot( root.rootName, SAMPLE_READ_ONLY_LOCK_ID ); + } + + setDisabledRoots( new Set( disabledRoots ) ); + }; + + // Function to simulate an error in the editor. + // It is used for testing purposes to trigger the Watchdog to restart the editor. + // Remove it in the actual integration. + const simulateError = () => { + setTimeout( () => { + const err: any = new Error( 'foo' ); + + err.context = editor; + err.is = () => true; + + throw err; + } ); + }; + + const addRoot = ( newRootAttributes: Record, rootId?: string ) => { + const id = rootId || new Date().getTime(); + + for ( let i = 1; i <= numberOfRoots; i++ ) { + const rootName = `root-${ i }-${ id }`; + + data[ rootName ] = ''; + + // Remove code related to rows if you don't need to handle multiple roots in one row. + attributes[ rootName ] = { ...newRootAttributes, order: i * 10, row: id }; + } + + setData( { ...data } ); + setAttributes( { ...attributes } ); + // Reset the element to the default value. + setNumberOfRoots( 1 ); + }; + + const removeRoot = ( rootName: string ) => { + setData( previousData => { + const { [ rootName! ]: _, ...newData } = previousData; + + return { ...newData }; + } ); + + setSelectedRoot( '' ); + }; + + // Group elements based on their row attribute and sort them by order attribute. + // Grouping in a row is used for presentation purposes, and you may remove it in actual integration. + // However, we recommend ordering the roots, so that rows are put in a correct places when undo/redo is used. + const groupedElements = Object.entries( + editableElements + .sort( ( a, b ) => ( attributes[ a.props.id ].order as number ) - ( attributes[ b.props.id ].order as number ) ) + .reduce( ( acc: Record>, element ) => { + const row = attributes[ element.props.id ].row as string; + acc[ row ] = acc[ row ] || []; + acc[ row ].push( element ); + + return acc; + }, {} ) + ); + + return ( + <> +

Multi-root Editor Demo (rich integration)

+

This sample demonstrates a more advanced integration of the multi-root editor in React.

+

+ Multiple extra features are implemented to illustrate how you can customize your application and use the provided API.
+ They are optional, and you do not need to include them in your application.
+ However, they can be a good starting point for your own custom features. +

+

+ The 'Simulate an error' button makes the editor throw an error to show you how it is restarted by + the Watchdog mechanism.
+ Note, that Watchdog is enabled by default.
+ It can be disabled by passing the `disableWatchdog` flag to the `useMultiRootEditor` hook. +

+

Component's events are logged to the console.

+

+ +
+ + + +
+ +
+ + + +
+ +
+ + + Number( e.target.value ) <= 4 && setNumberOfRoots( Number( e.target.value ) )} + /> +
+ +
+ + { toolbarElement } + + { /* Maps through `groupedElements` array to render rows that contains the editor roots. */ } + { groupedElements.map( ( [ row, elements ] ) => ( +
+ { elements } +
+ ) ) } + + ); +} ); + +export default MultiRootEditorRichDemo; diff --git a/demos/cdn-multiroot-react/index.html b/demos/cdn-multiroot-react/index.html new file mode 100644 index 00000000..f0066fe6 --- /dev/null +++ b/demos/cdn-multiroot-react/index.html @@ -0,0 +1,54 @@ + + + + + + CKEditor 5 via CDN – React Multi Root Component – demo + + + + + +
+ + + diff --git a/demos/multiroot-react/main.tsx b/demos/cdn-multiroot-react/main.tsx similarity index 100% rename from demos/multiroot-react/main.tsx rename to demos/cdn-multiroot-react/main.tsx diff --git a/demos/cdn-multiroot-react/useCKCdnMultiRootEditor.tsx b/demos/cdn-multiroot-react/useCKCdnMultiRootEditor.tsx new file mode 100644 index 00000000..b156404e --- /dev/null +++ b/demos/cdn-multiroot-react/useCKCdnMultiRootEditor.tsx @@ -0,0 +1,100 @@ +/** + * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. + * For licensing, see LICENSE.md. + */ + +import type { MultiRootEditor } from 'https://cdn.ckeditor.com/typings/ckeditor5.d.ts'; +import type { CKEditorCloudResult } from '../../src/index.js'; + +export const useCKCdnMultiRootEditor = ( cloud: CKEditorCloudResult ): typeof MultiRootEditor => { + const { + MultiRootEditor: MultiRootEditorBase, + CloudServices, + Essentials, + CKFinderUploadAdapter, + Autoformat, + Bold, + Italic, + BlockQuote, + CKBox, + CKFinder, + EasyImage, + Heading, + Image, + ImageCaption, + ImageStyle, + ImageToolbar, + ImageUpload, + Indent, + Link, + List, + MediaEmbed, + Paragraph, + PasteFromOffice, + PictureEditing, + Table, + TableToolbar, + TextTransformation + } = cloud.CKEditor; + + return class MultiRootEditor extends MultiRootEditorBase { + public static override builtinPlugins = [ + Essentials, + CKFinderUploadAdapter, + Autoformat, + Bold, + Italic, + BlockQuote, + CKBox, + CKFinder, + CloudServices, + EasyImage, + Heading, + Image, + ImageCaption, + ImageStyle, + ImageToolbar, + ImageUpload, + Indent, + Link, + List, + MediaEmbed, + Paragraph, + PasteFromOffice, + PictureEditing, + Table, + TableToolbar, + TextTransformation + ]; + + public static override defaultConfig = { + toolbar: { + items: [ + 'undo', 'redo', + '|', 'heading', + '|', 'bold', 'italic', + '|', 'link', 'uploadImage', 'insertTable', 'blockQuote', 'mediaEmbed', + '|', 'bulletedList', 'numberedList', 'outdent', 'indent' + ] + }, + image: { + toolbar: [ + 'imageStyle:inline', + 'imageStyle:block', + 'imageStyle:side', + '|', + 'toggleImageCaption', + 'imageTextAlternative' + ] + }, + table: { + contentToolbar: [ + 'tableColumn', + 'tableRow', + 'mergeTableCells' + ] + }, + language: 'en' + }; + }; +}; diff --git a/demos/cdn-react/App.tsx b/demos/cdn-react/App.tsx new file mode 100644 index 00000000..3f4dfaf0 --- /dev/null +++ b/demos/cdn-react/App.tsx @@ -0,0 +1,58 @@ +/** + * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. + * For licensing, see LICENSE.md. + */ + +import React, { useState, type ReactNode } from 'react'; + +import { CKEditorCloudDemo } from './CKEditorCloudDemo'; +import { CKEditorCloudPluginsDemo } from './CKEditorCloudPluginsDemo'; +import { CKEditorCKBoxCloudDemo } from './CKEditorCKBoxCloudDemo'; +import { CKEditorCloudContextDemo } from './CKEditorCloudContextDemo'; + +const EDITOR_CONTENT = ` +

Sample

+

This is an instance of the + classic editor build. +

+
+ CKEditor 5 Sample image. +
+

You can use this sample to validate whether your + custom build works fine.

+`; + +const DEMOS = [ 'Editor', 'Context', 'CKBox', 'Cloud Plugins' ] as const; + +type Demo = ( typeof DEMOS )[ number ]; + +export const App = (): ReactNode => { + const [ currentDemo, setCurrentDemo ] = useState( 'Editor' ); + + const content = ( { + Editor: , + Context: , + CKBox: , + 'Cloud Plugins': + } )[ currentDemo ]; + + return ( + +

CKEditor 5 – React Component – CDN demo

+ +
+ { DEMOS.map( demo => ( + + ) ) } +
+ + { content } +
+ ); +}; diff --git a/demos/cdn-react/CKEditorCKBoxCloudDemo.tsx b/demos/cdn-react/CKEditorCKBoxCloudDemo.tsx new file mode 100644 index 00000000..2c25b8b0 --- /dev/null +++ b/demos/cdn-react/CKEditorCKBoxCloudDemo.tsx @@ -0,0 +1,75 @@ +/** + * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. + * For licensing, see LICENSE.md. + */ + +import React, { type ReactNode } from 'react'; +import { getCKCdnClassicEditor } from './getCKCdnClassicEditor.js'; +import { CKEditor, useCKEditorCloud } from '../../src/index.js'; + +type CKEditorCKBoxCloudDemoProps = { + content: string; +}; + +export const CKEditorCKBoxCloudDemo = ( { content }: CKEditorCKBoxCloudDemoProps ): ReactNode => { + const cloud = useCKEditorCloud( { + version: '43.0.0', + premium: true, + ckbox: { + version: '2.5.1' + } + } ); + + if ( cloud.status === 'error' ) { + console.error( cloud ); + } + + if ( cloud.status !== 'success' ) { + return
Loading...
; + } + + const { CKBox, CKBoxImageEdit } = cloud.CKEditor; + const CKEditorClassic = getCKCdnClassicEditor( { + cloud, + additionalPlugins: [ + CKBox, + CKBoxImageEdit + ], + overrideConfig: { + toolbar: { + items: [ + 'undo', 'redo', + '|', 'heading', + '|', 'bold', 'italic', + '|', 'link', 'uploadImage', 'insertTable', 'blockQuote', 'mediaEmbed', + '|', 'bulletedList', 'numberedList', 'outdent', 'indent', + '|', 'ckbox', 'ckboxImageEdit' + ] + }, + image: { + toolbar: [ + 'imageStyle:inline', + 'imageStyle:block', + 'imageStyle:side', + '|', + 'toggleImageCaption', + 'imageTextAlternative', + '|', + 'ckboxImageEdit' + ] + }, + ckbox: { + tokenUrl: 'https://api.ckbox.io/token/demo', + forceDemoLabel: true, + allowExternalImagesEditing: [ /^data:/, /^i.imgur.com\//, 'origin' ] + } + } + } ); + + return ( + + ); +}; diff --git a/demos/cdn-react/CKEditorCloudContextDemo.tsx b/demos/cdn-react/CKEditorCloudContextDemo.tsx new file mode 100644 index 00000000..513bb60d --- /dev/null +++ b/demos/cdn-react/CKEditorCloudContextDemo.tsx @@ -0,0 +1,128 @@ +/** + * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. + * For licensing, see LICENSE.md. + */ + +import React from 'react'; +import { CKEditor, CKEditorContext, useCKEditorCloud } from '../../src/index.js'; + +export const CKEditorCloudContextDemo = (): JSX.Element => { + const cloud = useCKEditorCloud( { + version: '43.0.0', + premium: true + } ); + + if ( cloud.status === 'error' ) { + console.error( cloud ); + return
Error!
; + } + + if ( cloud.status === 'loading' ) { + return
Loading...
; + } + + const { ClassicEditor } = cloud.CKEditor; + + return ( + { + console.log( 'Initialized editors:', editors ); + } } + > + + +
+ + +
+ ); +}; + +function CKEditorNestedInstanceDemo( { name, content }: { name: string; content?: string } ): JSX.Element { + const cloud = useCKEditorCloud( { + version: '43.0.0' + } ); + + if ( cloud.status === 'error' ) { + console.error( cloud ); + return
Error!
; + } + + if ( cloud.status === 'loading' ) { + return
Loading...
; + } + + const { CKEditor: CK } = cloud; + + return ( + + ); +} diff --git a/demos/cdn-react/CKEditorCloudDemo.tsx b/demos/cdn-react/CKEditorCloudDemo.tsx new file mode 100644 index 00000000..41c1e860 --- /dev/null +++ b/demos/cdn-react/CKEditorCloudDemo.tsx @@ -0,0 +1,38 @@ +/** + * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. + * For licensing, see LICENSE.md. + */ + +import React, { type ReactNode } from 'react'; +import { getCKCdnClassicEditor } from './getCKCdnClassicEditor.js'; +import { CKEditor, useCKEditorCloud } from '../../src/index.js'; + +type CKEditorCloudDemoProps = { + content: string; +}; + +export const CKEditorCloudDemo = ( { content }: CKEditorCloudDemoProps ): ReactNode => { + const cloud = useCKEditorCloud( { + version: '43.0.0', + premium: true + } ); + + if ( cloud.status === 'error' ) { + console.error( cloud ); + } + + if ( cloud.status !== 'success' ) { + return
Loading...
; + } + + const CKEditorClassic = getCKCdnClassicEditor( { + cloud + } ); + + return ( + + ); +}; diff --git a/demos/cdn-react/CKEditorCloudPluginsDemo.tsx b/demos/cdn-react/CKEditorCloudPluginsDemo.tsx new file mode 100644 index 00000000..cd3711df --- /dev/null +++ b/demos/cdn-react/CKEditorCloudPluginsDemo.tsx @@ -0,0 +1,75 @@ +/** + * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. + * For licensing, see LICENSE.md. + */ + +import React, { type ReactNode } from 'react'; + +import type { Plugin } from 'https://cdn.ckeditor.com/typings/ckeditor5.d.ts'; + +import { getCKCdnClassicEditor } from './getCKCdnClassicEditor.js'; +import { CKEditor, useCKEditorCloud } from '../../src/index.js'; + +type CKEditorCloudPluginsDemoProps = { + content: string; +}; + +declare global { + interface Window { + '@wiris/mathtype-ckeditor5': typeof Plugin; + } +} + +export const CKEditorCloudPluginsDemo = ( { content }: CKEditorCloudPluginsDemoProps ): ReactNode => { + const cloud = useCKEditorCloud( { + version: '43.0.0', + languages: [ 'pl', 'de' ], + premium: true, + plugins: { + Wiris: { + scripts: [ + 'https://www.wiris.net/demo/plugins/app/WIRISplugins.js', + 'https://cdn.jsdelivr.net/npm/@wiris/mathtype-ckeditor5@8.11.0/dist/browser/index.umd.js' + ], + stylesheets: [ + 'https://cdn.jsdelivr.net/npm/@wiris/mathtype-ckeditor5@8.11.0/dist/browser/index.css' + ], + checkPluginLoaded: () => window[ '@wiris/mathtype-ckeditor5' ] + } + } + } ); + + if ( cloud.status === 'error' ) { + console.error( cloud ); + } + + if ( cloud.status !== 'success' ) { + return
Loading...
; + } + + const CKEditorClassic = getCKCdnClassicEditor( { + cloud, + additionalPlugins: [ + cloud.loadedPlugins!.Wiris + ], + overrideConfig: { + toolbar: { + items: [ + 'undo', 'redo', + '|', 'heading', + '|', 'bold', 'italic', + '|', 'link', 'uploadImage', 'insertTable', 'blockQuote', 'mediaEmbed', + '|', 'bulletedList', 'numberedList', 'outdent', 'indent', + '|', 'MathType', 'ChemType' + ] + } + } + } ); + + return ( + + ); +}; diff --git a/demos/cdn-react/getCKCdnClassicEditor.ts b/demos/cdn-react/getCKCdnClassicEditor.ts new file mode 100644 index 00000000..9423ea13 --- /dev/null +++ b/demos/cdn-react/getCKCdnClassicEditor.ts @@ -0,0 +1,104 @@ +/** + * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. + * For licensing, see LICENSE.md. + */ + +import type { ClassicEditor, Plugin, ContextPlugin, EditorConfig } from 'https://cdn.ckeditor.com/typings/ckeditor5.d.ts'; +import type { CKEditorCloudResult } from '../../src'; + +type ClassicEditorCreatorConfig = { + cloud: CKEditorCloudResult; + additionalPlugins?: Array; + overrideConfig?: EditorConfig; +}; + +export const getCKCdnClassicEditor = ( { + cloud, additionalPlugins, overrideConfig +}: ClassicEditorCreatorConfig ): typeof ClassicEditor => { + const { + ClassicEditor: ClassicEditorBase, + Essentials, + Autoformat, + Bold, + Italic, + BlockQuote, + CloudServices, + Heading, + Image, + ImageCaption, + ImageStyle, + ImageToolbar, + ImageUpload, + Indent, + Link, + List, + MediaEmbed, + Paragraph, + PasteFromOffice, + PictureEditing, + Table, + TableToolbar, + TextTransformation + } = cloud.CKEditor; + + class CustomEditor extends ClassicEditorBase { + public static builtinPlugins = [ + Essentials, + Autoformat, + Bold, + Italic, + BlockQuote, + Heading, + Image, + ImageCaption, + ImageStyle, + ImageToolbar, + ImageUpload, + Indent, + Link, + List, + MediaEmbed, + Paragraph, + PasteFromOffice, + PictureEditing, + Table, + TableToolbar, + TextTransformation, + CloudServices, + ...additionalPlugins || [] + ]; + + public static defaultConfig = { + toolbar: { + items: [ + 'undo', 'redo', + '|', 'heading', + '|', 'bold', 'italic', + '|', 'link', 'uploadImage', 'insertTable', 'blockQuote', 'mediaEmbed', + '|', 'bulletedList', 'numberedList', 'outdent', 'indent' + ] + }, + image: { + toolbar: [ + 'imageStyle:inline', + 'imageStyle:block', + 'imageStyle:side', + '|', + 'toggleImageCaption', + 'imageTextAlternative' + ] + }, + table: { + contentToolbar: [ + 'tableColumn', + 'tableRow', + 'mergeTableCells' + ] + }, + language: 'en', + ...overrideConfig + }; + } + + return CustomEditor; +}; diff --git a/demos/react/index.html b/demos/cdn-react/index.html similarity index 75% rename from demos/react/index.html rename to demos/cdn-react/index.html index ea4d67b2..c515a040 100644 --- a/demos/react/index.html +++ b/demos/cdn-react/index.html @@ -3,7 +3,7 @@ - CKEditor 5 – React Component – demo + CKEditor 5 via CDN – React Component – demo + + + +
+ + + diff --git a/demos/npm-react/main.tsx b/demos/npm-react/main.tsx new file mode 100644 index 00000000..26eda597 --- /dev/null +++ b/demos/npm-react/main.tsx @@ -0,0 +1,25 @@ +/** + * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. + * For licensing, see LICENSE.md. + */ + +import React from 'react'; +import App from './App'; + +const element = document.getElementById( 'root' ) as HTMLDivElement; + +if ( __REACT_VERSION__ === 16 ) { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + const ReactDOM = await import( 'react-dom' ); + + ReactDOM.render( React.createElement( App ), element ); +} else { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + const { createRoot } = await import( 'react-dom/client' ); + + createRoot( element ).render( ); +} + +console.log( `%cVersion of React used: ${ React.version }`, 'color:red;font-weight:bold;' ); diff --git a/index.html b/index.html index 3be1d08e..edfc7f48 100644 --- a/index.html +++ b/index.html @@ -10,8 +10,11 @@

Select the demo you want to test:

- Editor - Multiroot editor + NPM Editor + NPM Multiroot editor + + CDN Editor + CDN Multiroot editor
diff --git a/package.json b/package.json index 16766ca2..33a7bf33 100644 --- a/package.json +++ b/package.json @@ -28,13 +28,16 @@ "./package.json": "./package.json" }, "dependencies": { - "prop-types": "^15.7.2" + "prop-types": "^15.7.2", + "@ckeditor/ckeditor5-integrations-common": "^1.0.0" }, "peerDependencies": { "ckeditor5": ">=42.0.0 || ^0.0.0-nightly", + "ckeditor5-premium-features": ">=42.0.0 || ^0.0.0-nightly", "react": "^16.13.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" }, "devDependencies": { + "@testing-library/jest-dom": "^6.4.8", "@ckeditor/ckeditor5-dev-bump-year": "^40.0.0", "@ckeditor/ckeditor5-dev-ci": "^40.0.0", "@ckeditor/ckeditor5-dev-release-tools": "^40.0.0", @@ -48,6 +51,7 @@ "@vitest/coverage-istanbul": "^2.0.0", "@vitest/ui": "^2.0.0", "ckeditor5": "^42.0.0", + "ckeditor5-premium-features": "^42.0.0", "coveralls": "^3.1.1", "eslint": "^7.19.0", "eslint-config-ckeditor5": "^5.3.2", diff --git a/src/ckeditor.tsx b/src/ckeditor.tsx index 456e1fe0..4213fb27 100644 --- a/src/ckeditor.tsx +++ b/src/ckeditor.tsx @@ -21,7 +21,7 @@ import type { import type { EditorSemaphoreMountResult } from './lifecycle/LifeCycleEditorSemaphore'; -import { uid } from './utils/uid'; +import { uid } from '@ckeditor/ckeditor5-integrations-common'; import { LifeCycleElementSemaphore } from './lifecycle/LifeCycleElementSemaphore'; import { diff --git a/src/cloud/useCKEditorCloud.tsx b/src/cloud/useCKEditorCloud.tsx new file mode 100644 index 00000000..4f8ef25d --- /dev/null +++ b/src/cloud/useCKEditorCloud.tsx @@ -0,0 +1,64 @@ +/** + * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. + * For licensing, see LICENSE.md. + */ + +import { + loadCKEditorCloud, + type CKEditorCloudConfig, + type CKEditorCloudResult, + type CdnPluginsPacks +} from '@ckeditor/ckeditor5-integrations-common'; + +import { useAsyncValue, type AsyncValueHookResult } from '../hooks/useAsyncValue'; + +/** + * Hook that loads CKEditor bundles from CDN. + * + * @template A The type of the additional resources to load. + * @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' ], + * premium: true + * } ); + * + * if ( cloud.status === 'success' ) { + * const { ClassicEditor, Bold, Essentials } = cloud.CKEditor; + * const { SlashCommand } = cloud.CKEditorPremiumFeatures; + * } + * ``` + */ +export default function useCKEditorCloud( + config: CKEditorCloudConfig +): CKEditorCloudHookResult { + // 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> => loadCKEditorCloud( config ), + [ serializedConfigKey ] + ); + + // Expose a bit better API for the hook consumers, so they don't need to access the constructor through the `data` property. + if ( result.status === 'success' ) { + return { + ...result.data, + status: 'success' + }; + } + + return result; +} + +/** + * The result of the `useCKEditorCloud` hook. It changes success state to be more intuitive. + */ +type CKEditorCloudHookResult = + | Exclude>, { status: 'success' }> + | ( CKEditorCloudResult & { status: 'success' } ); diff --git a/src/cloud/withCKEditorCloud.tsx b/src/cloud/withCKEditorCloud.tsx new file mode 100644 index 00000000..09950b33 --- /dev/null +++ b/src/cloud/withCKEditorCloud.tsx @@ -0,0 +1,108 @@ +/** + * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. + * For licensing, see LICENSE.md. + */ + +import React, { type ReactNode, type ComponentType } from 'react'; +import type { + CKEditorCloudConfig, + CKEditorCloudResult, + CdnPluginsPacks +} from '@ckeditor/ckeditor5-integrations-common'; + +import useCKEditorCloud from './useCKEditorCloud'; + +/** + * HOC that injects the CKEditor Cloud integration into a component. + * + * @template A The type of the additional resources to load. + * @param config The configuration of the CKEditor Cloud integration. + * @returns A function that injects the CKEditor Cloud integration into a component. + * @example + + * ```tsx + * const withCKCloud = withCKEditorCloud( { + * cloud: { + * version: '42.0.0', + * languages: [ 'en', 'de' ], + * premium: true + * } + * } ); + * + * const MyComponent = withCKCloud( ( { cloud } ) => { + * const { Paragraph } = cloud.CKEditor; + * const { SlashCommands } = cloud.CKEditorPremiumFeatures; + * const { YourPlugin } = cloud.CKPlugins; + * + * return
CKEditor Cloud is loaded!
; + * } ); + * ``` + */ +const withCKEditorCloud =
( config: CKEditorCloudHocConfig ) => +

( + WrappedComponent: ComponentType & P> + ): ComponentType> => { + const ComponentWithCKEditorCloud = ( props: Omit ) => { + const ckeditorCloudResult = useCKEditorCloud( config.cloud ); + + switch ( ckeditorCloudResult.status ) { + // An error occurred while fetching the cloud information. + case 'error': + if ( !config.renderError ) { + return 'Unable to load CKEditor Cloud data!'; + } + + return config.renderError( ckeditorCloudResult.error ); + + // The cloud information has been fetched successfully. + case 'success': + return ; + + // The cloud information is being fetched. + default: + return config.renderLoader?.() ?? null; + } + }; + + ComponentWithCKEditorCloud.displayName = 'ComponentWithCKEditorCloud'; + + return ComponentWithCKEditorCloud; + }; + +export default withCKEditorCloud; + +/** + * Props injected by the `withCKEditorCloud` HOC. + * + * @template A The type of the additional resources to load. + */ +export type WithCKEditorCloudHocProps = { + + /** + * The result of the CKEditor Cloud integration. + */ + cloud: CKEditorCloudResult; +}; + +/** + * The configuration of the CKEditor Cloud integration. + * + * @template A The type of the additional resources to load. + */ +type CKEditorCloudHocConfig = { + + /** + * The configuration of the CKEditor Cloud integration. + */ + cloud: CKEditorCloudConfig; + + /** + * Component to render while the cloud information is being fetched. + */ + renderLoader?: () => ReactNode; + + /** + * Component to render when an error occurs while fetching the cloud information. + */ + renderError?: ( error: any ) => ReactNode; +}; diff --git a/src/context/ckeditorcontext.tsx b/src/context/ckeditorcontext.tsx index 8c607f36..351dec20 100644 --- a/src/context/ckeditorcontext.tsx +++ b/src/context/ckeditorcontext.tsx @@ -9,8 +9,8 @@ import React, { type ReactElement } from 'react'; +import { uid } from '@ckeditor/ckeditor5-integrations-common'; import { useIsMountedRef } from '../hooks/useIsMountedRef'; -import { uid } from '../utils/uid'; import { useInitializedCKEditorsMap, type InitializedContextEditorsConfig diff --git a/src/hooks/useAsyncCallback.ts b/src/hooks/useAsyncCallback.ts new file mode 100644 index 00000000..6c8b1f38 --- /dev/null +++ b/src/hooks/useAsyncCallback.ts @@ -0,0 +1,125 @@ +/** + * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. + * For licensing, see LICENSE.md. + */ + +import { useState, useRef } from 'react'; +import { uid, isSSR } from '@ckeditor/ckeditor5-integrations-common'; + +import { useIsUnmountedRef } from './useIsUnmountedRef'; +import { useRefSafeCallback } from './useRefSafeCallback'; + +/** + * A hook that allows to execute an asynchronous function and provides the state of the execution. + * + * @param callback The asynchronous function to be executed. + * @returns A tuple with the function that triggers the execution and the state of the execution. + * + * @example + * ```tsx + * const [ onFetchData, fetchDataStatus ] = useAsyncCallback( async () => { + * const response = await fetch( 'https://api.example.com/data' ); + * const data = await response.json(); + * return data; + * } ); + * + * return ( + *

+ * ); + * ``` + */ +export const useAsyncCallback = , R>( + callback: ( ...args: Array ) => Promise +): AsyncCallbackHookResult => { + // The state of the asynchronous callback. + const [ asyncState, setAsyncState ] = useState>( { + status: 'idle' + } ); + + // A reference to the mounted state of the component. + const unmountedRef = useIsUnmountedRef(); + + // A reference to the previous execution UUID. It is used to prevent race conditions between multiple executions + // of the asynchronous function. If the UUID of the current execution is different than the UUID of the previous + // execution, the state is not updated. + const prevExecutionUIDRef = useRef( null ); + + // The asynchronous executor function, which is a wrapped version of the original callback. + const asyncExecutor = useRefSafeCallback( async ( ...args: Array ) => { + if ( unmountedRef.current || isSSR() ) { + return null; + } + + const currentExecutionUUID = uid(); + prevExecutionUIDRef.current = currentExecutionUUID; + + try { + // Prevent unnecessary state updates, keep loading state if the status is already 'loading'. + if ( asyncState.status !== 'loading' ) { + setAsyncState( { + status: 'loading' + } ); + } + + // Execute the asynchronous function. + const result = await callback( ...args ); + + // Update the state if the component is still mounted and the execution UUID matches the previous one, otherwise + // ignore the result and keep the previous state. + if ( !unmountedRef.current && prevExecutionUIDRef.current === currentExecutionUUID ) { + setAsyncState( { + status: 'success', + data: result + } ); + } + + return result; + } catch ( error: any ) { + console.error( error ); + + // Update the state if the component is still mounted and the execution UUID matches the previous one, otherwise + if ( !unmountedRef.current && prevExecutionUIDRef.current === currentExecutionUUID ) { + setAsyncState( { + status: 'error', + error + } ); + } + } + + return null; + } ); + + return [ asyncExecutor, asyncState ] as AsyncCallbackHookResult; +}; + +/** + * Represents the result of the `useAsyncCallback` hook. + */ +export type AsyncCallbackHookResult, R> = [ + ( ...args: Array ) => Promise, + AsyncCallbackState +]; + +/** + * Represents the state of an asynchronous callback. + */ +export type AsyncCallbackState = + | { + status: 'idle'; + } + | { + status: 'loading'; + } + | { + status: 'success'; + data: T; + } + | { + status: 'error'; + error: any; + }; diff --git a/src/hooks/useAsyncValue.ts b/src/hooks/useAsyncValue.ts new file mode 100644 index 00000000..208f14f7 --- /dev/null +++ b/src/hooks/useAsyncValue.ts @@ -0,0 +1,63 @@ +/** + * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. + * For licensing, see LICENSE.md. + */ + +import type { DependencyList } from 'react'; + +import { useInstantEffect } from './useInstantEffect'; +import { useAsyncCallback, type AsyncCallbackState } from './useAsyncCallback'; + +/** + * A hook that allows to execute an asynchronous function and provides the state of the execution. + * The asynchronous function is executed immediately after the component is mounted. + * + * @param callback The asynchronous function to be executed. + * @param deps The dependency list. + * @returns The state of the execution. + * + * @example + * ```tsx + * const asyncFetchState = useAsyncValue( async () => { + * const response = await fetch( 'https://api.example.com/data' ); + * const data = await response.json(); + * return data; + * }, [] ); + * + * if ( asyncFetchState.status === 'loading' ) { + * return

Loading...

; + * } + * + * if ( asyncFetchState.status === 'success' ) { + * return
{ JSON.stringify( asyncFetchState.data, null, 2 ) }
; + * } + * + * if ( asyncFetchState.status === 'error' ) { + * return

Error: { asyncFetchState.error.message }

; + * } + * ``` + */ +export const useAsyncValue =
, R>( + callback: ( ...args: Array ) => Promise, + deps: DependencyList +): AsyncValueHookResult => { + const [ asyncCallback, asyncState ] = useAsyncCallback( callback ); + + useInstantEffect( asyncCallback, deps ); + + // There might be short delay between the effect and the state update. + // So it is possible that the status is still 'idle' after the effect. + // In such case, we should return 'loading' status because the effect is already queued to be executed. + if ( asyncState.status === 'idle' ) { + return { + status: 'loading' + }; + } + + return asyncState; +}; + +/** + * The result of the `useAsyncValue` hook. + */ +export type AsyncValueHookResult = Exclude, { status: 'idle' }>; diff --git a/src/hooks/useInstantEditorEffect.ts b/src/hooks/useInstantEditorEffect.ts index 9a0b3e66..88759fa0 100644 --- a/src/hooks/useInstantEditorEffect.ts +++ b/src/hooks/useInstantEditorEffect.ts @@ -5,6 +5,7 @@ import type { DependencyList } from 'react'; import type { LifeCycleElementSemaphore } from '../lifecycle/LifeCycleElementSemaphore'; + import { useInstantEffect } from './useInstantEffect'; /** diff --git a/src/hooks/useInstantEffect.ts b/src/hooks/useInstantEffect.ts index f9d8913c..3f20802e 100644 --- a/src/hooks/useInstantEffect.ts +++ b/src/hooks/useInstantEffect.ts @@ -4,7 +4,7 @@ */ import { useRef, type DependencyList } from 'react'; -import { shallowCompareArrays } from '../utils/shallowCompareArrays'; +import { shallowCompareArrays } from '@ckeditor/ckeditor5-integrations-common'; /** * Triggers an effect immediately if the dependencies change (during rendering of component). diff --git a/src/hooks/useIsUnmountedRef.ts b/src/hooks/useIsUnmountedRef.ts new file mode 100644 index 00000000..202356d3 --- /dev/null +++ b/src/hooks/useIsUnmountedRef.ts @@ -0,0 +1,26 @@ +/** + * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. + * For licensing, see LICENSE.md. + */ + +import { useEffect, useRef, type MutableRefObject } from 'react'; + +/** + * Custom hook that returns a mutable ref object indicating whether the component is unmounted or not. + * + * @returns The mutable ref object. + */ +export const useIsUnmountedRef = (): MutableRefObject => { + const mountedRef = useRef( false ); + + useEffect( () => { + // Prevent issues in strict mode. + mountedRef.current = false; + + return () => { + mountedRef.current = true; + }; + }, [] ); + + return mountedRef; +}; diff --git a/src/index.ts b/src/index.ts index eb2356d0..202f2474 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,3 +6,15 @@ export { default as CKEditor } from './ckeditor'; export { default as CKEditorContext } from './context/ckeditorcontext'; export { default as useMultiRootEditor, type MultiRootHookProps, type MultiRootHookReturns } from './useMultiRootEditor'; + +export { default as useCKEditorCloud } from './cloud/useCKEditorCloud'; +export { + default as withCKEditorCloud, + type WithCKEditorCloudHocProps +} from './cloud/withCKEditorCloud'; + +export { + loadCKEditorCloud, + type CKEditorCloudResult, + type CKEditorCloudConfig +} from '@ckeditor/ckeditor5-integrations-common'; diff --git a/src/lifecycle/LifeCycleElementSemaphore.ts b/src/lifecycle/LifeCycleElementSemaphore.ts index ee96c391..bec5cbf5 100644 --- a/src/lifecycle/LifeCycleElementSemaphore.ts +++ b/src/lifecycle/LifeCycleElementSemaphore.ts @@ -3,8 +3,7 @@ * For licensing, see LICENSE.md. */ -import { createDefer, type Defer } from '../utils/defer'; -import { once } from '../utils/once'; +import { createDefer, once, type Defer } from '@ckeditor/ckeditor5-integrations-common'; /** * This class is utilized to pause the initialization of an editor when another instance is already present on a specified element. diff --git a/src/useMultiRootEditor.tsx b/src/useMultiRootEditor.tsx index fa419ef7..f372e581 100644 --- a/src/useMultiRootEditor.tsx +++ b/src/useMultiRootEditor.tsx @@ -8,6 +8,8 @@ import React, { type Dispatch, type SetStateAction, type RefObject } from 'react'; +import { overwriteArray, overwriteObject, uniq } from '@ckeditor/ckeditor5-integrations-common'; + import type { InlineEditableUIView, EditorConfig, @@ -29,10 +31,7 @@ import type { EditorSemaphoreMountResult } from './lifecycle/LifeCycleEditorSema import { useLifeCycleSemaphoreSyncRef, type LifeCycleSemaphoreSyncRefResult } from './lifecycle/useLifeCycleSemaphoreSyncRef'; import { mergeRefs } from './utils/mergeRefs'; import { LifeCycleElementSemaphore } from './lifecycle/LifeCycleElementSemaphore'; -import { overwriteObject } from './utils/overwriteObject'; import { useRefSafeCallback } from './hooks/useRefSafeCallback'; -import { uniq } from './utils/uniq'; -import { overwriteArray } from './utils/overwriteArray'; import { useInstantEditorEffect } from './hooks/useInstantEditorEffect'; const REACT_INTEGRATION_READ_ONLY_LOCK_ID = 'Lock from React integration (@ckeditor/ckeditor5-react)'; diff --git a/src/utils/defer.ts b/src/utils/defer.ts deleted file mode 100644 index d7f0a19b..00000000 --- a/src/utils/defer.ts +++ /dev/null @@ -1,26 +0,0 @@ -/** - * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. - * For licensing, see LICENSE.md. - */ - -export type Defer = { - promise: Promise; - resolve: ( value: E ) => void; -}; - -/** - * This function generates a promise that can be resolved by invoking the returned `resolve` method. - * It proves to be beneficial in the creation of various types of locks and semaphores. - */ -export function createDefer(): Defer { - const deferred: Defer = { - resolve: null as any, - promise: null as any - }; - - deferred.promise = new Promise( resolve => { - deferred.resolve = resolve; - } ); - - return deferred; -} diff --git a/src/utils/once.ts b/src/utils/once.ts deleted file mode 100644 index 2ad6716a..00000000 --- a/src/utils/once.ts +++ /dev/null @@ -1,21 +0,0 @@ -/** - * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. - * For licensing, see LICENSE.md. - */ - -/** - * Ensures that passed function will be executed only once. - */ -export function once, R = void>( fn: ( ...args: A ) => R ): ( ...args: A ) => R { - let lastResult: { current: R } | null = null; - - return ( ...args: A ): R => { - if ( !lastResult ) { - lastResult = { - current: fn( ...args ) - }; - } - - return lastResult.current; - }; -} diff --git a/src/utils/overwriteArray.ts b/src/utils/overwriteArray.ts deleted file mode 100644 index 4aee02ea..00000000 --- a/src/utils/overwriteArray.ts +++ /dev/null @@ -1,14 +0,0 @@ -/** - * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. - * For licensing, see LICENSE.md. - */ - -/** - * Clear whole array while keeping its reference. - */ -export function overwriteArray>( source: A, destination: A ): A { - destination.length = 0; - destination.push( ...source ); - - return destination; -} diff --git a/src/utils/overwriteObject.ts b/src/utils/overwriteObject.ts deleted file mode 100644 index fa258d92..00000000 --- a/src/utils/overwriteObject.ts +++ /dev/null @@ -1,22 +0,0 @@ -/** - * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. - * For licensing, see LICENSE.md. - */ - -/** - * Clears whole object while keeping its reference. - */ -export function overwriteObject>( source: O, destination: O ): O { - for ( const prop of Object.getOwnPropertyNames( destination ) ) { - delete destination[ prop ]; - } - - // Prevent assigning self referencing attributes which crashes `Object.assign`. - for ( const [ key, value ] of Object.entries( source ) ) { - if ( value !== destination && key !== 'prototype' && key !== '__proto__' ) { - ( destination as any )[ key ] = value; - } - } - - return destination; -} diff --git a/src/utils/shallowCompareArrays.ts b/src/utils/shallowCompareArrays.ts deleted file mode 100644 index 8a187e94..00000000 --- a/src/utils/shallowCompareArrays.ts +++ /dev/null @@ -1,28 +0,0 @@ -/** - * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. - * For licensing, see LICENSE.md. - */ - -/** - * Shallow comparison of two arrays. - */ -export const shallowCompareArrays = ( - a: Readonly>, - b: Readonly> -): boolean => { - if ( a === b ) { - return true; - } - - if ( !a || !b ) { - return false; - } - - for ( let i = 0; i < a.length; ++i ) { - if ( a[ i ] !== b[ i ] ) { - return false; - } - } - - return true; -}; diff --git a/src/utils/uid.ts b/src/utils/uid.ts deleted file mode 100644 index 0031a67f..00000000 --- a/src/utils/uid.ts +++ /dev/null @@ -1,57 +0,0 @@ -/** - * @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 ]; -} diff --git a/src/utils/uniq.ts b/src/utils/uniq.ts deleted file mode 100644 index ab002b4e..00000000 --- a/src/utils/uniq.ts +++ /dev/null @@ -1,11 +0,0 @@ -/** - * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. - * For licensing, see LICENSE.md. - */ - -/** - * A utility function that removes duplicate elements from an array. - */ -export function uniq( source: Array ): Array { - return Array.from( new Set( source ) ); -} diff --git a/tests/ckeditor.test.tsx b/tests/ckeditor.test.tsx index 8617d1f3..81c862df 100644 --- a/tests/ckeditor.test.tsx +++ b/tests/ckeditor.test.tsx @@ -20,12 +20,6 @@ import { expectToBeTruthy } from './_utils/expectToBeTruthy.js'; import type { LifeCycleElementSemaphore } from '../src/lifecycle/LifeCycleElementSemaphore.js'; import type { EditorSemaphoreMountResult } from '../src/lifecycle/LifeCycleEditorSemaphore.js'; -declare global { - interface Window { - CKEDITOR_VERSION: any; - } -} - const MockEditor = MockedEditor as any; describe( ' Component', () => { @@ -59,7 +53,7 @@ describe( ' Component', () => { describe( 'initialization', async () => { it( 'should print a warning if the "window.CKEDITOR_VERSION" variable is not available', async () => { - delete window.CKEDITOR_VERSION; + window.CKEDITOR_VERSION = ''; const warnStub = vi.spyOn( console, 'warn' ).mockImplementation( () => {} ); component = render( diff --git a/tests/cloud/useCKEditorCloud.test.tsx b/tests/cloud/useCKEditorCloud.test.tsx new file mode 100644 index 00000000..88e831da --- /dev/null +++ b/tests/cloud/useCKEditorCloud.test.tsx @@ -0,0 +1,72 @@ +/** + * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. + * For licensing, see LICENSE.md. + */ + +import { beforeEach, describe, expect, it } from 'vitest'; +import { renderHook, waitFor, act } from '@testing-library/react'; + +import type { CKEditorCloudConfig } from '@ckeditor/ckeditor5-integrations-common'; +import { removeAllCkCdnResources } from '@ckeditor/ckeditor5-integrations-common/test-utils'; + +import useCKEditorCloud from '../../src/cloud/useCKEditorCloud'; + +describe( 'useCKEditorCloud', () => { + beforeEach( removeAllCkCdnResources ); + + it( 'should load CKEditor bundles from CDN', async () => { + const { result } = renderHook( () => useCKEditorCloud( { + version: '43.0.0', + languages: [ 'en', 'de' ] + } ) ); + + expect( result.current.status ).toBe( 'loading' ); + + await waitFor( () => { + expect( result.current.status ).toBe( 'success' ); + + if ( result.current.status === 'success' ) { + expect( result.current.CKEditor ).toBeDefined(); + } + } ); + } ); + + it( 'should load additional bundle after updating deps', async () => { + const { result, rerender } = renderHook( + ( config: CKEditorCloudConfig ) => useCKEditorCloud( config ), + { + initialProps: { + version: '43.0.0', + premium: false + } + } + ); + + await waitFor( () => { + expect( result.current.status ).toBe( 'success' ); + + if ( result.current.status === 'success' ) { + expect( result.current.CKEditor ).toBeDefined(); + expect( result.current.CKEditorPremiumFeatures ).toBeUndefined(); + } + } ); + + rerender( { + version: '43.0.0', + premium: true + } ); + + act( () => { + expect( result.current.status ).toBe( 'loading' ); + } ); + + await waitFor( () => { + expect( result.current.status ).toBe( 'success' ); + + if ( result.current.status === 'success' ) { + expect( result.current.CKEditor ).toBeDefined(); + expect( result.current.CKEditorPremiumFeatures ).toBeDefined(); + } + } ); + } ); +} ); diff --git a/tests/cloud/withCKEditorCloud.test.tsx b/tests/cloud/withCKEditorCloud.test.tsx new file mode 100644 index 00000000..ca393821 --- /dev/null +++ b/tests/cloud/withCKEditorCloud.test.tsx @@ -0,0 +1,119 @@ +/** + * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. + * For licensing, see LICENSE.md. + */ + +import React, { type MutableRefObject } from 'react'; +import { afterEach, beforeEach, describe, expect, it } from 'vitest'; +import { cleanup, render } from '@testing-library/react'; + +import { createDefer } from '@ckeditor/ckeditor5-integrations-common'; +import { removeAllCkCdnResources } from '@ckeditor/ckeditor5-integrations-common/test-utils'; + +import withCKEditorCloud, { type WithCKEditorCloudHocProps } from '../../src/cloud/withCKEditorCloud'; + +describe( 'withCKEditorCloud', () => { + const lastRenderedMockProps: MutableRefObject = { + current: null + }; + + afterEach( cleanup ); + + beforeEach( () => { + removeAllCkCdnResources(); + lastRenderedMockProps.current = null; + } ); + + const MockComponent = ( props: WithCKEditorCloudHocProps & { editorId: number } ) => { + lastRenderedMockProps.current = { ...props }; + + return ( +
+ Your Editor { props.editorId } +
+ ); + }; + + it( 'should inject cloud integration to the wrapped component', async () => { + const WrappedComponent = withCKEditorCloud( { + cloud: { + version: '43.0.0' + } + } )( MockComponent ); + + const { findByText } = render( ); + + expect( await findByText( 'Your Editor 1' ) ).toBeVisible(); + expect( lastRenderedMockProps.current ).toMatchObject( { + editorId: 1, + cloud: expect.objectContaining( { + CKEditor: expect.objectContaining( { + ClassicEditor: expect.any( Function ) + } ) + } ) + } ); + } ); + + it( 'should show loading spinner when cloud is not ready', async () => { + const deferredPlugin = createDefer(); + const WrappedComponent = withCKEditorCloud( { + renderLoader: () =>
Loading...
, + cloud: { + version: '43.0.0', + plugins: { + Plugin: { + checkPluginLoaded: () => deferredPlugin.promise + } + } + } + } )( MockComponent ); + + const { findByText } = render( ); + + expect( await findByText( 'Loading...' ) ).toBeVisible(); + + deferredPlugin.resolve( 123 ); + + expect( await findByText( 'Your Editor 1' ) ).toBeVisible(); + expect( lastRenderedMockProps.current?.cloud.loadedPlugins?.Plugin ).toBe( 123 ); + } ); + + it( 'should show error message when cloud loading fails', async () => { + const WrappedComponent = withCKEditorCloud( { + renderError: error =>
Error: { error.message }
, + cloud: { + version: '43.0.0', + plugins: { + Plugin: { + checkPluginLoaded: () => { + throw new Error( 'Failed to load plugin' ); + } + } + } + } + } )( MockComponent ); + + const { findByText } = render( ); + + expect( await findByText( 'Error: Failed to load plugin' ) ).toBeVisible(); + } ); + + it( 'should render default error message when cloud loading fails and there is no error handler specified', async () => { + const WrappedComponent = withCKEditorCloud( { + cloud: { + version: '43.0.0', + plugins: { + Plugin: { + checkPluginLoaded: () => { + throw new Error( 'Failed to load plugin' ); + } + } + } + } + } )( MockComponent ); + + const { findByText } = render( ); + + expect( await findByText( 'Unable to load CKEditor Cloud data!' ) ).toBeVisible(); + } ); +} ); diff --git a/tests/hooks/useAsyncCallback.test.tsx b/tests/hooks/useAsyncCallback.test.tsx new file mode 100644 index 00000000..90d9cec0 --- /dev/null +++ b/tests/hooks/useAsyncCallback.test.tsx @@ -0,0 +1,160 @@ +/** + * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. + * For licensing, see LICENSE.md. + */ + +import { describe, expect, it, vi } from 'vitest'; +import { renderHook, act, waitFor } from '@testing-library/react'; +import { useAsyncCallback } from '../../src/hooks/useAsyncCallback'; +import { timeout } from '../_utils/timeout'; + +describe( 'useAsyncCallback', () => { + it( 'should execute the callback and update the state correctly when the callback resolves', async () => { + const fetchData = vi.fn().mockResolvedValue( 'data' ); + + const { result } = renderHook( () => useAsyncCallback( fetchData ) ); + const [ onFetchData ] = result.current; + + expect( result.current[ 1 ].status ).toBe( 'idle' ); + + act( () => { + onFetchData(); + } ); + + expect( result.current[ 1 ].status ).toBe( 'loading' ); + + await waitFor( () => { + const [ , fetchDataStatus ] = result.current; + + expect( fetchDataStatus.status ).toBe( 'success' ); + + if ( fetchDataStatus.status === 'success' ) { + expect( fetchDataStatus.data ).toBe( 'data' ); + } + } ); + } ); + + it( 'should execute the callback and update the state correctly when the callback rejects', async () => { + const fetchData = vi.fn().mockRejectedValue( new Error( 'error' ) ); + + const { result } = renderHook( () => useAsyncCallback( fetchData ) ); + const [ onFetchData ] = result.current; + + expect( result.current[ 1 ].status ).toBe( 'idle' ); + + act( () => { + onFetchData(); + } ); + + expect( result.current[ 1 ].status ).toBe( 'loading' ); + + await waitFor( () => { + const [ , fetchDataStatus ] = result.current; + + expect( fetchDataStatus.status ).toBe( 'error' ); + + if ( fetchDataStatus.status === 'error' ) { + expect( fetchDataStatus.error.message ).toBe( 'error' ); + } + } ); + } ); + + it( 'should not update the state to loading if the component is unmounted', async () => { + const fetchData = vi.fn().mockResolvedValue( 'data' ); + + const { result, unmount } = renderHook( () => useAsyncCallback( fetchData ) ); + + const [ onFetchData, fetchDataStatus ] = result.current; + + expect( fetchDataStatus.status ).toBe( 'idle' ); + unmount(); + + act( () => { + onFetchData(); + } ); + + expect( fetchDataStatus.status ).toBe( 'idle' ); + } ); + + it( 'should not update the state to error if the component is unmounted', async () => { + const fetchData = vi.fn().mockRejectedValue( new Error( 'error' ) ); + + const { result, unmount } = renderHook( () => useAsyncCallback( fetchData ) ); + const [ onFetchData ] = result.current; + + expect( result.current[ 1 ].status ).toBe( 'idle' ); + + act( () => { + onFetchData(); + } ); + + expect( result.current[ 1 ].status ).toBe( 'loading' ); + unmount(); + + await timeout( 50 ); + await waitFor( () => { + const [ , fetchDataStatus ] = result.current; + + expect( fetchDataStatus.status ).toBe( 'loading' ); + } ); + } ); + + it( 'should not update the state to success if the component is unmounted', async () => { + const fetchData = vi.fn().mockResolvedValue( 123 ); + + const { result, unmount } = renderHook( () => useAsyncCallback( fetchData ) ); + const [ onFetchData ] = result.current; + + expect( result.current[ 1 ].status ).toBe( 'idle' ); + + act( () => { + onFetchData(); + } ); + + expect( result.current[ 1 ].status ).toBe( 'loading' ); + unmount(); + + await timeout( 50 ); + await waitFor( () => { + const [ , fetchDataStatus ] = result.current; + + expect( fetchDataStatus.status ).toBe( 'loading' ); + } ); + } ); + + it( 'should not update the state if the execution UUID does not match the previous one', async () => { + let counter = 0; + const fetchData = vi.fn( async () => { + if ( !counter ) { + await timeout( 200 ); + } + + return counter++; + } ); + + const { result } = renderHook( () => useAsyncCallback( fetchData ) ); + + const [ onFetchData ] = result.current; + + expect( result.current[ 1 ].status ).toBe( 'idle' ); + + act( () => { + onFetchData(); + } ); + + // Do not batch this act() call with the previous one to ensure that the execution UUID is different. + act( () => { + onFetchData(); + } ); + + await waitFor( () => { + const [ , fetchDataStatus ] = result.current; + + expect( fetchDataStatus.status ).toBe( 'success' ); + + if ( fetchDataStatus.status === 'success' ) { + expect( fetchDataStatus.data ).toBe( 1 ); + } + } ); + } ); +} ); diff --git a/tests/hooks/useAsyncValue.test.tsx b/tests/hooks/useAsyncValue.test.tsx new file mode 100644 index 00000000..b4a6df8a --- /dev/null +++ b/tests/hooks/useAsyncValue.test.tsx @@ -0,0 +1,52 @@ +/** + * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. + * For licensing, see LICENSE.md. + */ + +import { describe, expect, it } from 'vitest'; +import { renderHook, waitFor } from '@testing-library/react'; +import { useAsyncValue } from '../../src/hooks/useAsyncValue'; + +describe( 'useAsyncValue', () => { + it( 'should return a mutable ref object', async () => { + const { result } = renderHook( () => useAsyncValue( async () => 123, [] ) ); + + expect( result.current.status ).to.equal( 'loading' ); + + await waitFor( () => { + expect( result.current.status ).to.equal( 'success' ); + + if ( result.current.status === 'success' ) { + expect( result.current.data ).to.equal( 123 ); + } + } ); + } ); + + it( 'should reload async value on deps change', async () => { + let value = 0; + const { result, rerender } = renderHook( () => useAsyncValue( async () => value, [ value ] ) ); + + expect( result.current.status ).to.equal( 'loading' ); + + await waitFor( () => { + expect( result.current.status ).to.equal( 'success' ); + + if ( result.current.status === 'success' ) { + expect( result.current.data ).to.equal( 0 ); + } + } ); + + value = 1; + rerender(); + + expect( result.current.status ).to.equal( 'loading' ); + + await waitFor( () => { + expect( result.current.status ).to.equal( 'success' ); + + if ( result.current.status === 'success' ) { + expect( result.current.data ).to.equal( 1 ); + } + } ); + } ); +} ); diff --git a/tests/hooks/useIsUnmountedRef.test.tsx b/tests/hooks/useIsUnmountedRef.test.tsx new file mode 100644 index 00000000..4fff4fe6 --- /dev/null +++ b/tests/hooks/useIsUnmountedRef.test.tsx @@ -0,0 +1,27 @@ +/** + * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. + * For licensing, see LICENSE.md. + */ + +import { describe, expect, it } from 'vitest'; +import { renderHook } from '@testing-library/react'; +import { useIsUnmountedRef } from '../../src/hooks/useIsUnmountedRef'; + +describe( 'useIsUnmountedRef', () => { + it( 'should return a mutable ref object', () => { + const { result } = renderHook( () => useIsUnmountedRef() ); + + expect( result.current ).toHaveProperty( 'current' ); + expect( typeof result.current.current ).toBe( 'boolean' ); + } ); + + it( 'should update the ref object when the component is unmounted', () => { + const { result, unmount } = renderHook( () => useIsUnmountedRef() ); + + expect( result.current.current ).toBe( false ); + + unmount(); + + expect( result.current.current ).toBe( true ); + } ); +} ); diff --git a/tests/index.test.tsx b/tests/index.test.tsx index 00adb549..2df93053 100644 --- a/tests/index.test.tsx +++ b/tests/index.test.tsx @@ -10,7 +10,7 @@ import { render, type RenderResult } from '@testing-library/react'; import ContextMock from './_utils/context.js'; import Editor from './_utils/editor.js'; import { PromiseManager } from './_utils/promisemanager.js'; -import { CKEditor, CKEditorContext } from '../src/index'; +import { CKEditor, CKEditorContext } from '../src/index.js'; const MockEditor = Editor as any; diff --git a/tests/tsconfig.json b/tests/tsconfig.json new file mode 100644 index 00000000..dad543dc --- /dev/null +++ b/tests/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "types": [ + "@testing-library/jest-dom/vitest", + "../vite-env.d.ts" + ] + }, + "include": [ + "./", + "../src" + ] +} diff --git a/tests/utils/defer.test.tsx b/tests/utils/defer.test.tsx deleted file mode 100644 index 7ef2d752..00000000 --- a/tests/utils/defer.test.tsx +++ /dev/null @@ -1,31 +0,0 @@ -/** - * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. - * For licensing, see LICENSE.md. - */ - -import { describe, expect, it } from 'vitest'; -import { createDefer, type Defer } from '../../src/utils/defer'; - -describe( 'createDefer', () => { - it( 'should resolve the promise with the provided value', async () => { - const value = 'test value'; - const defer: Defer = createDefer(); - - defer.resolve( value ); - - const result = await defer.promise; - expect( result ).toBe( value ); - } ); - - it( 'should create a promise that can be resolved asynchronously', async () => { - const value = 'test value'; - const defer: Defer = createDefer(); - - setTimeout( () => { - defer.resolve( value ); - }, 100 ); - - const result = await defer.promise; - expect( result ).toBe( value ); - } ); -} ); diff --git a/tests/utils/once.test.tsx b/tests/utils/once.test.tsx deleted file mode 100644 index 9b54aa12..00000000 --- a/tests/utils/once.test.tsx +++ /dev/null @@ -1,33 +0,0 @@ -/** - * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. - * For licensing, see LICENSE.md. - */ - -import { describe, expect, it, vi } from 'vitest'; -import { once } from '../../src/utils/once'; - -describe( 'once', () => { - it( 'should execute the function only once', () => { - const mockFn = vi.fn(); - const onceFn = once( mockFn ); - - onceFn(); - onceFn(); - onceFn(); - - expect( mockFn ).toHaveBeenCalledOnce(); - } ); - - it( 'should return the same result on subsequent calls', () => { - const mockFn = vi.fn().mockReturnValue( 'result' ); - const onceFn = once( mockFn ); - - const result1 = onceFn(); - const result2 = onceFn(); - const result3 = onceFn(); - - expect( result1 ).toBe( 'result' ); - expect( result2 ).toBe( 'result' ); - expect( result3 ).toBe( 'result' ); - } ); -} ); diff --git a/tests/utils/overwriteArray.test.tsx b/tests/utils/overwriteArray.test.tsx deleted file mode 100644 index bee61397..00000000 --- a/tests/utils/overwriteArray.test.tsx +++ /dev/null @@ -1,19 +0,0 @@ -/** - * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. - * For licensing, see LICENSE.md. - */ - -import { describe, expect, it } from 'vitest'; -import { overwriteArray } from '../../src/utils/overwriteArray'; - -describe( 'overwriteArray', () => { - it( 'should clear the destination array and copy the elements from the source array', () => { - const source = [ 1, 2, 3 ]; - const destination = [ 4, 5, 6 ]; - - const result = overwriteArray( source, destination ); - - expect( result ).toBe( destination ); - expect( result ).toEqual( source ); - } ); -} ); diff --git a/tests/utils/overwriteObject.test.tsx b/tests/utils/overwriteObject.test.tsx deleted file mode 100644 index f87dad39..00000000 --- a/tests/utils/overwriteObject.test.tsx +++ /dev/null @@ -1,51 +0,0 @@ -/** - * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. - * For licensing, see LICENSE.md. - */ - -import { describe, expect, it } from 'vitest'; -import { overwriteObject } from '../../src/utils/overwriteObject'; - -describe( 'overwriteObject', () => { - it( 'overwriteObject should clear the destination object and copy properties from the source object', () => { - const source = { a: 1, b: 2, c: 10 }; - const destination = { a: 10, b: 3, c: 20 }; - - const result = overwriteObject( source, destination ); - - expect( result ).toBe( destination ); - expect( result ).toEqual( { a: 1, b: 2, c: 10 } ); - } ); - - it( 'should not override prototype properties', () => { - const source = { a: 1, b: 2, c: 10 }; - const destination = Object.create( { a: 10, b: 3, c: 20 } ); - - const result = overwriteObject( source, destination ); - - expect( result ).toBe( destination ); - expect( result ).toEqual( { a: 1, b: 2, c: 10 } ); - } ); - - it( 'should remove properties from destination that are not present in source', () => { - const source = { a: 1, b: 2 }; - const destination = { a: 10, b: 3, c: 20 }; - - const result = overwriteObject( source, destination ); - - expect( result ).toBe( destination ); - expect( result ).toEqual( { a: 1, b: 2 } ); - } ); - - it( 'should not set self referencing attributes which crashes Object.assign', () => { - const source = { a: 1, b: 2, c: 10, d: null as any }; - const destination = { a: 10, b: 3, c: 20 }; - - source.d = destination; - - const result = overwriteObject( source, destination ); - - expect( result ).toBe( destination ); - expect( result ).toEqual( { a: 1, b: 2, c: 10 } ); - } ); -} ); diff --git a/tests/utils/shallowCompareArrays.test.tsx b/tests/utils/shallowCompareArrays.test.tsx deleted file mode 100644 index c052853f..00000000 --- a/tests/utils/shallowCompareArrays.test.tsx +++ /dev/null @@ -1,39 +0,0 @@ -/** - * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. - * For licensing, see LICENSE.md. - */ - -import { describe, expect, it } from 'vitest'; -import { shallowCompareArrays } from '../../src/utils/shallowCompareArrays'; - -describe( 'shallowCompareArrays', () => { - it( 'should return true if references are the same', () => { - const array = [ 1, 2, 3 ]; - expect( shallowCompareArrays( array, array ) ).to.be.true; - } ); - - it( 'should return true for equal arrays', () => { - const array1 = [ 1, 2, 3 ]; - const array2 = [ 1, 2, 3 ]; - - expect( shallowCompareArrays( array1, array2 ) ).to.be.true; - } ); - - it( 'should return false for different arrays', () => { - const array1 = [ 1, 2, 3 ]; - const array2 = [ 1, 2, 4 ]; - expect( shallowCompareArrays( array1, array2 ) ).to.be.false; - } ); - - it( 'should return false for arrays with different lengths', () => { - const array1 = [ 1, 2, 3 ]; - const array2 = [ 1, 2 ]; - expect( shallowCompareArrays( array1, array2 ) ).to.be.false; - } ); - - it( 'should return true for empty arrays', () => { - const array1: Array = []; - const array2: Array = []; - expect( shallowCompareArrays( array1, array2 ) ).to.be.true; - } ); -} ); diff --git a/tests/utils/uid.test.tsx b/tests/utils/uid.test.tsx deleted file mode 100644 index 7d913cce..00000000 --- a/tests/utils/uid.test.tsx +++ /dev/null @@ -1,31 +0,0 @@ -/** - * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. - * For licensing, see LICENSE.md. - */ - -import { it, expect, describe } from 'vitest'; -import { uid } from '../../src/utils/uid'; - -describe( 'uid', () => { - it( 'uid should return a string starting with "e"', () => { - const id = uid(); - expect( id.startsWith( 'e' ) ).toBe( true ); - } ); - - it( 'uid should return a string of length 33', () => { - const id = uid(); - expect( id.length ).toBe( 33 ); - } ); - - it( 'uid should return unique ids', () => { - const id1 = uid(); - const id2 = uid(); - expect( id1 ).not.toBe( id2 ); - } ); - - it( 'uid should only contain hexadecimal characters', () => { - const id = uid(); - const hexRegex = /^[a-fA-F0-9]+$/; - expect( hexRegex.test( id.substring( 1 ) ) ).toBe( true ); - } ); -} ); diff --git a/tests/utils/uniq.test.tsx b/tests/utils/uniq.test.tsx deleted file mode 100644 index 76c18529..00000000 --- a/tests/utils/uniq.test.tsx +++ /dev/null @@ -1,27 +0,0 @@ -/** - * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. - * For licensing, see LICENSE.md. - */ - -import { describe, expect, it } from 'vitest'; -import { uniq } from '../../src/utils/uniq'; - -describe( 'uniq', () => { - it( 'should remove duplicate elements from an array', () => { - const input = [ 1, 2, 2, 3, 4, 4, 5 ]; - const expectedOutput = [ 1, 2, 3, 4, 5 ]; - - const result = uniq( input ); - - expect( result ).toEqual( expectedOutput ); - } ); - - it( 'should return an empty array if the input is empty', () => { - const input: Array = []; - const expectedOutput: Array = []; - - const result = uniq( input ); - - expect( result ).toEqual( expectedOutput ); - } ); -} ); diff --git a/vite.config.ts b/vite.config.ts index 8324a69c..f93c36b5 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -41,7 +41,8 @@ export default defineConfig( { output: { globals: { 'react': 'React', - 'prop-types': 'PropTypes' + 'prop-types': 'PropTypes', + '@ckeditor/ckeditor5-integrations-common': 'CKEDITOR_INTEGRATIONS_COMMON' } } } @@ -49,6 +50,7 @@ export default defineConfig( { // https://vitest.dev/config/ test: { + setupFiles: [ './vitest-setup.ts' ], include: [ 'tests/**/*.test.[j|t]sx' ], diff --git a/vitest-setup.ts b/vitest-setup.ts new file mode 100644 index 00000000..bbd99e5f --- /dev/null +++ b/vitest-setup.ts @@ -0,0 +1,6 @@ +/** + * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. + * For licensing, see LICENSE.md. + */ + +import '@testing-library/jest-dom/vitest'; diff --git a/yarn.lock b/yarn.lock index fcf1715c..a281c991 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,11 @@ # yarn lockfile v1 +"@adobe/css-tools@^4.4.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.4.0.tgz#728c484f4e10df03d5a3acd0d8adcbbebff8ad63" + integrity sha512-Ff9+ksdQQB3rMncgqDK78uLznstjyfIf2Arnh22pW8kBpLs6rpKDwgnZT46hin5Hl1WzazzK64DOrhSwYpS7bQ== + "@ampproject/remapping@^2.2.0", "@ampproject/remapping@^2.3.0": version "2.3.0" resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" @@ -10,6 +15,459 @@ "@jridgewell/gen-mapping" "^0.3.5" "@jridgewell/trace-mapping" "^0.3.24" +"@aws-crypto/crc32@3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/crc32/-/crc32-3.0.0.tgz#07300eca214409c33e3ff769cd5697b57fdd38fa" + integrity sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA== + dependencies: + "@aws-crypto/util" "^3.0.0" + "@aws-sdk/types" "^3.222.0" + tslib "^1.11.1" + +"@aws-crypto/ie11-detection@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/ie11-detection/-/ie11-detection-3.0.0.tgz#640ae66b4ec3395cee6a8e94ebcd9f80c24cd688" + integrity sha512-341lBBkiY1DfDNKai/wXM3aujNBkXR7tq1URPQDL9wi3AUbI80NR74uF1TXHMm7po1AcnFk8iu2S2IeU/+/A+Q== + dependencies: + tslib "^1.11.1" + +"@aws-crypto/sha256-browser@3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/sha256-browser/-/sha256-browser-3.0.0.tgz#05f160138ab893f1c6ba5be57cfd108f05827766" + integrity sha512-8VLmW2B+gjFbU5uMeqtQM6Nj0/F1bro80xQXCW6CQBWgosFWXTx77aeOF5CAIAmbOK64SdMBJdNr6J41yP5mvQ== + dependencies: + "@aws-crypto/ie11-detection" "^3.0.0" + "@aws-crypto/sha256-js" "^3.0.0" + "@aws-crypto/supports-web-crypto" "^3.0.0" + "@aws-crypto/util" "^3.0.0" + "@aws-sdk/types" "^3.222.0" + "@aws-sdk/util-locate-window" "^3.0.0" + "@aws-sdk/util-utf8-browser" "^3.0.0" + tslib "^1.11.1" + +"@aws-crypto/sha256-js@3.0.0", "@aws-crypto/sha256-js@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/sha256-js/-/sha256-js-3.0.0.tgz#f06b84d550d25521e60d2a0e2a90139341e007c2" + integrity sha512-PnNN7os0+yd1XvXAy23CFOmTbMaDxgxXtTKHybrJ39Y8kGzBATgBFibWJKH6BhytLI/Zyszs87xCOBNyBig6vQ== + dependencies: + "@aws-crypto/util" "^3.0.0" + "@aws-sdk/types" "^3.222.0" + tslib "^1.11.1" + +"@aws-crypto/supports-web-crypto@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/supports-web-crypto/-/supports-web-crypto-3.0.0.tgz#5d1bf825afa8072af2717c3e455f35cda0103ec2" + integrity sha512-06hBdMwUAb2WFTuGG73LSC0wfPu93xWwo5vL2et9eymgmu3Id5vFAHBbajVWiGhPO37qcsdCap/FqXvJGJWPIg== + dependencies: + tslib "^1.11.1" + +"@aws-crypto/util@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/util/-/util-3.0.0.tgz#1c7ca90c29293f0883468ad48117937f0fe5bfb0" + integrity sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w== + dependencies: + "@aws-sdk/types" "^3.222.0" + "@aws-sdk/util-utf8-browser" "^3.0.0" + tslib "^1.11.1" + +"@aws-sdk/client-bedrock-runtime@3.470.0": + version "3.470.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-bedrock-runtime/-/client-bedrock-runtime-3.470.0.tgz#d1c04dee641447f3812baf99c72768d5b1fe1c64" + integrity sha512-oGMgVVpxJvHF7pz6BlLkzol403LYkqgV6yQeIyUX3CDLF6xZTF+ksSp8fMsZoTkqXz/0cRVzjykk+/e41T8pIg== + dependencies: + "@aws-crypto/sha256-browser" "3.0.0" + "@aws-crypto/sha256-js" "3.0.0" + "@aws-sdk/client-sts" "3.470.0" + "@aws-sdk/core" "3.468.0" + "@aws-sdk/credential-provider-node" "3.470.0" + "@aws-sdk/middleware-host-header" "3.468.0" + "@aws-sdk/middleware-logger" "3.468.0" + "@aws-sdk/middleware-recursion-detection" "3.468.0" + "@aws-sdk/middleware-signing" "3.468.0" + "@aws-sdk/middleware-user-agent" "3.470.0" + "@aws-sdk/region-config-resolver" "3.470.0" + "@aws-sdk/types" "3.468.0" + "@aws-sdk/util-endpoints" "3.470.0" + "@aws-sdk/util-user-agent-browser" "3.468.0" + "@aws-sdk/util-user-agent-node" "3.470.0" + "@smithy/config-resolver" "^2.0.21" + "@smithy/eventstream-serde-browser" "^2.0.15" + "@smithy/eventstream-serde-config-resolver" "^2.0.15" + "@smithy/eventstream-serde-node" "^2.0.15" + "@smithy/fetch-http-handler" "^2.3.1" + "@smithy/hash-node" "^2.0.17" + "@smithy/invalid-dependency" "^2.0.15" + "@smithy/middleware-content-length" "^2.0.17" + "@smithy/middleware-endpoint" "^2.2.3" + "@smithy/middleware-retry" "^2.0.24" + "@smithy/middleware-serde" "^2.0.15" + "@smithy/middleware-stack" "^2.0.9" + "@smithy/node-config-provider" "^2.1.8" + "@smithy/node-http-handler" "^2.2.1" + "@smithy/protocol-http" "^3.0.11" + "@smithy/smithy-client" "^2.1.18" + "@smithy/types" "^2.7.0" + "@smithy/url-parser" "^2.0.15" + "@smithy/util-base64" "^2.0.1" + "@smithy/util-body-length-browser" "^2.0.1" + "@smithy/util-body-length-node" "^2.1.0" + "@smithy/util-defaults-mode-browser" "^2.0.22" + "@smithy/util-defaults-mode-node" "^2.0.29" + "@smithy/util-endpoints" "^1.0.7" + "@smithy/util-retry" "^2.0.8" + "@smithy/util-stream" "^2.0.23" + "@smithy/util-utf8" "^2.0.2" + tslib "^2.5.0" + +"@aws-sdk/client-sso@3.470.0": + version "3.470.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.470.0.tgz#2fab6cc63af15a5dccbd985d784e49a3a3c634b4" + integrity sha512-iMXqdXuypE3OK0rggbvSz7vBGlLDG418dNidHhdaeLluMTG/GfHbh1fLOlavhYxRwrsPrtYvFiVkxXFGzXva4w== + dependencies: + "@aws-crypto/sha256-browser" "3.0.0" + "@aws-crypto/sha256-js" "3.0.0" + "@aws-sdk/core" "3.468.0" + "@aws-sdk/middleware-host-header" "3.468.0" + "@aws-sdk/middleware-logger" "3.468.0" + "@aws-sdk/middleware-recursion-detection" "3.468.0" + "@aws-sdk/middleware-user-agent" "3.470.0" + "@aws-sdk/region-config-resolver" "3.470.0" + "@aws-sdk/types" "3.468.0" + "@aws-sdk/util-endpoints" "3.470.0" + "@aws-sdk/util-user-agent-browser" "3.468.0" + "@aws-sdk/util-user-agent-node" "3.470.0" + "@smithy/config-resolver" "^2.0.21" + "@smithy/fetch-http-handler" "^2.3.1" + "@smithy/hash-node" "^2.0.17" + "@smithy/invalid-dependency" "^2.0.15" + "@smithy/middleware-content-length" "^2.0.17" + "@smithy/middleware-endpoint" "^2.2.3" + "@smithy/middleware-retry" "^2.0.24" + "@smithy/middleware-serde" "^2.0.15" + "@smithy/middleware-stack" "^2.0.9" + "@smithy/node-config-provider" "^2.1.8" + "@smithy/node-http-handler" "^2.2.1" + "@smithy/protocol-http" "^3.0.11" + "@smithy/smithy-client" "^2.1.18" + "@smithy/types" "^2.7.0" + "@smithy/url-parser" "^2.0.15" + "@smithy/util-base64" "^2.0.1" + "@smithy/util-body-length-browser" "^2.0.1" + "@smithy/util-body-length-node" "^2.1.0" + "@smithy/util-defaults-mode-browser" "^2.0.22" + "@smithy/util-defaults-mode-node" "^2.0.29" + "@smithy/util-endpoints" "^1.0.7" + "@smithy/util-retry" "^2.0.8" + "@smithy/util-utf8" "^2.0.2" + tslib "^2.5.0" + +"@aws-sdk/client-sts@3.470.0": + version "3.470.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sts/-/client-sts-3.470.0.tgz#f161d087564f9e545fbcd199c7197ec0cfce29b9" + integrity sha512-TP3A4t8FoFEQinm6axxduTUnlMMLpmLi4Sf00JTI2CszxLUFh/JyUhYQ5gSOoXgPFmfwVXUNKCtmR3jdP0ZGPw== + dependencies: + "@aws-crypto/sha256-browser" "3.0.0" + "@aws-crypto/sha256-js" "3.0.0" + "@aws-sdk/core" "3.468.0" + "@aws-sdk/credential-provider-node" "3.470.0" + "@aws-sdk/middleware-host-header" "3.468.0" + "@aws-sdk/middleware-logger" "3.468.0" + "@aws-sdk/middleware-recursion-detection" "3.468.0" + "@aws-sdk/middleware-sdk-sts" "3.468.0" + "@aws-sdk/middleware-signing" "3.468.0" + "@aws-sdk/middleware-user-agent" "3.470.0" + "@aws-sdk/region-config-resolver" "3.470.0" + "@aws-sdk/types" "3.468.0" + "@aws-sdk/util-endpoints" "3.470.0" + "@aws-sdk/util-user-agent-browser" "3.468.0" + "@aws-sdk/util-user-agent-node" "3.470.0" + "@smithy/config-resolver" "^2.0.21" + "@smithy/fetch-http-handler" "^2.3.1" + "@smithy/hash-node" "^2.0.17" + "@smithy/invalid-dependency" "^2.0.15" + "@smithy/middleware-content-length" "^2.0.17" + "@smithy/middleware-endpoint" "^2.2.3" + "@smithy/middleware-retry" "^2.0.24" + "@smithy/middleware-serde" "^2.0.15" + "@smithy/middleware-stack" "^2.0.9" + "@smithy/node-config-provider" "^2.1.8" + "@smithy/node-http-handler" "^2.2.1" + "@smithy/protocol-http" "^3.0.11" + "@smithy/smithy-client" "^2.1.18" + "@smithy/types" "^2.7.0" + "@smithy/url-parser" "^2.0.15" + "@smithy/util-base64" "^2.0.1" + "@smithy/util-body-length-browser" "^2.0.1" + "@smithy/util-body-length-node" "^2.1.0" + "@smithy/util-defaults-mode-browser" "^2.0.22" + "@smithy/util-defaults-mode-node" "^2.0.29" + "@smithy/util-endpoints" "^1.0.7" + "@smithy/util-retry" "^2.0.8" + "@smithy/util-utf8" "^2.0.2" + fast-xml-parser "4.2.5" + tslib "^2.5.0" + +"@aws-sdk/core@3.468.0": + version "3.468.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/core/-/core-3.468.0.tgz#1f356adedd63ef77042a3de10fc4c1fdcce4ad42" + integrity sha512-ezUJR9VvknKoXzNZ4wvzGi1jdkmm+/1dUYQ9Sw4r8bzlJDTsUnWbyvaDlBQh81RuhLtVkaUfTnQKoec0cwlZKQ== + dependencies: + "@smithy/smithy-client" "^2.1.18" + tslib "^2.5.0" + +"@aws-sdk/credential-provider-env@3.468.0": + version "3.468.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.468.0.tgz#4196d717d3f5485af863bd1fd84374ea3dcd6210" + integrity sha512-k/1WHd3KZn0EQYjadooj53FC0z24/e4dUZhbSKTULgmxyO62pwh9v3Brvw4WRa/8o2wTffU/jo54tf4vGuP/ZA== + dependencies: + "@aws-sdk/types" "3.468.0" + "@smithy/property-provider" "^2.0.0" + "@smithy/types" "^2.7.0" + tslib "^2.5.0" + +"@aws-sdk/credential-provider-ini@3.470.0": + version "3.470.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.470.0.tgz#d360d08f893d5d28a3e6a493bbef0989669c2f6a" + integrity sha512-eF22iPO6J2jY+LbuTv5dW0hZBmi6ksRDFFd/zT6TLasrzH2Ex+gAfN3c7rFHF+XAubL0JXFUKFA3UAwoZpO9Zg== + dependencies: + "@aws-sdk/credential-provider-env" "3.468.0" + "@aws-sdk/credential-provider-process" "3.468.0" + "@aws-sdk/credential-provider-sso" "3.470.0" + "@aws-sdk/credential-provider-web-identity" "3.468.0" + "@aws-sdk/types" "3.468.0" + "@smithy/credential-provider-imds" "^2.0.0" + "@smithy/property-provider" "^2.0.0" + "@smithy/shared-ini-file-loader" "^2.0.6" + "@smithy/types" "^2.7.0" + tslib "^2.5.0" + +"@aws-sdk/credential-provider-node@3.470.0": + version "3.470.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.470.0.tgz#9236a27f451fef06e1cb6c744b6b8b3dc3d633a3" + integrity sha512-paySXwzGxBVU+2cVUkRIXafKhYhtO2fJJ3MotR6euvRONK/dta+bhEc5Z4QnTo/gNLoELK/QUC0EGoF+oPfk8g== + dependencies: + "@aws-sdk/credential-provider-env" "3.468.0" + "@aws-sdk/credential-provider-ini" "3.470.0" + "@aws-sdk/credential-provider-process" "3.468.0" + "@aws-sdk/credential-provider-sso" "3.470.0" + "@aws-sdk/credential-provider-web-identity" "3.468.0" + "@aws-sdk/types" "3.468.0" + "@smithy/credential-provider-imds" "^2.0.0" + "@smithy/property-provider" "^2.0.0" + "@smithy/shared-ini-file-loader" "^2.0.6" + "@smithy/types" "^2.7.0" + tslib "^2.5.0" + +"@aws-sdk/credential-provider-process@3.468.0": + version "3.468.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.468.0.tgz#770ed72db036c5d011445e5abf4a4bcc4424c486" + integrity sha512-OYSn1A/UsyPJ7Z8Q2cNhTf55O36shPmSsvOfND04nSfu1nPaR+VUvvsP7v+brhGpwC/GAKTIdGAo4blH31BS6A== + dependencies: + "@aws-sdk/types" "3.468.0" + "@smithy/property-provider" "^2.0.0" + "@smithy/shared-ini-file-loader" "^2.0.6" + "@smithy/types" "^2.7.0" + tslib "^2.5.0" + +"@aws-sdk/credential-provider-sso@3.470.0": + version "3.470.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.470.0.tgz#12f14557be50a01bc99166610d83ea5be79b154a" + integrity sha512-biGDSh9S9KDR9Tl/8cCPn9g5KPNkXg/CIJIOk3X+6valktbJ2UVYBzi0ZX4vZiudt5ry/Hsu6Pgo+KN1AmBWdg== + dependencies: + "@aws-sdk/client-sso" "3.470.0" + "@aws-sdk/token-providers" "3.470.0" + "@aws-sdk/types" "3.468.0" + "@smithy/property-provider" "^2.0.0" + "@smithy/shared-ini-file-loader" "^2.0.6" + "@smithy/types" "^2.7.0" + tslib "^2.5.0" + +"@aws-sdk/credential-provider-web-identity@3.468.0": + version "3.468.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.468.0.tgz#5befcb593d99a84e16af9e9f285f0d59ed42771f" + integrity sha512-rexymPmXjtkwCPfhnUq3EjO1rSkf39R4Jz9CqiM7OsqK2qlT5Y/V3gnMKn0ZMXsYaQOMfM3cT5xly5R+OKDHlw== + dependencies: + "@aws-sdk/types" "3.468.0" + "@smithy/property-provider" "^2.0.0" + "@smithy/types" "^2.7.0" + tslib "^2.5.0" + +"@aws-sdk/middleware-host-header@3.468.0": + version "3.468.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.468.0.tgz#6da7b19032e9afccea54fbf8aa10cccd2f817bcf" + integrity sha512-gwQ+/QhX+lhof304r6zbZ/V5l5cjhGRxLL3CjH1uJPMcOAbw9wUlMdl+ibr8UwBZ5elfKFGiB1cdW/0uMchw0w== + dependencies: + "@aws-sdk/types" "3.468.0" + "@smithy/protocol-http" "^3.0.11" + "@smithy/types" "^2.7.0" + tslib "^2.5.0" + +"@aws-sdk/middleware-logger@3.468.0": + version "3.468.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-logger/-/middleware-logger-3.468.0.tgz#a1883fb7ad8e156444d30689de4ab897357ef1d8" + integrity sha512-X5XHKV7DHRXI3f29SAhJPe/OxWRFgDWDMMCALfzhmJfCi6Jfh0M14cJKoC+nl+dk9lB+36+jKjhjETZaL2bPlA== + dependencies: + "@aws-sdk/types" "3.468.0" + "@smithy/types" "^2.7.0" + tslib "^2.5.0" + +"@aws-sdk/middleware-recursion-detection@3.468.0": + version "3.468.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.468.0.tgz#85b05636a5c2638bf9e15c8b6be17654757e1bf4" + integrity sha512-vch9IQib2Ng9ucSyRW2eKNQXHUPb5jUPCLA5otTW/8nGjcOU37LxQG4WrxO7uaJ9Oe8hjHO+hViE3P0KISUhtA== + dependencies: + "@aws-sdk/types" "3.468.0" + "@smithy/protocol-http" "^3.0.11" + "@smithy/types" "^2.7.0" + tslib "^2.5.0" + +"@aws-sdk/middleware-sdk-sts@3.468.0": + version "3.468.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.468.0.tgz#773ed9f7087b184461c9cda0b442e58cb15c6a5b" + integrity sha512-xRy8NKfHbmafHwdbotdWgHBvRs0YZgk20GrhFJKp43bkqVbJ5bNlh3nQXf1DeFY9fARR84Bfotya4fwCUHWgZg== + dependencies: + "@aws-sdk/middleware-signing" "3.468.0" + "@aws-sdk/types" "3.468.0" + "@smithy/types" "^2.7.0" + tslib "^2.5.0" + +"@aws-sdk/middleware-signing@3.468.0": + version "3.468.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-signing/-/middleware-signing-3.468.0.tgz#d1b5a92c395f55063cfa72ee95e4921b16f4c515" + integrity sha512-s+7fSB1gdnnTj5O0aCCarX3z5Vppop8kazbNSZADdkfHIDWCN80IH4ZNjY3OWqaAz0HmR4LNNrovdR304ojb4Q== + dependencies: + "@aws-sdk/types" "3.468.0" + "@smithy/property-provider" "^2.0.0" + "@smithy/protocol-http" "^3.0.11" + "@smithy/signature-v4" "^2.0.0" + "@smithy/types" "^2.7.0" + "@smithy/util-middleware" "^2.0.8" + tslib "^2.5.0" + +"@aws-sdk/middleware-user-agent@3.470.0": + version "3.470.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.470.0.tgz#6cbb09fc8359acdb45c41f6fe5d6612c81f5ad92" + integrity sha512-s0YRGgf4fT5KwwTefpoNUQfB5JghzXyvmPfY1QuFEMeVQNxv0OPuydzo3rY2oXPkZjkulKDtpm5jzIHwut75hA== + dependencies: + "@aws-sdk/types" "3.468.0" + "@aws-sdk/util-endpoints" "3.470.0" + "@smithy/protocol-http" "^3.0.11" + "@smithy/types" "^2.7.0" + tslib "^2.5.0" + +"@aws-sdk/region-config-resolver@3.470.0": + version "3.470.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/region-config-resolver/-/region-config-resolver-3.470.0.tgz#74e5c5f7a5633ad8c482503bf940a9330bd1cd09" + integrity sha512-C1o1J06iIw8cyAAOvHqT4Bbqf+PgQ/RDlSyjt2gFfP2OovDpc2o2S90dE8f8iZdSGpg70N5MikT1DBhW9NbhtQ== + dependencies: + "@smithy/node-config-provider" "^2.1.8" + "@smithy/types" "^2.7.0" + "@smithy/util-config-provider" "^2.0.0" + "@smithy/util-middleware" "^2.0.8" + tslib "^2.5.0" + +"@aws-sdk/token-providers@3.470.0": + version "3.470.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/token-providers/-/token-providers-3.470.0.tgz#635fa5db3f10919868a9f94be43241fbce206ede" + integrity sha512-rzxnJxEUJiV69Cxsf0AHXTqJqTACITwcSH/PL4lWP4uvtzdrzSi3KA3u2aWHWpOcdE6+JFvdICscsbBSo3/TOg== + dependencies: + "@aws-crypto/sha256-browser" "3.0.0" + "@aws-crypto/sha256-js" "3.0.0" + "@aws-sdk/middleware-host-header" "3.468.0" + "@aws-sdk/middleware-logger" "3.468.0" + "@aws-sdk/middleware-recursion-detection" "3.468.0" + "@aws-sdk/middleware-user-agent" "3.470.0" + "@aws-sdk/region-config-resolver" "3.470.0" + "@aws-sdk/types" "3.468.0" + "@aws-sdk/util-endpoints" "3.470.0" + "@aws-sdk/util-user-agent-browser" "3.468.0" + "@aws-sdk/util-user-agent-node" "3.470.0" + "@smithy/config-resolver" "^2.0.21" + "@smithy/fetch-http-handler" "^2.3.1" + "@smithy/hash-node" "^2.0.17" + "@smithy/invalid-dependency" "^2.0.15" + "@smithy/middleware-content-length" "^2.0.17" + "@smithy/middleware-endpoint" "^2.2.3" + "@smithy/middleware-retry" "^2.0.24" + "@smithy/middleware-serde" "^2.0.15" + "@smithy/middleware-stack" "^2.0.9" + "@smithy/node-config-provider" "^2.1.8" + "@smithy/node-http-handler" "^2.2.1" + "@smithy/property-provider" "^2.0.0" + "@smithy/protocol-http" "^3.0.11" + "@smithy/shared-ini-file-loader" "^2.0.6" + "@smithy/smithy-client" "^2.1.18" + "@smithy/types" "^2.7.0" + "@smithy/url-parser" "^2.0.15" + "@smithy/util-base64" "^2.0.1" + "@smithy/util-body-length-browser" "^2.0.1" + "@smithy/util-body-length-node" "^2.1.0" + "@smithy/util-defaults-mode-browser" "^2.0.22" + "@smithy/util-defaults-mode-node" "^2.0.29" + "@smithy/util-endpoints" "^1.0.7" + "@smithy/util-retry" "^2.0.8" + "@smithy/util-utf8" "^2.0.2" + tslib "^2.5.0" + +"@aws-sdk/types@3.468.0": + version "3.468.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.468.0.tgz#f97b34fc92a800d1d8b866f47693ae8f3d46517b" + integrity sha512-rx/9uHI4inRbp2tw3Y4Ih4PNZkVj32h7WneSg3MVgVjAoVD5Zti9KhS5hkvsBxfgmQmg0AQbE+b1sy5WGAgntA== + dependencies: + "@smithy/types" "^2.7.0" + tslib "^2.5.0" + +"@aws-sdk/types@^3.222.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.609.0.tgz#06b39d799c9f197a7b43670243e8e78a3bf7d6a5" + integrity sha512-+Tqnh9w0h2LcrUsdXyT1F8mNhXz+tVYBtP19LpeEGntmvHwa2XzvLUCWpoIAIVsHp5+HdB2X9Sn0KAtmbFXc2Q== + dependencies: + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/util-endpoints@3.470.0": + version "3.470.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-endpoints/-/util-endpoints-3.470.0.tgz#94338991804f24e0225636abd4215b3bb4338c15" + integrity sha512-6N6VvPCmu+89p5Ez/+gLf+X620iQ9JpIs8p8ECZiCodirzFOe8NC1O2S7eov7YiG9IHSuodqn/0qNq+v+oLe0A== + dependencies: + "@aws-sdk/types" "3.468.0" + "@smithy/util-endpoints" "^1.0.7" + tslib "^2.5.0" + +"@aws-sdk/util-locate-window@^3.0.0": + version "3.568.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-locate-window/-/util-locate-window-3.568.0.tgz#2acc4b2236af0d7494f7e517401ba6b3c4af11ff" + integrity sha512-3nh4TINkXYr+H41QaPelCceEB2FXP3fxp93YZXB/kqJvX0U9j0N0Uk45gvsjmEPzG8XxkPEeLIfT2I1M7A6Lig== + dependencies: + tslib "^2.6.2" + +"@aws-sdk/util-user-agent-browser@3.468.0": + version "3.468.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.468.0.tgz#095caecb3fd75104ee38ae81ed78821de0f58e28" + integrity sha512-OJyhWWsDEizR3L+dCgMXSUmaCywkiZ7HSbnQytbeKGwokIhD69HTiJcibF/sgcM5gk4k3Mq3puUhGnEZ46GIig== + dependencies: + "@aws-sdk/types" "3.468.0" + "@smithy/types" "^2.7.0" + bowser "^2.11.0" + tslib "^2.5.0" + +"@aws-sdk/util-user-agent-node@3.470.0": + version "3.470.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.470.0.tgz#b78605f336859d6c3b5f573cff931ce41f83a27d" + integrity sha512-QxsZ9iVHcBB/XRdYvwfM5AMvNp58HfqkIrH88mY0cmxuvtlIGDfWjczdDrZMJk9y0vIq+cuoCHsGXHu7PyiEAQ== + dependencies: + "@aws-sdk/types" "3.468.0" + "@smithy/node-config-provider" "^2.1.8" + "@smithy/types" "^2.7.0" + tslib "^2.5.0" + +"@aws-sdk/util-utf8-browser@^3.0.0": + version "3.259.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz#3275a6f5eb334f96ca76635b961d3c50259fd9ff" + integrity sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw== + dependencies: + tslib "^2.3.1" + "@babel/code-frame@7.12.11": version "7.12.11" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" @@ -157,7 +615,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.24.7" -"@babel/runtime@^7.12.5", "@babel/runtime@^7.21.0": +"@babel/runtime@^7.12.5", "@babel/runtime@^7.21.0", "@babel/runtime@^7.9.2": version "7.25.0" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.25.0.tgz#3af9a91c1b739c569d5d80cc917280919c544ecb" integrity sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw== @@ -217,6 +675,17 @@ "@types/tough-cookie" "^4.0.5" tough-cookie "^4.1.4" +"@ckeditor/ckeditor-cloud-services-collaboration@52.6.10": + version "52.6.10" + resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor-cloud-services-collaboration/-/ckeditor-cloud-services-collaboration-52.6.10.tgz#6245b2d0b0c4b28bfacd3080ad3f6545be6a5026" + integrity sha512-Q2HcwoHjurV5OfTEFjGRM/pUX7FpCRP4I2d2BhBG6B2xO2mrWdExKITSODs6Qe8ypbVSeMViCP9u8wO1nV3afQ== + dependencies: + protobufjs "7.2.5" + socket.io-client "4.7.0" + socket.io-parser "~4.2.3" + url-parse "1.5.10" + uuid "^9.0.1" + "@ckeditor/ckeditor5-adapter-ckfinder@42.0.2": version "42.0.2" resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-adapter-ckfinder/-/ckeditor5-adapter-ckfinder-42.0.2.tgz#b5f7c43b3ac757adde4f06c91b861981681f5adb" @@ -226,6 +695,21 @@ "@ckeditor/ckeditor5-upload" "42.0.2" ckeditor5 "42.0.2" +"@ckeditor/ckeditor5-ai@42.0.2": + version "42.0.2" + resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-ai/-/ckeditor5-ai-42.0.2.tgz#d657f6c261b7345b165030765dfd8c4e9602ce22" + integrity sha512-7oR7Xcgbj0hTDEQnZGKaCshqJTytrqyp08MEGkjR/tbp70tYl8loaAvI4QuSJ5++k240i8kvl97XROjbZqCmsg== + dependencies: + "@aws-sdk/client-bedrock-runtime" "3.470.0" + "@ckeditor/ckeditor5-clipboard" "42.0.2" + "@ckeditor/ckeditor5-core" "42.0.2" + "@ckeditor/ckeditor5-engine" "42.0.2" + "@ckeditor/ckeditor5-ui" "42.0.2" + "@ckeditor/ckeditor5-utils" "42.0.2" + ckeditor5 "42.0.2" + ckeditor5-collaboration "42.0.2" + lodash-es "4.17.21" + "@ckeditor/ckeditor5-alignment@42.0.2": version "42.0.2" resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-alignment/-/ckeditor5-alignment-42.0.2.tgz#b0a6a480d04837cec8311e9a6d3168bd47ca7868" @@ -279,6 +763,17 @@ "@ckeditor/ckeditor5-utils" "42.0.2" ckeditor5 "42.0.2" +"@ckeditor/ckeditor5-case-change@42.0.2": + version "42.0.2" + resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-case-change/-/ckeditor5-case-change-42.0.2.tgz#69348aa35b1bee7f045f551c2d1e171e0b1f0e72" + integrity sha512-f42iK4OgtnO5Dny1O/rMW1WksHBEToyLMtGcf+NA4L7PkFEbfE5JxkddbIwXhP7GrNJzu19OtdG55lemQm3P6w== + dependencies: + "@ckeditor/ckeditor5-core" "42.0.2" + "@ckeditor/ckeditor5-ui" "42.0.2" + "@ckeditor/ckeditor5-utils" "42.0.2" + ckeditor5 "42.0.2" + ckeditor5-collaboration "42.0.2" + "@ckeditor/ckeditor5-ckbox@42.0.2": version "42.0.2" resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-ckbox/-/ckeditor5-ckbox-42.0.2.tgz#d09194fc01dfbdf8afd6ad25f42e5352e3e45e26" @@ -337,6 +832,36 @@ ckeditor5 "42.0.2" lodash-es "4.17.21" +"@ckeditor/ckeditor5-collaboration-core@42.0.2": + version "42.0.2" + resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-collaboration-core/-/ckeditor5-collaboration-core-42.0.2.tgz#a20ac6f8ef40e54c92c1ed9b4147c71f87a83f1e" + integrity sha512-T1TTLTzZyoYQZLXT9pC+SI0rkXfZaXsldDHTBndFOWP3YPHCHFwmr5Mz986IZ8fdMt8YnShw+5C8D6Jskfkv0A== + dependencies: + "@ckeditor/ckeditor5-core" "42.0.2" + "@ckeditor/ckeditor5-ui" "42.0.2" + "@ckeditor/ckeditor5-utils" "42.0.2" + ckeditor5 "42.0.2" + date-fns "2.30.0" + +"@ckeditor/ckeditor5-comments@42.0.2": + version "42.0.2" + resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-comments/-/ckeditor5-comments-42.0.2.tgz#a1ff69b666e22fa7bf2753049fb82830f921a7af" + integrity sha512-NpXPi0ww7RJlnPH1/d+26RuIBev+KfpEe47qQsU4DgsdoIO3bOtJSawoCulIby5mbXXDEUTO4nVfU7tUWhUB1g== + dependencies: + "@ckeditor/ckeditor5-clipboard" "42.0.2" + "@ckeditor/ckeditor5-core" "42.0.2" + "@ckeditor/ckeditor5-engine" "42.0.2" + "@ckeditor/ckeditor5-enter" "42.0.2" + "@ckeditor/ckeditor5-paragraph" "42.0.2" + "@ckeditor/ckeditor5-select-all" "42.0.2" + "@ckeditor/ckeditor5-typing" "42.0.2" + "@ckeditor/ckeditor5-ui" "42.0.2" + "@ckeditor/ckeditor5-undo" "42.0.2" + "@ckeditor/ckeditor5-utils" "42.0.2" + ckeditor5 "42.0.2" + ckeditor5-collaboration "42.0.2" + lodash-es "4.17.21" + "@ckeditor/ckeditor5-core@42.0.2": version "42.0.2" resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-core/-/ckeditor5-core-42.0.2.tgz#64894c4a09a2b5b5134c53e6add5d49f3439bd88" @@ -432,6 +957,20 @@ terser-webpack-plugin "^4.2.3" through2 "^3.0.1" +"@ckeditor/ckeditor5-document-outline@42.0.2": + version "42.0.2" + resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-document-outline/-/ckeditor5-document-outline-42.0.2.tgz#ca0dae8fa72b1467b20f72df99051629138c637c" + integrity sha512-wMabjAImkABxA3D0AUalgdQ8dZiqMWrxj2mZ9TVTF8mVMYc5kA5qdGO+B5snRcpX2vWOEe9TdXUSy6108TT/4Q== + dependencies: + "@ckeditor/ckeditor5-core" "42.0.2" + "@ckeditor/ckeditor5-engine" "42.0.2" + "@ckeditor/ckeditor5-ui" "42.0.2" + "@ckeditor/ckeditor5-utils" "42.0.2" + "@ckeditor/ckeditor5-widget" "42.0.2" + ckeditor5 "42.0.2" + ckeditor5-collaboration "42.0.2" + lodash-es "4.17.21" + "@ckeditor/ckeditor5-easy-image@42.0.2": version "42.0.2" resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-easy-image/-/ckeditor5-easy-image-42.0.2.tgz#10dbbc38bf24ac359509faaaa10c1cccbad1bfff" @@ -533,6 +1072,24 @@ "@ckeditor/ckeditor5-undo" "42.0.2" ckeditor5 "42.0.2" +"@ckeditor/ckeditor5-export-pdf@42.0.2": + version "42.0.2" + resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-export-pdf/-/ckeditor5-export-pdf-42.0.2.tgz#f53e804d3fe5f5d2b230b0dd687b8d7393f76728" + integrity sha512-Zz00WZPVOI2qHGm148oJh61yovpMBJKx3uJ7TXHgicDkGxtVR7BZxwLVq5JhxTtLRaPuhiTcBBsjrBQAowKiGw== + dependencies: + "@ckeditor/ckeditor5-core" "42.0.2" + "@ckeditor/ckeditor5-ui" "42.0.2" + ckeditor5 "42.0.2" + +"@ckeditor/ckeditor5-export-word@42.0.2": + version "42.0.2" + resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-export-word/-/ckeditor5-export-word-42.0.2.tgz#74f5b2880e2cb116014ba3d5297c364a8e35ff5e" + integrity sha512-XgKzZNXeRQyIcPhZmkFZZNdr+fE9ZQtkQLiTvMzuD/JknTpoc2T9QjBtGAeVf5a6HVp2BnvOthpdC1umIqyYmw== + dependencies: + "@ckeditor/ckeditor5-core" "42.0.2" + "@ckeditor/ckeditor5-ui" "42.0.2" + ckeditor5 "42.0.2" + "@ckeditor/ckeditor5-find-and-replace@42.0.2": version "42.0.2" resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-find-and-replace/-/ckeditor5-find-and-replace-42.0.2.tgz#7bed025d74c7eafda60803179a5d3a3926e5a23c" @@ -555,6 +1112,18 @@ "@ckeditor/ckeditor5-utils" "42.0.2" ckeditor5 "42.0.2" +"@ckeditor/ckeditor5-format-painter@42.0.2": + version "42.0.2" + resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-format-painter/-/ckeditor5-format-painter-42.0.2.tgz#9a17b606261cb6593636615ef289c78712598e1e" + integrity sha512-2G8jtuh3/NoBf3jXnylzA6Gn/SUTW4Mdy/la4EoZlxB1aV468uWu9cUQG2h/YgLWoTZTf5zCZV0lRlKQWKDOeQ== + dependencies: + "@ckeditor/ckeditor5-core" "42.0.2" + "@ckeditor/ckeditor5-engine" "42.0.2" + "@ckeditor/ckeditor5-ui" "42.0.2" + "@ckeditor/ckeditor5-utils" "42.0.2" + ckeditor5 "42.0.2" + ckeditor5-collaboration "42.0.2" + "@ckeditor/ckeditor5-heading@42.0.2": version "42.0.2" resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-heading/-/ckeditor5-heading-42.0.2.tgz#be597db9f9b36f895cdbb244b6dd05c66cf7dd5f" @@ -627,6 +1196,18 @@ ckeditor5 "42.0.2" lodash-es "4.17.21" +"@ckeditor/ckeditor5-import-word@42.0.2": + version "42.0.2" + resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-import-word/-/ckeditor5-import-word-42.0.2.tgz#97dd1aed9a16c3ec9aef92a02418934d9e71a84d" + integrity sha512-VO7mfOilJBJplPOCBNEdtgj8blI7UttqoKQzlJ54ZnmFrQ7MZdqQLJdRbcO7OaPm7h/towcbnqalNKFWIladQw== + dependencies: + "@ckeditor/ckeditor5-clipboard" "42.0.2" + "@ckeditor/ckeditor5-core" "42.0.2" + "@ckeditor/ckeditor5-engine" "42.0.2" + "@ckeditor/ckeditor5-ui" "42.0.2" + "@ckeditor/ckeditor5-utils" "42.0.2" + ckeditor5 "42.0.2" + "@ckeditor/ckeditor5-indent@42.0.2": version "42.0.2" resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-indent/-/ckeditor5-indent-42.0.2.tgz#428d2d1a63e39ab36744c3465bbcae2c927a3019" @@ -638,6 +1219,11 @@ "@ckeditor/ckeditor5-utils" "42.0.2" ckeditor5 "42.0.2" +"@ckeditor/ckeditor5-integrations-common@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-integrations-common/-/ckeditor5-integrations-common-1.0.0.tgz#f2f73509d029398929ee30da3ae23329de5a796a" + integrity sha512-HLToIJ7FAtKX0tu9GaGb1d39Kx0i0TFelAj2pQPiwPU/6DLgM5gi+m0WCZub+syruSonmZPONtWrrZZdUoDB/g== + "@ckeditor/ckeditor5-language@42.0.2": version "42.0.2" resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-language/-/ckeditor5-language-42.0.2.tgz#0d5f0382ec22e0572f0df23cd90e8bb85e8961db" @@ -663,6 +1249,17 @@ ckeditor5 "42.0.2" lodash-es "4.17.21" +"@ckeditor/ckeditor5-list-multi-level@42.0.2": + version "42.0.2" + resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-list-multi-level/-/ckeditor5-list-multi-level-42.0.2.tgz#ac3c7f0f5e5411535380ada99b68f03ff5c20263" + integrity sha512-4ccBRTYhXDaQDeAqj75Z2WiQGaQPJFwQIMRgkn8SjM71f5JLn70SxYNRXis2EKboqJ1KuYcQeA5/ADXfiVjbUw== + dependencies: + "@ckeditor/ckeditor5-core" "42.0.2" + "@ckeditor/ckeditor5-engine" "42.0.2" + "@ckeditor/ckeditor5-ui" "42.0.2" + "@ckeditor/ckeditor5-utils" "42.0.2" + ckeditor5 "42.0.2" + "@ckeditor/ckeditor5-list@42.0.2": version "42.0.2" resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-list/-/ckeditor5-list-42.0.2.tgz#bbed64ff90c3e764667f0a737a8f9566894dd1e3" @@ -728,6 +1325,16 @@ "@ckeditor/ckeditor5-utils" "42.0.2" ckeditor5 "42.0.2" +"@ckeditor/ckeditor5-operations-compressor@42.0.2": + version "42.0.2" + resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-operations-compressor/-/ckeditor5-operations-compressor-42.0.2.tgz#3c06ebe09f515f1936f4d127cb63a3429302fb12" + integrity sha512-GLk4qanbuRhFhSa42I+1ePHOSaCD9j2V3nrqtkBiZoMviUdemDZggf8JJT/dytPDWER9XtpQpVBD2USEo/t7+w== + dependencies: + "@ckeditor/ckeditor5-utils" "42.0.2" + ckeditor5 "42.0.2" + lodash-es "4.17.21" + protobufjs "7.2.5" + "@ckeditor/ckeditor5-page-break@42.0.2": version "42.0.2" resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-page-break/-/ckeditor5-page-break-42.0.2.tgz#5926704f351fa397dfada22f3cf470e8959f391a" @@ -738,6 +1345,18 @@ "@ckeditor/ckeditor5-widget" "42.0.2" ckeditor5 "42.0.2" +"@ckeditor/ckeditor5-pagination@42.0.2": + version "42.0.2" + resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-pagination/-/ckeditor5-pagination-42.0.2.tgz#756b47973b21b4e6d78eccdf2ea11748c423db44" + integrity sha512-jLQdNanCfmx1K9p7PlCgB6cZCbcksCkKMXRVHrbOfZrQ1vdHU4W1XysFVqADio4+NxxrSzvc3h4Ci5FECe4hQg== + dependencies: + "@ckeditor/ckeditor5-core" "42.0.2" + "@ckeditor/ckeditor5-theme-lark" "42.0.2" + "@ckeditor/ckeditor5-ui" "42.0.2" + "@ckeditor/ckeditor5-utils" "42.0.2" + ckeditor5 "42.0.2" + lodash-es "4.17.21" + "@ckeditor/ckeditor5-paragraph@42.0.2": version "42.0.2" resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-paragraph/-/ckeditor5-paragraph-42.0.2.tgz#0c7d4b8e600071582fed1f887e693327f93d5aa0" @@ -747,6 +1366,17 @@ "@ckeditor/ckeditor5-ui" "42.0.2" "@ckeditor/ckeditor5-utils" "42.0.2" +"@ckeditor/ckeditor5-paste-from-office-enhanced@42.0.2": + version "42.0.2" + resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-paste-from-office-enhanced/-/ckeditor5-paste-from-office-enhanced-42.0.2.tgz#37adbe7a9e1c008fde48286d003926dc7ca60d42" + integrity sha512-RCZYDQOiE36yJ3SXRYKP5JIdu3rb6BJn8TTo3knG6ZW0XP3SCQ4EG0gLzyDOc0KeJih+GC9tpl6OsWhG1VxWUg== + dependencies: + "@ckeditor/ckeditor5-core" "42.0.2" + "@ckeditor/ckeditor5-engine" "42.0.2" + "@ckeditor/ckeditor5-paste-from-office" "42.0.2" + "@ckeditor/ckeditor5-utils" "42.0.2" + ckeditor5 "42.0.2" + "@ckeditor/ckeditor5-paste-from-office@42.0.2": version "42.0.2" resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-paste-from-office/-/ckeditor5-paste-from-office-42.0.2.tgz#17bd46fc7f839158edf3859cb9706168ec13bac5" @@ -757,6 +1387,21 @@ "@ckeditor/ckeditor5-engine" "42.0.2" ckeditor5 "42.0.2" +"@ckeditor/ckeditor5-real-time-collaboration@42.0.2": + version "42.0.2" + resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-real-time-collaboration/-/ckeditor5-real-time-collaboration-42.0.2.tgz#64027ad0bdf579619e7ac55f18cd1ac76180a548" + integrity sha512-iR1nMBsbMrnv4ejmmERgtrdNrz/sGdmZEHfe4Jdym7qwFa3X3MFd7OXFYCfZq4woYRECBsOGxkB6hxF51soFwA== + dependencies: + "@ckeditor/ckeditor-cloud-services-collaboration" "52.6.10" + "@ckeditor/ckeditor5-core" "42.0.2" + "@ckeditor/ckeditor5-engine" "42.0.2" + "@ckeditor/ckeditor5-operations-compressor" "42.0.2" + "@ckeditor/ckeditor5-ui" "42.0.2" + "@ckeditor/ckeditor5-utils" "42.0.2" + ckeditor5 "42.0.2" + ckeditor5-collaboration "42.0.2" + lodash-es "4.17.21" + "@ckeditor/ckeditor5-remove-format@42.0.2": version "42.0.2" resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-remove-format/-/ckeditor5-remove-format-42.0.2.tgz#7cb9e096b1c494574ffeec830117e6b87032db30" @@ -778,6 +1423,21 @@ "@ckeditor/ckeditor5-utils" "42.0.2" ckeditor5 "42.0.2" +"@ckeditor/ckeditor5-revision-history@42.0.2": + version "42.0.2" + resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-revision-history/-/ckeditor5-revision-history-42.0.2.tgz#80101e034b99f2998195eba364edd63b73fcc743" + integrity sha512-c/ep6t+ajq7Qo/qFWTPvMcDxMSkAJgWX6H8P+yAX1IC8ok7JCj1NzfoHFKsUfpsciY8OS2Y6cXYtireQH6ZE6A== + dependencies: + "@ckeditor/ckeditor5-core" "42.0.2" + "@ckeditor/ckeditor5-editor-classic" "42.0.2" + "@ckeditor/ckeditor5-engine" "42.0.2" + "@ckeditor/ckeditor5-ui" "42.0.2" + "@ckeditor/ckeditor5-utils" "42.0.2" + ckeditor5 "42.0.2" + ckeditor5-collaboration "42.0.2" + lodash-es "4.17.21" + luxon "1.28.1" + "@ckeditor/ckeditor5-select-all@42.0.2": version "42.0.2" resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-select-all/-/ckeditor5-select-all-42.0.2.tgz#00be5e0686f2b8b43ba1209816eda6787fe18c2a" @@ -796,6 +1456,17 @@ "@ckeditor/ckeditor5-ui" "42.0.2" ckeditor5 "42.0.2" +"@ckeditor/ckeditor5-slash-command@42.0.2": + version "42.0.2" + resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-slash-command/-/ckeditor5-slash-command-42.0.2.tgz#fcf070db3c22f00efaadd7f017de4d9f1770b79c" + integrity sha512-leBbj6OIrIcoJELSi+nGO62iNJMleW44k3mxAmz8AFbrgRwa/2+MDsAzBWkRscSX4lsGba8JtXUY8SMBopr3KQ== + dependencies: + "@ckeditor/ckeditor5-core" "42.0.2" + "@ckeditor/ckeditor5-ui" "42.0.2" + "@ckeditor/ckeditor5-utils" "42.0.2" + ckeditor5 "42.0.2" + ckeditor5-collaboration "42.0.2" + "@ckeditor/ckeditor5-source-editing@42.0.2": version "42.0.2" resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-source-editing/-/ckeditor5-source-editing-42.0.2.tgz#e910ffb61d9c9978cb6c8a22ccd462abfdab3b0c" @@ -844,6 +1515,17 @@ ckeditor5 "42.0.2" lodash-es "4.17.21" +"@ckeditor/ckeditor5-template@42.0.2": + version "42.0.2" + resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-template/-/ckeditor5-template-42.0.2.tgz#83b4f1062fd86d6492d8be290b0ecb656161d582" + integrity sha512-bIOY/boLaldF+uofzHH8VLJAq29OdlBr85Dpt620ICQdGJSUoBi0DwZCPQOHcz4S3De15AvciQdgVx/tEYBJ4Q== + dependencies: + "@ckeditor/ckeditor5-core" "42.0.2" + "@ckeditor/ckeditor5-ui" "42.0.2" + "@ckeditor/ckeditor5-utils" "42.0.2" + ckeditor5 "42.0.2" + ckeditor5-collaboration "42.0.2" + "@ckeditor/ckeditor5-theme-lark@42.0.2": version "42.0.2" resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-theme-lark/-/ckeditor5-theme-lark-42.0.2.tgz#b674ca7ceacddad8addabd69b057f980a4c55307" @@ -851,6 +1533,22 @@ dependencies: "@ckeditor/ckeditor5-ui" "42.0.2" +"@ckeditor/ckeditor5-track-changes@42.0.2": + version "42.0.2" + resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-track-changes/-/ckeditor5-track-changes-42.0.2.tgz#a8bffd8b8e06e8c7d8859cbf8245b815d4d8a4d5" + integrity sha512-TQhflVPrYneuu2Qjt2ty6csB/WFBhoWVdMP/1jJxKo3vLGdD+PbT93OWlq7OgV0G/S/SeyUhc5khglj+6Ylj0Q== + dependencies: + "@ckeditor/ckeditor5-core" "42.0.2" + "@ckeditor/ckeditor5-engine" "42.0.2" + "@ckeditor/ckeditor5-enter" "42.0.2" + "@ckeditor/ckeditor5-typing" "42.0.2" + "@ckeditor/ckeditor5-ui" "42.0.2" + "@ckeditor/ckeditor5-utils" "42.0.2" + "@ckeditor/ckeditor5-widget" "42.0.2" + ckeditor5 "42.0.2" + ckeditor5-collaboration "42.0.2" + lodash-es "4.17.21" + "@ckeditor/ckeditor5-typing@42.0.2": version "42.0.2" resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-typing/-/ckeditor5-typing-42.0.2.tgz#b2765b3749aa198e427d68c3c110c52326086bea" @@ -1509,6 +2207,59 @@ dependencies: spacetrim "0.11.39" +"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf" + integrity sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ== + +"@protobufjs/base64@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/base64/-/base64-1.1.2.tgz#4c85730e59b9a1f1f349047dbf24296034bb2735" + integrity sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg== + +"@protobufjs/codegen@^2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@protobufjs/codegen/-/codegen-2.0.4.tgz#7ef37f0d010fb028ad1ad59722e506d9262815cb" + integrity sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg== + +"@protobufjs/eventemitter@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz#355cbc98bafad5978f9ed095f397621f1d066b70" + integrity sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q== + +"@protobufjs/fetch@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/fetch/-/fetch-1.1.0.tgz#ba99fb598614af65700c1619ff06d454b0d84c45" + integrity sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ== + dependencies: + "@protobufjs/aspromise" "^1.1.1" + "@protobufjs/inquire" "^1.1.0" + +"@protobufjs/float@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@protobufjs/float/-/float-1.0.2.tgz#5e9e1abdcb73fc0a7cb8b291df78c8cbd97b87d1" + integrity sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ== + +"@protobufjs/inquire@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/inquire/-/inquire-1.1.0.tgz#ff200e3e7cf2429e2dcafc1140828e8cc638f089" + integrity sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q== + +"@protobufjs/path@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/path/-/path-1.1.2.tgz#6cc2b20c5c9ad6ad0dccfd21ca7673d8d7fbf68d" + integrity sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA== + +"@protobufjs/pool@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/pool/-/pool-1.1.0.tgz#09fd15f2d6d3abfa9b65bc366506d6ad7846ff54" + integrity sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw== + +"@protobufjs/utf8@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570" + integrity sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw== + "@puppeteer/browsers@1.9.1", "@puppeteer/browsers@^1.6.0": version "1.9.1" resolved "https://registry.yarnpkg.com/@puppeteer/browsers/-/browsers-1.9.1.tgz#384ee8b09786f0e8f62b1925e4c492424cb549ee" @@ -1607,6 +2358,416 @@ resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-5.6.0.tgz#41dd6093d34652cddb5d5bdeee04eafc33826668" integrity sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g== +"@smithy/abort-controller@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@smithy/abort-controller/-/abort-controller-2.2.0.tgz#18983401a5e2154b5c94057730024a7d14cbcd35" + integrity sha512-wRlta7GuLWpTqtFfGo+nZyOO1vEvewdNR1R4rTxpC8XU6vG/NDyrFBhwLZsqg1NUoR1noVaXJPC/7ZK47QCySw== + dependencies: + "@smithy/types" "^2.12.0" + tslib "^2.6.2" + +"@smithy/config-resolver@^2.0.21", "@smithy/config-resolver@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@smithy/config-resolver/-/config-resolver-2.2.0.tgz#54f40478bb61709b396960a3535866dba5422757" + integrity sha512-fsiMgd8toyUba6n1WRmr+qACzXltpdDkPTAaDqc8QqPBUzO+/JKwL6bUBseHVi8tu9l+3JOK+tSf7cay+4B3LA== + dependencies: + "@smithy/node-config-provider" "^2.3.0" + "@smithy/types" "^2.12.0" + "@smithy/util-config-provider" "^2.3.0" + "@smithy/util-middleware" "^2.2.0" + tslib "^2.6.2" + +"@smithy/credential-provider-imds@^2.0.0", "@smithy/credential-provider-imds@^2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@smithy/credential-provider-imds/-/credential-provider-imds-2.3.0.tgz#326ce401b82e53f3c7ee4862a066136959a06166" + integrity sha512-BWB9mIukO1wjEOo1Ojgl6LrG4avcaC7T/ZP6ptmAaW4xluhSIPZhY+/PI5YKzlk+jsm+4sQZB45Bt1OfMeQa3w== + dependencies: + "@smithy/node-config-provider" "^2.3.0" + "@smithy/property-provider" "^2.2.0" + "@smithy/types" "^2.12.0" + "@smithy/url-parser" "^2.2.0" + tslib "^2.6.2" + +"@smithy/eventstream-codec@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-codec/-/eventstream-codec-2.2.0.tgz#63d74fa817188995eb55e792a38060b0ede98dc4" + integrity sha512-8janZoJw85nJmQZc4L8TuePp2pk1nxLgkxIR0TUjKJ5Dkj5oelB9WtiSSGXCQvNsJl0VSTvK/2ueMXxvpa9GVw== + dependencies: + "@aws-crypto/crc32" "3.0.0" + "@smithy/types" "^2.12.0" + "@smithy/util-hex-encoding" "^2.2.0" + tslib "^2.6.2" + +"@smithy/eventstream-serde-browser@^2.0.15": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-2.2.0.tgz#69c93cc0210f04caeb0770856ef88c9a82564e11" + integrity sha512-UaPf8jKbcP71BGiO0CdeLmlg+RhWnlN8ipsMSdwvqBFigl5nil3rHOI/5GE3tfiuX8LvY5Z9N0meuU7Rab7jWw== + dependencies: + "@smithy/eventstream-serde-universal" "^2.2.0" + "@smithy/types" "^2.12.0" + tslib "^2.6.2" + +"@smithy/eventstream-serde-config-resolver@^2.0.15": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-2.2.0.tgz#23c8698ce594a128bcc556153efb7fecf6d04f87" + integrity sha512-RHhbTw/JW3+r8QQH7PrganjNCiuiEZmpi6fYUAetFfPLfZ6EkiA08uN3EFfcyKubXQxOwTeJRZSQmDDCdUshaA== + dependencies: + "@smithy/types" "^2.12.0" + tslib "^2.6.2" + +"@smithy/eventstream-serde-node@^2.0.15": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-node/-/eventstream-serde-node-2.2.0.tgz#b82870a838b1bd32ad6e0cf33a520191a325508e" + integrity sha512-zpQMtJVqCUMn+pCSFcl9K/RPNtQE0NuMh8sKpCdEHafhwRsjP50Oq/4kMmvxSRy6d8Jslqd8BLvDngrUtmN9iA== + dependencies: + "@smithy/eventstream-serde-universal" "^2.2.0" + "@smithy/types" "^2.12.0" + tslib "^2.6.2" + +"@smithy/eventstream-serde-universal@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-2.2.0.tgz#a75e330040d5e2ca2ac0d8bccde3e390ac5afd38" + integrity sha512-pvoe/vvJY0mOpuF84BEtyZoYfbehiFj8KKWk1ds2AT0mTLYFVs+7sBJZmioOFdBXKd48lfrx1vumdPdmGlCLxA== + dependencies: + "@smithy/eventstream-codec" "^2.2.0" + "@smithy/types" "^2.12.0" + tslib "^2.6.2" + +"@smithy/fetch-http-handler@^2.3.1", "@smithy/fetch-http-handler@^2.5.0": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@smithy/fetch-http-handler/-/fetch-http-handler-2.5.0.tgz#0b8e1562807fdf91fe7dd5cde620d7a03ddc10ac" + integrity sha512-BOWEBeppWhLn/no/JxUL/ghTfANTjT7kg3Ww2rPqTUY9R4yHPXxJ9JhMe3Z03LN3aPwiwlpDIUcVw1xDyHqEhw== + dependencies: + "@smithy/protocol-http" "^3.3.0" + "@smithy/querystring-builder" "^2.2.0" + "@smithy/types" "^2.12.0" + "@smithy/util-base64" "^2.3.0" + tslib "^2.6.2" + +"@smithy/hash-node@^2.0.17": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@smithy/hash-node/-/hash-node-2.2.0.tgz#df29e1e64811be905cb3577703b0e2d0b07fc5cc" + integrity sha512-zLWaC/5aWpMrHKpoDF6nqpNtBhlAYKF/7+9yMN7GpdR8CzohnWfGtMznPybnwSS8saaXBMxIGwJqR4HmRp6b3g== + dependencies: + "@smithy/types" "^2.12.0" + "@smithy/util-buffer-from" "^2.2.0" + "@smithy/util-utf8" "^2.3.0" + tslib "^2.6.2" + +"@smithy/invalid-dependency@^2.0.15": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@smithy/invalid-dependency/-/invalid-dependency-2.2.0.tgz#ee3d8980022cb5edb514ac187d159b3e773640f0" + integrity sha512-nEDASdbKFKPXN2O6lOlTgrEEOO9NHIeO+HVvZnkqc8h5U9g3BIhWsvzFo+UcUbliMHvKNPD/zVxDrkP1Sbgp8Q== + dependencies: + "@smithy/types" "^2.12.0" + tslib "^2.6.2" + +"@smithy/is-array-buffer@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz#f84f0d9f9a36601a9ca9381688bd1b726fd39111" + integrity sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA== + dependencies: + tslib "^2.6.2" + +"@smithy/middleware-content-length@^2.0.17": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@smithy/middleware-content-length/-/middleware-content-length-2.2.0.tgz#a82e97bd83d8deab69e07fea4512563bedb9461a" + integrity sha512-5bl2LG1Ah/7E5cMSC+q+h3IpVHMeOkG0yLRyQT1p2aMJkSrZG7RlXHPuAgb7EyaFeidKEnnd/fNaLLaKlHGzDQ== + dependencies: + "@smithy/protocol-http" "^3.3.0" + "@smithy/types" "^2.12.0" + tslib "^2.6.2" + +"@smithy/middleware-endpoint@^2.2.3", "@smithy/middleware-endpoint@^2.5.1": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@smithy/middleware-endpoint/-/middleware-endpoint-2.5.1.tgz#1333c58304aff4d843e8ef4b85c8cb88975dd5ad" + integrity sha512-1/8kFp6Fl4OsSIVTWHnNjLnTL8IqpIb/D3sTSczrKFnrE9VMNWxnrRKNvpUHOJ6zpGD5f62TPm7+17ilTJpiCQ== + dependencies: + "@smithy/middleware-serde" "^2.3.0" + "@smithy/node-config-provider" "^2.3.0" + "@smithy/shared-ini-file-loader" "^2.4.0" + "@smithy/types" "^2.12.0" + "@smithy/url-parser" "^2.2.0" + "@smithy/util-middleware" "^2.2.0" + tslib "^2.6.2" + +"@smithy/middleware-retry@^2.0.24": + version "2.3.1" + resolved "https://registry.yarnpkg.com/@smithy/middleware-retry/-/middleware-retry-2.3.1.tgz#d6fdce94f2f826642c01b4448e97a509c4556ede" + integrity sha512-P2bGufFpFdYcWvqpyqqmalRtwFUNUA8vHjJR5iGqbfR6mp65qKOLcUd6lTr4S9Gn/enynSrSf3p3FVgVAf6bXA== + dependencies: + "@smithy/node-config-provider" "^2.3.0" + "@smithy/protocol-http" "^3.3.0" + "@smithy/service-error-classification" "^2.1.5" + "@smithy/smithy-client" "^2.5.1" + "@smithy/types" "^2.12.0" + "@smithy/util-middleware" "^2.2.0" + "@smithy/util-retry" "^2.2.0" + tslib "^2.6.2" + uuid "^9.0.1" + +"@smithy/middleware-serde@^2.0.15", "@smithy/middleware-serde@^2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@smithy/middleware-serde/-/middleware-serde-2.3.0.tgz#a7615ba646a88b6f695f2d55de13d8158181dd13" + integrity sha512-sIADe7ojwqTyvEQBe1nc/GXB9wdHhi9UwyX0lTyttmUWDJLP655ZYE1WngnNyXREme8I27KCaUhyhZWRXL0q7Q== + dependencies: + "@smithy/types" "^2.12.0" + tslib "^2.6.2" + +"@smithy/middleware-stack@^2.0.9", "@smithy/middleware-stack@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@smithy/middleware-stack/-/middleware-stack-2.2.0.tgz#3fb49eae6313f16f6f30fdaf28e11a7321f34d9f" + integrity sha512-Qntc3jrtwwrsAC+X8wms8zhrTr0sFXnyEGhZd9sLtsJ/6gGQKFzNB+wWbOcpJd7BR8ThNCoKt76BuQahfMvpeA== + dependencies: + "@smithy/types" "^2.12.0" + tslib "^2.6.2" + +"@smithy/node-config-provider@^2.1.8", "@smithy/node-config-provider@^2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@smithy/node-config-provider/-/node-config-provider-2.3.0.tgz#9fac0c94a14c5b5b8b8fa37f20c310a844ab9922" + integrity sha512-0elK5/03a1JPWMDPaS726Iw6LpQg80gFut1tNpPfxFuChEEklo2yL823V94SpTZTxmKlXFtFgsP55uh3dErnIg== + dependencies: + "@smithy/property-provider" "^2.2.0" + "@smithy/shared-ini-file-loader" "^2.4.0" + "@smithy/types" "^2.12.0" + tslib "^2.6.2" + +"@smithy/node-http-handler@^2.2.1", "@smithy/node-http-handler@^2.5.0": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@smithy/node-http-handler/-/node-http-handler-2.5.0.tgz#7b5e0565dd23d340380489bd5fe4316d2bed32de" + integrity sha512-mVGyPBzkkGQsPoxQUbxlEfRjrj6FPyA3u3u2VXGr9hT8wilsoQdZdvKpMBFMB8Crfhv5dNkKHIW0Yyuc7eABqA== + dependencies: + "@smithy/abort-controller" "^2.2.0" + "@smithy/protocol-http" "^3.3.0" + "@smithy/querystring-builder" "^2.2.0" + "@smithy/types" "^2.12.0" + tslib "^2.6.2" + +"@smithy/property-provider@^2.0.0", "@smithy/property-provider@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@smithy/property-provider/-/property-provider-2.2.0.tgz#37e3525a3fa3e11749f86a4f89f0fd7765a6edb0" + integrity sha512-+xiil2lFhtTRzXkx8F053AV46QnIw6e7MV8od5Mi68E1ICOjCeCHw2XfLnDEUHnT9WGUIkwcqavXjfwuJbGlpg== + dependencies: + "@smithy/types" "^2.12.0" + tslib "^2.6.2" + +"@smithy/protocol-http@^3.0.11", "@smithy/protocol-http@^3.3.0": + version "3.3.0" + resolved "https://registry.yarnpkg.com/@smithy/protocol-http/-/protocol-http-3.3.0.tgz#a37df7b4bb4960cdda560ce49acfd64c455e4090" + integrity sha512-Xy5XK1AFWW2nlY/biWZXu6/krgbaf2dg0q492D8M5qthsnU2H+UgFeZLbM76FnH7s6RO/xhQRkj+T6KBO3JzgQ== + dependencies: + "@smithy/types" "^2.12.0" + tslib "^2.6.2" + +"@smithy/querystring-builder@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@smithy/querystring-builder/-/querystring-builder-2.2.0.tgz#22937e19fcd0aaa1a3e614ef8cb6f8e86756a4ef" + integrity sha512-L1kSeviUWL+emq3CUVSgdogoM/D9QMFaqxL/dd0X7PCNWmPXqt+ExtrBjqT0V7HLN03Vs9SuiLrG3zy3JGnE5A== + dependencies: + "@smithy/types" "^2.12.0" + "@smithy/util-uri-escape" "^2.2.0" + tslib "^2.6.2" + +"@smithy/querystring-parser@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@smithy/querystring-parser/-/querystring-parser-2.2.0.tgz#24a5633f4b3806ff2888d4c2f4169e105fdffd79" + integrity sha512-BvHCDrKfbG5Yhbpj4vsbuPV2GgcpHiAkLeIlcA1LtfpMz3jrqizP1+OguSNSj1MwBHEiN+jwNisXLGdajGDQJA== + dependencies: + "@smithy/types" "^2.12.0" + tslib "^2.6.2" + +"@smithy/service-error-classification@^2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@smithy/service-error-classification/-/service-error-classification-2.1.5.tgz#0568a977cc0db36299d8703a5d8609c1f600c005" + integrity sha512-uBDTIBBEdAQryvHdc5W8sS5YX7RQzF683XrHePVdFmAgKiMofU15FLSM0/HU03hKTnazdNRFa0YHS7+ArwoUSQ== + dependencies: + "@smithy/types" "^2.12.0" + +"@smithy/shared-ini-file-loader@^2.0.6", "@smithy/shared-ini-file-loader@^2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-2.4.0.tgz#1636d6eb9bff41e36ac9c60364a37fd2ffcb9947" + integrity sha512-WyujUJL8e1B6Z4PBfAqC/aGY1+C7T0w20Gih3yrvJSk97gpiVfB+y7c46T4Nunk+ZngLq0rOIdeVeIklk0R3OA== + dependencies: + "@smithy/types" "^2.12.0" + tslib "^2.6.2" + +"@smithy/signature-v4@^2.0.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@smithy/signature-v4/-/signature-v4-2.3.0.tgz#c30dd4028ae50c607db99459981cce8cdab7a3fd" + integrity sha512-ui/NlpILU+6HAQBfJX8BBsDXuKSNrjTSuOYArRblcrErwKFutjrCNb/OExfVRyj9+26F9J+ZmfWT+fKWuDrH3Q== + dependencies: + "@smithy/is-array-buffer" "^2.2.0" + "@smithy/types" "^2.12.0" + "@smithy/util-hex-encoding" "^2.2.0" + "@smithy/util-middleware" "^2.2.0" + "@smithy/util-uri-escape" "^2.2.0" + "@smithy/util-utf8" "^2.3.0" + tslib "^2.6.2" + +"@smithy/smithy-client@^2.1.18", "@smithy/smithy-client@^2.5.1": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@smithy/smithy-client/-/smithy-client-2.5.1.tgz#0fd2efff09dc65500d260e590f7541f8a387eae3" + integrity sha512-jrbSQrYCho0yDaaf92qWgd+7nAeap5LtHTI51KXqmpIFCceKU3K9+vIVTUH72bOJngBMqa4kyu1VJhRcSrk/CQ== + dependencies: + "@smithy/middleware-endpoint" "^2.5.1" + "@smithy/middleware-stack" "^2.2.0" + "@smithy/protocol-http" "^3.3.0" + "@smithy/types" "^2.12.0" + "@smithy/util-stream" "^2.2.0" + tslib "^2.6.2" + +"@smithy/types@^2.12.0", "@smithy/types@^2.7.0": + version "2.12.0" + resolved "https://registry.yarnpkg.com/@smithy/types/-/types-2.12.0.tgz#c44845f8ba07e5e8c88eda5aed7e6a0c462da041" + integrity sha512-QwYgloJ0sVNBeBuBs65cIkTbfzV/Q6ZNPCJ99EICFEdJYG50nGIY/uYXp+TbsdJReIuPr0a0kXmCvren3MbRRw== + dependencies: + tslib "^2.6.2" + +"@smithy/types@^3.3.0": + version "3.3.0" + resolved "https://registry.yarnpkg.com/@smithy/types/-/types-3.3.0.tgz#fae037c733d09bc758946a01a3de0ef6e210b16b" + integrity sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA== + dependencies: + tslib "^2.6.2" + +"@smithy/url-parser@^2.0.15", "@smithy/url-parser@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@smithy/url-parser/-/url-parser-2.2.0.tgz#6fcda6116391a4f61fef5580eb540e128359b3c0" + integrity sha512-hoA4zm61q1mNTpksiSWp2nEl1dt3j726HdRhiNgVJQMj7mLp7dprtF57mOB6JvEk/x9d2bsuL5hlqZbBuHQylQ== + dependencies: + "@smithy/querystring-parser" "^2.2.0" + "@smithy/types" "^2.12.0" + tslib "^2.6.2" + +"@smithy/util-base64@^2.0.1", "@smithy/util-base64@^2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@smithy/util-base64/-/util-base64-2.3.0.tgz#312dbb4d73fb94249c7261aee52de4195c2dd8e2" + integrity sha512-s3+eVwNeJuXUwuMbusncZNViuhv2LjVJ1nMwTqSA0XAC7gjKhqqxRdJPhR8+YrkoZ9IiIbFk/yK6ACe/xlF+hw== + dependencies: + "@smithy/util-buffer-from" "^2.2.0" + "@smithy/util-utf8" "^2.3.0" + tslib "^2.6.2" + +"@smithy/util-body-length-browser@^2.0.1": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@smithy/util-body-length-browser/-/util-body-length-browser-2.2.0.tgz#25620645c6b62b42594ef4a93b66e6ab70e27d2c" + integrity sha512-dtpw9uQP7W+n3vOtx0CfBD5EWd7EPdIdsQnWTDoFf77e3VUf05uA7R7TGipIo8e4WL2kuPdnsr3hMQn9ziYj5w== + dependencies: + tslib "^2.6.2" + +"@smithy/util-body-length-node@^2.1.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@smithy/util-body-length-node/-/util-body-length-node-2.3.0.tgz#d065a9b5e305ff899536777bbfe075cdc980136f" + integrity sha512-ITWT1Wqjubf2CJthb0BuT9+bpzBfXeMokH/AAa5EJQgbv9aPMVfnM76iFIZVFf50hYXGbtiV71BHAthNWd6+dw== + dependencies: + tslib "^2.6.2" + +"@smithy/util-buffer-from@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz#6fc88585165ec73f8681d426d96de5d402021e4b" + integrity sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA== + dependencies: + "@smithy/is-array-buffer" "^2.2.0" + tslib "^2.6.2" + +"@smithy/util-config-provider@^2.0.0", "@smithy/util-config-provider@^2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@smithy/util-config-provider/-/util-config-provider-2.3.0.tgz#bc79f99562d12a1f8423100ca662a6fb07cde943" + integrity sha512-HZkzrRcuFN1k70RLqlNK4FnPXKOpkik1+4JaBoHNJn+RnJGYqaa3c5/+XtLOXhlKzlRgNvyaLieHTW2VwGN0VQ== + dependencies: + tslib "^2.6.2" + +"@smithy/util-defaults-mode-browser@^2.0.22": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-2.2.1.tgz#9db31416daf575d2963c502e0528cfe8055f0c4e" + integrity sha512-RtKW+8j8skk17SYowucwRUjeh4mCtnm5odCL0Lm2NtHQBsYKrNW0od9Rhopu9wF1gHMfHeWF7i90NwBz/U22Kw== + dependencies: + "@smithy/property-provider" "^2.2.0" + "@smithy/smithy-client" "^2.5.1" + "@smithy/types" "^2.12.0" + bowser "^2.11.0" + tslib "^2.6.2" + +"@smithy/util-defaults-mode-node@^2.0.29": + version "2.3.1" + resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-2.3.1.tgz#4613210a3d107aadb3f85bd80cb71c796dd8bf0a" + integrity sha512-vkMXHQ0BcLFysBMWgSBLSk3+leMpFSyyFj8zQtv5ZyUBx8/owVh1/pPEkzmW/DR/Gy/5c8vjLDD9gZjXNKbrpA== + dependencies: + "@smithy/config-resolver" "^2.2.0" + "@smithy/credential-provider-imds" "^2.3.0" + "@smithy/node-config-provider" "^2.3.0" + "@smithy/property-provider" "^2.2.0" + "@smithy/smithy-client" "^2.5.1" + "@smithy/types" "^2.12.0" + tslib "^2.6.2" + +"@smithy/util-endpoints@^1.0.7": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@smithy/util-endpoints/-/util-endpoints-1.2.0.tgz#b8b805f47e8044c158372f69b88337703117665d" + integrity sha512-BuDHv8zRjsE5zXd3PxFXFknzBG3owCpjq8G3FcsXW3CykYXuEqM3nTSsmLzw5q+T12ZYuDlVUZKBdpNbhVtlrQ== + dependencies: + "@smithy/node-config-provider" "^2.3.0" + "@smithy/types" "^2.12.0" + tslib "^2.6.2" + +"@smithy/util-hex-encoding@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@smithy/util-hex-encoding/-/util-hex-encoding-2.2.0.tgz#87edb7c88c2f422cfca4bb21f1394ae9602c5085" + integrity sha512-7iKXR+/4TpLK194pVjKiasIyqMtTYJsgKgM242Y9uzt5dhHnUDvMNb+3xIhRJ9QhvqGii/5cRUt4fJn3dtXNHQ== + dependencies: + tslib "^2.6.2" + +"@smithy/util-middleware@^2.0.8", "@smithy/util-middleware@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@smithy/util-middleware/-/util-middleware-2.2.0.tgz#80cfad40f6cca9ffe42a5899b5cb6abd53a50006" + integrity sha512-L1qpleXf9QD6LwLCJ5jddGkgWyuSvWBkJwWAZ6kFkdifdso+sk3L3O1HdmPvCdnCK3IS4qWyPxev01QMnfHSBw== + dependencies: + "@smithy/types" "^2.12.0" + tslib "^2.6.2" + +"@smithy/util-retry@^2.0.8", "@smithy/util-retry@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@smithy/util-retry/-/util-retry-2.2.0.tgz#e8e019537ab47ba6b2e87e723ec51ee223422d85" + integrity sha512-q9+pAFPTfftHXRytmZ7GzLFFrEGavqapFc06XxzZFcSIGERXMerXxCitjOG1prVDR9QdjqotF40SWvbqcCpf8g== + dependencies: + "@smithy/service-error-classification" "^2.1.5" + "@smithy/types" "^2.12.0" + tslib "^2.6.2" + +"@smithy/util-stream@^2.0.23", "@smithy/util-stream@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@smithy/util-stream/-/util-stream-2.2.0.tgz#b1279e417992a0f74afa78d7501658f174ed7370" + integrity sha512-17faEXbYWIRst1aU9SvPZyMdWmqIrduZjVOqCPMIsWFNxs5yQQgFrJL6b2SdiCzyW9mJoDjFtgi53xx7EH+BXA== + dependencies: + "@smithy/fetch-http-handler" "^2.5.0" + "@smithy/node-http-handler" "^2.5.0" + "@smithy/types" "^2.12.0" + "@smithy/util-base64" "^2.3.0" + "@smithy/util-buffer-from" "^2.2.0" + "@smithy/util-hex-encoding" "^2.2.0" + "@smithy/util-utf8" "^2.3.0" + tslib "^2.6.2" + +"@smithy/util-uri-escape@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@smithy/util-uri-escape/-/util-uri-escape-2.2.0.tgz#56f5764051a33b67bc93fdd2a869f971b0635406" + integrity sha512-jtmJMyt1xMD/d8OtbVJ2gFZOSKc+ueYJZPW20ULW1GOp/q/YIM0wNh+u8ZFao9UaIGz4WoPW8hC64qlWLIfoDA== + dependencies: + tslib "^2.6.2" + +"@smithy/util-utf8@^2.0.2", "@smithy/util-utf8@^2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@smithy/util-utf8/-/util-utf8-2.3.0.tgz#dd96d7640363259924a214313c3cf16e7dd329c5" + integrity sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A== + dependencies: + "@smithy/util-buffer-from" "^2.2.0" + tslib "^2.6.2" + +"@socket.io/component-emitter@~3.1.0": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz#821f8442f4175d8f0467b9daf26e3a18e2d02af2" + integrity sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA== + "@szmarczak/http-timer@^5.0.1": version "5.0.1" resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-5.0.1.tgz#c7c1bf1141cdd4751b0399c8fc7b8b664cd5be3a" @@ -1628,6 +2789,20 @@ lz-string "^1.5.0" pretty-format "^27.0.2" +"@testing-library/jest-dom@^6.4.8": + version "6.4.8" + resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-6.4.8.tgz#9c435742b20c6183d4e7034f2b329d562c079daa" + integrity sha512-JD0G+Zc38f5MBHA4NgxQMR5XtO5Jx9g86jqturNTt2WUfRmLDIY7iKkWHDCCTiDuFMre6nxAD5wHw9W5kI4rGw== + dependencies: + "@adobe/css-tools" "^4.4.0" + "@babel/runtime" "^7.9.2" + aria-query "^5.0.0" + chalk "^3.0.0" + css.escape "^1.5.1" + dom-accessibility-api "^0.6.3" + lodash "^4.17.21" + redent "^3.0.0" + "@testing-library/react@^16.0.0": version "16.0.0" resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-16.0.0.tgz#0a1e0c7a3de25841c3591b8cb7fb0cf0c0a27321" @@ -1740,6 +2915,13 @@ dependencies: undici-types "~6.13.0" +"@types/node@>=13.7.0": + version "22.4.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.4.1.tgz#9b595d292c65b94c20923159e2ce947731b6fdce" + integrity sha512-1tbpb9325+gPnKK0dMm+/LMriX0vKxf6RnB0SZUqfyVkQ4fMgUSySqhxE/y8Jvs4NyF1yHzTfG9KlnkIODxPKg== + dependencies: + undici-types "~6.19.2" + "@types/node@^20.1.0": version "20.14.15" resolved "https://registry.yarnpkg.com/@types/node/-/node-20.14.15.tgz#e59477ab7bc7db1f80c85540bfd192a0becc588b" @@ -2485,6 +3667,11 @@ boolbase@^1.0.0: resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== +bowser@^2.11.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/bowser/-/bowser-2.11.0.tgz#5ca3c35757a7aa5771500c70a73a9f91ef420a8f" + integrity sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA== + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -2714,6 +3901,37 @@ chromium-bidi@0.5.8: mitt "3.0.1" urlpattern-polyfill "10.0.0" +ckeditor5-collaboration@42.0.2: + version "42.0.2" + resolved "https://registry.yarnpkg.com/ckeditor5-collaboration/-/ckeditor5-collaboration-42.0.2.tgz#4e29740439343803b64c4e2370cb0766e16f5a49" + integrity sha512-Gbl/1p6+N3hU40tLdVKrwf4ajdE3dKQyLB+vKBnLRgL/bHayerAfZGdK3g8zZJ7tye/VTT2FnU6U2e87pYoKXQ== + dependencies: + "@ckeditor/ckeditor5-collaboration-core" "42.0.2" + +ckeditor5-premium-features@^42.0.0: + version "42.0.2" + resolved "https://registry.yarnpkg.com/ckeditor5-premium-features/-/ckeditor5-premium-features-42.0.2.tgz#a5bfb5f126b9757a6d68a87b7017348714d9e39e" + integrity sha512-SvcQ4sFSVE0OmwDJm9T05n9hFvrSJRdzcLmy2rwN/uIt2OA1pwY40msYergHGEERLzTaVpCeu2xYShylv9L2XQ== + dependencies: + "@ckeditor/ckeditor5-ai" "42.0.2" + "@ckeditor/ckeditor5-case-change" "42.0.2" + "@ckeditor/ckeditor5-collaboration-core" "42.0.2" + "@ckeditor/ckeditor5-comments" "42.0.2" + "@ckeditor/ckeditor5-document-outline" "42.0.2" + "@ckeditor/ckeditor5-export-pdf" "42.0.2" + "@ckeditor/ckeditor5-export-word" "42.0.2" + "@ckeditor/ckeditor5-format-painter" "42.0.2" + "@ckeditor/ckeditor5-import-word" "42.0.2" + "@ckeditor/ckeditor5-list-multi-level" "42.0.2" + "@ckeditor/ckeditor5-pagination" "42.0.2" + "@ckeditor/ckeditor5-paste-from-office-enhanced" "42.0.2" + "@ckeditor/ckeditor5-real-time-collaboration" "42.0.2" + "@ckeditor/ckeditor5-revision-history" "42.0.2" + "@ckeditor/ckeditor5-slash-command" "42.0.2" + "@ckeditor/ckeditor5-template" "42.0.2" + "@ckeditor/ckeditor5-track-changes" "42.0.2" + ckeditor5-collaboration "42.0.2" + ckeditor5@42.0.2, ckeditor5@^42.0.0: version "42.0.2" resolved "https://registry.yarnpkg.com/ckeditor5/-/ckeditor5-42.0.2.tgz#bc765effacfda49a7edf20e1c45ff0fffb166ad6" @@ -3133,6 +4351,11 @@ css-what@^6.1.0: resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== +css.escape@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/css.escape/-/css.escape-1.5.1.tgz#42e27d4fa04ae32f931a4b4d4191fa9cddee97cb" + integrity sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg== + cssesc@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" @@ -3248,7 +4471,7 @@ data-view-byte-offset@^1.0.0: es-errors "^1.3.0" is-data-view "^1.0.1" -date-fns@^2.30.0: +date-fns@2.30.0, date-fns@^2.30.0: version "2.30.0" resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.30.0.tgz#f367e644839ff57894ec6ac480de40cae4b0f4d0" integrity sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw== @@ -3260,7 +4483,7 @@ dateformat@^3.0.3: resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q== -debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0, debug@^4.3.1, debug@^4.3.4, debug@^4.3.5: +debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0, debug@^4.3.1, debug@^4.3.4, debug@^4.3.5, debug@~4.3.1, debug@~4.3.2: version "4.3.6" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.6.tgz#2ab2c38fbaffebf8aa95fdfe6d88438c7a13c52b" integrity sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg== @@ -3421,6 +4644,11 @@ dom-accessibility-api@^0.5.9: resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz#5a7429e6066eb3664d911e33fb0e45de8eb08453" integrity sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg== +dom-accessibility-api@^0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz#993e925cc1d73f2c662e7d75dd5a5445259a8fd8" + integrity sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w== + dom-serializer@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-2.0.0.tgz#e41b802e1eedf9f6cae183ce5e622d789d7d8e53" @@ -3509,6 +4737,22 @@ end-of-stream@^1.1.0: dependencies: once "^1.4.0" +engine.io-client@~6.5.0: + version "6.5.4" + resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-6.5.4.tgz#b8bc71ed3f25d0d51d587729262486b4b33bd0d0" + integrity sha512-GeZeeRjpD2qf49cZQ0Wvh/8NJNfeXkXXcoGh+F77oEAgo9gUHwT1fCRxSNU+YEEaysOJTnsFHmM5oAcPy4ntvQ== + dependencies: + "@socket.io/component-emitter" "~3.1.0" + debug "~4.3.1" + engine.io-parser "~5.2.1" + ws "~8.17.1" + xmlhttprequest-ssl "~2.0.0" + +engine.io-parser@~5.2.1: + version "5.2.3" + resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-5.2.3.tgz#00dc5b97b1f233a23c9398d0209504cf5f94d92f" + integrity sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q== + enhanced-resolve@^5.15.0: version "5.17.1" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz#67bfbbcc2f81d511be77d686a90267ef7f898a15" @@ -4049,6 +5293,13 @@ fast-uri@^3.0.1: resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.0.1.tgz#cddd2eecfc83a71c1be2cc2ef2061331be8a7134" integrity sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw== +fast-xml-parser@4.2.5: + version "4.2.5" + resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz#a6747a09296a6cb34f2ae634019bf1738f3b421f" + integrity sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g== + dependencies: + strnum "^1.0.5" + fast-xml-parser@^4.4.1: version "4.4.1" resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz#86dbf3f18edf8739326447bcaac31b4ae7f6514f" @@ -5378,7 +6629,7 @@ lodash.zip@^4.2.0: resolved "https://registry.yarnpkg.com/lodash.zip/-/lodash.zip-4.2.0.tgz#ec6662e4896408ed4ab6c542a3990b72cc080020" integrity sha512-C7IOaBBK/0gMORRBd8OETNx3kmOkgIWIPvyDpZSCTwUrpYmgZwJkjZeOD8ww4xbOUOs4/attY+pciKvadNfFbg== -lodash@^4.17.15, lodash@^4.17.19: +lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.21: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -5427,6 +6678,11 @@ loglevel@^1.6.0: resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.9.1.tgz#d63976ac9bcd03c7c873116d41c2a85bafff1be7" integrity sha512-hP3I3kCrDIMuRwAwHltphhDM1r8i55H33GgqjXbrisuJhF4kRhW1dNuxsRklp4bXl8DSdLaNLuiL4A/LWRfxvg== +long@^5.0.0: + version "5.2.3" + resolved "https://registry.yarnpkg.com/long/-/long-5.2.3.tgz#a3ba97f3877cf1d778eccbcb048525ebb77499e1" + integrity sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q== + loose-envify@^1.1.0, loose-envify@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" @@ -5470,6 +6726,11 @@ lru-cache@^7.14.1: resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.18.3.tgz#f793896e0fd0e954a59dfdd82f0773808df6aa89" integrity sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA== +luxon@1.28.1: + version "1.28.1" + resolved "https://registry.yarnpkg.com/luxon/-/luxon-1.28.1.tgz#528cdf3624a54506d710290a2341aa8e6e6c61b0" + integrity sha512-gYHAa180mKrNIUJCbwpmD0aTu9kV0dREDrwNnuyFAsO1Wt0EVYSZelPnJlbj9HplzXX/YWXHFTL45kvZ53M0pw== + lz-string@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.5.0.tgz#c1ab50f77887b712621201ba9fd4e3a6ed099941" @@ -6497,6 +7758,24 @@ prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: object-assign "^4.1.1" react-is "^16.13.1" +protobufjs@7.2.5: + version "7.2.5" + resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-7.2.5.tgz#45d5c57387a6d29a17aab6846dcc283f9b8e7f2d" + integrity sha512-gGXRSXvxQ7UiPgfw8gevrfRWcTlSbOFg+p/N+JVJEK5VhueL2miT6qTymqAmjr1Q5WbOCyJbyrk6JfWKwlFn6A== + dependencies: + "@protobufjs/aspromise" "^1.1.2" + "@protobufjs/base64" "^1.1.2" + "@protobufjs/codegen" "^2.0.4" + "@protobufjs/eventemitter" "^1.1.0" + "@protobufjs/fetch" "^1.1.0" + "@protobufjs/float" "^1.0.2" + "@protobufjs/inquire" "^1.1.0" + "@protobufjs/path" "^1.1.2" + "@protobufjs/pool" "^1.1.0" + "@protobufjs/utf8" "^1.1.0" + "@types/node" ">=13.7.0" + long "^5.0.0" + proxy-agent@6.3.1: version "6.3.1" resolved "https://registry.yarnpkg.com/proxy-agent/-/proxy-agent-6.3.1.tgz#40e7b230552cf44fd23ffaf7c59024b692612687" @@ -7183,6 +8462,24 @@ smart-buffer@^4.2.0: resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== +socket.io-client@4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-4.7.0.tgz#f869a41a2593bc36f058f3b46175024491d997b5" + integrity sha512-7Q8CeDrhuZzg4QLXl3tXlk5yb086oxYzehAVZRLiGCzCmtDneiHz1qHyyWcxhTgxXiokVpWQXoG/u60HoXSQew== + dependencies: + "@socket.io/component-emitter" "~3.1.0" + debug "~4.3.2" + engine.io-client "~6.5.0" + socket.io-parser "~4.2.4" + +socket.io-parser@~4.2.3, socket.io-parser@~4.2.4: + version "4.2.4" + resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.2.4.tgz#c806966cf7270601e47469ddeec30fbdfda44c83" + integrity sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew== + dependencies: + "@socket.io/component-emitter" "~3.1.0" + debug "~4.3.1" + socks-proxy-agent@^8.0.2, socks-proxy-agent@^8.0.4: version "8.0.4" resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz#9071dca17af95f483300316f4b063578fa0db08c" @@ -7730,12 +9027,12 @@ trim-newlines@^3.0.0: resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.1.tgz#260a5d962d8b752425b32f3a7db0dcacd176c144" integrity sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw== -tslib@^1.8.1, tslib@^1.9.0: +tslib@^1.11.1, tslib@^1.8.1, tslib@^1.9.0: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.0.1, tslib@^2.1.0: +tslib@^2.0.1, tslib@^2.1.0, tslib@^2.3.1, tslib@^2.5.0, tslib@^2.6.2: version "2.6.3" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.3.tgz#0438f810ad7a9edcde7a241c3d80db693c8cbfe0" integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ== @@ -7915,6 +9212,11 @@ undici-types@~6.13.0: resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.13.0.tgz#e3e79220ab8c81ed1496b5812471afd7cf075ea5" integrity sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg== +undici-types@~6.19.2: + version "6.19.8" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" + integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== + unique-filename@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230" @@ -7964,7 +9266,7 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" -url-parse@^1.5.3: +url-parse@1.5.10, url-parse@^1.5.3: version "1.5.10" resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== @@ -7992,6 +9294,11 @@ uuid@^3.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== +uuid@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30" + integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA== + v8-compile-cache@^2.0.3: version "2.4.0" resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.4.0.tgz#cdada8bec61e15865f05d097c5f4fd30e94dc128" @@ -8258,11 +9565,16 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== -ws@8.16.0, ws@^8, ws@^8.18.0, ws@^8.8.0: +ws@8.16.0, ws@^8, ws@^8.18.0, ws@^8.8.0, ws@~8.17.1: version "8.18.0" resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc" integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw== +xmlhttprequest-ssl@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz#91360c86b914e67f44dce769180027c0da618c67" + integrity sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A== + y18n@^5.0.5: version "5.0.8" resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"