ckeditor5 0.0.1 → 1.0.1

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.
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'url_generator'
4
+ require_relative 'ckeditor_bundle'
5
+ require_relative 'ckbox_bundle'
6
+
7
+ module CKEditor5::Rails
8
+ module Cdn::Helpers
9
+ def ckeditor5_cdn_assets(version:, cdn:, license_key: 'GPL', premium: false, translations: [], ckbox: nil)
10
+ bundle = build_base_cdn_bundle(cdn, version, translations)
11
+ bundle << build_premium_cdn_bundle(cdn, version, translations) if premium
12
+ bundle << build_ckbox_cdn_bundle(ckbox) if ckbox
13
+
14
+ @__ckeditor_context = {
15
+ license_key: license_key,
16
+ bundle: bundle
17
+ }
18
+
19
+ Assets::AssetsBundleHtmlSerializer.new(bundle).to_html
20
+ end
21
+
22
+ Cdn::UrlGenerator::CDN_THIRD_PARTY_GENERATORS.each_key do |key|
23
+ define_method(:"ckeditor5_#{key.to_s.parameterize}_assets") do |**kwargs|
24
+ ckeditor5_cdn_assets(**kwargs.merge(cdn: key))
25
+ end
26
+ end
27
+
28
+ def ckeditor5_assets(**kwargs)
29
+ if kwargs[:license_key] && kwargs[:license_key] != 'GPL'
30
+ ckeditor5_cloud_assets(**kwargs)
31
+ else
32
+ ckeditor5_cdn_assets(**kwargs.merge(cdn: Engine.base.default_cdn))
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ def build_base_cdn_bundle(cdn, version, translations)
39
+ Cdn::CKEditorBundle.new(
40
+ Semver.new(version),
41
+ 'ckeditor5',
42
+ translations: translations,
43
+ cdn: cdn
44
+ )
45
+ end
46
+
47
+ def build_premium_cdn_bundle(cdn, version, translations)
48
+ Cdn::CKEditorBundle.new(
49
+ Semver.new(version),
50
+ 'ckeditor5-premium-features',
51
+ translations: translations,
52
+ cdn: cdn
53
+ )
54
+ end
55
+
56
+ def build_ckbox_cdn_bundle(ckbox)
57
+ Cdn::CKBoxBundle.new(
58
+ Semver.new(ckbox[:version]),
59
+ theme: ckbox[:theme] || :lark,
60
+ cdn: ckbox[:cdn] || :ckbox
61
+ )
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support'
4
+
5
+ module CKEditor5::Rails::Cdn
6
+ module UrlGenerator
7
+ extend ActiveSupport::Concern
8
+
9
+ CDN_THIRD_PARTY_GENERATORS = {
10
+ jsdelivr: lambda { |bundle, version, path|
11
+ base_url = "https://cdn.jsdelivr.net/npm/#{bundle}@#{version}/dist"
12
+ "#{base_url}/#{path.start_with?('translations/') ? '' : 'browser/'}#{path}"
13
+ },
14
+
15
+ unpkg: lambda { |bundle, version, path|
16
+ base_url = "https://unpkg.com/#{bundle}@#{version}/dist"
17
+ "#{base_url}/#{path.start_with?('translations/') ? '' : 'browser/'}#{path}"
18
+ }
19
+ }.freeze
20
+
21
+ CDN_COMMERCIAL_GENERATORS = {
22
+ cloud: ->(bundle, version, path) { "https://cdn.ckeditor.com/#{bundle}/#{version}/#{path}" },
23
+ ckbox: ->(bundle, version, path) { "https://cdn.ckbox.io/#{bundle}/#{version}/#{path}" }
24
+ }.freeze
25
+
26
+ included do
27
+ attr_reader :cdn
28
+ end
29
+
30
+ def create_cdn_url(bundle, version, path)
31
+ generator = CDN_THIRD_PARTY_GENERATORS[cdn] || CDN_COMMERCIAL_GENERATORS[cdn]
32
+
33
+ raise ArgumentError, "Unknown provider: #{cdn}" unless generator
34
+
35
+ generator.call(bundle, version, path)
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CKEditor5::Rails
4
+ module Cloud
5
+ module Helpers
6
+ def ckeditor5_cloud_assets(license_key:, **kwargs)
7
+ raise 'Cloud assets are not permitted in GPL license!' if license_key == 'GPL'
8
+
9
+ ckeditor5_cdn_assets(cdn: :cloud, license_key: license_key, **kwargs)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'props_plugin'
4
+ require_relative 'props'
5
+
6
+ module CKEditor5::Rails
7
+ module Editor::Helpers
8
+ class EditorContextError < StandardError; end
9
+ class PresetNotFoundError < ArgumentError; end
10
+
11
+ def ckeditor5_editor(
12
+ config: nil, extra_config: {},
13
+ type: nil, preset: :default,
14
+ **html_attributes, &block
15
+ )
16
+ context = validate_and_get_editor_context!
17
+ preset = fetch_editor_preset(preset)
18
+
19
+ config ||= preset.config
20
+ type ||= preset.type
21
+
22
+ editor_props = build_editor_props(
23
+ config: config.deep_merge(extra_config),
24
+ type: type,
25
+ context: context
26
+ )
27
+
28
+ render_editor_component(editor_props, html_attributes, &(type == :multiroot ? block : nil))
29
+ end
30
+
31
+ def ckeditor5_editable(name, **kwargs, &block)
32
+ tag.send(:'ckeditor-editable-component', name: name, **kwargs, &block)
33
+ end
34
+
35
+ def ckeditor5_toolbar(**kwargs)
36
+ tag.send(:'ckeditor-toolbar-component', **kwargs)
37
+ end
38
+
39
+ private
40
+
41
+ def validate_and_get_editor_context!
42
+ unless defined?(@__ckeditor_context)
43
+ raise EditorContextError,
44
+ 'CKEditor installation context is not defined. ' \
45
+ 'Ensure ckeditor5_assets is called in the head section.'
46
+ end
47
+
48
+ @__ckeditor_context
49
+ end
50
+
51
+ def fetch_editor_preset(preset)
52
+ Engine.base.presets[preset] or
53
+ raise PresetNotFoundError, "Preset #{preset} is not defined."
54
+ end
55
+
56
+ def build_editor_props(config:, type:, context:)
57
+ Editor::Props.new(context, type, config)
58
+ end
59
+
60
+ def render_editor_component(props, html_attributes, &block)
61
+ tag.send(:'ckeditor-component', **props.to_attributes, **html_attributes, &block)
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'props_plugin'
4
+
5
+ module CKEditor5::Rails::Editor
6
+ class Props
7
+ EDITOR_TYPES = {
8
+ classic: 'ClassicEditor',
9
+ inline: 'InlineEditor',
10
+ balloon: 'BalloonEditor',
11
+ decoupled: 'DecoupledEditor',
12
+ multiroot: 'MultiRootEditor'
13
+ }.freeze
14
+
15
+ def initialize(context, type, config)
16
+ raise ArgumentError, "Invalid editor type: #{type}" unless Props.valid_editor_type?(type)
17
+
18
+ @context = context
19
+ @type = type
20
+ @config = config
21
+ end
22
+
23
+ def to_attributes
24
+ {
25
+ type: EDITOR_TYPES[@type],
26
+ **serialized_attributes
27
+ }
28
+ end
29
+
30
+ def self.valid_editor_type?(type)
31
+ EDITOR_TYPES.key?(type)
32
+ end
33
+
34
+ private
35
+
36
+ attr_reader :context, :type, :config
37
+
38
+ def serialized_attributes
39
+ {
40
+ translations: serialize_translations,
41
+ plugins: serialize_plugins,
42
+ config: serialize_config
43
+ }
44
+ end
45
+
46
+ def serialize_translations
47
+ context[:bundle].translations_scripts.map { |script| script.import_meta.to_h }.to_json
48
+ end
49
+
50
+ def serialize_plugins
51
+ (config[:plugins] || []).map { |plugin| PropsPlugin.normalize(plugin).to_h }.to_json
52
+ end
53
+
54
+ def serialize_config
55
+ config
56
+ .except(:plugins)
57
+ .merge(licenseKey: context[:license_key] || 'GPL')
58
+ .to_json
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CKEditor5::Rails::Editor
4
+ class PropsPlugin
5
+ delegate :to_h, to: :import_meta
6
+
7
+ def initialize(name, premium: false)
8
+ @name = name
9
+ @premium = premium
10
+ end
11
+
12
+ def self.normalize(plugin)
13
+ case plugin
14
+ when String, Symbol then new(plugin)
15
+ when PropsPlugin then plugin
16
+ else raise ArgumentError, "Invalid plugin: #{plugin}"
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ attr_reader :name, :premium
23
+
24
+ def import_meta
25
+ ::CKEditor5::Rails::Assets::JSImportMeta.new(
26
+ import_as: name,
27
+ import_name: premium ? 'ckeditor5-premium-features' : 'ckeditor5'
28
+ )
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/engine'
4
+ require_relative 'presets'
5
+
6
+ module CKEditor5::Rails
7
+ class Engine < ::Rails::Engine
8
+ config.ckeditor5 = ActiveSupport::OrderedOptions.new
9
+
10
+ # Specifies which CDN should be used to load CKEditor 5 using the ckeditor5_assets helper.
11
+ # It is possible to use the following CDNs:
12
+ # - :unpkg
13
+ # - :jsdelivr (default)
14
+ config.ckeditor5.default_cdn = :jsdelivr
15
+
16
+ # Specifies configuration of editors generated by gem.
17
+ config.ckeditor5.presets = PresetsManager.new
18
+
19
+ initializer 'helper' do
20
+ ActiveSupport.on_load(:action_view) do
21
+ include Helpers
22
+ end
23
+ end
24
+
25
+ def self.base
26
+ config.ckeditor5
27
+ end
28
+
29
+ def self.configure
30
+ yield config.ckeditor5
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'cdn/helpers'
4
+ require_relative 'cloud/helpers'
5
+ require_relative 'editor/helpers'
6
+
7
+ module CKEditor5::Rails
8
+ module Helpers
9
+ include Cdn::Helpers
10
+ include Cloud::Helpers
11
+ include Editor::Helpers
12
+ end
13
+ end
@@ -0,0 +1,99 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CKEditor5::Rails
4
+ class PresetsManager
5
+ attr_reader :presets
6
+
7
+ def initialize
8
+ @presets = {}
9
+ define_default_preset
10
+ end
11
+
12
+ def define(name, &block)
13
+ preset = PresetBuilder.new
14
+ preset.instance_eval(&block)
15
+ @presets[name] = preset
16
+ end
17
+
18
+ def override(name, &block)
19
+ @presets[name].instance_eval(&block)
20
+ end
21
+
22
+ def default
23
+ @presets[:default] || {}
24
+ end
25
+
26
+ def [](name)
27
+ @presets[name] || {}
28
+ end
29
+
30
+ private
31
+
32
+ def define_default_preset
33
+ define :default do
34
+ shape :classic
35
+
36
+ menubar
37
+
38
+ toolbar :undo, :redo, :|, :heading, :|, :bold, :italic, :underline, :|,
39
+ :link, :insertImage, :ckbox, :mediaEmbed, :insertTable, :blockQuote, :|,
40
+ :bulletedList, :numberedList, :todoList, :outdent, :indent
41
+
42
+ plugins :AccessibilityHelp, :Autoformat, :AutoImage, :Autosave,
43
+ :BlockQuote, :Bold, :CKBox, :CKBoxImageEdit, :CloudServices,
44
+ :Essentials, :Heading, :ImageBlock, :ImageCaption, :ImageInline,
45
+ :ImageInsert, :ImageInsertViaUrl, :ImageResize, :ImageStyle,
46
+ :ImageTextAlternative, :ImageToolbar, :ImageUpload, :Indent,
47
+ :IndentBlock, :Italic, :Link, :LinkImage, :List, :ListProperties,
48
+ :MediaEmbed, :Paragraph, :PasteFromOffice, :PictureEditing,
49
+ :SelectAll, :Table, :TableCaption, :TableCellProperties,
50
+ :TableColumnResize, :TableProperties, :TableToolbar,
51
+ :TextTransformation, :TodoList, :Underline, :Undo, :Base64UploadAdapter
52
+ end
53
+ end
54
+ end
55
+
56
+ class PresetBuilder
57
+ attr_reader :type, :config
58
+
59
+ def initialize
60
+ @type = :classic
61
+ @config = {
62
+ plugins: [],
63
+ toolbar: []
64
+ }
65
+ end
66
+
67
+ def shape(type)
68
+ raise ArgumentError, "Invalid editor type: #{type}" unless Editor::Props.valid_editor_type?(type)
69
+
70
+ @type = type
71
+ end
72
+
73
+ def configure(key, value)
74
+ @config[key] = value
75
+ end
76
+
77
+ def menubar(visible: true)
78
+ @config[:menuBar] = {
79
+ isVisible: visible
80
+ }
81
+ end
82
+
83
+ def toolbar(*items)
84
+ @config[:toolbar] = items
85
+ end
86
+
87
+ def plugin(name, premium: false)
88
+ @config[:plugins] << Editor::PropsPlugin.new(name, premium: premium)
89
+ end
90
+
91
+ def plugins(*names, premium: false)
92
+ names.each { |name| plugin(name, premium: premium) }
93
+ end
94
+
95
+ def language(lang)
96
+ @config[:language] = lang
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CKEditor5::Rails::Semver
4
+ attr_reader :version
5
+
6
+ alias to_s :version
7
+
8
+ def initialize(version)
9
+ @version = version
10
+ validate!
11
+ end
12
+
13
+ private
14
+
15
+ def validate!
16
+ raise ArgumentError, 'version must be a string' unless version.is_a?(String)
17
+ raise ArgumentError, 'invalid version format' unless version.match?(/\A\d+\.\d+\.\d+\z/)
18
+ end
19
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CKEditor5::Rails
4
+ VERSION = '1.0.1'
5
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CKEditor5
4
+ module Rails
5
+ require_relative 'rails/version'
6
+ require_relative 'rails/semver'
7
+ require_relative 'rails/assets/assets_bundle'
8
+ require_relative 'rails/assets/assets_bundle_html_serializer'
9
+ require_relative 'rails/helpers'
10
+ require_relative 'rails/engine'
11
+ end
12
+ end
@@ -1,3 +1,3 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'ckeditor5/version'
3
+ require 'ckeditor5/rails'
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: 0.0.1
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mateusz Bagiński
@@ -9,23 +9,50 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2024-10-09 00:00:00.000000000 Z
13
- dependencies: []
12
+ date: 2024-10-31 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rails
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: '6.0'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: '6.0'
14
28
  description:
15
29
  email: cziken58@gmail.com
16
30
  executables: []
17
31
  extensions: []
18
- extra_rdoc_files: []
32
+ extra_rdoc_files:
33
+ - README.md
19
34
  files:
20
- - ".github/workflows/ruby.yml"
21
- - ".gitignore"
22
35
  - Gemfile
23
36
  - LICENSE
24
37
  - README.md
25
- - Rakefile
26
- - ckeditor5.gemspec
27
- - lib/ckeditor5.rb
28
- - lib/ckeditor5/version.rb
38
+ - lib/ckeditor5/rails.rb
39
+ - lib/ckeditor5/rails/assets/assets_bundle.rb
40
+ - lib/ckeditor5/rails/assets/assets_bundle_html_serializer.rb
41
+ - lib/ckeditor5/rails/assets/webcomponent.mjs
42
+ - lib/ckeditor5/rails/cdn/ckbox_bundle.rb
43
+ - lib/ckeditor5/rails/cdn/ckeditor_bundle.rb
44
+ - lib/ckeditor5/rails/cdn/helpers.rb
45
+ - lib/ckeditor5/rails/cdn/url_generator.rb
46
+ - lib/ckeditor5/rails/cloud/helpers.rb
47
+ - lib/ckeditor5/rails/editor/helpers.rb
48
+ - lib/ckeditor5/rails/editor/props.rb
49
+ - lib/ckeditor5/rails/editor/props_plugin.rb
50
+ - lib/ckeditor5/rails/engine.rb
51
+ - lib/ckeditor5/rails/helpers.rb
52
+ - lib/ckeditor5/rails/presets.rb
53
+ - lib/ckeditor5/rails/semver.rb
54
+ - lib/ckeditor5/rails/version.rb
55
+ - lib/ckeditor5_rails.rb
29
56
  homepage: https://github.com/Mati365/ckeditor5-rails
30
57
  licenses:
31
58
  - MIT
@@ -38,14 +65,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
38
65
  requirements:
39
66
  - - ">="
40
67
  - !ruby/object:Gem::Version
41
- version: 2.7.0
68
+ version: 3.0.0
42
69
  required_rubygems_version: !ruby/object:Gem::Requirement
43
70
  requirements:
44
71
  - - ">="
45
72
  - !ruby/object:Gem::Version
46
73
  version: '0'
47
74
  requirements: []
48
- rubygems_version: 3.5.16
75
+ rubygems_version: 3.5.22
49
76
  signing_key:
50
77
  specification_version: 4
51
78
  summary: CKEditor 5 for Rails
@@ -1,28 +0,0 @@
1
- name: Ruby
2
-
3
- on:
4
- push:
5
- branches: [ "main" ]
6
- pull_request:
7
- branches: [ "main" ]
8
-
9
- permissions:
10
- contents: read
11
-
12
- jobs:
13
- test:
14
-
15
- runs-on: ubuntu-latest
16
- strategy:
17
- matrix:
18
- ruby-version: ['2.6', '2.7', '3.0']
19
-
20
- steps:
21
- - uses: actions/checkout@v4
22
- - name: Set up Ruby
23
- uses: ruby/setup-ruby@v1
24
- with:
25
- ruby-version: ${{ matrix.ruby-version }}
26
- bundler-cache: true # runs 'bundle install' and caches installed gems automatically
27
- - name: Run tests
28
- run: bundle exec rake
data/.gitignore DELETED
@@ -1,56 +0,0 @@
1
- *.gem
2
- *.rbc
3
- /.config
4
- /coverage/
5
- /InstalledFiles
6
- /pkg/
7
- /spec/reports/
8
- /spec/examples.txt
9
- /test/tmp/
10
- /test/version_tmp/
11
- /tmp/
12
-
13
- # Used by dotenv library to load environment variables.
14
- # .env
15
-
16
- # Ignore Byebug command history file.
17
- .byebug_history
18
-
19
- ## Specific to RubyMotion:
20
- .dat*
21
- .repl_history
22
- build/
23
- *.bridgesupport
24
- build-iPhoneOS/
25
- build-iPhoneSimulator/
26
-
27
- ## Specific to RubyMotion (use of CocoaPods):
28
- #
29
- # We recommend against adding the Pods directory to your .gitignore. However
30
- # you should judge for yourself, the pros and cons are mentioned at:
31
- # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
32
- #
33
- # vendor/Pods/
34
-
35
- ## Documentation cache and generated files:
36
- /.yardoc/
37
- /_yardoc/
38
- /doc/
39
- /rdoc/
40
-
41
- ## Environment normalization:
42
- /.bundle/
43
- /vendor/bundle
44
- /lib/bundler/man/
45
-
46
- # for a library or gem, you might want to ignore these files since the code is
47
- # intended to run in multiple environments; otherwise, check them in:
48
- # Gemfile.lock
49
- # .ruby-version
50
- # .ruby-gemset
51
-
52
- # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
53
- .rvmrc
54
-
55
- # Used by RuboCop. Remote config files pulled in from inherit_from directive.
56
- # .rubocop-https?--*
data/Rakefile DELETED
@@ -1,3 +0,0 @@
1
- require 'bundler/gem_tasks'
2
-
3
- task :gem => :build
data/ckeditor5.gemspec DELETED
@@ -1,23 +0,0 @@
1
- lib = File.expand_path('lib', __dir__)
2
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
-
4
- require 'ckeditor5/version'
5
-
6
- Gem::Specification.new do |s|
7
- s.name = 'ckeditor5'
8
- s.version = CKEditor5::VERSION
9
- s.platform = Gem::Platform::RUBY
10
- s.summary = 'CKEditor 5 for Rails'
11
- s.authors = [
12
- 'Mateusz Bagiński',
13
- 'Łukasz Modliński'
14
- ]
15
-
16
- s.license = 'MIT'
17
- s.email = 'cziken58@gmail.com'
18
- s.homepage = 'https://github.com/Mati365/ckeditor5-rails'
19
- s.files = `git ls-files`.split("\n")
20
- s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
21
- s.require_paths = ['lib']
22
- s.required_ruby_version = '>= 2.7.0'
23
- end
@@ -1,5 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module CKEditor5
4
- VERSION = '0.0.1'
5
- end