ckeditor5 1.21.0 → 1.23.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -0
- data/README.md +33 -0
- data/lib/ckeditor5/rails/assets/webcomponent_bundle.rb +14 -3
- data/lib/ckeditor5/rails/presets/toolbar_builder.rb +117 -3
- data/lib/ckeditor5/rails/version.rb +1 -1
- data/spec/lib/ckeditor5/rails/presets/toolbar_builder_spec.rb +119 -0
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a6209f7ab70666ad0c3e5c368f47832871d740429238bb62199c5956ca73fe77
|
4
|
+
data.tar.gz: 3e3af0099b5150b6c2df7bb578a11cd63b81f88cb9ded596806e5ea980ebf90a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1d7f113a286468066aa941cba9d735c5312d8558ed83a1d3f9fa7e4a2959d7c58a843f6b0bf8fd4e296b0ab34dedc303f0a6533c5adf6af1c60a1a77dbe4c5e9
|
7
|
+
data.tar.gz: c4304b80a54b9bf94629b9aa8c27d640e2ff0783e3d78d2a577400d3cd29df337aa1a8b40fc7bc8f050bc3ee3c528becfa0a12b68158fdb980df5ea2b897b6f8
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -610,6 +610,39 @@ CKEditor5::Rails.configure do
|
|
610
610
|
end
|
611
611
|
end
|
612
612
|
```
|
613
|
+
|
614
|
+
If you want to append groups of items, you can use the `group` method:
|
615
|
+
|
616
|
+
```rb
|
617
|
+
# config/initializers/ckeditor5.rb
|
618
|
+
|
619
|
+
CKEditor5::Rails.configure do
|
620
|
+
# ... other configuration
|
621
|
+
|
622
|
+
toolbar do
|
623
|
+
group :text_formatting, label: 'Text Formatting', icon: 'threeVerticalDots' do
|
624
|
+
append :bold, :italic, :underline, :strikethrough, separator,
|
625
|
+
:subscript, :superscript, :removeFormat
|
626
|
+
end
|
627
|
+
end
|
628
|
+
end
|
629
|
+
```
|
630
|
+
|
631
|
+
If you want add new line or the separator, you can use the `break_line` or `separator` methods:
|
632
|
+
|
633
|
+
```rb
|
634
|
+
# config/initializers/ckeditor5.rb
|
635
|
+
|
636
|
+
CKEditor5::Rails.configure do
|
637
|
+
# ... other configuration
|
638
|
+
|
639
|
+
toolbar do
|
640
|
+
append :bold, break_line
|
641
|
+
append separator, :italic
|
642
|
+
end
|
643
|
+
end
|
644
|
+
```
|
645
|
+
|
613
646
|
</details>
|
614
647
|
|
615
648
|
#### `menubar(visible: true)` method
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'singleton'
|
4
|
+
require 'terser'
|
4
5
|
|
5
6
|
module CKEditor5::Rails::Assets
|
6
7
|
class WebComponentBundle
|
@@ -17,13 +18,23 @@ module CKEditor5::Rails::Assets
|
|
17
18
|
].freeze
|
18
19
|
|
19
20
|
def source
|
20
|
-
@source ||=
|
21
|
-
File.read(File.join(WEBCOMPONENTS_PATH, file))
|
22
|
-
end.join("\n").html_safe
|
21
|
+
@source ||= compress_source(raw_source)
|
23
22
|
end
|
24
23
|
|
25
24
|
def to_html
|
26
25
|
@to_html ||= tag.script(source, type: 'module', nonce: true)
|
27
26
|
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def raw_source
|
31
|
+
@raw_source ||= WEBCOMPONENTS_MODULES.map do |file|
|
32
|
+
File.read(File.join(WEBCOMPONENTS_PATH, file))
|
33
|
+
end.join("\n")
|
34
|
+
end
|
35
|
+
|
36
|
+
def compress_source(code)
|
37
|
+
Terser.new(compress: true, mangle: true).compile(code).html_safe
|
38
|
+
end
|
28
39
|
end
|
29
40
|
end
|
@@ -1,13 +1,46 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module CKEditor5::Rails::Presets
|
4
|
+
# Builder class for configuring CKEditor5 toolbar items.
|
5
|
+
#
|
6
|
+
# @example Basic toolbar configuration
|
7
|
+
# toolbar = ToolbarBuilder.new([:bold, :italic])
|
8
|
+
# toolbar.append(:link)
|
9
|
+
# toolbar.prepend(:heading)
|
4
10
|
class ToolbarBuilder
|
5
11
|
attr_reader :items
|
6
12
|
|
13
|
+
# Initialize a new toolbar builder with given items.
|
14
|
+
#
|
15
|
+
# @param items [Array<Symbol>] Initial toolbar items
|
16
|
+
# @example Create new toolbar
|
17
|
+
# ToolbarBuilder.new([:bold, :italic, :|, :link])
|
7
18
|
def initialize(items)
|
8
19
|
@items = items
|
9
20
|
end
|
10
21
|
|
22
|
+
# Returns toolbar line break symbol
|
23
|
+
#
|
24
|
+
# @return [Symbol] Line break symbol (-)
|
25
|
+
# @example Add line break to toolbar
|
26
|
+
# toolbar do
|
27
|
+
# append :bold, break_line, :italic
|
28
|
+
# end
|
29
|
+
def break_line
|
30
|
+
:-
|
31
|
+
end
|
32
|
+
|
33
|
+
# Returns toolbar separator symbol
|
34
|
+
#
|
35
|
+
# @return [Symbol] Separator symbol (|)
|
36
|
+
# @example Add separator to toolbar
|
37
|
+
# toolbar do
|
38
|
+
# append :bold, separator, :italic
|
39
|
+
# end
|
40
|
+
def separator
|
41
|
+
:|
|
42
|
+
end
|
43
|
+
|
11
44
|
# Remove items from the editor toolbar.
|
12
45
|
#
|
13
46
|
# @param removed_items [Array<Symbol>] Toolbar items to be removed
|
@@ -16,7 +49,9 @@ module CKEditor5::Rails::Presets
|
|
16
49
|
# remove :underline, :heading
|
17
50
|
# end
|
18
51
|
def remove(*removed_items)
|
19
|
-
|
52
|
+
items.delete_if do |existing_item|
|
53
|
+
removed_items.any? { |item_to_remove| item_matches?(existing_item, item_to_remove) }
|
54
|
+
end
|
20
55
|
end
|
21
56
|
|
22
57
|
# Prepend items to the editor toolbar.
|
@@ -34,7 +69,7 @@ module CKEditor5::Rails::Presets
|
|
34
69
|
# @raise [ArgumentError] When the specified 'before' item is not found
|
35
70
|
def prepend(*prepended_items, before: nil)
|
36
71
|
if before
|
37
|
-
index =
|
72
|
+
index = find_item_index(before)
|
38
73
|
raise ArgumentError, "Item '#{before}' not found in array" unless index
|
39
74
|
|
40
75
|
items.insert(index, *prepended_items)
|
@@ -58,7 +93,7 @@ module CKEditor5::Rails::Presets
|
|
58
93
|
# @raise [ArgumentError] When the specified 'after' item is not found
|
59
94
|
def append(*appended_items, after: nil)
|
60
95
|
if after
|
61
|
-
index =
|
96
|
+
index = find_item_index(after)
|
62
97
|
raise ArgumentError, "Item '#{after}' not found in array" unless index
|
63
98
|
|
64
99
|
items.insert(index + 1, *appended_items)
|
@@ -66,5 +101,84 @@ module CKEditor5::Rails::Presets
|
|
66
101
|
items.push(*appended_items)
|
67
102
|
end
|
68
103
|
end
|
104
|
+
|
105
|
+
# Find group by name in toolbar items
|
106
|
+
#
|
107
|
+
# @param name [Symbol] Group name to find
|
108
|
+
# @return [ToolbarGroupItem, nil] Found group or nil
|
109
|
+
def find_group(name)
|
110
|
+
items.find { |item| item.is_a?(ToolbarGroupItem) && item.name == name }
|
111
|
+
end
|
112
|
+
|
113
|
+
# Remove group by name from toolbar items
|
114
|
+
#
|
115
|
+
# @param name [Symbol] Group name to remove
|
116
|
+
def remove_group(name)
|
117
|
+
items.delete_if { |item| item.is_a?(ToolbarGroupItem) && item.name == name }
|
118
|
+
end
|
119
|
+
|
120
|
+
# Create and add new group to toolbar
|
121
|
+
#
|
122
|
+
# @param name [Symbol] Group name
|
123
|
+
# @param options [Hash] Group options (label:, icons:)
|
124
|
+
# @param block [Proc] Configuration block
|
125
|
+
# @return [ToolbarGroupItem] Created group
|
126
|
+
def group(name, **options, &block)
|
127
|
+
group = ToolbarGroupItem.new(name, [], **options)
|
128
|
+
group.instance_eval(&block) if block_given?
|
129
|
+
items << group
|
130
|
+
group
|
131
|
+
end
|
132
|
+
|
133
|
+
private
|
134
|
+
|
135
|
+
# Find index of an item or group by name
|
136
|
+
#
|
137
|
+
# @param item [Symbol] Item or group name to find
|
138
|
+
# @return [Integer, nil] Index of the found item or nil
|
139
|
+
def find_item_index(item)
|
140
|
+
items.find_index { |existing_item| item_matches?(existing_item, item) }
|
141
|
+
end
|
142
|
+
|
143
|
+
# Checks if the existing item matches the given item or group name
|
144
|
+
#
|
145
|
+
# @param existing_item [Symbol, ToolbarGroupItem] Item to check
|
146
|
+
# @param item [Symbol] Item or group name to match against
|
147
|
+
# @return [Boolean] true if items match, false otherwise
|
148
|
+
# @example Check if items match
|
149
|
+
# item_matches?(:bold, :bold) # => true
|
150
|
+
# item_matches?(group(:text), :text) # => true
|
151
|
+
def item_matches?(existing_item, item)
|
152
|
+
if existing_item.is_a?(ToolbarGroupItem)
|
153
|
+
existing_item.name == item
|
154
|
+
else
|
155
|
+
existing_item == item
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
# Builder class for configuring CKEditor5 toolbar groups.
|
161
|
+
# Allows creating named groups of toolbar items with optional labels and icons.
|
162
|
+
#
|
163
|
+
# @example Creating a text formatting group
|
164
|
+
# group = ToolbarGroupItem.new(:text_formatting, [:bold, :italic], label: 'Text')
|
165
|
+
# group.append(:underline)
|
166
|
+
class ToolbarGroupItem < ToolbarBuilder
|
167
|
+
attr_reader :name, :label, :icon
|
168
|
+
|
169
|
+
# Initialize a new toolbar group item.
|
170
|
+
#
|
171
|
+
# @param name [Symbol] Name of the toolbar group
|
172
|
+
# @param items [Array<Symbol>, ToolbarBuilder] Items to be included in the group
|
173
|
+
# @param label [String, nil] Optional label for the group
|
174
|
+
# @param icon [String, nil] Optional icon for the group
|
175
|
+
# @example Create a new toolbar group
|
176
|
+
# ToolbarGroupItem.new(:text, [:bold, :italic], label: 'Text formatting')
|
177
|
+
def initialize(name, items = [], label: nil, icon: nil)
|
178
|
+
super(items)
|
179
|
+
@name = name
|
180
|
+
@label = label
|
181
|
+
@icon = icon
|
182
|
+
end
|
69
183
|
end
|
70
184
|
end
|
@@ -67,4 +67,123 @@ RSpec.describe CKEditor5::Rails::Presets::ToolbarBuilder do
|
|
67
67
|
end
|
68
68
|
end
|
69
69
|
end
|
70
|
+
|
71
|
+
describe '#break_line' do
|
72
|
+
it 'returns line break symbol' do
|
73
|
+
expect(builder.break_line).to eq(:-)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe '#separator' do
|
78
|
+
it 'returns separator symbol' do
|
79
|
+
expect(builder.separator).to eq(:|)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe '#group' do
|
84
|
+
it 'creates and adds a new group' do
|
85
|
+
builder.group(:text, label: 'Text') do
|
86
|
+
append(:bold, :italic)
|
87
|
+
end
|
88
|
+
|
89
|
+
group = builder.items.last
|
90
|
+
expect(group).to be_a(CKEditor5::Rails::Presets::ToolbarGroupItem)
|
91
|
+
expect(group.name).to eq(:text)
|
92
|
+
expect(group.items).to eq(%i[bold italic])
|
93
|
+
expect(group.label).to eq('Text')
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'creates group without configuration block' do
|
97
|
+
group = builder.group(:text, label: 'Text')
|
98
|
+
|
99
|
+
expect(group).to be_a(CKEditor5::Rails::Presets::ToolbarGroupItem)
|
100
|
+
expect(group.items).to be_empty
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe '#find_group' do
|
105
|
+
it 'returns group by name' do
|
106
|
+
builder.group(:text, label: 'Text')
|
107
|
+
builder.group(:formatting, label: 'Format')
|
108
|
+
|
109
|
+
group = builder.find_group(:formatting)
|
110
|
+
expect(group).to be_a(CKEditor5::Rails::Presets::ToolbarGroupItem)
|
111
|
+
expect(group.name).to eq(:formatting)
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'returns nil when group not found' do
|
115
|
+
expect(builder.find_group(:nonexistent)).to be_nil
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
describe '#remove_group' do
|
120
|
+
it 'removes group by name' do
|
121
|
+
builder.group(:text, label: 'Text')
|
122
|
+
builder.group(:formatting, label: 'Format')
|
123
|
+
|
124
|
+
builder.remove_group(:text)
|
125
|
+
expect(builder.find_group(:text)).to be_nil
|
126
|
+
expect(builder.find_group(:formatting)).to be_present
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'ignores non-existent groups' do
|
130
|
+
builder.group(:text, label: 'Text')
|
131
|
+
|
132
|
+
expect { builder.remove_group(:nonexistent) }.not_to(change { builder.items.count })
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
describe 'interacting with groups' do
|
137
|
+
let(:text_group) do
|
138
|
+
builder.group(:text, label: 'Text') do
|
139
|
+
append(:bold, :italic)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
before do
|
144
|
+
text_group
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'prepends items before group' do
|
148
|
+
builder.prepend(:undo, :redo, before: :text)
|
149
|
+
expect(builder.items.map { |i| i.is_a?(CKEditor5::Rails::Presets::ToolbarGroupItem) ? i.name : i })
|
150
|
+
.to eq(%i[bold italic | link undo redo text])
|
151
|
+
end
|
152
|
+
|
153
|
+
it 'appends items after group' do
|
154
|
+
builder.append(:undo, :redo, after: :text)
|
155
|
+
expect(builder.items.map { |i| i.is_a?(CKEditor5::Rails::Presets::ToolbarGroupItem) ? i.name : i })
|
156
|
+
.to eq(%i[bold italic | link text undo redo])
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'removes group using remove method' do
|
160
|
+
builder.remove(:text)
|
161
|
+
expect(builder.items).to eq(%i[bold italic | link])
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
RSpec.describe CKEditor5::Rails::Presets::ToolbarGroupItem do
|
167
|
+
let(:items) { %i[bold italic] }
|
168
|
+
let(:group) { described_class.new(:formatting, items, label: 'Format', icon: 'format') }
|
169
|
+
|
170
|
+
describe '#initialize' do
|
171
|
+
it 'creates a group with given parameters' do
|
172
|
+
expect(group.name).to eq(:formatting)
|
173
|
+
expect(group.items).to eq(items)
|
174
|
+
expect(group.label).to eq('Format')
|
175
|
+
expect(group.icon).to eq('format')
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
it 'inherits toolbar manipulation methods' do
|
180
|
+
group.append(:underline)
|
181
|
+
expect(group.items).to eq(%i[bold italic underline])
|
182
|
+
|
183
|
+
group.prepend(:heading)
|
184
|
+
expect(group.items).to eq(%i[heading bold italic underline])
|
185
|
+
|
186
|
+
group.remove(:italic)
|
187
|
+
expect(group.items).to eq(%i[heading bold underline])
|
188
|
+
end
|
70
189
|
end
|
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.
|
4
|
+
version: 1.23.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-12-
|
12
|
+
date: 2024-12-04 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
@@ -31,6 +31,20 @@ dependencies:
|
|
31
31
|
- - "<"
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '9.0'
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: terser
|
36
|
+
requirement: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.0'
|
41
|
+
type: :runtime
|
42
|
+
prerelease: false
|
43
|
+
version_requirements: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.0'
|
34
48
|
description:
|
35
49
|
email: cziken58@gmail.com
|
36
50
|
executables: []
|