smeditor 0.1.0 → 0.2.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.
@@ -5,47 +5,21 @@ require "rails/generators"
5
5
  module SMEditor
6
6
  module Generators
7
7
  class InstallGenerator < ::Rails::Generators::Base
8
- # Thor вывел бы из имени класса namespace "sm_editor:install".
9
- # Задаём явно, чтобы генератор звался `rails g smeditor:install`.
10
8
  namespace "smeditor:install"
9
+ desc "Install SMEditor Rails configuration"
11
10
 
12
- desc "Install SMEditor Rails configuration and the editor boot script"
13
-
14
- class_option :skip_javascript,
15
- type: :boolean,
16
- default: false,
17
- desc: "Do not copy smeditor.js into app/javascript"
18
-
19
- # Two source roots: the generator templates, and the packaged boot
20
- # script. Copying the shipped asset rather than a duplicate template
21
- # keeps a single source of truth for the JavaScript.
22
- def self.source_paths
23
- [
24
- File.expand_path("templates", __dir__),
25
- File.expand_path("../../../app/assets/javascripts", __dir__),
26
- ]
27
- end
11
+ source_root File.expand_path("templates", __dir__)
28
12
 
29
13
  def copy_initializer
30
14
  template "initializer.rb", "config/initializers/smeditor.rb"
31
15
  end
32
16
 
33
- # The boot script imports @smeditor/* by bare specifier, so it has to
34
- # be compiled by the host app's JavaScript bundler. Sprockets and
35
- # importmap cannot resolve those imports; jsbundling-rails (esbuild,
36
- # rollup, webpack) or Vite can.
37
- def copy_boot_script
38
- copy_file "smeditor.js", "app/javascript/smeditor.js" unless options[:skip_javascript]
39
- end
40
-
41
17
  def show_next_steps
42
18
  say ""
43
- say "SMEditor installed. Next:"
44
- say " 1. npm install @smeditor/react @smeditor/starter-kit \\"
45
- say " @smeditor/full-kit @smeditor/theme-default react react-dom"
46
- say " 2. Add `import \"./smeditor\"` to app/javascript/application.js"
47
- say " 3. For uploads: set config.uploads = :active_storage and mount"
48
- say " `mount SMEditor::Rails::Engine => \"/smeditor\"` in config/routes.rb"
19
+ say "SMEditor installed. No npm packages or JavaScript bundler are required."
20
+ say "Use `form.smeditor_editor :content` in a form."
21
+ say "For uploads: set config.uploads = :active_storage and mount"
22
+ say "`SMEditor::Rails::Engine => \"/smeditor\"` in config/routes.rb."
49
23
  say ""
50
24
  end
51
25
  end
@@ -7,6 +7,10 @@ SMEditor.configure do |config|
7
7
  # Used by the JavaScript adapter when uploads are enabled.
8
8
  config.upload_path = "/smeditor/uploads"
9
9
 
10
+ # Assets are shipped inside the gem and inserted automatically with the
11
+ # first editor field. Set false if you call `smeditor_assets` in your layout.
12
+ config.auto_include_assets = true
13
+
10
14
  # "starter" gives the MVP toolbar; "full" enables the larger extension set.
11
15
  config.default_kit = "starter"
12
16
 
@@ -20,6 +20,9 @@ module SMEditor
20
20
  attr_accessor :default_kit
21
21
  # Upload endpoint used by the JavaScript adapter when uploads are enabled.
22
22
  attr_accessor :upload_path
23
+ # Include the packaged JS/CSS automatically with the first editor field.
24
+ # Set false when the host app calls `smeditor_assets` in its layout.
25
+ attr_accessor :auto_include_assets
23
26
  # Hard ceiling on an uploaded file, in bytes. The endpoint is reachable
24
27
  # by anyone who can reach the host app unless the controller is
25
28
  # subclassed with authentication, so it refuses anything larger.
@@ -38,6 +41,7 @@ module SMEditor
38
41
  ]
39
42
  @default_kit = "starter"
40
43
  @upload_path = "/smeditor/uploads"
44
+ @auto_include_assets = true
41
45
  @max_upload_size = 10 * 1024 * 1024
42
46
  @allowed_upload_types = %w[
43
47
  image/png image/jpeg image/gif image/webp image/avif image/bmp
@@ -1,42 +1,33 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # `rails/engine` не подтягивает core-расширения ActiveSupport сам. Вне
4
- # приложения (например, в rspec) гем грузится первым, и Rails::Initializable
5
- # падает на delegate_missing_to. `require "rails"` ставит их на место.
6
3
  require "rails"
7
4
  require "rails/engine"
8
5
 
9
6
  module SMEditor
10
7
  module Rails
11
- # Rails::Engine subclass the gem's plumbing.
12
- #
13
- # It does three things and nothing more (per PLAN.md the gem stays
14
- # a thin adapter):
15
- # 1. Isolates the SMEditor namespace so routes / controllers
16
- # don't collide with the host app.
17
- # 2. Mixes the view helpers into ActionView.
18
- # 3. Adds smeditor_editor to the form builder.
19
- #
20
- # The upload route lives in config/routes.rb and is mounted by the
21
- # host with `mount SMEditor::Rails::Engine => "/smeditor"`.
8
+ # Self-contained Rails engine. The browser bundle and theme are packaged
9
+ # under app/assets, so consuming applications only need the Ruby gem.
22
10
  class Engine < ::Rails::Engine
23
11
  isolate_namespace SMEditor
24
12
 
25
- # `isolate_namespace` выводит "sm_editor" из имени константы. Закрепляем
26
- # "smeditor", чтобы прокси маршрутов у смонтированного движка назывался
27
- # `smeditor.uploads_path`.
28
13
  engine_name "smeditor"
29
14
  railtie_name "smeditor"
30
15
 
31
- # Zeitwerk по имени каталога `smeditor/` вывел бы константу `Smeditor`.
32
- # Оба автозагрузчика узнают про `SMEditor` до сканирования autoload-путей —
33
- # иначе `SMEditor::UploadsController` не найдётся.
34
16
  initializer "smeditor.inflections", before: :set_autoload_paths do
35
17
  ::Rails.autoloaders.each do |autoloader|
36
18
  autoloader.inflector.inflect("smeditor" => "SMEditor")
37
19
  end
38
20
  end
39
21
 
22
+ # Sprockets requires non-application assets to be explicitly precompiled.
23
+ # Propshaft discovers engine assets through the normal Rails asset paths,
24
+ # so this block intentionally runs only when config.assets is available.
25
+ initializer "smeditor.assets" do |app|
26
+ if app.config.respond_to?(:assets) && app.config.assets.respond_to?(:precompile)
27
+ app.config.assets.precompile += %w[smeditor.js smeditor.css]
28
+ end
29
+ end
30
+
40
31
  initializer "smeditor.view_helpers" do
41
32
  ActiveSupport.on_load(:action_view) do
42
33
  include SMEditor::Rails::FormHelper
@@ -2,25 +2,34 @@
2
2
 
3
3
  module SMEditor
4
4
  module Rails
5
- # View helper that mounts a SMEditor editor inside a Rails form.
6
- #
7
- # <%= form.smeditor_editor :content %> # via FormBuilder
8
- # <%= smeditor_editor(form, :content) %> # standalone
9
- #
10
- # Emits a hidden field carrying the document HTML plus an empty
11
- # mount point. The boot script (smeditor.js) finds the mount,
12
- # attaches a real editor seeded from the hidden field, and writes
13
- # editor.getHTML() back into that field on every change — so a
14
- # normal form submit persists the content with no extra wiring.
5
+ # View helper that mounts a self-contained SMEditor inside a Rails form.
6
+ # The gem ships the browser bundle and default theme itself; host apps do
7
+ # not need npm, React, esbuild, importmap pins, or jsbundling-rails.
15
8
  module FormHelper
9
+ # Render the packaged JS/CSS once for this view context. This makes the
10
+ # form helper work without editing the host layout. Apps that prefer to
11
+ # include assets in <head> can call `smeditor_assets` there and disable
12
+ # auto inclusion with config.auto_include_assets = false.
13
+ def smeditor_assets
14
+ return "".html_safe if defined?(@_smeditor_assets_rendered) && @_smeditor_assets_rendered
15
+
16
+ @_smeditor_assets_rendered = true
17
+ safe_join([
18
+ stylesheet_link_tag("smeditor", "data-turbo-track": "reload"),
19
+ javascript_include_tag("smeditor", defer: true, "data-turbo-track": "reload"),
20
+ ])
21
+ end
22
+
16
23
  # form - a Rails FormBuilder
17
24
  # method - the model attribute (stored as an HTML string)
18
- # options - :kit ("starter" | "full"), :class, :placeholder, :upload_url
25
+ # options - :kit ("starter" | "full"), :class, :placeholder,
26
+ # :upload_url, :label, :include_assets
19
27
  def smeditor_editor(form, method, options = {})
20
28
  object = form.object
21
29
  current = object.respond_to?(method) ? object.public_send(method) : nil
22
30
  kit = (options[:kit] || SMEditor.config.default_kit).to_s
23
31
  upload_url = options.fetch(:upload_url, smeditor_upload_url)
32
+ include_assets = options.fetch(:include_assets, SMEditor.config.auto_include_assets)
24
33
 
25
34
  hidden = form.hidden_field(
26
35
  method,
@@ -37,24 +46,23 @@ module SMEditor
37
46
  smeditor_kit: kit,
38
47
  smeditor_placeholder: options[:placeholder],
39
48
  smeditor_upload_url: upload_url,
40
- },
49
+ smeditor_label: options[:label],
50
+ }.compact,
41
51
  )
42
52
 
43
53
  wrapper_class = ["smeditor-field", options[:class]].compact.join(" ")
44
- content_tag(:div, safe_join([hidden, mount]), class: wrapper_class)
54
+ field = content_tag(:div, safe_join([hidden, mount]), class: wrapper_class)
55
+
56
+ include_assets ? safe_join([smeditor_assets, field]) : field
45
57
  end
46
58
 
47
59
  private
48
60
 
49
61
  def smeditor_upload_url
50
- if SMEditor.config.uploads == :active_storage
51
- SMEditor.config.upload_path
52
- end
62
+ SMEditor.config.upload_path if SMEditor.config.uploads == :active_storage
53
63
  end
54
64
  end
55
65
 
56
- # Mixed into ActionView::Helpers::FormBuilder so `form.smeditor_editor`
57
- # works alongside the standalone helper.
58
66
  module FormBuilderExtension
59
67
  def smeditor_editor(method, options = {})
60
68
  @template.smeditor_editor(self, method, options)
@@ -2,6 +2,6 @@
2
2
 
3
3
  module SMEditor
4
4
  module Rails
5
- VERSION = "0.1.0"
5
+ VERSION = "0.2.0"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: smeditor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - SMEditor contributors
@@ -16,6 +16,9 @@ dependencies:
16
16
  - - ">="
17
17
  - !ruby/object:Gem::Version
18
18
  version: '7.0'
19
+ - - "<"
20
+ - !ruby/object:Gem::Version
21
+ version: '9.0'
19
22
  type: :runtime
20
23
  prerelease: false
21
24
  version_requirements: !ruby/object:Gem::Requirement
@@ -23,6 +26,9 @@ dependencies:
23
26
  - - ">="
24
27
  - !ruby/object:Gem::Version
25
28
  version: '7.0'
29
+ - - "<"
30
+ - !ruby/object:Gem::Version
31
+ version: '9.0'
26
32
  - !ruby/object:Gem::Dependency
27
33
  name: rspec
28
34
  requirement: !ruby/object:Gem::Requirement
@@ -41,21 +47,21 @@ dependencies:
41
47
  name: rails-html-sanitizer
42
48
  requirement: !ruby/object:Gem::Requirement
43
49
  requirements:
44
- - - ">="
50
+ - - "~>"
45
51
  - !ruby/object:Gem::Version
46
52
  version: '1.6'
47
53
  type: :development
48
54
  prerelease: false
49
55
  version_requirements: !ruby/object:Gem::Requirement
50
56
  requirements:
51
- - - ">="
57
+ - - "~>"
52
58
  - !ruby/object:Gem::Version
53
59
  version: '1.6'
54
60
  description: |
55
- Thin Rails adapter for SMEditor. Provides a form helper, a safe
56
- server-side renderer, and an optional ActiveStorage-backed upload
57
- endpoint. The editor itself is the upstream npm packages — this gem
58
- never replaces or duplicates them.
61
+ Self-contained SMEditor integration for Rails. The gem ships the editor
62
+ core, starter/full extension kits, browser bundle, default theme, form
63
+ helper, safe renderer, and optional ActiveStorage upload endpoint. Host
64
+ applications do not need npm, React, esbuild, or jsbundling-rails.
59
65
  email:
60
66
  - sCruze@users.noreply.github.com
61
67
  executables: []
@@ -69,6 +75,7 @@ files:
69
75
  - LICENSE
70
76
  - README.md
71
77
  - app/assets/javascripts/smeditor.js
78
+ - app/assets/stylesheets/smeditor.css
72
79
  - app/controllers/smeditor/uploads_controller.rb
73
80
  - config/routes.rb
74
81
  - lib/generators/smeditor/install_generator.rb
@@ -89,7 +96,7 @@ metadata:
89
96
  source_code_uri: https://github.com/sCruze/smeditor/tree/main/gems/smeditor
90
97
  changelog_uri: https://github.com/sCruze/smeditor/blob/main/gems/smeditor/CHANGELOG.md
91
98
  bug_tracker_uri: https://github.com/sCruze/smeditor/issues
92
- documentation_uri: https://rubydoc.info/gems/smeditor/0.1.0
99
+ documentation_uri: https://rubydoc.info/gems/smeditor/0.2.0
93
100
  rubygems_mfa_required: 'true'
94
101
  rdoc_options: []
95
102
  require_paths:
@@ -107,5 +114,5 @@ required_rubygems_version: !ruby/object:Gem::Requirement
107
114
  requirements: []
108
115
  rubygems_version: 4.0.6
109
116
  specification_version: 4
110
- summary: Rails integration for the SMEditor rich text editor.
117
+ summary: Self-contained SMEditor rich text editor for Rails.
111
118
  test_files: []