ckeditor5 icon indicating copy to clipboard operation
ckeditor5 copied to clipboard

CKEditor sources cannot be imported dynamically

Open pomek opened this issue 1 year ago • 5 comments

📝 Provide detailed reproduction steps (if any)

  • Create a TypeScript project that allows dynamic imports to be used.
  • Then, install the @ckeditor/ckedito5-ui package.
  • Then, try to import something like this:
const { DefaultMenuBarItems } = await import('@ckeditor/ckeditor5-ui/src/menubar/utils.js');

or

const { DefaultMenuBarItems } = await import('@ckeditor/ckeditor5-ui');

✔️ Expected result

Import what I ask for.

❌ Actual result

When importing a particular file:

TypeError: Unknown file extension ".css" for /home/pomek/Projects/ckeditor/ckeditor5-builder/node_modules/@ckeditor/ckeditor5-ui/theme/components/menubar/menubarmenulistitem.css
    at Object.getFileProtocolModuleFormat [as file:] (node:internal/modules/esm/get_format:160:9)
    at defaultGetFormat (node:internal/modules/esm/get_format:203:36)
    at defaultLoad (node:internal/modules/esm/load:143:22)
    at async ModuleLoader.load (node:internal/modules/esm/loader:396:7)
    at async ModuleLoader.moduleProvider (node:internal/modules/esm/loader:278:45) {
  code: 'ERR_UNKNOWN_FILE_EXTENSION'
}

When importing the package:

TypeError: Unknown file extension ".css" for /home/pomek/Projects/ckeditor/ckeditor5-builder/node_modules/@ckeditor/ckeditor5-ui/theme/globals/globals.css
    at Object.getFileProtocolModuleFormat [as file:] (node:internal/modules/esm/get_format:160:9)
    at defaultGetFormat (node:internal/modules/esm/get_format:203:36)
    at defaultLoad (node:internal/modules/esm/load:143:22)
    at async ModuleLoader.load (node:internal/modules/esm/loader:396:7)
    at async ModuleLoader.moduleProvider (node:internal/modules/esm/loader:278:45) {
  code: 'ERR_UNKNOWN_FILE_EXTENSION'
}

❓ Possible solution

For this case, we can extract the object to a JSON file that I can import using a full path. It will no longer work once we drop the old installation methods support, but it gives us time to find the proper solution.

pomek avatar Jun 21 '24 06:06 pomek

Working sample:

import JSDOM from 'jsdom';

const jsdom = new JSDOM.JSDOM();
const { window } = jsdom;
const { document } = window;

global.document = document
global.window = window
global.DOMParser = window.DOMParser
global.HTMLElement = window.HTMLElement

const { DefaultMenuBarItems } = await import('ckeditor5');
console.log( DefaultMenuBarItems );

I am not happy with that.

pomek avatar Jun 21 '24 10:06 pomek

```ts
const { DefaultMenuBarItems } = await import('@ckeditor/ckeditor5-ui/src/menubar/utils.js');

```

```ts
const { DefaultMenuBarItems } = await import('@ckeditor/ckeditor5-ui');

```

These are both imports from the "old methods". They won't work because there are CSSes and SVGs in the dependency tree of those files.

If you want to import CKEditor sources in Node, you need to use the new installation methods, just like you did here:

const { DefaultMenuBarItems } = await import('ckeditor5');

The only "ugly" part is polyfiling the globals, but I don't see anything particularly wrong with this because, after all, CKEditor is a browser component and it's designed to work in this environment.

In other words, with the new installation methods that we're introducing, I think there's not much more that we need to improve here.

cc @filipsobol

Reinmar avatar Jun 24 '24 08:06 Reinmar

you need to use the new installation methods, just like you did here:

Or accessing a specific package dist.

The only "ugly" part is polyfiling the globals, but I don't see anything particularly wrong with this because, after all, CKEditor is a browser component and it's designed to work in this environment.

One thing that we shouldn't do, and I don't like is that it breaks on the import and not initialization. This means we are doing something before the editor is created.

Witoso avatar Jun 24 '24 08:06 Witoso

One thing that we shouldn't do, and I don't like is that it breaks on the import and not initialization. This means we are doing something before the editor is created.

This is the exact same issue we have with SSR.

filipsobol avatar Jun 24 '24 09:06 filipsobol

const { DefaultMenuBarItems } = await import('@ckeditor/ckeditor5-ui/dist/index.js');
file:///home/pomek/Projects/ckeditor/ckeditor5-builder/node_modules/@ckeditor/ckeditor5-engine/src/view/filler.ts:72
        const fillerBr = domDocument.createElement( 'br' );
                              ^
TypeError: domDocument.createElement is not a function
    at BR_FILLER (file:///home/pomek/Projects/ckeditor/ckeditor5-builder/node_modules/@ckeditor/ckeditor5-engine/src/view/filler.ts:72:31)
    at file:///home/pomek/Projects/ckeditor/ckeditor5-builder/node_modules/@ckeditor/ckeditor5-engine/src/view/domconverter.ts:54:23

pomek avatar Jun 24 '24 09:06 pomek

There has been no activity on this issue for the past year. We've marked it as stale and will close it in 30 days. We understand it may still be relevant, so if you're interested in the solution, leave a comment or reaction under this issue.

CKEditorBot avatar Jun 24 '25 23:06 CKEditorBot

We've closed your issue due to inactivity. We understand that the issue may still be relevant. If so, feel free to open a new one (and link this issue to it).

CKEditorBot avatar Jul 25 '25 23:07 CKEditorBot