Shoelace

A railsbyte to add shoelace web components to a project.
Icons/chart bar
Used 53 times
Created by
K Konnor Rogers

Usage

Prerequisites


  • Rails 6
  • Node >= 12.10.0
  • Webpacker >= 5

What this Railsbyte does:


it will add the following npm package:


it will modify these files:

  • app/javascript/packs/application.js
  • config/webpack/environment.js
  • app/views/application.html.erb

it will create or modify this file:

  • app/javascript/stylesheets/application.scss

Documentation


Make sure to check out the Shoelace Github Repo and the Shoelace Documentation Site for more info on how to use Shoelace web components in your Rails project.

Special Thanks


Thank you to Nate Hopkins (Hopsoft) for the easy to follow git diff on how to add shoelace.

Thank you to Corey Laviska for creating Shoelace.

Example repo

https://github.com/ParamagicDev/rails-shoelace-example

Run this command in your Rails app directory in the terminal:

rails app:template LOCATION="https://www.railsbytes.com/script/X8BsEb"
Template Source

Review the code before running this template on your machine.

require "fileutils"

run "yarn add @shoelace-style/shoelace copy-webpack-plugin"

javascript_path = File.join("app", "javascript")
stylesheet_path = File.join(javascript_path, "stylesheets")

application_scss_file = File.join(stylesheet_path, "application.scss")
application_js_file = File.join(javascript_path, "packs", "application.js")

# Create a app/javascript/stylesheets/application.scss file if it does not exist.
unless File.exist?(application_scss_file)
  FileUtils.mkdir_p(stylesheet_path)
  FileUtils.touch(application_scss_file)
end


prepend_to_file(application_scss_file) do <<~SCSS
  @import '~@shoelace-style/shoelace/dist/shoelace/shoelace';
  SCSS
end


append_to_file(application_js_file) do <<~JS
  import '../stylesheets/application.scss'
  import { defineCustomElements, setAssetPath } from '@shoelace-style/shoelace'
  
  setAssetPath(document.currentScript.src)
  
  // This will import all shoelace web components for convenience.
  // Check out the webpack documentation below on selective imports.
  // https://shoelace.style/getting-started/installation?id=using-webpack
  defineCustomElements()
  JS
end

webpack_environment_file = File.join("config", "webpack", "environment.js")
environment_string = "const { environment } = require('@rails/webpacker')\n"

inject_into_file(webpack_environment_file, after: environment_string) do <<~JS
  const path = require('path')
  const CopyPlugin = require('copy-webpack-plugin')

  environment.plugins.append(
    'CopyPlugin',
    new CopyPlugin({
      patterns: [
        {
          from: path.resolve(
            __dirname,
            '../../node_modules/@shoelace-style/shoelace/dist/shoelace/icons'
          ),
          to: path.resolve(__dirname, '../../public/packs/js/icons')
        }
      ]
    })
  )
  JS
end

def string_exists_in_file?(file:, string:)
  return true if File.foreach(file).grep(/#{string}/).any?
  
  false
end

application_view = File.join("app", "views", "layouts", "application.html.erb")
application_stylesheet_tag = "<%= stylesheet_pack_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>"

return if string_exists_in_file?(file: application_view, string: application_stylesheet_tag)

inject_into_file("app/views/layouts/application.html.erb", before: "</head>") do <<~HTML
  #{application_stylesheet_tag}
  
  HTML
end
Comments
Patrick Baselier
Nice. I found out I had to use copy-webpack-plugin version 6.4.1, since the latest (7.0.0 at the time of writing) caused a `TypeError: compilation.getCache is not a function` error when starting `bin/webpack-dev-server`. I used Rails 6.1.0.