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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +23 -3
- data/README.md +113 -74
- data/app/assets/javascripts/smeditor.js +8951 -232
- data/app/assets/stylesheets/smeditor.css +1218 -0
- data/lib/generators/smeditor/install_generator.rb +6 -32
- data/lib/generators/smeditor/templates/initializer.rb +4 -0
- data/lib/smeditor/rails/config.rb +4 -0
- data/lib/smeditor/rails/engine.rb +11 -20
- data/lib/smeditor/rails/form_helper.rb +26 -18
- data/lib/smeditor/rails/version.rb +1 -1
- metadata +16 -9
|
@@ -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
|
-
|
|
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.
|
|
44
|
-
say "
|
|
45
|
-
say "
|
|
46
|
-
say "
|
|
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
|
|
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
|
|
6
|
-
#
|
|
7
|
-
#
|
|
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,
|
|
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)
|
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.
|
|
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
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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.
|
|
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:
|
|
117
|
+
summary: Self-contained SMEditor rich text editor for Rails.
|
|
111
118
|
test_files: []
|