Skip to content
Draft
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
26 changes: 24 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
------

Expand Down
5 changes: 5 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 6 additions & 6 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand All @@ -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"
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
102 changes: 17 additions & 85 deletions app/helpers/ember_cli_rails_assets_helper.rb
Original file line number Diff line number Diff line change
@@ -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|
%{<script src="#{src}"></script>}
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`).
Expand All @@ -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| %{<link rel="stylesheet" href="#{src}">}.html_safe }.
inject(&:+)
tags_for(embedding.stylesheet_assets(prepend: prepend)) do |href|
%{<link rel="stylesheet" href="#{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| %{<script src="#{src}"></script>}.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
29 changes: 22 additions & 7 deletions bin/setup
Original file line number Diff line number Diff line change
Expand Up @@ -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
7 changes: 6 additions & 1 deletion bin/setup_ember
Original file line number Diff line number Diff line change
Expand Up @@ -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 '<img src="assets/logo.png">' >> spec/dummy/my-app/app/templates/application.hbs
if [ -f spec/dummy/my-app/app/templates/application.gjs ]; then
sed -i -e 's|</template>| <img src="assets/logo.png">\n</template>|' \
spec/dummy/my-app/app/templates/application.gjs
else
echo '<img src="assets/logo.png">' >> 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/
5 changes: 4 additions & 1 deletion ember-cli-rails-assets.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -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
1 change: 1 addition & 0 deletions lib/ember-cli-rails-assets.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
require "ember-cli-rails"
require "ember_cli/assets/engine"

module EmberCli
Expand Down
Loading
Loading