How to add a custom plugin to a CKEditor 5 build? - javascript

Tools used:
Visual Code Studio (1.39.2)
Node JS (13.0.1)
NPM (6.12.0)
CKEditor 5 (15.0.0)
Mozilla Firefox (69.0.3 32-bits)
Intro
I am learning how to use CKEditor 5 and how to add and create plugins. I have been successful in adding a existing and oficial plugin by following this tutorial:
https://ckeditor.com/docs/ckeditor5/latest/builds/guides/integration/installing-plugins.html#adding-a-plugin-to-a-build
It is said there are two ways to add plugins in CKEditor 5. Basically, you can use a ready-made builds and add plugins to them, or you can change the editor creation settings.
The advantage of modify a build is that you no longer need to configure anything whenever a CKEditor instance is created, since everything has already been built with the desired settings. Also, the client app does not need to do a new distribution with, for instance, Webpack, importing code.
How I did the process
I do not use Git/GitHub in my development process, so I downloaded the ckeditor5-build-classic zip file from this Git repository, and I moved the inside contents to a desired folder. Using visual studio code, I opened the folder as a project, and started to manipulate it following the same procedures described in the mentioned tutorial:
npm install
Then:
npm install --save-dev #ckeditor/ckeditor5-alignment
I made the same modifications to the src/ckeditor.js source code, and finally created the build with the following command:
npm run build
With the build created, I put all 3 resulting files (ckeditor.js, ckeditor.js.map and translations folder) together with a index.html page:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script type="text/javascript" src="ckeditor.js"></script>
<script type="text/javascript" src="jquery-3.4.1.min.js"></script>
<script type="text/javascript" src="app.js"></script>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div id="editor-container">
<div id="editor">CKEditor content.</div>
</div>
</body>
</html>
My directory structure:
Test App+
|---index.html
|---app.js
|---jquery-3.4.1.min.js
|---ckeditor.js
|---ckeditor.js.map
|---translations (folder)
|---styles.css
Here is my app.js:
$( document ).ready(function() {
ClassicEditor
.create(document.querySelector('#editor'))
.then(editor => {
console.log('CKEditor is ready.');
})
.catch(error => {
console.error('Error: ' + error);
});
});
When I open index.html, CKEditor 5 works wonderfully and includes the added plugin.
Creating my own plugin (the problem)
Installing a plugin this way is very easy and practical, so I tried to create my own plugin and perform the same process to install it. To do this, I've been following directions from:
https://ckeditor.com/docs/ckeditor5/latest/framework/guides/tutorials/implementing-a-block-widget.html
https://ckeditor.com/docs/ckeditor5/latest/framework/guides/creating-simple-plugin.html
https://github.com/ckeditor/ckeditor5-alignment
My project meets this structure:
MyPlugin+
|---package.json
|---package-lock.json
|---src+
|---|---myplugin.js
|---|---myplugin_ui.js
|---|---myplugin_editing.js
|---node_modules+
|---|---lodash-es (folder)
|---|---ckeditor5 (folder)
|---|---#ckeditor (folder)
package.json:
{
"name": "myplugin",
"version": "1.0.0",
"description": "My first CKEditor 5 plugin project.",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "RDS",
"license": "ISC",
"dependencies": {
"#ckeditor/ckeditor5-core": "^15.0.0",
"#ckeditor/ckeditor5-ui": "^15.0.0"
}
}
myplugin.js:
import Plugin from '#ckeditor/ckeditor5-core/src/plugin';
import MyPlugin_ui from './myplugin_ui';
import MyPlugin_editing from './myplugin_editing';
export default class MyPlugin extends Plugin
{
static get requires()
{
return [MyPlugin_editing , MyPlugin_ui];
}
}
myplugin_ui.js:
import Plugin from '#ckeditor/ckeditor5-core/src/plugin';
export default class MyPlugin_ui extends Plugin
{
init()
{
console.log('MyPlugin_ui#init() has been called.');
}
}
myplugin_editing.js:
import Plugin from '#ckeditor/ckeditor5-core/src/plugin';
export default class MyPlugin_editing extends Plugin
{
init()
{
console.log('MyPlugin_editing#init() has been called.');
}
}
When I install the plugin in the CKEditor 5 project the build is successfully created. However, when testing the editor the browser shows the following problem:
ckeditor-duplicated-modules
https://ckeditor.com/docs/ckeditor5/latest/framework/guides/support/error-codes.html#error-ckeditor-duplicated-modules
In the link shown it is said:
Therefore, you must never add plugins to an existing build unless your
plugin has no dependencies.
But at the same time, the opposite seems to be taught on the tutorial page:
https://ckeditor.com/docs/ckeditor5/latest/builds/guides/integration/installing-plugins.html#adding-a-plugin-to-a-build
I don't have much experience using Node JS or npm. I'm sure I have some misconfiguration in my project, but I don't know where. I believe it could be in my package.json file.
What I have tried
Delete node_modules and package-lock.json files from plugin project.
Consequences:
When building the CKEditor build with installed plugin, Webpack says:
ERROR in ../MyPlugin/src/myplugin.js
Module not found: Error: Can't resolve '#ckeditor/ckeditor5-core/src/plugin' in 'C:\Users\RDS\Desktop\CKEditor\MyPlugin\src'
# ../MyPlugin/src/myplugin.js 1:0-57 5:38-44
# ./src/ckeditor.js
ERROR in ../MyPlugin/src/myplugin_editing.js
Module not found: Error: Can't resolve '#ckeditor/ckeditor5-core/src/plugin' in 'C:\Users\RDS\Desktop\CKEditor\MyPlugin\src'
# ../MyPlugin/src/myplugin_editing.js 1:0-57 3:46-52
# ../MyPlugin/src/myplugin.js
# ./src/ckeditor.js
ERROR in ../MyPlugin/src/myplugin_ui.js
Module not found: Error: Can't resolve '#ckeditor/ckeditor5-core/src/plugin' in 'C:\Users\RDS\Desktop\CKEditor\MyPlugin\src'
# ../MyPlugin/src/myplugin_ui.js 1:0-57 3:41-47
# ../MyPlugin/src/myplugin.js
# ./src/ckeditor.js
ERROR in chunk main [entry]
ckeditor.js
C:\Users\RDS\Desktop\CKEditor\ckeditor5-build-classic-master\src\ckeditor.js 15684830ec81692702e020bf47ce4f65
Unexpected token (4:26)
|
|
| class MyPlugin_ui extends !(function webpackMissingModule() { var e = new Error("Cannot find module '#ckeditor/ckeditor5-core/src/plugin'"); e.code = 'MODULE_NOT_FOUND'; throw e; }())
| {
| init()
npm ERR! code ELIFECYCLE
npm ERR! errno 2
npm ERR! #ckeditor/ckeditor5-build-classic#15.0.0 build: `webpack --mode production`
npm ERR! Exit status 2
npm ERR!
npm ERR! Failed at the #ckeditor/ckeditor5-build-classic#15.0.0 build script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! C:\Users\RDS\AppData\Roaming\npm-cache\_logs\2019-11-01T12_40_26_177Z-debug.log
Change the dependencies between the dependencies and devDependencies properties set within package.json.
Consequences: The same things happen.
All CKEditor 5 project dependencies are set on devDependencies in package.json. The installation of my plugin in the CKEditor 5 project has already been done by two existing modes:
npm link
package.json file as dependency
And again the same problems are shown. Ah! Also, something strange happened. I have already said that I properly performed the installation of the CKeditor 5 alignment plugin. I have even shown how this was done. After all this problem, I tried to install the alignment plugin locally. I downloaded it from repository, and I did the same installation via link and also file. With this approach, the plugin mysteriously gave me ckeditor-duplicated-modules problem, as previously mentioned.
I don't know exactly how it would be the right way to install this plugin from CKEditor 5 itself locally without having to download it from the internet (with npm install <module name> from npm repository). I am well aware that I am doing something wrong, but I cannot identify what it is. I would appreciate if anyone could give me tips, alternatives, and of course, maybe a solution. I've been trying for a few days now, and I don't know what I can and can't do anymore. I would be really grateful if someone could help me.

Having been unsuccessful in finding a solution here, I learned that I could ask for help in the ckeditor git repository. Please follow the following address for a resolution:
https://github.com/ckeditor/ckeditor5/issues/5699

Maybe it is just wording, but you shouldn't have to "install" your custom plugin. Simply add your plugin info to the \src\ckeditor.js file (the import, the builtinPlugins[], the toolbar [] etc). Then do npm run build and it will include it in the \build\ckeditor.js
You would do follow the same steps in changing the \src\ckeditor.js as you did for the alignment plugin except you reference your local plugin. Just make sure the names of your custom plugin match.
Since you have no UI toolbar code I think all you would need is the import and an entry in the ClassicEditor.builtInPlugins = [..., MyPlugin]
That should be enough to test init

Related

Yarn and wasm module linking does not work due to yarn caching

I have a very simple app here where index.html simply imports index.js where:
index.js
import * as wasm from "wasm";
wasm.greet();
lib.rs
mod utils;
use wasm_bindgen::prelude::*;
#[cfg(feature = "wee_alloc")]
#[global_allocator]
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
#[wasm_bindgen]
extern { fn alert(s: &str); }
#[wasm_bindgen]
pub fn greet() { alert("Wasm is running haha!"); }
package.json
...
"dependencies": {
"wasm": "portal:../pkg"
},
...
Now, here is my issue:
When I use "file:../pkg" in package.json, everything works, but if
I make a change and recompile using wasm-pack it does not update.
Even running yarn install will not update. The only way I can get
changes to show is by running yarn install --check-files but then
the install takes time and it's quite painful.
When I use "portal:../pkg" in package.json instead, I get an error ERROR in ./index.js Module not found: Error: Can't resolve "wasm" ..... This is not what I expect.
When I use "link:../pkg" everything works as planned, and I do not have to run yarn install every-time I compile to see the changes. This is great and what I really want.
Yet, when I read protocols here https://yarnpkg.com/features/protocols the difference between link and portal is only that portal will follow dependencies if package.json exists in my ../pkg folder. In my case, it does, and I expect to have further dependencies there. So how can I get portal to work? And why is it not working now when link is working?

SCSS not working within a REACT app specifically

I'm pretty sure its my folders filepath for my compile Sass script, but I've been at this one a few hours now, so I'm hoping you can help... (maybe there's a setup setting IDK about?...
Two similar projects - 1 Vanilla, 1 React.
1. On both I have node, NPM and node-sass installed; via: npm i --save-dev node-sass
2. I've got livesass compiler going. On vanilla it works as expected. On the React project live-sass-compiler keeps on crashing (it is working long enough for me to test it though) and when i run in the terminal: npm run compile:sass the terminal turns into a node, never compiles, and also seems to get stuck in this state.
Please help!
NOW FOR THE DIFFERENCES:
==========Filepaths==========
(Filepath is indicated by "./", multiple files indicated by array syntax.
Vanilla (root):
index.html (stylesheet href="./STYLES/SCSS/index.css")
index.js
./STYLES/ [index.css, index.css.map, index.scss]
package.json (script: "compile:sass": "node-sass STYLES/SCSS/index.scss STYLES/output.css -w")
Works great!
REACT (root):
./public/index.html (stylesheet href="../src/STYLES/CSS/index.css")
./src/index.js
.src/STYLES/ [index.scss, (desired css output)]
package.json (script: "compile:sass": "node-sass src/STYLES/index.scss src/STYLES/CSS/index.css -w")
in both of them, inside the node-modules folder, I have installed:
"devDependencies": {"node-sass": "^7.0.1"}
Hey, I figured it out! - I got rid of live-sass-compiler (it's depreciated). - I also removed the "script: "compile:sass": "node-s..."" as it's no longer required. Compilation will happen natively every time you save the file.
TO USE WITH REACT:
Terminal:
npm install -D sass
sass —watch scss:css
1. add an .env file to the root. Inside type: “SASS_PATH=src/STYLES/SCSS”
(this allowed relative paths to be ignored on previous versions. I haven't gotten this to work but everything else seems to work. It may be depreciated... IDK.)
2. include the filepath import to the JS page you’d like the CSS to live under:
(example (for APP-WIDE Changes): index.js: import './STYLES/index.scss’ //imports to the app component
3. to import another file from index.scss:
Within the index.scss file:
#use './SCSS/_unorganized.scss'; // ("#import" will soon be depreciated, instead use #use)
Hope this saves someone else some time!

Parcel.js says to add the type="module" attribute to the <script> tag but I've already added it

I'm getting an error that is telling me to add the type="module" attribute to the <script> tag when I run Parcel but I already have. I am trying to follow this tutorial but using my own code which has exports in it. See below:
I'm new to Parcel so I'm unsure if this is a bug with Parcel or if I'm doing something wrong and the error message is misleading. I'm simply trying to use parcel to package this code but I'm getting the below error. I'm using the default configuration.
When I run npx parcel test2.html --no-hmr (I have hmr off because it just does not seem to work and causes issues.) I'm expecting it to build but instead I get:
#parcel/transformer-js: Browser scripts cannot have imports or exports.
I was under the impression that Parcel was supposed to repackage these files so they would work in a browser. That seems like the whole point. Am I missing something?
Here is the rest of the output:
C:\wamp64\www\wp-content\plugins\application\js\Person.js:4:12
3 | exports.PersonType = exports.Person = void 0;
> 4 | const _1 = require("./");
> | ^^^^^^^^^^^^^
5 | const uuid_1 = require("uuid");
6 | class Person {
C:\wamp64\www\wp-content\plugins\application\js\ts\tests\test2.html:6:5
5 | <title>Test 2</title>
> 6 | <script type="module" src="../../Address.js"></script>
> | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The environment was originally created here
7 | <script type="module" src="../../Application.js"></script>
8 | <script type="module" src="../../ApplicationForm.js"></script>
ℹ Add the type="module" attribute to the <script> tag.
ℹ Learn more: https://parceljs.org/languages/javascript/#classic-scripts
As you can see it recommends to: Add the type="module" attribute to the <script> tag.
But if you look at the line it is referencing as the problem it already has type="module"
My environment:
Parcel: 2.4.0
Node: 16.14.2
Windows 10
If I remove the script tags from my html file it builds fine but obviously that is not a real solution. It does isolate the problem to the script tags, the files being imported, or Parcel itself.
It doesn't seem to matter what modules I try to import with the script tag. Some files export more than one module so I thought that could be the issue. It, however, give the same results when I try to bring in a file with only one module.
After searching the internet it seems like the recommendation to add type="module" to the script tags is working for everyone else but continues to fail for me. I suspect that I either have something misconfigured or this is a bug with Parcel.
There are two ways you can resolve this error
1st -
just add the type attribute in script tag module
<script type="module" src="./index.js"></script>
and make sure the package.json
"scripts": {
"start": "parcel src/index.html"
}
and now run the npm run start it will run
if this not work then try 2nd method
2nd -
Recreate the project like this,
Make a project folder
now run npm init -y to create package.json
now create your files or copy and paste them into this folder. (Example all your code in a src folder then copy paste src folder in this project folder)
Now run this command to install parcel npm install -g parcel-bundler
it took some time to install
Now open package.json and change the script
"scripts": {
"start": "parcel serve src/index.html"
},
save it
Now run this command npm run start
And Boom it will work.
Well it seems to be working and I believe it was one of two things that did it:
I tried using babel to transpile and then decided to go back to using the default built into Parcel.
During this process I reinstalled my dependencies including Parcel.
If anyone knows why this fixed the problem please comment below for future visitors.
Its something in Parcel 2 and in this version because of Differential bundling which you can read from here and its automatically using the module/nomodule pattern base on the browsers which you declared in the "browserslist" key in your package.json file. the only thing you need to do while working with parcel 2 is Just use a **<script type="module"tag> **in your HTML file, pointing to your source code, and Parcel will automatically generate a nomodule version as well if needed and if its not needed then its mean your browser support and you are good to go

Can't understand importing node modules

I'm very new to web development. I'll try to make the question short. Im trying to use a javascript library called euclid.ts. Its page tells you this:
Instructions to import euclid.ts
So this i what i did:
First I ran the command. Then in my html file, called index.html I import a script file called sketch.js
<body>
<script type="module" src="sketch.js"></script>
</body>
Then in my sketch.js file i have this line right at the top:
import {Point, Line} from '#mathigon/euclid'
The problem is, when I open index.html in the browser I get this error:
Uncaught TypeError: Error solving the module “#flatten-js/core”.
Mode specifiers must start with “./”, “../” or “/”.
I can't understand what I'm doing wrong (and how is the browser supposed to know which file to import if I don't even specify the file in the import line)
One option for compiling/bundling is via "webpack". https://webpack.js.org/guides/getting-started/
If you setup a folder like so:
/project
package.json
sketch.js
package.json
{
"dependencies": {
"#mathigon/euclid": "^0.6.9",
"webpack": "^5.20.1",
"webpack-cli": "^4.5.0"
}
}
sketch.js
import { Point, Line } from '#mathigon/euclid'
console.log ("sketch")
and then run either npm install or yarn install
and then run ./node_modules/.bin/webpack ./sketch.js
you can generate a bundle that includes #mathingo/euclid at dist/sketch.js
Afterwards, the script tag could look like:
<script src="dist/sketch.js"></script>
You need some way of resolving the packages before they go into browser. Browser doesn't not know how to resolve the dependencies for the package '#mathigon/euclid'. Code editors on the other hand can resolve the dependencies. The error that you see would be an error for a package that '#mathigon/euclid' depends upon.
So the actual sketch.js which runs in the browser should be packaged and should be the file with code from '#mathigon/euclid' and all it's dependencies.
You can look at webpack-cli for an easy way to generate the bundled sketch.js https://www.npmjs.com/package/webpack-cli
After installing cli i believe you could do webpack-cli build --entry sketch.js (Not tested)

Vue JS Module not found (datepicker)

I am pretty new to vue.js - I only started using it today and naturally I have run into an error I cannot seem to resolve.
I am using the v-md-date-range-picker module:
(https://ly525.github.io/material-vue-daterange-picker/#quick-start.
The instructions tell me to do the following:
1
npm install --save v-md-date-range-picker
2
<template>
<v-md-date-range-picker></v-md-date-range-picker>
</template>
3
<script>
import Vue from 'vue';
import VMdDateRangePicker from "v-md-date-range-picker";
import "v-md-date-range-picker/dist/v-md-date-range-picker.css";
Vue.use(VMdDateRangePicker);
</script>
So, I ran the command in terminal in my project folder, added the 2 bit of code to my HelloWorld.vue page and then added the code from step 3 into the main.js.
When I have a look in my package.json file, I see:
"dependencies": {
"core-js": "^2.6.5",
"v-md-date-range-picker": "^2.6.0",
"vue": "^2.6.10"
},
However, I get the error:
Module not found: Error: Can't resolve 'v-md-date-range-picker/dist/v-md-date-range-picker.css' in '/Users/James/Documents/projects/vue-test/src'
am I missing something blatantly obvious here?
Edit:
I tried the response in the comments below which did not work.
On the main page of the module, I followed the instructions. However, going through the pages I found the same instructions with some extra text:
I assume that you have a working bundler setup e.g. generated by the vue-cli thats capable of loading SASS stylesheets and Vue.js SFC (Single File Components).
I am going to go out on a limb here and say I do not have a working bundler. I went into the node_modules folder, found that module and looked inside. There was no dist folder. Just .scss files etc..
So, I assume that I somehow need to build this project first.
How do I do that?
I thought running it in the browser would have done this on the fly but it clearly has not.
Edit 2:
After some googling around I found the command:
$ npm run build.
Which gives me this error:
This dependency is not found, To install it, you can run: npm install --save v-md-date-range-picker/dist/v-md-date-range-picker.css
So, I run that command and then I get the error:
Could not install from "v-md-date-range-picker/dist/v-md-date-range-picker.css" as it does not contain a package.json file.
Check if you can find this in the webpack.base.conf.js inside the build folder. If not add it.
module: {
rules: [
{
test: /\.css$/,
loader: ['style-loader', 'css-loader'], // Note that the order is very important
},
Run npm install style-loader css-loader --save before adding it to the file if it isn't there.
To Address your question
Run the command: npm install sass-loader --save
Then add an import for every SCSS file in the module.
This is not the most optimal solution, but that package looks broken to me and this is merely a workaround.
I will take time to try out the library myself and try to provide a fix for it.
Create v-md-date-range-picker.css in v-md-date-range-picker/dist/ and copy css from
md-date-range-picker.min.css
and refresh your page. For some reason css file is not being created when we install md-date-range-picker.min

Categories