-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow adding plugins to a CKEditor 5 build #667
Comments
Talking about exposing engine elements note, that some of them are already done this way (for instance markers are available only through markers collection) and after https://github.com/ckeditor/ckeditor5-engine/issues/858 all model elements will have to be created through batch API, and all view elements through view writer. |
We need to find a good balance between exposing everything and ultimately allowing to write every kind of feature without building the editor and exposing too little and making writing typical features impossible. E.g. with UI, it's rather impossible for us to expose all UI components. We may expose some, but then people will ask why not the other ones and it will be confusing. So, let's maybe make it possible to duplicate UI's code in a way that it won't blow up. But then... PostCSS will be a problem (duplicated styles), so I guess there's just no option. With the conversion we can perhaps try to define some std set of tools which make it possible to write most basic features. This should be more understandable. With tree walkers and stuff – they are already available from ranges, so that's not a problem. Etc, etc. We need to look at every case and see if there's a simple and reasonable solution. If not, then let's just state that a certain thing can only be done by rebuilding the editor. We may also create a guide which explains this. |
Another question about this: https://stackoverflow.com/questions/49358150/is-there-any-way-to-select-all-the-content-of-ckeditor-5-by-code/49358509#49358509 Here, the requirement is to have access to Those questions repeat all the time. So, let's simply write it down here what developers have missed. So far, I saw that lack of |
This asks for an entry in FAQ. |
I don't know what we could write there, expect warning that adding plugins without rebuilding the editor might not be possible. You should not install e.g. |
This CI check will help a bit in verifying how much we depend on ckeditor5-engine: https://github.com/ckeditor/ckeditor5-dev/issues/392 From my checks, ckeditor5-heading does not depend on the engine any more, and ckeditor5-highlight only on the range. So, again, |
Another issue caused, most likely, by package duplication: #957 There are a couple more things I'm considering:
|
One thing I like in the fact that feature packages need to depend on
That may be a counterargument for getting rid of |
Last but not least, our |
I think it's not so hard to warn developers about duplicates. And it's possible to force webpack to use one version of some package using e.g https://webpack.js.org/configuration/resolve/#resolve-alias. But that's on the developer side. From our side, it's also doable, but harder and dependent on the low-level webpack stuff. But either way, we would need to know where correct packages are while resolving imports and that might be tricky though. |
I imagine we could, perhaps, record all resolve paths, store them and once detecting that someone tries to resolve the same module but in a different package path, use the stored package path. |
I think, that it might be worth checking whether versions of these packages are the same. I imagine somebody might have:
and import stuff from both packages. Then the approach to just take first found package and reuse it might break the build. |
Another thing regarding duplicated pkgs: https://gitter.im/ckeditor/ckeditor5?at=5ad59c017c3a01610deddd3e
If we'd avoid the need to use the |
I've got a brilliant idea . We want to allow writing plugins without including So far, we've done that by forcing everyone to import many classes from So, it's only reasonable to abandon the idea that npm/semver may help us here. My idea is that we can both enable people to write the most type of plugins without depending on any of our core packages, and to express with which version of CKEditor 5 that plugin worked. How to do that?
I'm not 100% sure yet how peer deps work, but one downside I see is that people will have to remember to install What will |
👍 I am not sure about details, how we will be able to get rid of
|
Another case, which, unfortunately, I don't see how we could fix: https://github.com/ckeditor/ckeditor5-markdown-gfm/issues/22 |
One more idea, log a warning when we discover that someone added plugins to an already existing build. We can fairly easy discover that some new constructors were passed to However, this would have a very negative side effect – you wouldn't be able to write simple, dependency-less plugins at all. So that would actually work in the other direction than asked in this ticket – you wouldn't be able to add any new functionality to a build. Back to the drawing board... |
Hi, Is it possible to create a custom plugin and load it dynamically into the page by using a script tag? The only problem that I can think of is the fact that there is no entry file for @ckeditor/ckeditor5-core and @ckeditor/ckeditor5-engine. And because of this, it is not possible to import all features at once. // Wrap the plugin with a custom webpack loader
window.MODULE_LOADER.addModuleSource('custom-plugin', (require, exports) => {
return (Plugin code)
});
class ModuleLoader {
private moduleSources: {[key: string]: any} = {};
public addModuleSource(name: string, source: any) {
this.moduleSources[name] = source;
}
public getModuleSource(name: string): any {
return this.moduleSources[name];
}
public loadModule(path: string, moduleName: string, deps: {[key: string]: any}): Promise<any> {
return new Promise((resolve, reject) => {
get(path, () => {
this.compileSource(this.moduleSources[moduleName], deps).then((result) => {
resolve(result);
}, reject);
});
});
}
private compileSource(source: any, deps: {[key: string]: any}): Promise<any> {
const modules: {[key: string]: any} = {
...deps,
};
const require = (module: string) => modules[module];
try {
const exports = {};
const result = source(require, exports);
return Promise.resolve({
result,
exports,
require
});
}
catch (e) {
return Promise.reject(e);
}
}
}
const deps = {
'@ckeditor/ckeditor5-core': { ...exports },
'@ckeditor/ckeditor5-engine': { ...exports },
};
moduleLoader.loadModule('custom-plugin', deps).then(() => {
// M
}); |
Any updates on this one? |
I'm afraid that adding plugins to CKEditor 5 builds is and will be impossible because of many architectural blockers such as:
For any advanced usage I'd recommend building the editor from source. This way:
On the other hand if you're not familiar with the NPM ecosystem but you want to create quickly a PoC of CKEditor 5 editor containing given set of features I'd recommend using the online builder tool. |
Worth also including #7981 in the "nice-to-have" requirements. |
Another interesting idea: #8184. |
This comment has been minimized.
This comment has been minimized.
Thanks for all the input on the matter. The majority of work to allow adding plugins to the build will be tracked in #8395. A rough summary of the above conversation is available here: #8395 (comment). As we have to restart the work on this problem I'm closing this issue as there's no need to track this in two issues. Please follow #8395 to track progres. |
Right now there is no easy way to add a real plugin to the CKEditor 5 build. Even if it is theoretically possible, you will not be able to create a position or fire an event.
The problem is that build has all classes build in and expose only editors API. If a custom plugin imports
Position
from theckeditor5-engine
and use it in the plugin it will not be the same instance as the one used in the engine in the build. Because of it, this position will returnfalse
whenposition instanceof Position
will be called, so the user will get an ugly bug.There is a simmilar problem with symbols, which are used in the events system.
Note that it is even worse because the same issue will appear when a custom plugin will have a different version of the engine on the list of dependencies. We could say that in such case semantic versioning will save us, but it still means that with every major engine release all 3rd party plugins will stop working immediately, even if changes in the engine breaks nothing important for them. The version of the dependency will not match anymore and 2 separate engines will be included with not matching classes.
This very ticky problem, but there are some improvements we could think about.
Since editor usually needs all engine features, we could expose them as
document
property, have something likedocument.createPosition
. Then all plugins will use instances of the same class and the problem disappears. In fact, when all engine utiles will be exposed on thedocument
model (or controller), plugins will not need to depends on the engine and only use engine exposed by the editor.Unfortunately, it looks fine only in the theory. Only for position we have:
Then there is range:
Then,
treeWalker
... But hey! It's only the model. We have also all conversion utils to be exposed because one will need them for sure. And working with converters one will need to be able to use view API, so multiple constructors in the view need to be exposed too. It means a lot of factories and a lot of ugly APIs. And I'm talking here only about the engine, but note that there is the same problem with utils and UI. The additional problem with utils is that we can not expose all of them because we don't know which are really needed.Another solution would be to stop using
instanceof
and symbols since they are problematic. We would have to haveis
method in each class or use duck typing. Symbols could be replaced with unique strings. It would not solve the problem of duplicated dependencies, the build will be bigger but the editor will work fine.I think that we should end up with something in between. We may accept that some utils will be duplicated as long as they don't break the editor, but we should ensure that only one engine will be loaded.
The text was updated successfully, but these errors were encountered: