Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use Importmaps for admin JS #2498

Merged
merged 7 commits into from
Jun 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,10 @@ pkg
tmp
log
.sass-cache
spec/dummy/app/assets/builds/*.js*
spec/dummy/app/javascript/
spec/dummy/config/alchemy/config.yml
spec/dummy/db/*.sqlite3*
spec/dummy/package.json
spec/dummy/postcss.config.js
spec/dummy/public/assets/
spec/dummy/public/packs/
spec/dummy/public/packs-test/
spec/dummy/uploads/
.rvmrc
/coverage/
Expand Down
1 change: 0 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ group :development, :test do
# in our case the culprit is `handlebars-assets`. The changes between 2.7.0 and 2.8.0 are
# minimal, but breaking.
gem "execjs", "= 2.8.1"
gem "jsbundling-rails", "~> 1.1"
gem "rubocop", require: false
gem "standard", "~> 1.25", require: false

Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ $ bin/start

### Bump version

Bump the version number in both `lib/alchemy/version.rb` and `./package.json`. Make sure both are exactly the same and follow [SemVer format](https://semver.org/#semantic-versioning-specification-semver).
Bump the version number in `lib/alchemy/version.rb`.

### Update the changelog

Expand All @@ -357,11 +357,11 @@ $ git commit -am "Bump version to vX.Y.Z"

### Release a new version

This task will publish both the ruby gem and the npm package.
This task will publish the ruby gem.
It also tags the latest commit.

```bash
$ bundle exec rake alchemy:release
$ bundle exec rake release
```

## ❓Getting Help
Expand Down
19 changes: 0 additions & 19 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -41,17 +41,12 @@ namespace :alchemy do
task :prepare do
system(
<<~BASH
yarn install && \
yarn link && \
cd spec/dummy && \
export RAILS_ENV=test && \
bin/rake db:create && \
bin/rake db:environment:set && \
bin/rake db:migrate:reset && \
bin/rails javascript:install:esbuild && \
bin/rails g alchemy:install --skip --skip-demo-files --auto-accept --skip-db-create && \
yarn link @alchemy_cms/admin && \
bin/rails javascript:build && \
cd -
BASH
) || fail
Expand Down Expand Up @@ -81,18 +76,4 @@ namespace :alchemy do
File.delete(backup)
end
end

desc "Release a new Ruby gem and npm package in one command"
task :release do
require "json"
require_relative "lib/alchemy/version"
package = File.read("package.json")
unless JSON.parse(package)["version"] == Alchemy.version
abort "Ruby gem and npm package versions are out of sync! Please fix."
end
# Release the Ruby gem with bundler
Rake::Task["release"].invoke
# Publish npm package via CLI
system "npm publish"
end
end
1 change: 1 addition & 0 deletions alchemy_cms.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ Gem::Specification.new do |gem|
gem.add_runtime_dependency "dragonfly_svg", ["~> 0.0.4"]
gem.add_runtime_dependency "gutentag", ["~> 2.2", ">= 2.2.1"]
gem.add_runtime_dependency "handlebars_assets", ["~> 0.23"]
gem.add_runtime_dependency "importmap-rails", ["~> 1.2", ">= 1.2.1"]
gem.add_runtime_dependency "jquery-rails", ["~> 4.0", ">= 4.0.4"]
gem.add_runtime_dependency "jquery-ui-rails", ["~> 6.0"]
gem.add_runtime_dependency "kaminari", ["~> 1.1"]
Expand Down
1 change: 1 addition & 0 deletions app/assets/config/alchemy_manifest.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@
//= link_tree ../images/alchemy/
//= link_tree ../../../vendor/assets/fonts/
//= link_tree ../../../vendor/assets/images/
//= link_tree ../../javascript .js
32 changes: 32 additions & 0 deletions app/javascript/alchemy_admin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import translate from "./alchemy_admin/i18n"
import translationData from "./alchemy_admin/translations"
import fileEditors from "./alchemy_admin/file_editors"
import IngredientAnchorLink from "./alchemy_admin/ingredient_anchor_link"
import pictureEditors from "./alchemy_admin/picture_editors"
import ImageLoader from "./alchemy_admin/image_loader"
import ImageCropper from "./alchemy_admin/image_cropper"
import Datepicker from "./alchemy_admin/datepicker"
import Sitemap from "./alchemy_admin/sitemap"
import Tinymce from "./alchemy_admin/tinymce"
import PagePublicationFields from "./alchemy_admin/page_publication_fields.js"

// Global Alchemy object
if (typeof window.Alchemy === "undefined") {
window.Alchemy = {}
}

// Enhance the global Alchemy object with imported features
Object.assign(Alchemy, {
// Global utility method for translating a given string
t: translate,
translations: Object.assign(Alchemy.translations || {}, translationData),
fileEditors,
pictureEditors,
ImageLoader: ImageLoader.init,
ImageCropper,
IngredientAnchorLink,
Datepicker,
Sitemap,
Tinymce,
PagePublicationFields
})
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
6 changes: 4 additions & 2 deletions app/views/alchemy/admin/nodes/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@
<% end %>
</div>

<script>
Alchemy.NodeTree()
<script type="module">
import NodeTree from "alchemy_admin/node_tree"

NodeTree()
</script>
6 changes: 1 addition & 5 deletions app/views/layouts/alchemy/admin.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,7 @@
</script>
<%= render 'alchemy/admin/partials/routes' %>
<%= javascript_include_tag('alchemy/admin/all', 'data-turbolinks-track' => true) %>
<% if respond_to?(:javascript_pack_tag) %>
<%= javascript_pack_tag('alchemy/admin', 'data-turbolinks-track' => true) %>
<% else %>
<%= javascript_include_tag('alchemy_admin', 'data-turbolinks-track' => true) %>
<% end %>
<%= javascript_importmap_tags("alchemy_admin", importmap: Alchemy.importmap) %>
<%= yield :javascript_includes %>
</head>
<%= content_tag :body, id: 'alchemy', class: alchemy_body_class do %>
Expand Down
4 changes: 4 additions & 0 deletions bin/importmap
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/usr/bin/env ruby

require_relative "../spec/dummy/config/application"
require "importmap/commands"
9 changes: 0 additions & 9 deletions bin/setup
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,14 @@ def system!(*args)
end

FileUtils.chdir GEM_ROOT do
puts "\n== Linking Admin JS package =="
system! "yarn link"
puts "== Installing dependencies =="
system! "yarn install"
system! "gem install bundler --conservative"
system("bundle check") || system!("bundle install")
end

FileUtils.chdir APP_ROOT do
puts "\n== Installing Alchemy into dummy app =="
system!("bin/rails javascript:install:esbuild")
system!("bin/rails g alchemy:install --skip --skip-demo-files --auto-accept")

puts "\n== Link Alchemy admin package =="
system! "yarn link @alchemy_cms/admin"
system! "yarn install"

puts "\n== Removing old logs and tempfiles =="
system! "bin/rails log:clear tmp:clear"
end
Expand Down
2 changes: 1 addition & 1 deletion bin/start
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@ end

FileUtils.chdir APP_ROOT do
puts "\n== Starting dummy app =="
system! "bin/dev"
system! "bin/rails server"
end
46 changes: 0 additions & 46 deletions config/brakeman.ignore
Original file line number Diff line number Diff line change
Expand Up @@ -80,29 +80,6 @@
],
"note": ""
},
{
"warning_type": "Command Injection",
"warning_code": 14,
"fingerprint": "6addfcb9d23d2d6f699f2f3542169744ff749dc4d0a97f8ac783ab92593e1d84",
"check_name": "Execute",
"message": "Possible command injection",
"file": "lib/alchemy/upgrader.rb",
"line": 33,
"link": "https://brakemanscanner.org/docs/warning_types/command_injection/",
"code": "`yarn add @alchemy_cms/admin@~#{Alchemy.version}`",
"render_path": null,
"location": {
"type": "method",
"class": "Alchemy::Upgrader",
"method": "update_npm_package"
},
"user_input": "Alchemy.version",
"confidence": "Medium",
"cwe_id": [
77
],
"note": "The alchemy version is safe"
},
{
"warning_type": "Cross-Site Scripting",
"warning_code": 4,
Expand Down Expand Up @@ -227,29 +204,6 @@
],
"note": ""
},
{
"warning_type": "Command Injection",
"warning_code": 14,
"fingerprint": "98ca8e77026312eaa7eec15ce26bfe45aa8dd0fcd38e4cff104cb9dffbde1733",
"check_name": "Execute",
"message": "Possible command injection",
"file": "lib/alchemy/upgrader.rb",
"line": 31,
"link": "https://brakemanscanner.org/docs/warning_types/command_injection/",
"code": "`bin/importmap pin @alchemy_cms/admin@~#{Alchemy.version}`",
"render_path": null,
"location": {
"type": "method",
"class": "Alchemy::Upgrader",
"method": "update_npm_package"
},
"user_input": "Alchemy.version",
"confidence": "Medium",
"cwe_id": [
77
],
"note": ""
},
{
"warning_type": "File Access",
"warning_code": 16,
Expand Down
7 changes: 7 additions & 0 deletions config/importmap.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
pin "flatpickr", to: "https://ga.jspm.io/npm:flatpickr@4.6.13/dist/esm/index.js", preload: true
pin "lodash-es/debounce", to: "https://ga.jspm.io/npm:lodash-es@4.17.21/debounce.js", preload: true
pin "lodash-es/max", to: "https://ga.jspm.io/npm:lodash-es@4.17.21/max.js", preload: true
pin "sortablejs", to: "https://ga.jspm.io/npm:sortablejs@1.15.0/modular/sortable.esm.js", preload: true

pin "alchemy_admin", to: "alchemy_admin.js", preload: true
pin_all_from File.expand_path("../app/javascript/alchemy_admin", __dir__), under: "alchemy_admin"
5 changes: 5 additions & 0 deletions lib/alchemy.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# frozen_string_literal: true

require "alchemy/admin/preview_url"
require "importmap-rails"

module Alchemy
YAML_PERMITTED_CLASSES = %w[Symbol Date Regexp]
Expand Down Expand Up @@ -78,4 +79,8 @@ def self.publish_targets
# Alchemy.enable_searchable = true
#
mattr_accessor :enable_searchable, default: false

# JS Importmap instance
singleton_class.attr_accessor :importmap
self.importmap = Importmap::Map.new
end
14 changes: 14 additions & 0 deletions lib/alchemy/engine.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,20 @@ class Engine < Rails::Engine
NonStupidDigestAssets.whitelist += [/^tinymce\//]
end

initializer "alchemy.importmap" do |app|
Alchemy.importmap.draw(Engine.root.join("config", "importmap.rb"))

package_path = Engine.root.join("app/javascript")
app.config.assets.paths << package_path

if app.config.importmap.sweep_cache
Alchemy.importmap.cache_sweeper(watches: package_path)
ActiveSupport.on_load(:action_controller_base) do
before_action { Alchemy.importmap.cache_sweeper.execute_if_updated }
end
end
end

# Gutentag downcases all tags before save
# and Gutentag validations are not case sensitive.
# But we support having tags with uppercase characters.
Expand Down
11 changes: 0 additions & 11 deletions lib/alchemy/upgrader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,6 @@ def copy_new_config_file
todo "Check the default configuration file (./config/alchemy/config.yml.defaults) for new configuration options and insert them into your config file.", "Configuration has changed"
end
end

def update_npm_package
desc "Update npm package."
if File.exist? Rails.root.join("config/importmap.rb")
`bin/importmap pin @alchemy_cms/admin@~#{Alchemy.version}`
elsif File.exist? Rails.root.join("package.json")
`yarn add @alchemy_cms/admin@~#{Alchemy.version}`
else
log("Could not update alchemy admin package! Make sure you have a JS bundler installed", :warning)
end
end
end
end
end
36 changes: 13 additions & 23 deletions lib/alchemy/upgrader/seven_point_zero.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,30 +8,20 @@ class Upgrader::SevenPointZero < Upgrader
include Thor::Actions

class << self
def update_admin_entrypoint
if File.exist? "app/javascript/packs/alchemy/admin.js"
FileUtils.mv "app/javascript/packs/alchemy/admin.js", "app/javascript/alchemy_admin.js"
else
log "Skipping. No alchemy/admin entrypoint found. Maybe already migrated from Webpacker?", :info
end
if Dir.exist?("app/javascript/packs/alchemy") && Dir.empty?("app/javascript/packs/alchemy")
FileUtils.rm_r "app/javascript/packs/alchemy"
end
if File.exist? "config/importmap.rb"
# We want the bundled package if using importmaps
task.gsub_file "app/javascript/alchemy_admin.js", 'import "@alchemy_cms/admin"', 'import "@alchemy_cms/dist/admin"'
end
if task.ask("Do you want to remove webpacker now? (y/N)", default: "N") == "y"
def remove_admin_entrypoint
FileUtils.rm_rf "app/javascript/packs/alchemy/admin.js"
FileUtils.rm_rf "app/javascript/packs/alchemy_admin.js"
FileUtils.rm_rf "app/javascript/packs/alchemy"
FileUtils.rm_rf "app/javascript/packs/alchemy"
task.run "yarn remove @alchemy_cms/admin"
if task.ask("Do you want to remove webpacker as well? (y/N)", default: "N") == "y"
task.run "bundle remove webpacker"
task.run "yarn remove @rails/webpacker webpack webpack-cli webpack-dev-server"
FileUtils.rm_r "app/javascript/packs"
FileUtils.rm_r "config/webpack"
FileUtils.rm "config/webpacker.yml"
FileUtils.rm "bin/webpack"
FileUtils.rm "bin/webpack-dev-server"
end
if task.ask("Do you want to add jsbundling-rails now? (Y/n)", default: "Y") == "Y"
task.run "bundle add jsbundling-rails"
task.run "bin/rails javascript:install:esbuild"
FileUtils.rm_rf "app/javascript/packs"
FileUtils.rm_rf "config/webpack"
FileUtils.rm_f "config/webpacker.yml"
FileUtils.rm_f "bin/webpack"
FileUtils.rm_f "bin/webpack-dev-server"
end
end

Expand Down
1 change: 1 addition & 0 deletions lib/alchemy_cms.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
require "dragonfly"
require "gutentag"
require "handlebars_assets"
require "importmap-rails"
require "jquery-rails"
require "jquery-ui-rails"
require "kaminari"
Expand Down
24 changes: 0 additions & 24 deletions lib/generators/alchemy/install/install_generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -99,30 +99,6 @@ def install_gutentag_migrations
rake "gutentag:install:migrations"
end

def add_npm_package
if File.exist? app_root.join("package.json")
run "yarn add @alchemy_cms/admin@~#{Alchemy.version}"
elsif File.exist? app_root.join("config/importmap.rb")
run "bin/importmap pin @alchemy_cms/admin@~#{Alchemy.version}"
else
log("Could not add alchemy admin package! Make sure you have a JS bundler installed", :warning)
end
end

def copy_alchemy_entry_point
if Dir.exist? app_root.join("app/javascript")
if File.exist? app_root.join("config/importmap.rb")
# We want the bundled package if using importmaps
create_file app_root.join("app/javascript/alchemy_admin.js"), 'import "@alchemy_cms/dist/admin"'
else
# We want the normal package if using a bundler locally
create_file app_root.join("app/javascript/alchemy_admin.js"), 'import "@alchemy_cms/admin"'
end
else
log("Could not add alchemy admin entry point! Make sure you have a JS bundler installed", :warning)
end
end

def set_primary_language
header
install_tasks.set_primary_language(
Expand Down
Loading