smeditor
Self-contained Rails integration for SMEditor.
The gem ships the editor core, StarterKit, FullKit, browser bundle and default
CSS theme inside the gem itself. A Rails application does not need npm,
React, esbuild, Vite, importmap pins, or jsbundling-rails to use SMEditor.
Requirements
- Ruby >= 3.0
- Rails >= 7.0
Install
# Gemfile
gem "smeditor"
bundle install
bin/rails generate smeditor:install
That is enough for normal editor usage. The generator only creates
config/initializers/smeditor.rb; it does not copy JavaScript into the host
application and does not ask you to install frontend packages.
For ActiveStorage-backed image uploads, mount the engine:
# config/routes.rb
mount SMEditor::Rails::Engine => "/smeditor"
Configure
# config/initializers/smeditor.rb
SMEditor.configure do |config|
config.uploads = :none # or :active_storage
config.upload_path = "/smeditor/uploads"
config.default_kit = "starter" # or "full"
config.min_height = 320 # desktop, px when numeric
config.tablet_min_height = 280 # <= 1024px
config.mobile_min_height = 220 # <= 640px
config.sanitize_output = true
# true by default: the first editor field includes smeditor.js/css.
# Set false if you prefer calling `smeditor_assets` in your layout.
config.auto_include_assets = true
config.max_upload_size = 10 * 1024 * 1024
config.allowed_upload_types = %w[
image/png image/jpeg image/gif image/webp image/avif image/bmp
]
end
Use
<%= form_with model: @article do |form| %>
<%= form.smeditor_editor :content,
kit: "full",
placeholder: "Write…",
min_height: 420,
tablet_min_height: 340,
mobile_min_height: 260 %>
<%= form.submit %>
<% end %>
The helper renders a hidden Rails field plus the editor mount. The packaged
browser bundle updates the hidden field on every editor change, including a
normal bubbling input event and a smeditor:change custom event, so form submit and autosave code can
observe the value without CKEditor-specific integration.
Available options:
kit: "starter" | "full"placeholder:class:label:— editor ARIA labelupload_url:— custom image upload endpointmin_height:— minimum height on desktop (> 1024px)tablet_min_height:— minimum height on tablet widths (641-1024px)mobile_min_height:— minimum height on phone widths (<= 640px)include_assets: false— skip automatic asset tags for this field
Height options accept numbers (treated as pixels) or CSS lengths such as 24rem,
45vh, or 60dvh. Per-field values override the initializer defaults.
Assets in the layout (optional)
By default the first smeditor_editor call includes the packaged assets once.
If you prefer explicit layout assets:
# config/initializers/smeditor.rb
SMEditor.configure { |config| config.auto_include_assets = false }
<head>
<%= smeditor_assets %>
</head>
The files still come from the gem; this only changes where the tags are rendered.
Programmatic access
After boot, the editor instance is available on both the hidden input and the mount element:
const input = document.querySelector("[data-smeditor-input]")
const editor = input.smeditorInstance
editor.getHTML()
editor.setContent("<p>New content</p>")
editor.commands.toggleBold?.()
The bundle also exposes window.SMEditor.boot() and
window.SMEditor.destroy() for advanced integrations.
Turbo
SMEditor boots on DOMContentLoaded, turbo:load, and turbo:frame-load.
Before Turbo caches a page, editor instances are destroyed and their mounts are
reset, preventing stale contenteditable state after navigation.
Rendering saved content
<%= smeditor_render(@article.content) %>
Stored editor HTML is treated as untrusted input. smeditor_render sanitizes
allowed tags, URLs and inline formatting and hardens _blank links by default.
Set config.sanitize_output = false only if the stored HTML is already trusted.
Uploads
With config.uploads = :active_storage, the engine exposes
POST /smeditor/uploads. It stores the image through ActiveStorage and returns
{ src, alt, title } to the editor.
The default upload endpoint is unauthenticated. It enforces the configured file size and MIME allow-list, but public applications should add their own authorization policy.
What the gem contains
The published .gem includes:
- SMEditor browser bundle (core + StarterKit + FullKit)
- default SMEditor theme
- Rails form helper and FormBuilder extension
- safe renderer/sanitizer
- optional ActiveStorage upload endpoint
- install generator
The source monorepo still uses TypeScript/pnpm to develop and rebuild the frontend packages. Those are build-time tools for SMEditor maintainers only; they are not runtime dependencies of applications that install the gem.
Development
Rebuild the vendored Rails assets after changing core/extensions or the Rails browser adapter:
node scripts/build-gem-assets.mjs
Then test/build the gem:
cd gems/smeditor
bundle install
bundle exec rspec
gem build smeditor.gemspec
License
MIT © SMEditor contributors