diff --git a/.gitignore b/.gitignore index b268508..ec4f801 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,132 @@ +# Created by https://www.toptal.com/developers/gitignore/api/ruby,macos,linux,windows +# Edit at https://www.toptal.com/developers/gitignore?templates=ruby,macos,linux,windows + +### Linux ### +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### macOS Patch ### +# iCloud generated files +*.icloud + +### Ruby ### +*.gem +*.rbc +/.config +/coverage/ +/InstalledFiles +/pkg/ +/spec/reports/ +/spec/examples.txt +/test/tmp/ +/test/version_tmp/ +/tmp/ + +# Used by dotenv library to load environment variables. +# .env + +# Ignore Byebug command history file. +.byebug_history + +## Documentation cache and generated files: +/.yardoc/ +/_yardoc/ +/doc/ +/rdoc/ + +## Environment normalization: +/.bundle/ +/vendor/bundle +/lib/bundler/man/ + +## Ignore bundler config: .bundle/ + +## Ignore all logfiles and tempfiles. log/*.log -pkg/ + +## Ignore tempfiles created by testing frameworks. test/dummy/db/*.sqlite3 test/dummy/db/*.sqlite3-journal test/dummy/log/*.log test/dummy/tmp/ test/dummy/.sass-cache -*.gem + +# for a library or gem, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# Gemfile.lock +# .ruby-version +# .ruby-gemset + +# unless supporting rvm < 1.11.0 or doing something fancy, ignore this: +.rvmrc + +# Used by RuboCop. Remote config files pulled in from inherit_from directive. +# .rubocop-https?--* + +### Windows ### +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# End of https://www.toptal.com/developers/gitignore/api/ruby,macos,linux,windows diff --git a/CHANGELOG.md b/CHANGELOG.md index 6191fde..f995c13 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,44 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2.4.0] - 2025-12-30 + +### Added + +- Adds a `help` target in the Makefile to list available commands +- Introduced Propshaft asset pipeline support (Rails 8+) alongside existing + Sprockets compatibility +- Refactored Engine initialiser to automatically register framework gem asset + paths (govuk_template, govuk_elements_rails, bootstrap-sass, + font-awesome-rails, govuk_frontend_toolkit) +- Added development environment logging for asset path registration in debug + mode +- Added `make compile` target to clobber and precompile gem assets; also run via + make assets for consistent builds +- Includes code guards to ensure asset pipeline configuration only runs when + assets pipeline is available + +### Changed + +- Replaced `sass-rails` with `dartsass-rails` as primary SCSS compiler + dependency +- Refactored SCSS entrypoint (`lr_common_styles.scss`) to contain only internal + Common Styles imports; host applications are now responsible for importing + framework dependencies +- Updated `app/assets/config/manifest.js` to remove incorrect stylesheet + directory link and duplicate build references +- Test dummy app configuration also now guards asset configuration with + `respond_to?(:assets)` check for compatibility with Propshaft/Sprockets +- Gem initialiser configuration now conditional on asset pipeline presence, + enabling seamless operation in both Sprockets and Propshaft environments + +### Fixed + +- Clarified asset dependency structure through updated documentation in SCSS + entrypoint +- Removed misleading configuration directives that conflicted with host + application asset compilation + ## [2.3.1] - 2025-10 ### Changed diff --git a/Gemfile b/Gemfile index cfb108a..b86fca9 100644 --- a/Gemfile +++ b/Gemfile @@ -20,6 +20,7 @@ group :development, :test do gem 'rubocop' gem 'rubocop-ast' gem 'rubocop-rails' + gem 'sprockets-rails' # Required for test dummy app end group :development do diff --git a/Gemfile.lock b/Gemfile.lock index 210a7f1..fa49247 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,8 +1,9 @@ PATH remote: . specs: - lr_common_styles (2.3.1) + lr_common_styles (2.4.0.beta) bootstrap-sass (~> 3.4.1) + dartsass-rails (~> 0.5.1) font-awesome-rails (~> 4.7.0) govuk_elements_rails (= 3.0.2) govuk_frontend_toolkit (~> 9.0) @@ -13,7 +14,6 @@ PATH modernizr-rails (~> 2.7) modulejs-rails (~> 2.2.0) rails (~> 8.0) - sass-rails (~> 6.0) GEM remote: https://rubygems.org/ @@ -107,6 +107,9 @@ GEM concurrent-ruby (1.3.5) connection_pool (2.5.4) crass (1.0.6) + dartsass-rails (0.5.1) + railties (>= 6.0.0) + sass-embedded (~> 1.63) date (3.5.0) diff-lcs (1.6.2) drb (2.2.3) @@ -127,6 +130,33 @@ GEM railties (>= 3.2, < 9.0) globalid (1.3.0) activesupport (>= 6.1) + google-protobuf (4.33.2) + bigdecimal + rake (>= 13) + google-protobuf (4.33.2-aarch64-linux-gnu) + bigdecimal + rake (>= 13) + google-protobuf (4.33.2-aarch64-linux-musl) + bigdecimal + rake (>= 13) + google-protobuf (4.33.2-arm64-darwin) + bigdecimal + rake (>= 13) + google-protobuf (4.33.2-x86-linux-gnu) + bigdecimal + rake (>= 13) + google-protobuf (4.33.2-x86-linux-musl) + bigdecimal + rake (>= 13) + google-protobuf (4.33.2-x86_64-darwin) + bigdecimal + rake (>= 13) + google-protobuf (4.33.2-x86_64-linux-gnu) + bigdecimal + rake (>= 13) + google-protobuf (4.33.2-x86_64-linux-musl) + bigdecimal + rake (>= 13) govuk_elements_rails (3.0.2) govuk_frontend_toolkit (>= 5.2.0) rails (>= 4.1.0) @@ -318,19 +348,30 @@ GEM rubyzip (2.4.1) sass (3.7.4) sass-listen (~> 4.0.0) + sass-embedded (1.97.1) + google-protobuf (~> 4.31) + rake (>= 13) + sass-embedded (1.97.1-aarch64-linux-gnu) + google-protobuf (~> 4.31) + sass-embedded (1.97.1-aarch64-linux-musl) + google-protobuf (~> 4.31) + sass-embedded (1.97.1-arm-linux-gnueabihf) + google-protobuf (~> 4.31) + sass-embedded (1.97.1-arm-linux-musleabihf) + google-protobuf (~> 4.31) + sass-embedded (1.97.1-arm64-darwin) + google-protobuf (~> 4.31) + sass-embedded (1.97.1-x86_64-darwin) + google-protobuf (~> 4.31) + sass-embedded (1.97.1-x86_64-linux-gnu) + google-protobuf (~> 4.31) + sass-embedded (1.97.1-x86_64-linux-musl) + google-protobuf (~> 4.31) sass-listen (4.0.0) rb-fsevent (~> 0.9, >= 0.9.4) rb-inotify (~> 0.9, >= 0.9.7) - sass-rails (6.0.0) - sassc-rails (~> 2.1, >= 2.1.1) sassc (2.4.0) ffi (~> 1.9) - sassc-rails (2.1.2) - railties (>= 4.0.0) - sassc (>= 2.0) - sprockets (> 3.0) - sprockets-rails - tilt securerandom (0.4.1) solargraph (0.57.0) backport (~> 1.2) @@ -412,6 +453,7 @@ DEPENDENCIES rubocop-rails ruby-lsp solargraph + sprockets-rails BUNDLED WITH - 2.7.1 + 2.7.2 diff --git a/Makefile b/Makefile index 76418dd..2fa8b2b 100644 --- a/Makefile +++ b/Makefile @@ -21,42 +21,60 @@ ${GEM}: ${SPEC} ./lib/${NAME}/version.rb all: publish -assets: auth - @echo "Installing all packages ..." - @bundle install +assets: auth bundle compile ## Compile assets for gem distribution + @echo assets completed. + +auth: ${AUTH} ## Set up authentication for GitHub Packages + @echo "Authentication set up for GitHub Packages." -auth: ${AUTH} +build: gem ## Alias for the gem target + @echo "Built ${GEM}." -build: gem +bundle: ## Install Ruby gems via Bundler + @echo "Installing Ruby gems via Bundler..." + @bundle install -checks: lint test +checks: lint test ## Run all checks: linting and tests + @echo "All checks passed." -clean: +clean: ## Clean up gem files + @echo "Cleaning up ${GEM} files..." @rm -rf ${GEM} -gem: ${GEM} - @echo ${GEM} +compile: ## Compile assets for gem distribution + @echo "Removing old compiled assets and compiling ..." + @rake assets:clobber assets:precompile + +gem: ${GEM} ## Build the gem package + @gem build ${SPEC} + +help: ## Display this message + @echo "Available make targets:" + @grep -hE '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "%-20s %s\n", $$1, $$2}' + @echo "" + @echo "Environment variables (optional: all variables have defaults):" + @make vars -lint: assets +lint: assets ## Run linting checks @echo "Running rubocop..." @bundle exec rubocop -publish: ${AUTH} ${GEM} +publish: ${AUTH} ${GEM} ## Publish the gem to GitHub Packages @echo Publishing package ${NAME}:${VERSION} to ${OWNER} ... @gem push --key github --host ${GPR} ${GEM} @echo Done. -realclean: clean +realclean: clean ## Remove all generated files including authentication @rm -rf ${AUTH} -tags: +tags: ## Show version tags @echo version=${VERSION} -test: assets +test: assets ## Run tests in the dummy application @echo "Running tests..." @rake test -vars: +vars: ## Show important variables @echo "GEM" = ${GEM} @echo "GPR" = ${GPR} @echo "NAME = ${NAME}" diff --git a/app/assets/config/manifest.js b/app/assets/config/manifest.js index 609946e..a2de13e 100644 --- a/app/assets/config/manifest.js +++ b/app/assets/config/manifest.js @@ -1,3 +1,2 @@ //= link_tree ../images //= link_directory ../javascripts/lr_common_styles .js -//= link_directory ../stylesheets/lr_common_styles .css diff --git a/app/assets/stylesheets/lr_common_styles.scss b/app/assets/stylesheets/lr_common_styles.scss new file mode 100644 index 0000000..fbcb8aa --- /dev/null +++ b/app/assets/stylesheets/lr_common_styles.scss @@ -0,0 +1,30 @@ +/* + * Entry point stylesheet for both Sprockets and Propshaft-enabled apps. + * + * This file includes only LR Common Styles internal assets. + * Host applications are responsible for importing framework dependencies: + * @import "govuk-template"; + * @import "govuk-elements"; + * @import "bootstrap-sprockets"; + * @import "bootstrap"; + * @import "font-awesome"; + * @import "lr_common_styles"; + * + * The asset paths for these dependencies are automatically registered by the engine, + * so they will be discoverable when imported directly from host applications. + */ + +// LR Common Styles partials +@import "lr_common_styles/common-elements"; +@import "lr_common_styles/cookie-banner"; +@import "lr_common_styles/header"; +@import "lr_common_styles/footer"; +@import "lr_common_styles/feedback"; +@import "lr_common_styles/lr-common"; + +// Common global styles +@import "skip_to_main"; + +// Gem override stylesheets +@import "lr_common_styles/gov_uk_refine"; +@import "lr_common_styles/bootstrap-refine"; diff --git a/app/assets/stylesheets/lr_common_styles/header.scss b/app/assets/stylesheets/lr_common_styles/_header.scss similarity index 100% rename from app/assets/stylesheets/lr_common_styles/header.scss rename to app/assets/stylesheets/lr_common_styles/_header.scss diff --git a/app/assets/stylesheets/lr_common_styles/_lr-common.scss b/app/assets/stylesheets/lr_common_styles/_lr-common.scss index 5509381..d222508 100644 --- a/app/assets/stylesheets/lr_common_styles/_lr-common.scss +++ b/app/assets/stylesheets/lr_common_styles/_lr-common.scss @@ -27,16 +27,8 @@ $lr-green-nav-darkened: darken($lr-green-nav, 20%); /* elements */ -@import 'common-elements'; - /* objects */ -@import - 'cookie-banner', - 'header', - 'footer', - 'feedback', - 'skip_to_main'; .o-container { @extend %site-width-container; @@ -51,6 +43,3 @@ $lr-green-nav-darkened: darken($lr-green-nav, 20%); .u-font-bold { font-weight: bold; } - -@import 'gov_uk_refine'; -@import 'bootstrap-refine'; diff --git a/app/models/lr_common_config.rb b/app/models/lr_common_config.rb index 4c356c9..91859e2 100644 --- a/app/models/lr_common_config.rb +++ b/app/models/lr_common_config.rb @@ -54,7 +54,7 @@ def set_link_classes(name, classes, root, current_url) if root == false && current_url =~ /#{name}/ classes << 'lr-header--header-proposition--a__active' end - classes.join(' ') if classes.present? + classes.presence&.join(' ') end end end diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index 706fd8c..b08931b 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -13,15 +13,7 @@ = javascript_include_tag "application" = csrf_meta_tags - %link{ rel: "apple-touch-icon", sizes: "180x180", href: image_path( "favicon/apple-touch-icon.png" )} - %link{ rel: "icon", type: "image/png", href: image_path( "favicon/favicon-32x32.png" ), sizes: "32x32"} - %link{ rel: "icon", type: "image/png", href: image_path( "favicon/favicon-16x16.png" ), sizes: "16x16"} - %link{ rel: "manifest", href: image_path( "favicon/manifest.json" )} - %link{ rel: "mask-icon", href: image_path( "favicon/safari-pinned-tab.svg" ), color: "#5bbad5"} - %link{ rel: "shortcut icon", href: image_path( "favicon/favicon.ico" )} - - %meta{ name: "msapplication-config", content: image_path( "favicon/browserconfig.xml" )} - %meta{ name: "theme-color", content: "#ffffff"} + = render partial: "application/favicon" - if @preferences %link{ rel: "canonical", href: "http://#{request.host_with_port}#{@preferences.as_path( :view )}"} diff --git a/bin/rails b/bin/rails index 18497ae..4b89902 100755 --- a/bin/rails +++ b/bin/rails @@ -1,12 +1,18 @@ #!/usr/bin/env ruby -# This command will automatically be run when you run "rails" with Rails 4 gems installed from the root of your application. +# This command will automatically be run when you run "rails" with Rails gems installed from the root of your application. -ENGINE_ROOT = File.expand_path('../..', __FILE__) -ENGINE_PATH = File.expand_path('../../lib/lr_common_styles/engine', __FILE__) +ENGINE_ROOT = File.expand_path('..', __dir__) +ENGINE_PATH = File.expand_path('../lib/lr_common_styles/engine', __dir__) # Set up gems listed in the Gemfile. -ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE']) +# Note: This gem primarily uses ActionView and ActionDispatch (not ActiveRecord, +# ActionController, ActionMailer, etc.). While best practice would be to require +# only specific components (e.g., 'action_view/railtie', 'action_dispatch/railtie'), +# we keep 'rails/all' here since this bin/rails file is only used during gem +# development/testing, not in production. The performance impact is negligible and +# this ensures full Rails functionality is available during development. require 'rails/all' require 'rails/engine/commands' diff --git a/config/initializers/lr_common_styles_assets.rb b/config/initializers/lr_common_styles_assets.rb index c5ecbfb..937140b 100644 --- a/config/initializers/lr_common_styles_assets.rb +++ b/config/initializers/lr_common_styles_assets.rb @@ -1,3 +1,6 @@ # frozen_string_literal: true -Rails.application.config.assets.precompile += %w[favicon/*] +# Only configure asset precompilation if Sprockets is available (Rails < 8 or explicit sprockets-rails) +if Rails.application.config.respond_to?(:assets) + Rails.application.config.assets.precompile += %w[favicon/*] +end diff --git a/lib/lr_common_styles/engine.rb b/lib/lr_common_styles/engine.rb index eb1e7c5..02be111 100644 --- a/lib/lr_common_styles/engine.rb +++ b/lib/lr_common_styles/engine.rb @@ -1,6 +1,53 @@ # frozen_string_literal: true +# :nodoc: module LrCommonStyles + # :nodoc: class Engine < ::Rails::Engine + initializer 'lr_common_styles.assets' do |app| + # Only configure asset paths if an asset pipeline is available + if app.config.respond_to?(:assets) + # Add this gem's asset paths + assets_path = root.join('app', 'assets', 'stylesheets') + unless app.config.assets.paths.include?(assets_path.to_s) + app.config.assets.paths << assets_path + end + + # Add asset paths for gem dependencies so they're discoverable + # when scss files import them + dependency_gems = %w[ + govuk_template + govuk_elements_rails + bootstrap-sass + font-awesome-rails + govuk_frontend_toolkit + ] + + dependency_gems.each do |gem_name| + gem_spec = Gem.loaded_specs[gem_name] + if gem_spec + gem_assets_path = File.join(gem_spec.gem_dir, 'app', 'assets', 'stylesheets') + if File.directory?(gem_assets_path) && app.config.assets.paths.exclude?(gem_assets_path) + app.config.assets.paths << gem_assets_path + end + end + rescue StandardError => e + # Log but don't fail if gem is not available + if Rails.env.development? + Rails.logger.debug do + "Could not add asset path for #{gem_name}: #{e.message}" + end + end + end + end + end + + initializer 'lr_common_styles.debug' do |app| + if Rails.env.development? && app.config.respond_to?(:assets) + puts "\nAsset paths:\n#{app.config.assets.paths.map do |path| + "#{path.inspect}\n" + end.join}\n" + end + end end end diff --git a/lib/lr_common_styles/version.rb b/lib/lr_common_styles/version.rb index 963691c..d7105a4 100644 --- a/lib/lr_common_styles/version.rb +++ b/lib/lr_common_styles/version.rb @@ -2,8 +2,8 @@ module LrCommonStyles MAJOR = 2 - MINOR = 3 - PATCH = 1 - SUFFIX = nil # nil or 'rc' or 'beta' or 'alpha' for pre-release versions - VERSION = "#{MAJOR}.#{MINOR}.#{PATCH}#{SUFFIX && "-#{SUFFIX}"}".freeze + MINOR = 4 + PATCH = 0 + SUFFIX = 'beta' # nil or 'rc' or 'beta' or 'alpha' for pre-release versions + VERSION = "#{MAJOR}.#{MINOR}.#{PATCH}#{SUFFIX && ".#{SUFFIX}"}".freeze end diff --git a/lr_common_styles.gemspec b/lr_common_styles.gemspec index 58db729..8374bb5 100644 --- a/lr_common_styles.gemspec +++ b/lr_common_styles.gemspec @@ -34,9 +34,11 @@ Gem::Specification.new do |spec| # ! Styles is a gem as well, we cannot use a forked repo as a dependency. As a # ! result we are stuck using version 3.0.2 until further investigations provide # ! a better solution. + spec.add_dependency 'govuk_elements_rails', '3.0.2' + spec.add_dependency 'bootstrap-sass', '~> 3.4.1' + spec.add_dependency 'dartsass-rails', '~> 0.5.1' spec.add_dependency 'font-awesome-rails', '~> 4.7.0' - spec.add_dependency 'govuk_elements_rails', '3.0.2' spec.add_dependency 'govuk_frontend_toolkit', '~> 9.0' spec.add_dependency 'govuk_template', '~> 0.26.0' spec.add_dependency 'haml-rails', '~> 3.0' @@ -44,5 +46,4 @@ Gem::Specification.new do |spec| spec.add_dependency 'lodash-rails', '~> 4.17' spec.add_dependency 'modernizr-rails', '~> 2.7' spec.add_dependency 'modulejs-rails', '~> 2.2.0' - spec.add_dependency 'sass-rails', '~> 6.0' end diff --git a/test/dummy/config/application.rb b/test/dummy/config/application.rb index 1305833..23cad7c 100644 --- a/test/dummy/config/application.rb +++ b/test/dummy/config/application.rb @@ -23,12 +23,6 @@ class Application < Rails::Application # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. # config.time_zone = 'Central Time (US & Canada)' - # !DEPRECATION WARNING: `to_time` will always preserve the full system - # ! timezone offset rather than offset of the receiver in Rails 8.1. - # * To opt in to the new behavior and maintain system timezone, - # * set the value to :zone; otherwise, set to false - config.active_support.to_time_preserves_timezone = :zone - # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] # config.i18n.default_locale = :de diff --git a/test/dummy/config/initializers/assets.rb b/test/dummy/config/initializers/assets.rb index 678efe9..2acfd78 100644 --- a/test/dummy/config/initializers/assets.rb +++ b/test/dummy/config/initializers/assets.rb @@ -2,12 +2,15 @@ # Be sure to restart your server when you modify this file. -# Version of your assets, change this if you want to expire all your assets. -Rails.application.config.assets.version = '1.0' +# Only configure assets if an asset pipeline is available (Sprockets or Propshaft) +if Rails.application.config.respond_to?(:assets) + # Version of your assets, change this if you want to expire all your assets. + Rails.application.config.assets.version = '1.0' -# Add additional assets to the asset load path -# Rails.application.config.assets.paths << Emoji.images_path + # Add additional assets to the asset load path + # Rails.application.config.assets.paths << Emoji.images_path -# Precompile additional assets. -# application.js, application.css, and all non-JS/CSS in app/assets folder are already added. -# Rails.application.config.assets.precompile += %w( search.js ) + # Precompile additional assets. + # application.js, application.css, and all non-JS/CSS in app/assets folder are already added. + # Rails.application.config.assets.precompile += %w( search.js ) +end