ckeditor5 1.16.2 → 1.17.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 80773f82ac9fcdf35feac2e568206c4dd5dbd04240ae891b880549fc7192ef12
4
- data.tar.gz: d4c4244344977827288691f7846bce8737c70d9df170aff1fa2fb52a3a400d1a
3
+ metadata.gz: 843e4c645212f665f1c8e1efe8ae6b623d84e8a42cfd5c4e8181def8450e0dde
4
+ data.tar.gz: b0980b0adcf055278856758e38e304d5eaa3927d3dd75a703abec2bd7366d5fb
5
5
  SHA512:
6
- metadata.gz: 2b681fd82436a62b4da89064979c02f4952ba1c210473b3d00791fe34627555e6df6761c4fb9cdbd49ea3258a3ce508c7c2c013ae4dccb56eb452848f936024a
7
- data.tar.gz: 1c2170807abc784d8905b6817a8b1fb03c08d1f8ce3be48403923b96c255232c7acea65bacd417922e0014e5b18f7eb58dd6702837d0fc7bca3df936bee9774d
6
+ metadata.gz: 315c863ea830f41cc5b68e6bbfbd736fdb89facab2233d75648313befecaa419ffe9e42a84545da347e0575db6c6da58f0f690ce32c6fc989fa5408a48d8110d
7
+ data.tar.gz: 6dafb2dc99b0cb3496e5e106f0a90a0d8cd93f25ee78e86d5e4d2a3f67cd987c59af0aad45d1d4b0651cf237606856e4399f48d1d6a0a20b3a31639f094641f1
data/README.md CHANGED
@@ -44,8 +44,8 @@ In your view:
44
44
  <!-- app/views/demos/index.html.erb -->
45
45
 
46
46
  <% content_for :head do %>
47
- <!-- 📦 Loads CKEditor assets via importmap based on initializer config -->
48
- <%= ckeditor5_assets %>
47
+ <!-- 📦 Adds importmap with CKEditor 5 assets. Language is optional. -->
48
+ <%= ckeditor5_assets language: :en %>
49
49
  <% end %>
50
50
 
51
51
  <!-- 🖋️ CKEditor 5 might be placed using simple view helper ... -->
@@ -113,12 +113,12 @@ For extending CKEditor's functionality, refer to the [plugins directory](https:/
113
113
  - [`license_key(key)` method](#license_keykey-method)
114
114
  - [`premium` method](#premium-method)
115
115
  - [`editable_height(height)` method](#editable_heightheight-method)
116
+ - [`language(ui, content:)` method](#languageui-content-method)
116
117
  - [`translations(*languages)` method](#translationslanguages-method)
117
118
  - [`ckbox` method](#ckbox-method)
118
119
  - [`type(type)` method](#typetype-method)
119
120
  - [`toolbar(*items, should_group_when_full: true, &block)` method](#toolbaritems-should_group_when_full-true-block-method)
120
121
  - [`menubar(visible: true)` method](#menubarvisible-true-method)
121
- - [`language(ui, content:)` method](#languageui-content-method)
122
122
  - [`configure(name, value)` method](#configurename-value-method)
123
123
  - [`plugin(name, premium:, import_name:)` method](#pluginname-premium-import_name-method)
124
124
  - [`plugins(*names, **kwargs)` method](#pluginsnames-kwargs-method)
@@ -126,7 +126,7 @@ For extending CKEditor's functionality, refer to the [plugins directory](https:/
126
126
  - [`simple_upload_adapter(url)` method](#simple_upload_adapterurl-method)
127
127
  - [Controller / View helpers 📦](#controller--view-helpers-)
128
128
  - [`ckeditor5_element_ref(selector)` method](#ckeditor5_element_refselector-method)
129
- - [`ckeditor5_preset(&block)` method](#ckeditor5_presetblock-method)
129
+ - [`ckeditor5_preset(name = nil, &block)` method](#ckeditor5_presetname--nil-block-method)
130
130
  - [Including CKEditor 5 assets 📦](#including-ckeditor-5-assets-)
131
131
  - [Format 📝](#format-)
132
132
  - [Using default preset](#using-default-preset)
@@ -256,6 +256,11 @@ end
256
256
 
257
257
  #### `cdn(cdn = nil, &block)` method
258
258
 
259
+ <details>
260
+ <summary>Configure custom CDN URL pattern or use predefined CDNs like jsdelivr or unpkg</summary>
261
+
262
+ <br />
263
+
259
264
  Defines the CDN to be used for CKEditor 5 assets. The example below shows how to set the CDN to `:jsdelivr`:
260
265
 
261
266
  ```rb
@@ -283,9 +288,15 @@ CKEditor5::Rails.configure do
283
288
  end
284
289
  end
285
290
  ```
291
+ </details>
286
292
 
287
293
  #### `version(version)` method
288
294
 
295
+ <details>
296
+ <summary>Set up the version of CKEditor 5 to be used by the integration</summary>
297
+
298
+ <br />
299
+
289
300
  Defines the version of CKEditor 5 to be used. The example below shows how to set the version to `43.2.0`:
290
301
 
291
302
  ```rb
@@ -297,9 +308,15 @@ CKEditor5::Rails.configure do
297
308
  version '43.3.1'
298
309
  end
299
310
  ```
311
+ </details>
300
312
 
301
313
  #### `automatic_upgrades(enabled: true)` method
302
314
 
315
+ <details>
316
+ <summary>Enable or disable automatic security patches and bug fixes</summary>
317
+
318
+ <br />
319
+
303
320
  Defines if automatic upgrades should be enabled. It's enabled for the `:default` preset by default. The example below shows how to disable automatic upgrades:
304
321
 
305
322
  ```rb
@@ -315,9 +332,15 @@ end
315
332
  It means that the editor will automatically upgrade to the latest version when the gem is updated. It'll upgrade the editor only if the new patch or minor version is released. If you want to disable automatic upgrades, you can pass the `enabled: false` keyword argument to the `automatic_upgrades` method.
316
333
 
317
334
  Version is checked every nth day, where n is the number of days since the last check. Currently it's 4 days.
335
+ </details>
318
336
 
319
337
  #### `gpl` method
320
338
 
339
+ <details>
340
+ <summary>Defines the license of CKEditor 5. The example below shows how to set the license to GPL:</summary>
341
+
342
+ <br />
343
+
321
344
  Defines the license of CKEditor 5. The example below shows how to set the license to GPL:
322
345
 
323
346
  ```rb
@@ -329,9 +352,15 @@ CKEditor5::Rails.configure do
329
352
  gpl
330
353
  end
331
354
  ```
355
+ </details>
332
356
 
333
357
  #### `license_key(key)` method
334
358
 
359
+ <details>
360
+ <summary>Defines the license key of CKEditor 5. It calls `premium` method internally. The example below shows how to set the license key:</summary>
361
+
362
+ <br />
363
+
335
364
  Defines the license key of CKEditor 5. It calls `premium` method internally. The example below shows how to set the license key:
336
365
 
337
366
  ```rb
@@ -343,9 +372,15 @@ CKEditor5::Rails.configure do
343
372
  license_key 'your-license-key'
344
373
  end
345
374
  ```
375
+ </details>
346
376
 
347
377
  #### `premium` method
348
378
 
379
+ <details>
380
+ <summary>Defines if premium package should be included in JS assets. The example below shows how to add `ckeditor5-premium-features` to import maps:</summary>
381
+
382
+ <br />
383
+
349
384
  Defines if premium package should be included in JS assets. The example below shows how to add `ckeditor5-premium-features` to import maps:
350
385
 
351
386
  ```rb
@@ -357,9 +392,15 @@ CKEditor5::Rails.configure do
357
392
  premium
358
393
  end
359
394
  ```
395
+ </details>
360
396
 
361
397
  #### `editable_height(height)` method
362
398
 
399
+ <details>
400
+ <summary>Set editor height in pixels - useful for fixed-size layouts</summary>
401
+
402
+ <br />
403
+
363
404
  Defines the height of the editor. The example below shows how to set the height to `300px`:
364
405
 
365
406
  ```rb
@@ -371,9 +412,50 @@ CKEditor5::Rails.configure do
371
412
  editable_height 300
372
413
  end
373
414
  ```
415
+ </details>
416
+
417
+ #### `language(ui, content:)` method
418
+
419
+ <details>
420
+ <summary>Set UI and content language for the editor</summary>
421
+
422
+ <br />
423
+
424
+ Defines the language of the editor. You can pass the language code as an argument. Keep in mind that the UI and content language can be different. The example below shows how to set the Polish language for the UI and content:
425
+
426
+ ```rb
427
+ # config/initializers/ckeditor5.rb
428
+
429
+ CKEditor5::Rails.configure do
430
+ # ... other configuration
431
+
432
+ language :pl
433
+ end
434
+ ```
435
+
436
+ In order to set the language for the content, you can pass the `content` keyword argument:
437
+
438
+ ```rb
439
+ # config/initializers/ckeditor5.rb
440
+
441
+ CKEditor5::Rails.configure do
442
+ # ... other configuration
443
+
444
+ language :pl
445
+ end
446
+ ```
447
+
448
+ The example above sets the Polish language for the UI and content. If `pl` language was not defined in the translations, the builder will append the language to the list of translations to fetch. In order to prefetch more translations, use the helper below.
449
+
450
+ </details>
374
451
 
375
452
  #### `translations(*languages)` method
376
453
 
454
+ <details>
455
+ <summary>Load additional language files for the editor interface</summary>
456
+
457
+ <br />
458
+
377
459
  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:
378
460
 
379
461
  ```rb
@@ -398,9 +480,15 @@ CKEditor5::Rails.configure do
398
480
  language :pl
399
481
  end
400
482
  ```
483
+ </details>
401
484
 
402
485
  #### `ckbox` method
403
486
 
487
+ <details>
488
+ <summary>Configure CKBox file manager integration</summary>
489
+
490
+ <br />
491
+
404
492
  Defines the CKBox plugin to be included in the editor. The example below shows how to include the CKBox plugin:
405
493
 
406
494
  ```rb
@@ -412,9 +500,15 @@ CKEditor5::Rails.configure do
412
500
  ckbox '2.6.0', theme: :lark
413
501
  end
414
502
  ```
503
+ </details>
415
504
 
416
505
  #### `type(type)` method
417
506
 
507
+ <details>
508
+ <summary>Select editor type (classic, inline, balloon, decoupled, multiroot)</summary>
509
+
510
+ <br />
511
+
418
512
  Defines the type of editor. Available options:
419
513
 
420
514
  - `:classic` - classic edytor
@@ -434,9 +528,15 @@ CKEditor5::Rails.configure do
434
528
  type :multiroot
435
529
  end
436
530
  ```
531
+ </details>
437
532
 
438
533
  #### `toolbar(*items, should_group_when_full: true, &block)` method
439
534
 
535
+ <details>
536
+ <summary>Define toolbar items and their grouping behavior</summary>
537
+
538
+ <br />
539
+
440
540
  Defines the toolbar items. You can use predefined items like `:undo`, `:redo`, `:|` or specify custom items. There are a few special items:
441
541
 
442
542
  - `:_` - breakpoint
@@ -486,9 +586,15 @@ CKEditor5::Rails.configure do
486
586
  end
487
587
  end
488
588
  ```
589
+ </details>
489
590
 
490
591
  #### `menubar(visible: true)` method
491
592
 
593
+ <details>
594
+ <summary>Set the visibility and options for the editor menubar</summary>
595
+
596
+ <br />
597
+
492
598
  Defines the visibility of the menubar. By default, it's set to `true`.
493
599
 
494
600
  ```rb
@@ -502,34 +608,14 @@ CKEditor5::Rails.configure do
502
608
  :bulletedList, :numberedList, :todoList, :outdent, :indent
503
609
  end
504
610
  ```
611
+ </details>
505
612
 
506
- #### `language(ui, content:)` method
507
-
508
- Defines the language of the editor. You can pass the language code as an argument. Keep in mind that the UI and content language can be different. The example below shows how to set the Polish language for the UI and content:
509
-
510
- ```rb
511
- # config/initializers/ckeditor5.rb
512
-
513
- CKEditor5::Rails.configure do
514
- # ... other configuration
515
-
516
- language :pl
517
- end
518
- ```
519
-
520
- In order to set the language for the content, you can pass the `content` keyword argument:
521
-
522
- ```rb
523
- # config/initializers/ckeditor5.rb
524
-
525
- CKEditor5::Rails.configure do
526
- # ... other configuration
613
+ #### `configure(name, value)` method
527
614
 
528
- language :en, content: :pl
529
- end
530
- ```
615
+ <details>
616
+ <summary>Add custom configuration options to the editor instance</summary>
531
617
 
532
- #### `configure(name, value)` method
618
+ <br />
533
619
 
534
620
  Allows you to set custom configuration options. You can pass the name of the option and its value as arguments. The [`ckeditor5_element_ref(selector)` helper](#ckeditor5_element_refselector-method) allows you to reference DOM elements that will be used by the editor's features. It's particularly useful for features that need to check element presence or operate on specific DOM elements.
535
621
 
@@ -557,9 +643,15 @@ CKEditor5::Rails.configure do
557
643
  }
558
644
  end
559
645
  ```
646
+ </details>
560
647
 
561
648
  #### `plugin(name, premium:, import_name:)` method
562
649
 
650
+ <details>
651
+ <summary>Register individual CKEditor plugins with optional premium flag</summary>
652
+
653
+ <br />
654
+
563
655
  Defines a plugin to be included in the editor. You can pass the name of the plugin as an argument. The `premium` keyword argument determines whether the plugin is premium. The `import_name` keyword argument specifies the name of the package to import the plugin from.
564
656
 
565
657
  The example below show how to import Bold plugin from the `ckeditor5` npm package:
@@ -597,11 +689,19 @@ CKEditor5::Rails.configure do
597
689
  plugin :YourPlugin, window_name: 'YourPlugin'
598
690
  end
599
691
  ```
692
+ </details>
600
693
 
601
694
  #### `plugins(*names, **kwargs)` method
602
695
 
696
+ <details>
697
+ <summary>Register multiple CKEditor plugins at once</summary>
698
+
699
+ <br />
700
+
603
701
  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.
604
702
 
703
+ <br />
704
+
605
705
  ```rb
606
706
  # config/initializers/ckeditor5.rb
607
707
 
@@ -625,9 +725,15 @@ CKEditor5::Rails.configure do
625
725
  end
626
726
  end
627
727
  ```
728
+ </details>
628
729
 
629
730
  #### `inline_plugin(name, code)` method
630
731
 
732
+ <details>
733
+ <summary>Define custom CKEditor plugins directly in the configuration</summary>
734
+
735
+ <br />
736
+
631
737
  ⚠️ **Warning:** Use with caution as this is an inline definition of the plugin code, and it can potentially cause XSS vulnerabilities. Only use this method with static, trusted JavaScript code. The example below shows how to define a custom plugin that highlights the text:
632
738
 
633
739
  ```rb
@@ -670,11 +776,19 @@ end
670
776
  ```
671
777
 
672
778
  This approach is resistant to XSS attacks as it avoids inline JavaScript.
779
+ </details>
673
780
 
674
781
  #### `simple_upload_adapter(url)` method
675
782
 
783
+ <details>
784
+ <summary>Configure server-side image upload endpoint</summary>
785
+
786
+ <br />
787
+
676
788
  Defines the URL for the simple upload adapter. The default endpoint is `/uploads` and the method is `POST`. The example below shows how to set the URL to `/uploads`:
677
789
 
790
+ <br />
791
+
678
792
  ```rb
679
793
  # config/initializers/ckeditor5.rb
680
794
 
@@ -685,12 +799,18 @@ CKEditor5::Rails.configure do
685
799
  # or: simple_upload_adapter '/uploads'
686
800
  end
687
801
  ```
802
+ </details>
688
803
 
689
804
  ### Controller / View helpers 📦
690
805
 
691
806
  #### `ckeditor5_element_ref(selector)` method
692
807
 
693
- Defines a reference to a CKEditor 5 element. In other words, it allows you to reference DOM elements that will be used by the editor's features. It's particularly useful for features that need to check element presence or operate on specific DOM elements. The primary example is the `presence list` feature that requires a reference to the element that will be used to display the list.
808
+ <details>
809
+ <summary>Defines a reference to a CKEditor 5 element.</summary>
810
+
811
+ <br />
812
+
813
+ In other words, it allows you to reference DOM elements that will be used by the editor's features. It's particularly useful for features that need to check element presence or operate on specific DOM elements. The primary example is the `presence list` feature that requires a reference to the element that will be used to display the list.
694
814
 
695
815
  ```rb
696
816
  # config/initializers/ckeditor5.rb
@@ -703,10 +823,16 @@ CKEditor5::Rails.configure do
703
823
  }
704
824
  end
705
825
  ```
826
+ </details>
827
+
828
+ #### `ckeditor5_preset(name = nil, &block)` method
829
+
830
+ <details>
831
+ <summary>The `ckeditor5_preset` method allows you to define a custom preset in your application controller.</summary>
706
832
 
707
- #### `ckeditor5_preset(&block)` method
833
+ <br />
708
834
 
709
- The `ckeditor5_preset` method allows you to define a custom preset in your application controller. It may be useful when you want to define a preset based on the current user or request.
835
+ It may be useful when you want to define a preset based on the current user or request.
710
836
 
711
837
  ```rb
712
838
  # app/controllers/application_controller.rb
@@ -740,6 +866,9 @@ In order to use the preset in the view, you can pass it to the `ckeditor5_assets
740
866
 
741
867
  <%= ckeditor5_editor %>
742
868
  ```
869
+ </details>
870
+
871
+ If `name` is provided then the preset is returned.
743
872
 
744
873
  ## Including CKEditor 5 assets 📦
745
874
 
@@ -1018,7 +1147,8 @@ If you want to override the configuration of the editor specified in default or
1018
1147
  <!-- app/views/demos/index.html.erb -->
1019
1148
 
1020
1149
  <% content_for :head do %>
1021
- <%= ckeditor5_assets %>
1150
+ <!-- You can override default preset in assets helper too. -->
1151
+ <%= ckeditor5_assets translations: [:pl] %>
1022
1152
  <% end %>
1023
1153
 
1024
1154
  <%= ckeditor5_editor extra_config: { toolbar: [:Bold, :Italic] }, style: 'width: 600px' %>
@@ -1253,15 +1383,37 @@ This section covers frequent questions and scenarios when working with CKEditor
1253
1383
 
1254
1384
  ### Setting Editor Language 🌐
1255
1385
 
1256
- You can set the language of the editor using the `language` method in the `config/initializers/ckeditor5.rb` file. The `translations` method fetches the translations files, while the `language` method sets the default language of the editor.
1386
+ You can set the language of the editor using the `language` keyword argument. The example below shows how to set the language of the editor to Polish:
1387
+
1388
+ ```erb
1389
+ <!-- app/views/demos/index.html.erb -->
1390
+
1391
+ <% content_for :head do %>
1392
+ <%= ckeditor5_assets language: :pl %>
1393
+ <% end %>
1394
+
1395
+ <%= ckeditor5_editor %>
1396
+ ```
1397
+
1398
+ It can be also set in the initializer:
1257
1399
 
1258
1400
  ```rb
1259
- config.presets.override :default do
1260
- translations :pl, :es
1401
+ # config/initializers/ckeditor5.rb
1402
+
1403
+ CKEditor5::Rails.configure do
1404
+ # Optional, it load multiple translation packs: translations :pl, :es
1261
1405
  language :pl
1262
1406
  end
1263
1407
  ```
1264
1408
 
1409
+ ... or on the editor level (keep in mind to load translations in the assets helper):
1410
+
1411
+ ```erb
1412
+ <!-- app/views/demos/index.html.erb -->
1413
+
1414
+ <%= ckeditor5_editor language: :pl %>
1415
+ ```
1416
+
1265
1417
  ### Integrating with Forms 📋
1266
1418
 
1267
1419
  You can integrate CKEditor 5 with Rails form builders like `form_for` or `simple_form`. The example below shows how to integrate CKEditor 5 with a Rails form using the `form_for` helper:
@@ -13,14 +13,14 @@ require_relative 'ckbox_bundle'
13
13
  module CKEditor5::Rails
14
14
  module Cdn::Helpers
15
15
  def ckeditor5_assets(preset: :default, **kwargs)
16
- merge_with_editor_preset(preset, **kwargs) => {
16
+ mapped_preset = merge_with_editor_preset(preset, **kwargs)
17
+ mapped_preset => {
17
18
  cdn:,
18
19
  version:,
19
20
  translations:,
20
21
  ckbox:,
21
22
  license_key:,
22
- premium:,
23
- **kwargs
23
+ premium:
24
24
  }
25
25
 
26
26
  bundle = build_base_cdn_bundle(cdn, version, translations)
@@ -30,7 +30,7 @@ module CKEditor5::Rails
30
30
  @__ckeditor_context = {
31
31
  license_key: license_key,
32
32
  bundle: bundle,
33
- preset: preset
33
+ preset: mapped_preset
34
34
  }
35
35
 
36
36
  Assets::AssetsBundleHtmlSerializer.new(bundle).to_html
@@ -53,17 +53,17 @@ module CKEditor5::Rails
53
53
  'Please define it in initializer. Thank you!'
54
54
  end
55
55
 
56
- hash = found_preset.to_h_with_overrides(**kwargs)
56
+ new_preset = found_preset.clone.merge_with_hash!(**kwargs)
57
57
 
58
58
  %i[version type].each do |key|
59
- next if hash[key].present?
59
+ next if new_preset.public_send(key).present?
60
60
 
61
61
  raise ArgumentError,
62
62
  "Poor thing. You forgot to define #{key}. Make sure you passed `#{key}:` parameter to " \
63
63
  "`ckeditor5_assets` or defined default one in your `#{preset}` preset!"
64
64
  end
65
65
 
66
- hash
66
+ new_preset
67
67
  end
68
68
 
69
69
  def build_base_cdn_bundle(cdn, version, translations)
@@ -22,12 +22,13 @@ module CKEditor5::Rails
22
22
  # @param initial_data [String] Initial content for the editor
23
23
  # @param watchdog [Boolean] Whether to enable the CKEditor watchdog feature
24
24
  # @param editable_height [String, Integer] Height of the editable area (Classic editor only)
25
+ # @param language [String] Language code for the editor UI
25
26
  # @param html_attributes [Hash] Additional HTML attributes for the editor element
26
27
  def ckeditor5_editor( # rubocop:disable Metrics/ParameterLists
27
28
  preset: nil,
28
29
  config: nil, extra_config: {}, type: nil,
29
30
  initial_data: nil, watchdog: true,
30
- editable_height: nil,
31
+ editable_height: nil, language: nil,
31
32
  **html_attributes, &block
32
33
  )
33
34
  validate_editor_input!(initial_data, block)
@@ -41,7 +42,8 @@ module CKEditor5::Rails
41
42
  editor_props = Editor::Props.new(
42
43
  controller_context, type, config,
43
44
  watchdog: watchdog,
44
- editable_height: editable_height
45
+ editable_height: editable_height,
46
+ language: language
45
47
  )
46
48
 
47
49
  tag_attributes = html_attributes.merge(editor_props.to_attributes)
@@ -13,13 +13,17 @@ module CKEditor5::Rails::Editor
13
13
  multiroot: 'MultiRootEditor'
14
14
  }.freeze
15
15
 
16
- def initialize(controller_context, type, config, watchdog: true, editable_height: nil)
16
+ def initialize(
17
+ controller_context, type, config,
18
+ watchdog: true, editable_height: nil, language: nil
19
+ )
17
20
  raise ArgumentError, "Invalid editor type: #{type}" unless Props.valid_editor_type?(type)
18
21
 
19
22
  @controller_context = controller_context
20
23
  @watchdog = watchdog
21
24
  @type = type
22
25
  @config = config
26
+ @language = language
23
27
  @editable_height = EditableHeightNormalizer.new(type).normalize(editable_height)
24
28
  end
25
29
 
@@ -59,7 +63,10 @@ module CKEditor5::Rails::Editor
59
63
  def serialize_config
60
64
  config
61
65
  .except(:plugins)
62
- .tap { |cfg| cfg[:licenseKey] = controller_context[:license_key] if controller_context[:license_key] }
66
+ .tap do |cfg|
67
+ cfg[:licenseKey] = controller_context[:license_key] if controller_context[:license_key]
68
+ cfg[:language] = { ui: @language } if @language
69
+ end
63
70
  .to_json
64
71
  end
65
72
  end
@@ -49,17 +49,27 @@ module CKEditor5::Rails
49
49
  license_key == 'GPL'
50
50
  end
51
51
 
52
- def to_h_with_overrides(**overrides)
53
- {
54
- version: overrides.fetch(:version, version),
55
- premium: overrides.fetch(:premium, premium),
56
- cdn: overrides.fetch(:cdn, cdn),
57
- translations: overrides.fetch(:translations, translations),
58
- license_key: overrides.fetch(:license_key, license_key),
59
- type: overrides.fetch(:type, type),
60
- ckbox: overrides.fetch(:ckbox, ckbox),
61
- config: config.merge(overrides.fetch(:config, {}))
62
- }
52
+ def deconstruct_keys(keys)
53
+ keys.index_with do |key|
54
+ public_send(key)
55
+ end
56
+ end
57
+
58
+ def merge_with_hash!(language: nil, **overrides) # rubocop:disable Metrics/AbcSize
59
+ @version = Semver.new(overrides[:version]) if overrides.key?(:version)
60
+ @premium = overrides.fetch(:premium, premium)
61
+ @cdn = overrides.fetch(:cdn, cdn)
62
+ @translations = overrides.fetch(:translations, translations)
63
+ @license_key = overrides.fetch(:license_key, license_key)
64
+ @type = overrides.fetch(:type, type)
65
+ @editable_height = overrides.fetch(:editable_height, editable_height)
66
+ @automatic_upgrades = overrides.fetch(:automatic_upgrades, automatic_upgrades)
67
+ @ckbox = overrides.fetch(:ckbox, ckbox) if overrides.key?(:ckbox) || ckbox
68
+ @config = config.merge(overrides.fetch(:config, {}))
69
+
70
+ language(language) if language
71
+
72
+ self
63
73
  end
64
74
 
65
75
  def editable_height(height = nil)
@@ -169,6 +179,8 @@ module CKEditor5::Rails
169
179
  def language(ui = nil, content: ui) # rubocop:disable Naming/MethodParameterName
170
180
  return config[:language] if ui.nil?
171
181
 
182
+ @translations << ui.to_sym unless @translations.map(&:to_sym).include?(ui.to_sym)
183
+
172
184
  config[:language] = {
173
185
  ui: ui,
174
186
  content: content
@@ -2,7 +2,7 @@
2
2
 
3
3
  module CKEditor5
4
4
  module Rails
5
- VERSION = '1.16.2'
5
+ VERSION = '1.17.0'
6
6
 
7
7
  DEFAULT_CKEDITOR_VERSION = '43.3.1'
8
8
  end
@@ -6,19 +6,16 @@ RSpec.describe CKEditor5::Rails::Cdn::Helpers do
6
6
  let(:test_class) { Class.new { include CKEditor5::Rails::Cdn::Helpers } }
7
7
  let(:helper) { test_class.new }
8
8
  let(:preset) do
9
- instance_double(
10
- CKEditor5::Rails::Presets::PresetBuilder,
11
- to_h_with_overrides: {
12
- cdn: :cloud,
13
- version: '34.1.0',
14
- type: 'classic',
15
- translations: %w[pl],
16
- ckbox: nil,
17
- license_key: nil,
18
- premium: false
19
- }
20
- )
9
+ CKEditor5::Rails::Presets::PresetBuilder.new do
10
+ version '34.1.0'
11
+ type :classic
12
+ translations :pl
13
+ cdn :cloud
14
+ license_key nil
15
+ premium false
16
+ end
21
17
  end
18
+
22
19
  let(:bundle_html) { '<script src="test.js"></script>' }
23
20
  let(:serializer) do
24
21
  instance_double(CKEditor5::Rails::Assets::AssetsBundleHtmlSerializer, to_html: bundle_html)
@@ -40,7 +37,7 @@ RSpec.describe CKEditor5::Rails::Cdn::Helpers do
40
37
  .with(
41
38
  instance_of(CKEditor5::Rails::Semver),
42
39
  'ckeditor5',
43
- translations: %w[pl],
40
+ translations: [:pl],
44
41
  cdn: :cloud
45
42
  )
46
43
  .and_call_original
@@ -50,18 +47,13 @@ RSpec.describe CKEditor5::Rails::Cdn::Helpers do
50
47
 
51
48
  context 'with premium features' do
52
49
  let(:preset) do
53
- instance_double(
54
- CKEditor5::Rails::Presets::PresetBuilder,
55
- to_h_with_overrides: {
56
- cdn: :cloud,
57
- version: '34.1.0',
58
- type: 'classic',
59
- translations: %w[pl],
60
- ckbox: nil,
61
- license_key: nil,
62
- premium: true
63
- }
64
- )
50
+ CKEditor5::Rails::Presets::PresetBuilder.new do
51
+ version '34.1.0'
52
+ type :classic
53
+ translations :pl
54
+ cdn :cloud
55
+ premium true
56
+ end
65
57
  end
66
58
 
67
59
  it 'creates base and premium bundles' do
@@ -69,7 +61,7 @@ RSpec.describe CKEditor5::Rails::Cdn::Helpers do
69
61
  .with(
70
62
  instance_of(CKEditor5::Rails::Semver),
71
63
  'ckeditor5',
72
- translations: %w[pl],
64
+ translations: [:pl],
73
65
  cdn: :cloud
74
66
  )
75
67
  .and_call_original
@@ -79,7 +71,7 @@ RSpec.describe CKEditor5::Rails::Cdn::Helpers do
79
71
  .with(
80
72
  instance_of(CKEditor5::Rails::Semver),
81
73
  'ckeditor5-premium-features',
82
- translations: %w[pl],
74
+ translations: [:pl],
83
75
  cdn: :cloud
84
76
  )
85
77
  .and_call_original
@@ -91,18 +83,13 @@ RSpec.describe CKEditor5::Rails::Cdn::Helpers do
91
83
 
92
84
  context 'with ckbox' do
93
85
  let(:preset) do
94
- instance_double(
95
- CKEditor5::Rails::Presets::PresetBuilder,
96
- to_h_with_overrides: {
97
- cdn: :cloud,
98
- version: '34.1.0',
99
- type: 'classic',
100
- translations: %w[pl],
101
- ckbox: { version: '1.0.0', theme: :lark },
102
- license_key: nil,
103
- premium: false
104
- }
105
- )
86
+ CKEditor5::Rails::Presets::PresetBuilder.new do
87
+ version '34.1.0'
88
+ type :classic
89
+ translations :pl
90
+ cdn :cloud
91
+ ckbox '1.0.0', theme: :lark
92
+ end
106
93
  end
107
94
 
108
95
  it 'creates ckbox bundle' do
@@ -117,49 +104,40 @@ RSpec.describe CKEditor5::Rails::Cdn::Helpers do
117
104
  helper.ckeditor5_assets(preset: :default)
118
105
  end
119
106
  end
107
+ end
120
108
 
121
- context 'when destructuring preset hash' do
122
- let(:preset) do
123
- instance_double(
124
- CKEditor5::Rails::Presets::PresetBuilder,
125
- to_h_with_overrides: {
126
- cdn: :cloud,
127
- version: '34.1.0',
128
- type: 'classic',
129
- translations: %w[pl],
130
- ckbox: nil,
131
- license_key: nil,
132
- premium: false,
133
- extra: 'value'
134
- }
135
- )
136
- end
137
-
138
- it 'successfully matches and extracts required parameters' do
139
- expect { helper.ckeditor5_assets(preset: :default) }.not_to raise_error
109
+ context 'when overriding preset values' do
110
+ let(:preset) do
111
+ CKEditor5::Rails::Presets::PresetBuilder.new do
112
+ version '34.1.0'
113
+ type :classic
114
+ translations :pl
115
+ cdn :cloud
116
+ license_key 'preset-license'
117
+ premium false
140
118
  end
141
119
  end
142
- end
143
120
 
144
- context 'with invalid preset' do
145
- before do
146
- allow(CKEditor5::Rails::Engine).to receive(:find_preset).and_return(nil)
121
+ it 'allows overriding preset values' do
122
+ helper.ckeditor5_assets(preset: :default, license_key: 'overridden-license')
123
+
124
+ expect(helper.instance_variable_get(:@__ckeditor_context)[:preset].license_key)
125
+ .to eq('overridden-license')
147
126
  end
148
127
 
149
- it 'raises error' do
150
- expect { helper.ckeditor5_assets(preset: :invalid) }
151
- .to raise_error(ArgumentError, /forgot to define your invalid preset/)
128
+ it 'preserves non-overridden preset values' do
129
+ helper.ckeditor5_assets(preset: :default, license_key: 'overridden-license')
130
+ preset_context = helper.instance_variable_get(:@__ckeditor_context)[:preset]
131
+
132
+ expect(preset_context.version).to eq('34.1.0')
133
+ expect(preset_context.premium?).to be false
134
+ expect(preset_context.cdn).to eq(:cloud)
135
+ expect(preset_context.translations).to eq([:pl])
136
+ expect(preset_context.type).to eq(:classic)
152
137
  end
153
138
  end
154
139
 
155
140
  context 'with missing required parameters' do
156
- let(:preset) do
157
- instance_double(
158
- CKEditor5::Rails::Presets::PresetBuilder,
159
- to_h_with_overrides: { cdn: :cloud }
160
- )
161
- end
162
-
163
141
  before do
164
142
  allow(helper).to receive(:merge_with_editor_preset).and_return({})
165
143
  end
@@ -170,54 +148,24 @@ RSpec.describe CKEditor5::Rails::Cdn::Helpers do
170
148
  end
171
149
  end
172
150
 
173
- context 'with empty hash from preset' do
174
- let(:preset) do
175
- instance_double(
176
- CKEditor5::Rails::Presets::PresetBuilder,
177
- to_h_with_overrides: {}
178
- )
179
- end
180
-
181
- it 'raises error about missing version and type' do
182
- expect { helper.ckeditor5_assets(preset: :default) }
183
- .to raise_error(ArgumentError, /forgot to define version/)
151
+ context 'destructure non-matching preset override' do
152
+ before do
153
+ allow(CKEditor5::Rails::Engine).to receive(:find_preset).and_return(nil)
184
154
  end
185
- end
186
- end
187
155
 
188
- context 'when overriding preset values with kwargs' do
189
- let(:preset) do
190
- CKEditor5::Rails::Presets::PresetBuilder.new do
191
- version '34.1.0'
192
- type :classic
193
- translations :pl
194
- cdn :cloud
195
- license_key 'preset-license'
196
- premium false
156
+ it 'raises error' do
157
+ expect { helper.ckeditor5_assets(preset: :invalid) }
158
+ .to raise_error(ArgumentError, /forgot to define your invalid preset/)
197
159
  end
198
160
  end
199
161
 
200
- before do
201
- allow(CKEditor5::Rails::Engine).to receive(:find_preset).and_return(preset)
202
- end
203
-
204
- it 'allows overriding preset values with kwargs' do
205
- result = helper.send(:merge_with_editor_preset, :default, license_key: 'overridden-license')
206
- expect(result).to include(license_key: 'overridden-license')
207
- end
162
+ context 'with empty preset' do
163
+ let(:preset) { CKEditor5::Rails::Presets::PresetBuilder.new }
208
164
 
209
- it 'preserves non-overridden preset values' do
210
- result = helper.send(:merge_with_editor_preset, :default, license_key: 'overridden-license')
211
- expect(result).to eq(
212
- version: '34.1.0',
213
- premium: false,
214
- cdn: :cloud,
215
- translations: [:pl],
216
- license_key: 'overridden-license',
217
- type: :classic,
218
- ckbox: nil,
219
- config: { plugins: [], toolbar: [] }
220
- )
165
+ it 'raises error about missing version and type' do
166
+ expect { helper.ckeditor5_assets(preset: :default) }
167
+ .to raise_error(ArgumentError, /forgot to define version/)
168
+ end
221
169
  end
222
170
  end
223
171
 
@@ -65,6 +65,19 @@ RSpec.describe CKEditor5::Rails::Editor::Helpers::Editor do
65
65
  end.to raise_error(ArgumentError, /Cannot pass initial data and block/)
66
66
  end
67
67
 
68
+ context 'when language is present' do
69
+ it 'passes language to editor props' do
70
+ result = helper.ckeditor5_editor(language: 'pl')
71
+
72
+ expect(result).to include('config=')
73
+ config_attr = result.match(/config="([^"]+)"/)[1]
74
+ decoded_config = CGI.unescape_html(config_attr)
75
+ parsed_config = JSON.parse(decoded_config)
76
+
77
+ expect(parsed_config['language']).to eq({ 'ui' => 'pl' })
78
+ end
79
+ end
80
+
68
81
  context 'when automatic upgrades are enabled' do
69
82
  before do
70
83
  allow(preset).to receive(:automatic_upgrades?).and_return(true)
@@ -45,6 +45,17 @@ RSpec.describe CKEditor5::Rails::Editor::Props do
45
45
  end
46
46
  end
47
47
 
48
+ context 'with language' do
49
+ subject(:props) { described_class.new(controller_context, type, config, language: 'pl') }
50
+
51
+ it 'includes language in config' do
52
+ config_json = props.to_attributes[:config]
53
+
54
+ expect(config_json).to include('language')
55
+ expect(JSON.parse(config_json)['language']).to eq({ 'ui' => 'pl' })
56
+ end
57
+ end
58
+
48
59
  context 'with license key' do
49
60
  let(:controller_context) do
50
61
  { bundle: double('Bundle', translations_scripts: []), license_key: 'ABC123' }
@@ -266,35 +266,49 @@ RSpec.describe CKEditor5::Rails::Presets::PresetBuilder do
266
266
  end
267
267
  end
268
268
 
269
- describe '#to_h_with_overrides' do
270
- let(:builder) do
271
- described_class.new do
272
- version '35.0.0'
273
- premium true
274
- translations :en, :pl
275
- end
269
+ describe '#merge_with_hash!' do
270
+ it 'merges hash with current configuration' do
271
+ builder.merge_with_hash!(version: '32.0.0', type: :inline)
272
+ expect(builder.version).to eq('32.0.0')
273
+ expect(builder.type).to eq(:inline)
276
274
  end
277
275
 
278
- it 'returns hash with default values' do
279
- result = builder.to_h_with_overrides
280
- expect(result).to include(
281
- version: '35.0.0',
282
- premium: true,
283
- translations: %i[en pl]
284
- )
276
+ it 'returns self' do
277
+ expect(builder.merge_with_hash!(version: '35.0.0')).to eq(builder)
285
278
  end
286
279
 
287
- it 'applies overrides' do
288
- result = builder.to_h_with_overrides(
289
- version: '36.0.0',
290
- premium: false,
291
- translations: [:en]
292
- )
293
- expect(result).to include(
294
- version: '36.0.0',
295
- premium: false,
296
- translations: [:en]
297
- )
280
+ it 'merges language configuration' do
281
+ builder.merge_with_hash!(language: :pl)
282
+ expect(builder.config[:language]).to eq({ ui: :pl, content: :pl })
283
+ end
284
+
285
+ it 'preserves existing values when not overridden' do
286
+ builder.version '34.0.0'
287
+ builder.translations :en, :pl
288
+ builder.premium true
289
+
290
+ builder.merge_with_hash!(type: :inline)
291
+
292
+ expect(builder.version).to eq('34.0.0')
293
+ expect(builder.translations).to eq(%i[en pl])
294
+ expect(builder.premium?).to be true
295
+ end
296
+
297
+ it 'merges ckbox configuration' do
298
+ builder.merge_with_hash!(ckbox: { version: '1.0.0', theme: :lark })
299
+ expect(builder.ckbox).to eq({ version: '1.0.0', theme: :lark })
300
+ end
301
+
302
+ it 'merges config options deeply' do
303
+ original_config = { plugins: [:Essentials], toolbar: { items: [:bold] } }
304
+ new_config = { menuBar: { isVisible: true } }
305
+
306
+ builder.merge_with_hash!(config: original_config)
307
+ builder.merge_with_hash!(config: new_config)
308
+
309
+ expect(builder.config[:plugins]).to eq([:Essentials])
310
+ expect(builder.config[:toolbar]).to eq({ items: [:bold] })
311
+ expect(builder.config[:menuBar]).to eq({ isVisible: true })
298
312
  end
299
313
  end
300
314
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ckeditor5
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.16.2
4
+ version: 1.17.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mateusz Bagiński
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2024-11-23 00:00:00.000000000 Z
12
+ date: 2024-11-26 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails