I have an idea for a plugin for CKEditor5 but configuring everything seems to be overwhelming and complicated. So pretty much don't know how to start. Is there any way how I could test if my idea for a plugin is worth going deeper into this project? Some step by step guide will be helpful.
There are at least 2 ways, which I found. You can write some simple proof of concept plugins in manual test for CKEditor5 or extend one of CKEditor5's builds.
Creating new plugin inside manual test:
CKEditor5 code is compiled and served by pre-configured webpack, so you can only worry about writing proper plugin's code.
What's more you can use watch mode which will in real time reflect changes in your simple plugin. Webpack also rebuild page with test which contains your simple plugin.
Step by step guide:
Follow with guide to setup environment here
npm install -g yarn mgit2
git clone https://github.com/ckeditor/ckeditor5.git
cd ckeditor5
mgit sync
yarn install
Open file with test: ckeditor5/packages/ckeditor5-core/tests/manual/article.js. You can write plugin in this file
Run test in watch mode to have builded editor available in your browsers: yarn run manual -sw --files=core/manual/article.js
Open browser on page: http://localhost:8125
Write simple plugins in "article" test. You can add those entries to see if its works:
Add this part, before editor creation.
import Plugin from '#ckeditor/ckeditor5-core/src/plugin';
class SimplePlugin extends Plugin {
init() {
console.log( 'Hello world' );
}
}
And modify list of included plugins in configuration
from: plugins: [ ArticlePluginSet ],, to: plugins: [ ArticlePluginSet, SimplePlugin ],
Refresh page with test and you should see in the console text: Hello world. Now you can implement new changes to your Simple Plugin and see result on page.
Creating new plugin inside CKEditor5 build:
Alternative solution is to use one of CKEditor5 builds and extend it with your own simple plugin.
Step by step guide:
Clone build, e.g: git clone https://github.com/ckeditor/ckeditor5-build-classic.git
Install dependencies: npm install
You can add plugin in src/ckeditor.js in a similar way as it was done in previous guide.
Add this part, before editor creation.
import Plugin from '#ckeditor/ckeditor5-core/src/plugin';
class SimplePlugin extends Plugin {
init() {
console.log( 'Hello world' );
}
}
And modify list of included plugins in configuration. To plugins array add SimplePlugin,
Now build your new package with npm run build
Run some http server in your project directory and run samples/index.html. You should see Hello world in browser's console.
Related
I like the automated organize feature in VSCode, but having it doing it on every save has given me some trouble.
...
"editor.codeActionsOnSave": {
"source.organizeImports": true
},
...
Is it possible to set up some git hooks that organize the imports (either via vscode or some other script/lib) when I stage them?
Issues
If I hit save too early (do it to kick off prettier all the time) before I have used the imported methods - then it removes it and I have to write the import again.
If I break the code (.jsx) and something appears to not be used and I hit save (to trigger prettier), then it removes the imports. I then have to import them again.
There is some form of hook that can be applied when running git add : filters defined in gitconfig and .gitattributes.
See this section of git book for detailed explanations.
Here are the sketches from the documentation (it illustrates how you can configure a filter to run on *.txt files) :
when running git add :
when running git checkout :
You can define in your gitconfig a filter, which consists of two commands to "clean" and "smudge" :
$ git config --global filter.jsximports.clean fiximports
$ git config --global filter.jsximports.smudge cat
and edit the .gitattributes file to apply this filter on jsx files
*.jsx filter=jsximports
The script to apply may be tslint --fix, with the ordered-imports rule.
Actually : tslint's rule seem to have its own implementation, but it does something similar (see https://github.com/palantir/tslint/pull/4064)
In this answer : https://stackoverflow.com/a/57458656/86072
user thorn points to this npm package :
https://www.npmjs.com/package/organize-imports-cli
which calls organizeImports from cli
I'm trying to build a new project with ES6 modules without bundling. I still want to use babel-7 to translate TypeScript and JSX to JS. I find it hard to figure out how to set up a development-server for it. I couldn't find any kind of "babel-dev-server" that works similar to webpack-dev-server (hot-module-reloading, browser-sync, file-watcher).
One possibility would be to use browser sync as a static server on e.g. dist and run something like babel src --out-dir dist --watch in parallel. But this excludes hot-reloading and seems a bit clumsy to me. Besides, it would still be useful for build- and dev-steps if you could give the JS-files a hash to control caching better. Or can I configure a build-tool like webpack so that it doesn't perform bundling but still performs some transformations (like putting the hashs in the filenames in imports)?
Prototyping way
A very simple way to do this is to see the server and the transpiling as separate steps
You could use a standalone version of babel as the first script that you load, so you can write jsx inside your html document of javascript files without compiling them.
Simply add on of the cdn links from https://cdnjs.com/libraries/babel-standalone/ as a script like so:
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/7.0.0-beta.3/babel.min.js"></script>
<script src="/your/jsx/here.js"></script>
<script>
// or here
</script>
</head>
<body>
<div id="application" />
<noscript>This app needs javascript enabled in order to run.</noscript>
</body>
</html>
This would allow you to really quickly prototype things using any webserver that watches files. You can do this using any task runner plugin (i.e. for grunt or gulp) or if you are using visual studio have a look at LiveServer plugin.
When you are moving to production grade you might not want to include the entire babel library. See the other two approaches.
Webpack way
You're asking how to use webpack without bundling. Which can be done using file loader plugin to load every file separately, using a glob pattern. Do make sure whether this is indeed what you need. If all you want is to simply debug your code an relate it back to the original file after compiling, all you need is a standard webpack configuration using bundling and sourcemaps.
Taskrunner way
One way to have even more control over how each file is processed, you can use a taskrunner to do the compile step for you. Below is a simplified example configuration for taskrunner https://gulpjs.com/.
gulpfile.js
const gulp = require('gulp');
const watch = require('gulp-watch');
const webpackStream = require('webpack-stream');
const webpack = require('webpack');
const eslint = require('gulp-eslint');
gulp.task('watch', function() {
return watch('src/**.js', ['compile']);
});
gulp.task('lint', function() {
return gulp.src(['src/*.js', 'src/*/*.js'])
.pipe(eslint({
parser: 'babel-eslint',
parserOptions: {
ecmaFeatures: {
jsx: true
},
sourceType: 'module'
}
}))
.pipe(eslint.format())
.pipe(eslint.failAfterError());
});
gulp.task('compile', ['lint'], function() {
return gulp.src('src/main.js')
.pipe(webpackStream({
output: {
filename: 'main.js',
libraryTarget: 'commonjs2',
sourceMapFilename: 'main.js.map',
},
plugins: [],
module: {
loaders: [
{
test: /\.js$/,
loader: 'babel-loader',
query: {
presets: [
require.resolve('babel-preset-es2015'),
require.resolve('babel-preset-stage-0'),
],
},
},
],
},
}), webpack)
.pipe(gulp.dest('dist/'));
});
This example file can be run, using gulp watch. It'll watch the files for a chance and when it does trigger the other tasks.
I only had an example with webpack, but you can replace it by any other compiler component or even write your own compile step if you want (probably you don't).
This way you have exact control over every step your files go through. Most of which (and more) can also be achieved using the Webpack way. However, it would have the downside of inserting all its boilerplate on top of each processed file, when processing each file as a separate bundle. Ultimately probably something could be done with common chunks plugin.
With the latest release of Snowpack (formerly #pika/web) this should be possible now!
From their website:
TL;DR - With Snowpack you can build modern web apps (using React, Vue, etc.) without a bundler (like Webpack, Parcel, Rollup). No more waiting for your bundler to rebuild your site every time you hit save. Instead, every change is reflected in the browser instantly.
And their "How it Works":
Instead of bundling on every change, just run Snowpack once right after npm install.
Snowpack re-installs your dependencies as single JS files to a new web_modules/ directory. It never touches your source code.
Write code, import those dependencies via an ESM import, and then run it all in the browser.
Skip the bundle step and see your changes reflected in the browser immediately after hitting save.
Keep using your favorite web frameworks and build tools! Babel & TypeScript supported.
check https://www.snowpack.dev/ for more information, they have done a great job with their documentation, it looks really promising!
With webpack and source maps, it shouldn't matter that it changes your code. While this can be a challenge to set up initially, once you get it working you can look at your original source code in the browser debugging tools exactly as they appear to you on disk. The VS Code editor also does a good job of supporting this feature, allowing you to set breakpoints and look at the values of variables directly in your editor without having to use the browser developer tools.
However, if you are still set on trying to get this to work with your original source files then you are right that your ES6 code should just work in most modern browsers
For live reload you could check out the npm livereload package.
Or you could roll your own and figure out how webpack-dev-server does it. They use the chokidar npm package to watch the file system for changes and then they notify the broswer via web sockets. You could probably throw something together that's similar with a little effort.
Here is how webpack-dev-server initiates it:
const watcher = chokidar.watch(watchPath, options);
watcher.on('change', () => {
this.sockWrite(this.sockets, 'content-changed');
});
Obviously there is some JavaScript that runs in the browser waiting on a websocket for that message.
You could use a Webpack plugin like Emit All.
My web project serves static web pages and scripts. There is no preprocessing done at all. All changes are done in the client.
It has a main page that lists some other pages. When the user clicks a link, jQuery-UI will load the associated HTML page and any linked Javascript/CSS files.
This works great, and gives us flexibility to add/remove new pages with ease. The problem is when we want to debug the loaded JS and the browser appears not to know about it.
Took me a while to find out about Source Maps, and then find out they are all geared towards framework projects like Angular and React.
We don't want that in this project. Just basic HTML & JS that we can plug in and reload. I realize we may need to run an external command to generate the source maps, but it must be a free standing tool - no NPM or frameworks.
It's an internal web project, so security/privacy is not a concern. We want the clients to see the source code if they need to.
I know there are a lot of Questions about JS source maps, but every single one that I've found assumes using some framework tools. We have no framework and do not want one in this project.
Any suggestions on how we can generate the source maps we need, or do you know of any alternative to debug simple JS loaded via jQuery?
First and foremost, you do not need to use Angular/React for sourcemaps to work. These are just a common use case.
Secondly, NPM is exactly what it says it is; a package manager. So you don't need NPM either.
What you need is a build process. You're quite clear that you don't want to minify the js, but you do want sourcemaps. This is a common configuration used to debug js, and is typically accomplished by "building" or "Uglifying" the code with all of the optimizations disabled.
You could likely avoid NPM entirely if you were willing to use the Closure Compiler, but that is a can of worms and I'd suggest you avoid.
Instead I suggest using installing Uglify* globally* (per dev machine) with NPM. This is a "once per machine" step.
npm install uglify-js -g
*: Hopefully this side steps your NPM-less requirement. I did experiment with cloning the Uglify repo directly, but even then you'd need to get it running, and to do that, at a minimum, you'd want to install its dependencies with NPM). I'd love to be proven wrong about this, but I figured it was very unrelated to this post.
And then writing a build script using that. I've attempted to gather the parts for you here:
File: gen-map.sh
#!/usr/bin/env bash
uglifyjs file1.js --config-file gen-map.json \
-o file1.min.js \
--source-map "root='http://foo.com/src',url='file1.min.js.map'"
cat file1.min.js
File: gen-map.json
{
"compress": false,
"output": {
"beautify": true
},
"sourceMap": {
"content": "content from file1.js.map",
"url": "file1.js.map"
}
}
File: file1.js
var b = function() {
console.log('b');
};
function c() {
console.log('c');
};
console.log('a');
b();
c();
(function() {
console.log('d');
})();
File: file1.min.js
var b = function() {
console.log("b");
};
function c() {
console.log("c");
}
console.log("a");
b();
c();
(function() {
console.log("d");
})();
//# sourceMappingURL=file1.min.js.map
File: file1.min.js.map
{"version":3,"sources":["file1.js"],"names":["b","console","log","c"],"mappings":"AAAA,IAAIA,IAAI;IACNC,QAAQC,IAAI;;;AAGd,SAASC;IACPF,QAAQC,IAAI;;;AAGdD,QAAQC,IAAI;;AACZF;;AACAG;;CACA;IACEF,QAAQC,IAAI;EADd","sourceRoot":"http://foo.com/src"}
*: Uglify-es if you're using ES6 features.
After that the only thing left to do would be to update the paths, filenames, and actual script tags. Using this config you must still serve the min.js file, although it seems possible that manually tagging your JS file to point to the map might work...
With this config, you'll need to keep your built files up to date by running:
🐚 ./gen-map.sh
Doing this with npm and gulp would be simpler, but, if you don't mind another package, there are 2 generic "files been changed watchers" that I can suggest;
Nodemon:
🐚 nodemon gen-map.sh
entr
🐚 entr gen-map.sh
I'm developing an Extjs project using 6.5.2 version and modern toolkit, i want to use https://momentjs.com/ package but i couldn't import the node_dependency.
The Momentjs page has the downloads or install methods, but if i download the code, where i want to use whatever method, this throw an exception and if i install the package using 'npm install moment --save' command, i don't know how to import and call it.
Someone can help me importing this dependency in extjs.
#Carlos You can do by adding script tag in the index.html file as suggested by Akrion.
Another way -
Inside app.json file you can add following inside js [] -
"js":[
{
"path": "https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js",
"remote": true
}
]
Once this is added then you need to do sencha app refresh or sencha app build.
Then in the application code you can use it like following -
var welcomeText = 'Welcome to Sencha Fiddle! Today is: '+ moment(new Date()).format("MM-DD-YYYY");
Ext.Msg.alert('Welcome message',welcomeText);
Another approach would be to Ext.mixin.Mashup mixin.
This mixin allows users to easily require external scripts in their
classes. This load process delays application launch (Ext.onReady)
until all such scripts are loaded ensuring that your class will have
access to its required scripts from the start.
So you could have an Moment.js adapter class, like so:
Ext.define('MomentjsAdapter', {
mixins: ['Ext.mixin.Mashup'],
requiredScripts: [
'https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js'
],
...
});
I like this very much, because you keep the external dependency close to the place where it's used. Which is very handy when you might want to remove the dependency or reuse it in a different place/project.
So I am trying to add pikaday date picker to Ember-CLI app.
I've got the following in my /app/views/calendar-view.js
import Ember from 'ember';
export default Ember.TextView.extend({
modelChangedValue: function(){
console.log(this.get('value'));
}.observes("value"),
didInsertElement: function(){
currentYear = (new Date()).getFullYear();
formElement = this.$()[0];
picker = new Pikaday({
field: formElement,
yearRange: [1900,currentYear+2]
});
this.set("_picker", picker);
},
willDestroyElement: function(){
picker = this.get("_picker");
if (picker) {
picker.destroy();
}
this.set("_picker", null);
}
});
My main issue is how to add the plugin itself into ember-cli?
This is the github link for pikaday: https://github.com/dbushell/Pikaday
More specifically I think this part might be important since Ember-CLI uses AMD: https://github.com/dbushell/Pikaday#amd-support
So how do I add the plugin itself to ember-cli?
Update
Since writing this answer, the Ember Addon API has become more usable and are a perfect option if you're building an Ember component/mixin/other class that adds to the regular js plugin.
Regular install
In a 'regular install' situation, you want the plugin to be available through your app and be included in the app's payload no matter what. To do this, add the file/package to your project's vendor directory. There are two immediately available ways to do this: use Bower or simply save a file or package in the directory.
1) Bower
Use Bower to install the package either through the terminal, like:
bower install ember-validations
Or, if there is no easy-install Bower package available, in your bower.json file:
{
"name": "app",
"dependencies": {
"chosen": "https://github.com/harvesthq/chosen/releases/download/v1.1.0/chosen_v1.1.0.zip"
}
}
2) Writing a file
You don't have to use Bower to add files and directories to your vendor directory. You could create a file anywhere inside the vendor directory, copy and paste the plugins javascript into it and save it, and it will still be available to import into your app.
3) Making it available in your app
Regardless of the method through which you create and save the plugin scripts, you have to still have to import the file directly into your app. You do this in Brocfile.js. Add an import with the path to the file (main file if it's a bower installed package) just before module.exports = app.toTree();.
app.import('vendor/ember-validations/index.js');
app.import('vendor/chosen/chosen.jquery.min.js');
There's more info in the Managing Dependencies section of the ember-cli docs.
Polyfill or other non-essential plugins
There are some situation in which you don't want to always load/run a script in your app. For example, you are loading a large polyfill only when the user is using IE. In this situation, you can create a directory in public/assets to hold the javascript files and load them using jQuery's $.getScript() method in an initializer or somewhere else within your Ember app.
I answered a similar question about that kind of scenario here.