ckeditor5 1.0.5 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +541 -86
- data/lib/ckeditor5/rails/assets/assets_bundle.rb +1 -1
- data/lib/ckeditor5/rails/assets/assets_bundle_html_serializer.rb +3 -2
- data/lib/ckeditor5/rails/assets/webcomponent.mjs +134 -19
- data/lib/ckeditor5/rails/cdn/ckbox_bundle.rb +1 -1
- data/lib/ckeditor5/rails/cdn/ckeditor_bundle.rb +1 -1
- data/lib/ckeditor5/rails/cdn/helpers.rb +34 -2
- data/lib/ckeditor5/rails/editor/helpers.rb +6 -1
- data/lib/ckeditor5/rails/editor/props.rb +2 -2
- data/lib/ckeditor5/rails/editor/props_inline_plugin.rb +32 -0
- data/lib/ckeditor5/rails/editor/props_plugin.rb +18 -13
- data/lib/ckeditor5/rails/engine.rb +21 -6
- data/lib/ckeditor5/rails/hooks/form.rb +23 -0
- data/lib/ckeditor5/rails/hooks/simple_form.rb +25 -0
- data/lib/ckeditor5/rails/presets.rb +122 -11
- data/lib/ckeditor5/rails/semver.rb +1 -1
- data/lib/ckeditor5/rails/version.rb +1 -1
- metadata +5 -2
data/README.md
CHANGED
@@ -8,6 +8,10 @@
|
|
8
8
|
|
9
9
|
Unofficial CKEditor 5 Ruby on Rails integration gem. Provides seamless integration of CKEditor 5 with Rails applications through web components and helper methods.
|
10
10
|
|
11
|
+
<p align="center">
|
12
|
+
<img src="docs/intro-classic-editor.png" alt="CKEditor 5 Classic Editor in Ruby on Rails application">
|
13
|
+
</p>
|
14
|
+
|
11
15
|
## Installation 🛠️
|
12
16
|
|
13
17
|
Add this line to your application's Gemfile:
|
@@ -16,21 +20,33 @@ Add this line to your application's Gemfile:
|
|
16
20
|
gem 'ckeditor5'
|
17
21
|
```
|
18
22
|
|
19
|
-
|
23
|
+
In your config:
|
24
|
+
|
25
|
+
```rb
|
26
|
+
# config/initializers/ckeditor5.rb
|
27
|
+
|
28
|
+
CKEditor5::Rails::Engine.configure do |config|
|
29
|
+
config.presets.override :default do
|
30
|
+
version '43.3.0'
|
31
|
+
end
|
32
|
+
end
|
33
|
+
```
|
34
|
+
|
35
|
+
In your view:
|
20
36
|
|
21
37
|
```erb
|
22
38
|
<!-- app/views/demos/index.html.erb -->
|
23
39
|
|
24
40
|
<% content_for :head do %>
|
25
|
-
<%= ckeditor5_assets
|
41
|
+
<%= ckeditor5_assets %>
|
42
|
+
<!-- or using inline config: ckeditor5_assets version: '43.3.0', premium: false -->
|
26
43
|
<% end %>
|
27
44
|
|
28
|
-
<%= ckeditor5_editor style: 'width: 600px' %>
|
45
|
+
<%= ckeditor5_editor style: 'width: 600px', initial_data: '<YOUR DATA>' %>
|
46
|
+
<!-- or using inline config: ckeditor5_editor type: :classic, config: { toolbar: [:Bold, :Italic] }, ... -->
|
29
47
|
```
|
30
48
|
|
31
|
-
|
32
|
-
|
33
|
-

|
49
|
+
Voilà! You have CKEditor 5 integrated with your Rails application. 🎉
|
34
50
|
|
35
51
|
## Table of Contents 📚
|
36
52
|
|
@@ -39,13 +55,20 @@ Effect:
|
|
39
55
|
- [Table of Contents 📚](#table-of-contents-)
|
40
56
|
- [Presets 🎨](#presets-)
|
41
57
|
- [Available Configuration Methods ⚙️](#available-configuration-methods-️)
|
42
|
-
- [`
|
43
|
-
- [`
|
44
|
-
- [`
|
58
|
+
- [`version(version)` method](#versionversion-method)
|
59
|
+
- [`gpl` method](#gpl-method)
|
60
|
+
- [`license_key(key)` method](#license_keykey-method)
|
61
|
+
- [`premium` method](#premium-method)
|
62
|
+
- [`translations(*languages)` method](#translationslanguages-method)
|
63
|
+
- [`ckbox` method](#ckbox-method)
|
64
|
+
- [`type(type)` method](#typetype-method)
|
65
|
+
- [`toolbar(*items, should_group_when_full: true, &block)` method](#toolbaritems-should_group_when_full-true-block-method)
|
45
66
|
- [`menubar(visible: true)` method](#menubarvisible-true-method)
|
46
67
|
- [`language(ui, content:)` method](#languageui-content-method)
|
47
68
|
- [`configure(name, value)` method](#configurename-value-method)
|
48
69
|
- [`plugin(name, premium:, import_name:)` method](#pluginname-premium-import_name-method)
|
70
|
+
- [`plugins(*names, **kwargs)` method](#pluginsnames-kwargs-method)
|
71
|
+
- [`inline_plugin(name, code)` method](#inline_pluginname-code-method)
|
49
72
|
- [Including CKEditor 5 assets 📦](#including-ckeditor-5-assets-)
|
50
73
|
- [Lazy loading 🚀](#lazy-loading-)
|
51
74
|
- [GPL usage 🆓](#gpl-usage-)
|
@@ -56,31 +79,41 @@ Effect:
|
|
56
79
|
- [Inline editor 📝](#inline-editor-)
|
57
80
|
- [Balloon editor 🎈](#balloon-editor-)
|
58
81
|
- [Decoupled editor 🌐](#decoupled-editor-)
|
82
|
+
- [How to access editor instance? 🤔](#how-to-access-editor-instance-)
|
83
|
+
- [Events fired by the editor 🔊](#events-fired-by-the-editor-)
|
84
|
+
- [`editor-ready` event](#editor-ready-event)
|
85
|
+
- [`editor-error` event](#editor-error-event)
|
86
|
+
- [Common Tasks and Solutions 💡](#common-tasks-and-solutions-)
|
87
|
+
- [Setting Initial Content 📝](#setting-initial-content-)
|
88
|
+
- [Setting Editor Language 🌐](#setting-editor-language-)
|
89
|
+
- [Integrating with Forms 📋](#integrating-with-forms-)
|
90
|
+
- [Rails form builder integration](#rails-form-builder-integration)
|
91
|
+
- [Simple form integration](#simple-form-integration)
|
92
|
+
- [Custom Styling 🎨](#custom-styling-)
|
93
|
+
- [Custom plugins 🧩](#custom-plugins-)
|
59
94
|
- [License 📜](#license-)
|
60
95
|
|
61
96
|
## Presets 🎨
|
62
97
|
|
63
98
|
Presets are predefined configurations of CKEditor 5, allowing quick setup with specific features. The gem includes a `:default` preset with common features like bold, italic, underline, and link for the classic editor.
|
64
99
|
|
65
|
-
You can
|
66
|
-
|
67
|
-
The example below shows how to define a custom preset with a classic editor and a custom toolbar:
|
100
|
+
You can create your own by defining it in the `config/initializers/ckeditor5.rb` file using the `config.presets.define` method. The example below illustrates the setup of a custom preset with a classic editor and a custom toolbar:
|
68
101
|
|
69
102
|
```rb
|
70
103
|
# config/initializers/ckeditor5.rb
|
71
104
|
|
72
105
|
CKEditor5::Rails::Engine.configure do |config|
|
73
106
|
config.presets.define :custom
|
74
|
-
|
107
|
+
gpl
|
108
|
+
type :classic
|
75
109
|
|
76
110
|
menubar
|
77
|
-
|
78
111
|
toolbar :undo, :redo, :|, :heading, :|, :bold, :italic, :underline, :|,
|
79
|
-
:link, :insertImage, :
|
112
|
+
:link, :insertImage, :mediaEmbed, :insertTable, :blockQuote, :|,
|
80
113
|
:bulletedList, :numberedList, :todoList, :outdent, :indent
|
81
114
|
|
82
115
|
plugins :AccessibilityHelp, :Autoformat, :AutoImage, :Autosave,
|
83
|
-
:BlockQuote, :Bold, :
|
116
|
+
:BlockQuote, :Bold, :CloudServices,
|
84
117
|
:Essentials, :Heading, :ImageBlock, :ImageCaption, :ImageInline,
|
85
118
|
:ImageInsert, :ImageInsertViaUrl, :ImageResize, :ImageStyle,
|
86
119
|
:ImageTextAlternative, :ImageToolbar, :ImageUpload, :Indent,
|
@@ -89,11 +122,15 @@ CKEditor5::Rails::Engine.configure do |config|
|
|
89
122
|
:SelectAll, :Table, :TableCaption, :TableCellProperties,
|
90
123
|
:TableColumnResize, :TableProperties, :TableToolbar,
|
91
124
|
:TextTransformation, :TodoList, :Underline, :Undo, :Base64UploadAdapter
|
125
|
+
|
126
|
+
configure :image, {
|
127
|
+
toolbar: ['imageTextAlternative', 'imageStyle:inline', 'imageStyle:block', 'imageStyle:side']
|
128
|
+
}
|
92
129
|
end
|
93
130
|
end
|
94
131
|
```
|
95
132
|
|
96
|
-
In order to override existing presets, you can use the `config.presets.override` method. The method takes the name of the preset you want to override and a block with the
|
133
|
+
In order to override existing presets, you can use the `config.presets.override` method. The method takes the name of the preset you want to override and a block with the old configuration. The example below shows how to hide the menubar in the default preset:
|
97
134
|
|
98
135
|
```rb
|
99
136
|
# config/initializers/ckeditor5.rb
|
@@ -105,46 +142,132 @@ CKEditor5::Rails::Engine.configure do |config|
|
|
105
142
|
end
|
106
143
|
```
|
107
144
|
|
108
|
-
|
145
|
+
Configuration of the editor can be complex, and it's recommended to use the CKEditor 5 [online builder](https://ckeditor.com/ckeditor-5/online-builder/) to generate the configuration. It allows you to select the features you want to include and generate the configuration code in JavaScript format. Keep in mind that you need to convert the JavaScript configuration to Ruby format before using it in this gem.
|
109
146
|
|
110
147
|
### Available Configuration Methods ⚙️
|
111
148
|
|
112
149
|
<details>
|
113
150
|
<summary>Expand to show available methods 📖</summary>
|
114
151
|
|
115
|
-
#### `
|
152
|
+
#### `version(version)` method
|
116
153
|
|
117
|
-
Defines the
|
154
|
+
Defines the version of CKEditor 5 to be used. The example below shows how to set the version to `43.2.0`:
|
118
155
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
156
|
+
```rb
|
157
|
+
# config/initializers/ckeditor5.rb
|
158
|
+
|
159
|
+
config.presets.define :custom do
|
160
|
+
# ... other configuration
|
161
|
+
|
162
|
+
version '43.2.0'
|
163
|
+
end
|
164
|
+
```
|
165
|
+
|
166
|
+
#### `gpl` method
|
167
|
+
|
168
|
+
Defines the license of CKEditor 5. The example below shows how to set the license to GPL:
|
169
|
+
|
170
|
+
```rb
|
171
|
+
# config/initializers/ckeditor5.rb
|
172
|
+
|
173
|
+
config.presets.define :custom do
|
174
|
+
# ... other configuration
|
175
|
+
|
176
|
+
gpl
|
177
|
+
end
|
178
|
+
```
|
179
|
+
|
180
|
+
#### `license_key(key)` method
|
124
181
|
|
125
|
-
The example below shows how to
|
182
|
+
Defines the license key of CKEditor 5. It calls `premium` method internally. The example below shows how to set the license key:
|
126
183
|
|
127
184
|
```rb
|
128
185
|
# config/initializers/ckeditor5.rb
|
129
186
|
|
130
187
|
config.presets.define :custom do
|
131
|
-
|
188
|
+
# ... other configuration
|
189
|
+
|
190
|
+
license_key 'your-license-key'
|
132
191
|
end
|
133
192
|
```
|
134
193
|
|
135
|
-
#### `
|
194
|
+
#### `premium` method
|
136
195
|
|
137
|
-
Defines
|
196
|
+
Defines if premium package should be included in JS assets. The example below shows how to add `ckeditor5-premium-features` to import maps:
|
138
197
|
|
139
198
|
```rb
|
140
199
|
# config/initializers/ckeditor5.rb
|
141
200
|
|
142
201
|
config.presets.define :custom do
|
143
|
-
|
202
|
+
# ... other configuration
|
203
|
+
|
204
|
+
premium
|
144
205
|
end
|
145
206
|
```
|
146
207
|
|
147
|
-
#### `
|
208
|
+
#### `translations(*languages)` method
|
209
|
+
|
210
|
+
Defines the translations of CKEditor 5. You can pass the language codes as arguments. The example below shows how tell integration to fetch Polish and Spanish translations:
|
211
|
+
|
212
|
+
```rb
|
213
|
+
# config/initializers/ckeditor5.rb
|
214
|
+
|
215
|
+
config.presets.define :custom do
|
216
|
+
# ... other configuration
|
217
|
+
|
218
|
+
translations :pl, :es
|
219
|
+
end
|
220
|
+
```
|
221
|
+
|
222
|
+
⚠️ You need to use `language` method to set the default language of the editor, as the `translations` only fetch the translations files and makes them available to later use.
|
223
|
+
|
224
|
+
```rb
|
225
|
+
# config/initializers/ckeditor5.rb
|
226
|
+
|
227
|
+
config.presets.define :custom do
|
228
|
+
translations :pl
|
229
|
+
|
230
|
+
language :pl
|
231
|
+
end
|
232
|
+
```
|
233
|
+
|
234
|
+
#### `ckbox` method
|
235
|
+
|
236
|
+
Defines the CKBox plugin to be included in the editor. The example below shows how to include the CKBox plugin:
|
237
|
+
|
238
|
+
```rb
|
239
|
+
# config/initializers/ckeditor5.rb
|
240
|
+
|
241
|
+
config.presets.define :custom do
|
242
|
+
# ... other configuration
|
243
|
+
|
244
|
+
ckbox '2.5.4', theme: :lark
|
245
|
+
end
|
246
|
+
```
|
247
|
+
|
248
|
+
#### `type(type)` method
|
249
|
+
|
250
|
+
Defines the type of editor. Available options:
|
251
|
+
|
252
|
+
- `:classic` - classic edytor
|
253
|
+
- `:inline` - inline editor
|
254
|
+
- `:decoupled` - decoupled editor
|
255
|
+
- `:balloon` - balloon editor
|
256
|
+
- `:multiroot` - editor with multiple editing areas
|
257
|
+
|
258
|
+
The example below sets the editor type to `multiroot` in the custom preset:
|
259
|
+
|
260
|
+
```rb
|
261
|
+
# config/initializers/ckeditor5.rb
|
262
|
+
|
263
|
+
config.presets.define :custom do
|
264
|
+
# ... other configuration
|
265
|
+
|
266
|
+
type :multiroot
|
267
|
+
end
|
268
|
+
```
|
269
|
+
|
270
|
+
#### `toolbar(*items, should_group_when_full: true, &block)` method
|
148
271
|
|
149
272
|
Defines the toolbar items. You can use predefined items like `:undo`, `:redo`, `:|` or specify custom items. There are a few special items:
|
150
273
|
|
@@ -167,6 +290,21 @@ end
|
|
167
290
|
|
168
291
|
Keep in mind that the order of items is important, and you should install the corresponding plugins. You can find the list of available plugins in the [CKEditor 5 documentation](https://ckeditor.com/docs/ckeditor5/latest/framework/architecture/plugins.html).
|
169
292
|
|
293
|
+
If you want to add or prepend items to the existing toolbar, you can use the block syntax:
|
294
|
+
|
295
|
+
```rb
|
296
|
+
# config/initializers/ckeditor5.rb
|
297
|
+
|
298
|
+
config.presets.override :default do
|
299
|
+
# ... other configuration
|
300
|
+
|
301
|
+
toolbar do
|
302
|
+
append :selectAll, :|, :selectAll, :selectAll
|
303
|
+
# Or prepend: prepend :selectAll, :|, :selectAll, :selectAll
|
304
|
+
end
|
305
|
+
end
|
306
|
+
```
|
307
|
+
|
170
308
|
#### `menubar(visible: true)` method
|
171
309
|
|
172
310
|
Defines the visibility of the menubar. By default, it's set to `true`.
|
@@ -241,7 +379,7 @@ config.presets.define :custom do
|
|
241
379
|
end
|
242
380
|
```
|
243
381
|
|
244
|
-
In order to import a plugin from a custom package, you can pass the `import_name` keyword argument:
|
382
|
+
In order to import a plugin from a custom ESM package, you can pass the `import_name` keyword argument:
|
245
383
|
|
246
384
|
```rb
|
247
385
|
# config/initializers/ckeditor5.rb
|
@@ -253,20 +391,71 @@ config.presets.define :custom do
|
|
253
391
|
end
|
254
392
|
```
|
255
393
|
|
394
|
+
In order to import a plugin from a custom Window entry, you can pass the `window_name` keyword argument:
|
395
|
+
|
396
|
+
```rb
|
397
|
+
# config/initializers/ckeditor5.rb
|
398
|
+
|
399
|
+
config.presets.define :custom do
|
400
|
+
# ... other configuration
|
401
|
+
|
402
|
+
plugin :YourPlugin, window_name: 'YourPlugin'
|
403
|
+
end
|
404
|
+
```
|
405
|
+
|
406
|
+
#### `plugins(*names, **kwargs)` method
|
407
|
+
|
408
|
+
Defines the plugins to be included in the editor. You can specify multiple plugins by passing their names as arguments. The keyword arguments are identical to the configuration of the `plugin` method defined below.
|
409
|
+
|
410
|
+
```rb
|
411
|
+
# config/initializers/ckeditor5.rb
|
412
|
+
|
413
|
+
config.presets.define :custom do
|
414
|
+
# ... other configuration
|
415
|
+
|
416
|
+
plugins :Bold, :Italic, :Underline, :Link
|
417
|
+
end
|
418
|
+
```
|
419
|
+
|
420
|
+
#### `inline_plugin(name, code)` method
|
421
|
+
|
422
|
+
Use with caution as this is an inline definition of the plugin code, and you can define a custom class or function for the plugin here. The example below shows how to define a custom plugin that highlights the text:
|
423
|
+
|
424
|
+
```rb
|
425
|
+
# config/initializers/ckeditor5.rb
|
426
|
+
|
427
|
+
config.presets.define :custom do
|
428
|
+
# ... other configuration
|
429
|
+
|
430
|
+
inline_plugin :MyCustomPlugin, <<~JS
|
431
|
+
import { Plugin } from 'ckeditor5';
|
432
|
+
|
433
|
+
export default class MyCustomPlugin extends Plugin {
|
434
|
+
static get pluginName() {
|
435
|
+
return 'MyCustomPlugin';
|
436
|
+
}
|
437
|
+
|
438
|
+
init() {
|
439
|
+
// ... Your plugin code
|
440
|
+
}
|
441
|
+
}
|
442
|
+
JS
|
443
|
+
end
|
444
|
+
```
|
256
445
|
</details>
|
257
446
|
|
258
447
|
## Including CKEditor 5 assets 📦
|
259
448
|
|
260
|
-
To include CKEditor 5 assets in your application, you can use the `ckeditor5_assets` helper method. This method takes the version of CKEditor 5 as an argument and includes the necessary
|
449
|
+
To include CKEditor 5 assets in your application, you can use the `ckeditor5_assets` helper method. This method takes the version of CKEditor 5 as an argument and includes the necessary resources of the editor. Depending on the specified configuration, it includes the JS and CSS assets from the official CKEditor 5 CDN or one of the popular CDNs.
|
261
450
|
|
262
|
-
Keep in mind that you need to include the
|
451
|
+
Keep in mind that you need to include the helper result in the `head` section of your layout. In examples below, we use `content_for` helper to include the assets in the `head` section of the view.
|
263
452
|
|
264
453
|
### Lazy loading 🚀
|
265
454
|
|
266
455
|
<details>
|
267
456
|
<summary>Loading JS and CSS Assets</summary>
|
268
457
|
|
269
|
-
All JS assets defined by the `ckeditor5_assets` helper method are loaded asynchronously
|
458
|
+
All JS assets defined by the `ckeditor5_assets` helper method are loaded **asynchronously**. It means that the assets are loaded in the background without blocking the rendering of the page. However, the CSS assets are loaded **synchronously** to prevent the flash of unstyled content and ensure that the editor is styled correctly.
|
270
459
|
|
271
460
|
It has been achieved by using web components, together with import maps, which are supported by modern browsers. The web components are used to define the editor and its plugins, while the import maps are used to define the dependencies between the assets.
|
272
461
|
|
@@ -274,7 +463,7 @@ It has been achieved by using web components, together with import maps, which a
|
|
274
463
|
|
275
464
|
### GPL usage 🆓
|
276
465
|
|
277
|
-
If you want to use CKEditor 5 under the GPL license, you can include the assets using the `ckeditor5_assets`
|
466
|
+
If you want to use CKEditor 5 under the GPL license, you can include the assets using the `ckeditor5_assets` without passing any arguments. However you can pass the `version` keyword argument with the version of CKEditor 5 you want to use:
|
278
467
|
|
279
468
|
```erb
|
280
469
|
<!-- app/views/demos/index.html.erb -->
|
@@ -286,6 +475,28 @@ If you want to use CKEditor 5 under the GPL license, you can include the assets
|
|
286
475
|
|
287
476
|
It'll include the necessary assets for the GPL license from one of the most popular CDNs. In our scenario, we use the `jsdelivr` CDN which is the default one.
|
288
477
|
|
478
|
+
Version is optional as long as you defined it in the `config/initializers/ckeditor5.rb` file. If you want to use the default version, you can omit the `version` keyword argument:
|
479
|
+
|
480
|
+
```erb
|
481
|
+
<!-- app/views/demos/index.html.erb -->
|
482
|
+
|
483
|
+
<% content_for :head do %>
|
484
|
+
<%= ckeditor5_assets %>
|
485
|
+
<% end %>
|
486
|
+
```
|
487
|
+
|
488
|
+
Set the version in the `config/initializers/ckeditor5.rb` file:
|
489
|
+
|
490
|
+
```rb
|
491
|
+
# config/initializers/ckeditor5.rb
|
492
|
+
|
493
|
+
CKEditor5::Rails::Engine.configure do
|
494
|
+
presets.override :default do
|
495
|
+
version '43.3.0'
|
496
|
+
end
|
497
|
+
end
|
498
|
+
```
|
499
|
+
|
289
500
|
In order to use `unpkg` CDN, you can pass the `cdn` keyword argument with the value `:unpkg`:
|
290
501
|
|
291
502
|
```erb
|
@@ -349,7 +560,7 @@ In this scenario, the assets are included from the official CKEditor 5 CDN which
|
|
349
560
|
|
350
561
|
## Editor placement 🏗️
|
351
562
|
|
352
|
-
The `ckeditor5_editor` helper renders CKEditor 5 instances in your views. Before using it, ensure you've included the necessary assets in your page's head section.
|
563
|
+
The `ckeditor5_editor` helper renders CKEditor 5 instances in your views. Before using it, ensure you've included the necessary assets in your page's head section otherwise the editor won't work as there are no CKEditor 5 JavaScript and CSS files loaded.
|
353
564
|
|
354
565
|
### Classic editor 📝
|
355
566
|
|
@@ -365,7 +576,7 @@ The example below shows how to include the classic editor in your view:
|
|
365
576
|
<!-- app/views/demos/index.html.erb -->
|
366
577
|
|
367
578
|
<% content_for :head do %>
|
368
|
-
<%= ckeditor5_assets
|
579
|
+
<%= ckeditor5_assets %>
|
369
580
|
<% end %>
|
370
581
|
|
371
582
|
<%= ckeditor5_editor style: 'width: 600px' %>
|
@@ -379,7 +590,7 @@ While example above uses predefined `:default` preset, you can use your custom p
|
|
379
590
|
<!-- app/views/demos/index.html.erb -->
|
380
591
|
|
381
592
|
<% content_for :head do %>
|
382
|
-
<%= ckeditor5_assets
|
593
|
+
<%= ckeditor5_assets %>
|
383
594
|
<% end %>
|
384
595
|
|
385
596
|
<%= ckeditor5_editor preset: :custom, style: 'width: 600px' %>
|
@@ -391,7 +602,7 @@ If your configuration is even more complex, you can pass the `config` and `type`
|
|
391
602
|
<!-- app/views/demos/index.html.erb -->
|
392
603
|
|
393
604
|
<% content_for :head do %>
|
394
|
-
<%= ckeditor5_assets
|
605
|
+
<%= ckeditor5_assets %>
|
395
606
|
<% end %>
|
396
607
|
|
397
608
|
<%= ckeditor5_editor type: :classic, config: { plugins: [:Bold, :Italic], toolbar: [:Bold, :Italic] }, style: 'width: 600px' %>
|
@@ -403,7 +614,7 @@ If you want to override the configuration of the editor specified in default or
|
|
403
614
|
<!-- app/views/demos/index.html.erb -->
|
404
615
|
|
405
616
|
<% content_for :head do %>
|
406
|
-
<%= ckeditor5_assets
|
617
|
+
<%= ckeditor5_assets %>
|
407
618
|
<% end %>
|
408
619
|
|
409
620
|
<%= ckeditor5_editor extra_config: { toolbar: [:Bold, :Italic] }, style: 'width: 600px' %>
|
@@ -425,7 +636,7 @@ If you want to use a multiroot editor, you can pass the `type` keyword argument
|
|
425
636
|
<!-- app/views/demos/index.html.erb -->
|
426
637
|
|
427
638
|
<% content_for :head do %>
|
428
|
-
<%= ckeditor5_assets
|
639
|
+
<%= ckeditor5_assets %>
|
429
640
|
<% end %>
|
430
641
|
|
431
642
|
<%= ckeditor5_editor type: :multiroot, style: 'width: 600px' do %>
|
@@ -454,7 +665,7 @@ If you want to use an inline editor, you can pass the `type` keyword argument wi
|
|
454
665
|
<!-- app/views/demos/index.html.erb -->
|
455
666
|
|
456
667
|
<% content_for :head do %>
|
457
|
-
<%= ckeditor5_assets
|
668
|
+
<%= ckeditor5_assets %>
|
458
669
|
<% end %>
|
459
670
|
|
460
671
|
<%= ckeditor5_editor type: :inline, style: 'width: 600px' %>
|
@@ -472,7 +683,7 @@ If you want to use a balloon editor, you can pass the `type` keyword argument wi
|
|
472
683
|
<!-- app/views/demos/index.html.erb -->
|
473
684
|
|
474
685
|
<% content_for :head do %>
|
475
|
-
<%= ckeditor5_assets
|
686
|
+
<%= ckeditor5_assets %>
|
476
687
|
<% end %>
|
477
688
|
|
478
689
|
<%= ckeditor5_editor type: :balloon, style: 'width: 600px' %>
|
@@ -488,60 +699,304 @@ If you want to use a decoupled editor, you can pass the `type` keyword argument
|
|
488
699
|
|
489
700
|
```erb
|
490
701
|
<% content_for :head do %>
|
491
|
-
<%= ckeditor5_assets
|
702
|
+
<%= ckeditor5_assets %>
|
492
703
|
<% end %>
|
493
704
|
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
position: relative;
|
499
|
-
border: 1px solid red;
|
500
|
-
}
|
705
|
+
<%= ckeditor5_editor type: :decoupled, style: 'width: 600px' do %>
|
706
|
+
<div class="menubar-container">
|
707
|
+
<%= ckeditor5_menubar %>
|
708
|
+
</div>
|
501
709
|
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
710
|
+
<div class="toolbar-container">
|
711
|
+
<%= ckeditor5_toolbar %>
|
712
|
+
</div>
|
713
|
+
|
714
|
+
<div class="editable-container">
|
715
|
+
<%= ckeditor5_editable %>
|
716
|
+
</div>
|
717
|
+
<% end %>
|
718
|
+
```
|
719
|
+
|
720
|
+
## How to access editor instance? 🤔
|
721
|
+
|
722
|
+
You can access the editor instance using plain HTML and JavaScript, as CKEditor 5 is a web component with defined `instance`, `instancePromise` and `editables` properties.
|
723
|
+
|
724
|
+
For example:
|
725
|
+
|
726
|
+
```erb
|
727
|
+
<!-- app/views/demos/index.html.erb -->
|
728
|
+
|
729
|
+
<% content_for :head do %>
|
730
|
+
<%= ckeditor5_assets %>
|
731
|
+
<% end %>
|
732
|
+
|
733
|
+
<%= ckeditor5_editor style: 'width: 600px', id: 'editor' %>
|
734
|
+
```
|
735
|
+
|
736
|
+
⚠️ Direct access of `instance` property of the web component. Keep in mind it's unsafe and may cause issues if the editor is not loaded yet.
|
737
|
+
|
738
|
+
```js
|
739
|
+
document.getElementById('editor').instance
|
740
|
+
```
|
741
|
+
|
742
|
+
👌 Accessing the editor instance using `instancePromise` property. It's a promise that resolves to the editor instance when the editor is ready.
|
743
|
+
|
744
|
+
```js
|
745
|
+
document.getElementById('editor').instancePromise.then(editor => {
|
746
|
+
console.log(editor);
|
747
|
+
});
|
748
|
+
```
|
749
|
+
|
750
|
+
✅ Accessing the editor through the `runAfterEditorReady` helper method. It's a safe way to access the editor instance when the editor is ready.
|
751
|
+
|
752
|
+
```js
|
753
|
+
document.getElementById('editor').runAfterEditorReady(editor => {
|
754
|
+
console.log(editor);
|
755
|
+
});
|
756
|
+
```
|
757
|
+
|
758
|
+
## Events fired by the editor 🔊
|
759
|
+
|
760
|
+
### `editor-ready` event
|
761
|
+
|
762
|
+
The event is fired when the initialization of the editor is completed. You can listen to it using the `editor-ready` event.
|
763
|
+
|
764
|
+
```js
|
765
|
+
document.getElementById('editor').addEventListener('editor-ready', () => {
|
766
|
+
console.log('Editor is ready');
|
767
|
+
});
|
768
|
+
```
|
769
|
+
|
770
|
+
### `editor-error` event
|
771
|
+
|
772
|
+
The event is fired when the initialization of the editor fails. You can listen to it using the `editor-error` event.
|
514
773
|
|
515
|
-
|
516
|
-
|
517
|
-
|
774
|
+
```js
|
775
|
+
document.getElementById('editor').addEventListener('editor-error', () => {
|
776
|
+
console.log('Editor has an error');
|
777
|
+
});
|
778
|
+
```
|
779
|
+
|
780
|
+
## Common Tasks and Solutions 💡
|
781
|
+
|
782
|
+
This section covers frequent questions and scenarios when working with CKEditor 5 in Rails applications.
|
783
|
+
|
784
|
+
### Setting Initial Content 📝
|
785
|
+
|
786
|
+
```erb
|
787
|
+
<%= ckeditor5_editor initial_data: "<p>Initial content</p>" %>
|
788
|
+
```
|
789
|
+
|
790
|
+
### Setting Editor Language 🌐
|
791
|
+
|
792
|
+
```rb
|
793
|
+
config.presets.override :default do
|
794
|
+
translations :pl, :es
|
795
|
+
language :pl
|
796
|
+
end
|
797
|
+
```
|
798
|
+
|
799
|
+
### Integrating with Forms 📋
|
800
|
+
|
801
|
+
#### Rails form builder integration
|
802
|
+
|
803
|
+
```erb
|
804
|
+
<%= form_for @post do |f| %>
|
805
|
+
<%= f.label :content %>
|
806
|
+
<%= f.ckeditor5 :content, required: true, style: 'width: 700px', initial_data: 'Hello World!' %>
|
807
|
+
<% end %>
|
808
|
+
```
|
809
|
+
|
810
|
+
#### Simple form integration
|
811
|
+
|
812
|
+
```erb
|
813
|
+
<%= simple_form_for :demo, url: '/demos', html: { novalidate: false } do |f| %>
|
814
|
+
<div class="form-group">
|
815
|
+
<%= f.input :content, as: :ckeditor5, initial_data: 'Hello, World 12!', input_html: { style: 'width: 600px' }, required: true %>
|
816
|
+
</div>
|
817
|
+
|
818
|
+
<div class="form-group mt-3">
|
819
|
+
<%= f.button :submit, 'Save', class: 'btn btn-primary' %>
|
820
|
+
</div>
|
821
|
+
<% end %>
|
822
|
+
```
|
823
|
+
|
824
|
+
### Custom Styling 🎨
|
825
|
+
|
826
|
+
```erb
|
827
|
+
<%= ckeditor5_editor style: 'height: 400px; margin: 20px;' %>
|
828
|
+
```
|
829
|
+
|
830
|
+
### Custom plugins 🧩
|
831
|
+
|
832
|
+
You can create custom plugins for CKEditor 5 using the `inline_plugin` method. It allows you to define a custom class or function inside your preset configuration.
|
833
|
+
|
834
|
+
The example below shows how to define a custom plugin that allows toggling the highlight of the selected text:
|
835
|
+
|
836
|
+

|
837
|
+
|
838
|
+
```rb
|
839
|
+
# config/initializers/ckeditor5.rb
|
840
|
+
|
841
|
+
config.presets.define :custom do
|
842
|
+
# ... other configuration
|
843
|
+
|
844
|
+
# 1. You can define it inline like below or in a separate file.
|
845
|
+
|
846
|
+
# In case if plugin is located in external file (recommended), you can simply import it:
|
847
|
+
|
848
|
+
# inline_plugin :MyCustomPlugin, <<~JS
|
849
|
+
# import MyPlugin from 'app/javascript/custom_plugins/highlight.js';
|
850
|
+
# export default MyPlugin;
|
851
|
+
# JS
|
852
|
+
|
853
|
+
# 2. You can also use "window_name" option to import plugin from window object:
|
854
|
+
|
855
|
+
# plugin :MyPlugin, window_name: 'MyPlugin'
|
856
|
+
|
857
|
+
# 3. Create JavaScript file in app/javascript/custom_plugins/highlight.js:
|
858
|
+
# You can also use "plugin" to import plugin from file using 'import_name' option.
|
859
|
+
# Your `my-custom-plugin` must be present in import map.
|
860
|
+
|
861
|
+
# plugin :MyCustomPlugin, import_name: 'my-custom-plugin'
|
862
|
+
|
863
|
+
# 4 Create JavaScript file in app/javascript/custom_plugins/highlight.js:
|
864
|
+
|
865
|
+
# In Ruby initializer you can also load plugin code directly from file:
|
866
|
+
plugin :MyCustomPlugin, File.read(
|
867
|
+
Rails.root.join('app/javascript/custom_plugins/highlight.js')
|
868
|
+
)
|
869
|
+
|
870
|
+
# 5. Or even define it inline:
|
871
|
+
# plugin :MyCustomPlugin, <<~JS
|
872
|
+
# import { Plugin } from 'ckeditor5';
|
873
|
+
#
|
874
|
+
# export default class MyCustomPlugin extends Plugin {
|
875
|
+
# // ...
|
876
|
+
# }
|
877
|
+
# JS
|
878
|
+
|
879
|
+
# Add item to beginning of the toolbar.
|
880
|
+
toolbar do
|
881
|
+
prepend :highlight
|
882
|
+
end
|
883
|
+
end
|
884
|
+
```
|
885
|
+
|
886
|
+
<details>
|
887
|
+
<summary>Example of Custom Highlight Plugin 🎨</summary>
|
888
|
+
|
889
|
+
```js
|
890
|
+
// app/javascript/custom_plugins/highlight.js
|
891
|
+
import { Plugin, Command, ButtonView } from 'ckeditor5';
|
892
|
+
|
893
|
+
export default class MyCustomPlugin extends Plugin {
|
894
|
+
static get pluginName() {
|
895
|
+
return 'MyCustomPlugin';
|
518
896
|
}
|
519
897
|
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
898
|
+
init() {
|
899
|
+
const editor = this.editor;
|
900
|
+
|
901
|
+
// Define schema for highlight attribute
|
902
|
+
editor.model.schema.extend('$text', { allowAttributes: 'highlight' });
|
903
|
+
|
904
|
+
// Define conversion between model and view
|
905
|
+
editor.conversion.attributeToElement({
|
906
|
+
model: 'highlight',
|
907
|
+
view: {
|
908
|
+
name: 'span',
|
909
|
+
styles: {
|
910
|
+
'background-color': 'yellow'
|
911
|
+
}
|
912
|
+
}
|
913
|
+
});
|
914
|
+
|
915
|
+
// Create command that handles highlighting logic
|
916
|
+
// Command pattern is used to encapsulate all the logic related to executing an action
|
917
|
+
const command = new HighlightCommand(editor);
|
918
|
+
|
919
|
+
// Register command in editor
|
920
|
+
editor.commands.add('highlight', command);
|
921
|
+
|
922
|
+
// Add UI button
|
923
|
+
editor.ui.componentFactory.add('highlight', locale => {
|
924
|
+
const view = new ButtonView(locale);
|
925
|
+
|
926
|
+
// Bind button state to command state using bind method
|
927
|
+
// bind() allows to sync button state with command state automatically
|
928
|
+
view.bind('isOn').to(command, 'value');
|
929
|
+
|
930
|
+
view.set({
|
931
|
+
label: 'Highlight',
|
932
|
+
withText: true,
|
933
|
+
tooltip: true
|
934
|
+
});
|
935
|
+
|
936
|
+
view.on('execute', () => {
|
937
|
+
editor.execute('highlight');
|
938
|
+
editor.editing.view.focus();
|
939
|
+
});
|
940
|
+
|
941
|
+
return view;
|
942
|
+
});
|
943
|
+
}
|
944
|
+
}
|
945
|
+
|
946
|
+
// Command class that handles the highlight feature
|
947
|
+
// isEnabled property determines if command can be executed
|
948
|
+
class HighlightCommand extends Command {
|
949
|
+
execute() {
|
950
|
+
const model = this.editor.model;
|
951
|
+
const selection = model.document.selection;
|
952
|
+
|
953
|
+
model.change(writer => {
|
954
|
+
const ranges = model.schema.getValidRanges(selection.getRanges(), 'highlight');
|
955
|
+
|
956
|
+
for (const range of ranges) {
|
957
|
+
if (this.value) {
|
958
|
+
writer.removeAttribute('highlight', range);
|
959
|
+
} else {
|
960
|
+
writer.setAttribute('highlight', true, range);
|
961
|
+
}
|
962
|
+
}
|
963
|
+
});
|
524
964
|
}
|
525
965
|
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
966
|
+
refresh() {
|
967
|
+
const model = this.editor.model;
|
968
|
+
const selection = model.document.selection;
|
969
|
+
const isAllowed = model.schema.checkAttributeInSelection(selection, 'highlight');
|
970
|
+
|
971
|
+
// Set if command is enabled based on schema
|
972
|
+
this.isEnabled = isAllowed;
|
973
|
+
this.value = this.#isHighlightedNodeSelected();
|
533
974
|
}
|
534
|
-
</style>
|
535
975
|
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
976
|
+
// Check if the highlighted node is selected.
|
977
|
+
#isHighlightedNodeSelected() {
|
978
|
+
const { model } = this.editor
|
979
|
+
const { schema } = model
|
980
|
+
const selection = model.document.selection
|
981
|
+
|
982
|
+
if (selection.isCollapsed) {
|
983
|
+
return selection.hasAttribute('highlight')
|
984
|
+
}
|
985
|
+
|
986
|
+
return selection.getRanges().some(range =>
|
987
|
+
Array
|
988
|
+
.from(range.getItems())
|
989
|
+
.some(item =>
|
990
|
+
schema.checkAttribute(item, 'highlight') &&
|
991
|
+
item.hasAttribute('highlight')
|
992
|
+
)
|
993
|
+
);
|
994
|
+
}
|
995
|
+
}
|
543
996
|
```
|
544
997
|
|
998
|
+
</details>
|
999
|
+
|
545
1000
|
## License 📜
|
546
1001
|
|
547
1002
|
The MIT License (MIT)
|