diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 2903b6a..338cdac 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -9,7 +9,8 @@ on:
jobs:
build:
# Named explicitly so that `experimental` stays out of the job name.
- name: "build (${{ matrix.ruby }}, ${{ matrix.rails }})"
+ # The Vite-based build is the default, so only the classic one is named.
+ name: "build (Ruby ${{ matrix.ruby }}, Rails ${{ matrix.rails }}${{ matrix.ember != 'vite' && format(', {0}', matrix.ember) || '' }})"
runs-on: "ubuntu-latest"
# Jobs normally finish in about 3 minutes, so cap hung runs well short
@@ -24,20 +25,41 @@ jobs:
matrix:
ruby: ["3.2", "3.3"]
rails: ["7.0", "7.1", "7.2"]
+ # A key of the matrix itself, so that the classic builds below run alongside these rather than replacing them.
+ ember: ["vite"]
include:
- ruby: "3.3"
rails: "8.0"
+ ember: "vite"
- ruby: "3.4"
rails: "8.0"
+ ember: "vite"
+ - ruby: "4.0"
+ rails: "7.2"
+ ember: "vite"
+ - ruby: "4.0"
+ rails: "8.0"
+ ember: "vite"
- ruby: "4.0"
rails: "8.1"
+ ember: "vite"
- ruby: "3.4"
rails: "main"
+ ember: "vite"
experimental: true
+ # The classic build at both ends of the supported range: the oldest Ruby, Rails and Node, and the newest.
+ - ruby: "3.2"
+ rails: "7.0"
+ ember: "classic"
+ node: "20.x"
+ - ruby: "4.0"
+ rails: "8.1"
+ ember: "classic"
env:
RAILS_ENV: test
RAILS_VERSION: "${{ matrix.rails }}"
+ EMBER_BUILD: "${{ matrix.ember }}"
steps:
- uses: actions/checkout@ee0669bd1cc54295c223e0bb666b733df41de1c5 # v2.7.0
@@ -51,7 +73,7 @@ jobs:
- name: Install NodeJS
uses: actions/setup-node@7c12f8017d5436eb855f1ed4399f037a36fbd9e8 # v2.5.2
with:
- node-version: "20.x"
+ node-version: "${{ matrix.node || '26.x' }}"
- name: Setup Google Chrome
uses: browser-actions/setup-chrome@latest
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0a5dcbf..e3181fc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,9 @@
+main
+------
+
+* Render what `ember-cli-rails` reports about a built application instead of deriving it here. This removes `EmberCli::Assets::Paths`, `EmberCli::Assets::Lookup`, `EmberCli::Assets::AssetMap`, `EmberCli::Assets::DirectoryAssetMap` and `EmberCli::Assets::Url`, and a missing or unresolvable asset now raises `EmberCli::BuildError` rather than `EmberCli::Assets::BuildError`
+* Declare the dependency on `ember-cli-rails`, which the helpers have always needed at runtime. `ember-cli-rails` no longer depends on this gem, so an application that renders the helpers adds both to its `Gemfile`
+
0.9.2
------
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 35f28f8..02b882f 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -16,6 +16,11 @@ After cloning the repository, execute the setup script:
$ bin/setup
+It builds the dummy Ember application from the Vite-based blueprint.
+To build it with the classic (Broccoli-based) pipeline instead, remove `spec/dummy/my-app` if it exists and set `EMBER_BUILD`:
+
+ $ EMBER_BUILD=classic bin/setup
+
Make sure the tests pass:
$ bin/rake
diff --git a/Gemfile b/Gemfile
index a304e15..182309a 100644
--- a/Gemfile
+++ b/Gemfile
@@ -13,12 +13,6 @@ end
gem "rails", rails_constraint
gem "webrick"
-group :development, :test do
- # The specs verify doubles against the development-server API,
- # which ships with 0.13.0.
- gem "ember-cli-rails", ">= 0.13.0"
-end
-
group :test do
gem "cuprite"
@@ -30,3 +24,9 @@ group :test do
gem "rspec-rails"
end
end
+
+# The helpers render an API that ember-cli-rails has not released yet, so
+# resolve it from the branch that adds it.
+# Remove this once that release is published; the gemspec constraint takes
+# over from there.
+gem "ember-cli-rails", github: "tricknotes/ember-cli-rails", branch: "claude/intelligent-goodall-foai0r"
diff --git a/README.md b/README.md
index 5cde20e..4ef6643 100644
--- a/README.md
+++ b/README.md
@@ -28,6 +28,9 @@ Then run `bundle install`:
$ bundle install
```
+The helpers render what [`ember-cli-rails`][ember-cli-rails] reports about a
+built application, so they require the release of it that reports that.
+
## Setup
To configure your project to use `ember-cli-rails`, follow the instructions
diff --git a/app/helpers/ember_cli_rails_assets_helper.rb b/app/helpers/ember_cli_rails_assets_helper.rb
index 8ba8bdd..dc8953d 100644
--- a/app/helpers/ember_cli_rails_assets_helper.rb
+++ b/app/helpers/ember_cli_rails_assets_helper.rb
@@ -1,33 +1,22 @@
require "ember_cli/assets/errors"
-require "ember_cli/assets/lookup"
-require "ember_cli/assets/paths"
-require "ember_cli/assets/url"
module EmberCliRailsAssetsHelper
def include_ember_script_tags(name, prepend: "")
- app = EmberCli[name]
- app.build
+ embedding = build_ember_embedding(name)
- if dev_server?(app)
- dev_server_ember_script_tags(app)
+ if embedding.startup_tags?
+ safe_join(embedding.startup_tags(prepend: prepend).map(&:html_safe), "\n")
else
- paths = EmberCli::Assets::Paths.new(app)
-
- if paths.vite?
- vite_ember_script_tags(paths, prepend)
- else
- classic_ember_script_tags(app, prepend)
+ tags_for(embedding.javascript_assets(prepend: prepend)) do |src|
+ %{}
end
end
end
def include_ember_stylesheet_tags(name, prepend: "")
- app = EmberCli[name]
- app.build
-
- paths = EmberCli::Assets::Paths.new(app)
+ embedding = build_ember_embedding(name)
- if dev_server?(app) || paths.vite?
+ if embedding.startup_tags?
raise EmberCli::Assets::NotSupportedError, <<~MSG
`include_ember_stylesheet_tags` does not support Vite-based
applications (`ember-cli >= 6.8`).
@@ -37,80 +26,23 @@ def include_ember_stylesheet_tags(name, prepend: "")
MSG
end
- assets = EmberCli::Assets::Lookup.new(app)
-
- assets.stylesheet_assets.
- map { |src| mount_asset(src, prepend) }.
- map { |src| %{}.html_safe }.
- inject(&:+)
+ tags_for(embedding.stylesheet_assets(prepend: prepend)) do |href|
+ %{}
+ end
end
private
- # Whether ember-cli-rails serves the application from Vite's development
- # server. Older ember-cli-rails releases have no development server, so
- # feature-detect the reader.
- def dev_server?(app)
- app.respond_to?(:dev_server?) && app.dev_server?
- end
+ def build_ember_embedding(name)
+ app = EmberCli[name]
+ app.build
- # The application is served by Vite's development server, so read
- # `index.html` from the server instead of a build directory, and rewrite
- # its root-relative URLs to absolute URLs on the server — the same way
- # ember-cli-rails serves the document itself. `app.build` has already
- # booted the server.
- def dev_server_ember_script_tags(app)
- vite_startup_tags(app.dev_server.index_html, prefix: app.dev_server.origin)
+ EmberCli::Embedding.new(app)
end
- # Classic builds ship a fixed set of scripts (vendor and app) resolved
- # through the asset map, so emit a plain script tag per JavaScript asset
- # with `prepend` joined onto each path.
- def classic_ember_script_tags(app, prepend)
- assets = EmberCli::Assets::Lookup.new(app)
-
- assets.javascript_assets.
- map { |src| mount_asset(src, prepend) }.
- map { |src| %{}.html_safe }.
+ def tags_for(assets)
+ assets.
+ map { |asset| yield(asset).html_safe }.
inject(&:+)
end
-
- # `prepend` mounts the build's assets onto a path (or another host), so it only applies to the URLs that point into the build.
- # Assets hosted elsewhere (a CDN, a font service) are already absolute.
- def mount_asset(src, prepend)
- if EmberCli::Assets::Url.remote?(src)
- src
- else
- [prepend, src].join
- end
- end
-
- # Vite builds boot from ES modules declared in dist/index.html, so extract
- # the tags required for startup (including the config meta tag and
- # stylesheets) and remap root-absolute paths onto the mount point.
- def vite_ember_script_tags(paths, prepend)
- vite_startup_tags(paths.index_html.read, prefix: prepend.to_s.chomp("/"))
- end
-
- # Extracts the tags a Vite-based application needs to boot from an
- # `index.html` document, with `prefix` joined onto every root-relative
- # URL. Protocol-relative URLs (`//`) are left alone.
- def vite_startup_tags(html, prefix:)
- document = Nokogiri::HTML5(html)
-
- tags = document.css(
- 'meta[name$="/config/environment"], link[rel="stylesheet"], link[rel="modulepreload"], script'
- ).map do |tag|
- %w(href src).each do |attribute|
- value = tag[attribute]
-
- if value&.start_with?("/") && !value.start_with?("//")
- tag[attribute] = "#{prefix}#{value}"
- end
- end
- tag.to_html.html_safe
- end
-
- safe_join(tags, "\n")
- end
end
diff --git a/bin/setup b/bin/setup
index 23da74a..4e79bb1 100755
--- a/bin/setup
+++ b/bin/setup
@@ -9,19 +9,34 @@ bundle check || bundle install
# Add binstubs to PATH via export PATH=".git/safe/../../bin:$PATH" in ~/.zshenv
mkdir -p .git/safe
+# `vite` is pinned to the Vite-based blueprint that `ember-cli >= 6.8` generates, and `classic` to the last release built by Broccoli.
+EMBER_BUILD="${EMBER_BUILD:-vite}"
+
if ! [ -d spec/dummy/my-app ]; then
- # Pinned to the last release built by Broccoli: the feature suite
- # exercises the classic build. The Vite path of
- # `include_ember_script_tags` is exercised by ember-cli-rails' own suite.
- git clone --branch v6.7.2 \
- https://github.com/kellyselden/ember-cli-output.git spec/dummy/my-app
+ case "$EMBER_BUILD" in
+ classic)
+ git clone --branch v6.7.2 \
+ https://github.com/kellyselden/ember-cli-output.git spec/dummy/my-app
+ ;;
+ vite)
+ git clone --branch v7.0.0 \
+ https://github.com/ember-cli/ember-new-output.git spec/dummy/my-app
+ ;;
+ *)
+ echo "Unsupported EMBER_BUILD '${EMBER_BUILD}'; use classic or vite" >&2
+ exit 1
+ ;;
+ esac
bin/setup_ember
fi
root="$(pwd)"
-cd ${root}/spec/dummy/my-app &&
- yarn add --dev ember-cli-rails-addon@rondale-sc/ember-cli-rails-addon
+# `ember-cli-rails-addon` is incompatible with the Vite-based build.
+if ! [ -f spec/dummy/my-app/vite.config.mjs ]; then
+ cd ${root}/spec/dummy/my-app &&
+ yarn add --dev ember-cli-rails-addon@rondale-sc/ember-cli-rails-addon
+fi
cd ${root}/spec/dummy && bundle exec rake ember:install
diff --git a/bin/setup_ember b/bin/setup_ember
index 129c2d9..efc3ed6 100755
--- a/bin/setup_ember
+++ b/bin/setup_ember
@@ -6,6 +6,11 @@ set -e
sed -i -e 's/history/hash/' spec/dummy/my-app/config/environment.js
# add an image to a template
-echo '
' >> spec/dummy/my-app/app/templates/application.hbs
+if [ -f spec/dummy/my-app/app/templates/application.gjs ]; then
+ sed -i -e 's||
\n|' \
+ spec/dummy/my-app/app/templates/application.gjs
+else
+ echo '
' >> spec/dummy/my-app/app/templates/application.hbs
+fi
mkdir -p spec/dummy/my-app/public/assets
cp spec/fixtures/logo.png spec/dummy/my-app/public/assets/
diff --git a/ember-cli-rails-assets.gemspec b/ember-cli-rails-assets.gemspec
index e518aff..227d02d 100644
--- a/ember-cli-rails-assets.gemspec
+++ b/ember-cli-rails-assets.gemspec
@@ -16,5 +16,8 @@ Gem::Specification.new do |s|
s.files = Dir["{app,lib}/**/*", "MIT-LICENSE", "Rakefile", "README.md"]
- s.add_dependency 'nokogiri'
+ # The helpers render what ember-cli-rails reports about a built application.
+ # Constrain this to the release that reports it once that release is
+ # published.
+ s.add_dependency "ember-cli-rails"
end
diff --git a/lib/ember-cli-rails-assets.rb b/lib/ember-cli-rails-assets.rb
index 853c81a..5ca453c 100644
--- a/lib/ember-cli-rails-assets.rb
+++ b/lib/ember-cli-rails-assets.rb
@@ -1,3 +1,4 @@
+require "ember-cli-rails"
require "ember_cli/assets/engine"
module EmberCli
diff --git a/lib/ember_cli/assets/asset_map.rb b/lib/ember_cli/assets/asset_map.rb
deleted file mode 100644
index f1e8b5b..0000000
--- a/lib/ember_cli/assets/asset_map.rb
+++ /dev/null
@@ -1,87 +0,0 @@
-require 'nokogiri'
-require "ember_cli/assets/errors"
-require "ember_cli/assets/url"
-
-module EmberCli
- module Assets
- class AssetMap
- def initialize(name:, asset_map:, index_html:)
- @name = name
- @asset_map = asset_map
- @index_html = index_html
- end
-
- def javascripts
- assert_asset_map!
-
- document.css('script').filter_map { |script| asset_for(script['src']) }
- end
-
- def stylesheets
- assert_asset_map!
-
- document.css('link[rel="stylesheet"]').filter_map { |link| asset_for(link['href']) }
- end
-
- private
-
- attr_reader :name, :asset_map, :index_html
-
- def document
- @document ||= Nokogiri::HTML(index_html.read)
- end
-
- # Assets hosted outside the build (a CDN, a font service) have no entry in the asset map, so their URL is emitted untouched.
- # A tag without a URL (an inline `
-
-
-
-
-
-