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

Generate compiled stylesheets / js #183

Merged
merged 18 commits into from
May 25, 2020
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,6 @@ yarn-debug.log*
.DS_Store
.vscode
Brewfile.lock.json
/dist
.sass-cache
/tmp
7 changes: 4 additions & 3 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -222,8 +222,6 @@ GEM
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.3.0)
ffi (~> 1.9)
sassc-rails (2.1.2)
Expand All @@ -250,6 +248,8 @@ GEM
tilt (2.0.10)
tzinfo (1.2.7)
thread_safe (~> 0.1)
uglifier (4.2.0)
execjs (>= 0.3.0, < 3)
unicode-display_width (1.4.1)
virtus (1.0.5)
axiom-types (~> 0.1)
Expand Down Expand Up @@ -281,8 +281,9 @@ DEPENDENCIES
rspec-rails
rspec_junit_formatter
rubocop (~> 0.64.0)
sass-rails
sassc-rails
selenium-webdriver
uglifier

BUNDLED WITH
1.17.3
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,11 @@ If the gem is being used in another project's Gemfile, the source can be locally
When finish, just revert the Gemfile to the original version and `bundle install` again.


### How do I use this outside a Ruby project?
Run `rake assets:package`

Check the `dist` directory for all the assets required and copy/paste them into your project!

### Running tests

A small test suite is available—please add to it!
Expand Down
18 changes: 18 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,22 @@ namespace :lint do
end
end

namespace :assets do
desc "Package JS and CSS assets to /dist for use externally."
task :package do
require "tasks/distribution"
require "sprockets"
add_jquery_to_path
Distribution.new
puts "Assets generated to /dist"
end
end

def add_jquery_to_path
jquery_path = Dir.entries("#{Gem.paths.home}/gems/").detect do |dir|
dir.match(/jquery-rails(.*)/)
end
$LOAD_PATH.unshift("#{Gem.paths.home}/gems/#{jquery_path}/vendor/")
end

task default: %w(lint:autocorrect spec)
3 changes: 2 additions & 1 deletion cfa-styleguide.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ Gem::Specification.new do |spec|
spec.add_development_dependency "rspec-rails"
spec.add_development_dependency "rspec_junit_formatter"
spec.add_development_dependency "rubocop", "~> 0.64.0"
spec.add_development_dependency "sass-rails"
spec.add_development_dependency "sassc-rails"
spec.add_development_dependency "selenium-webdriver"
spec.add_development_dependency "uglifier"
end
31 changes: 31 additions & 0 deletions lib/sprockets_extension/uglifier_source_maps_compressor.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
require "sprockets/digest_utils"
require "sprockets/uglifier_compressor"

class UglifierSourceMapsCompressor < Sprockets::UglifierCompressor
def call(input)
data = input.fetch(:data)
name = input.fetch(:name)

uglifier ||= Sprockets::Autoload::Uglifier.new
compressed_data, sourcemap_json = uglifier.compile_with_map(input[:data])

sourcemap = JSON.parse(sourcemap_json)
sourcemap["sources"] = [name + ".js"]
sourcemap["sourceRoot"] = Dir.pwd
sourcemap["sourcesContent"] = [data]
sourcemap_json = sourcemap.to_json

sourcemap_filename = "honeycrisp.min.js.map"
sourcemap_path = "#{Dir.pwd}/dist/js/#{sourcemap_filename}"
sourcemap_url = sourcemap_filename

FileUtils.mkdir_p File.dirname(sourcemap_path)
File.open(sourcemap_path, "w") { |f| f.write sourcemap_json }

compressed_data.concat "\n//# sourceMappingURL=#{sourcemap_url}\n"
end

def digest(io)
Sprockets::DigestUtils.pack_hexdigest Sprockets::DigestUtils.digest(io)
end
end
119 changes: 119 additions & 0 deletions lib/tasks/distribution.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
require "fileutils"
require "sassc"
require "sprockets_extension/uglifier_source_maps_compressor"

class Distribution
DIST_PATH = "#{Dir.pwd}/dist".freeze
SCSS_PATH = "#{DIST_PATH}/scss".freeze
CSS_PATH = "#{DIST_PATH}/css".freeze
JS_PATH = "#{DIST_PATH}/js".freeze
STYLESHEET_PATH = "#{SCSS_PATH}/cfa_styleguide_main.scss".freeze
ASSET_PATHS = [
SCSS_PATH,
"#{Dir.pwd}/app/assets/javascripts/",
"#{Dir.pwd}/app/assets/stylesheets/",
"#{Dir.pwd}/vendor/assets/javascripts/",
"#{Dir.pwd}/vendor/assets/stylesheets/",
"#{DIST_PATH}/vendor/bourbon",
"#{DIST_PATH}/vendor/neat",
].freeze

def initialize
create_directories
move_assets
install_dependencies
compile_css
compile_js
end

private

def create_directories
FileUtils.rm_rf(%W(#{DIST_PATH} #{Dir.pwd}.sass-cache #{Dir.pwd}/tmp))
FileUtils.mkdir_p("#{DIST_PATH}/vendor")
FileUtils.mkdir_p(CSS_PATH)
FileUtils.mkdir_p(SCSS_PATH)
end

def move_assets
FileUtils.cp_r("#{Dir.pwd}/app/assets/fonts", DIST_PATH)
FileUtils.cp_r("#{Dir.pwd}/app/assets/images", DIST_PATH)
FileUtils.cp_r("#{Dir.pwd}/app/assets/stylesheets/.", SCSS_PATH)
end

def compile_css
scss_file = File.read(Dir.pwd + "/app/assets/stylesheets/cfa_styleguide_main.scss")

load_paths = [
"#{Dir.pwd}/app/assets/stylesheets/",
"#{Dir.pwd}/vendor/assets/stylesheets/",
"#{DIST_PATH}/vendor/bourbon",
"#{DIST_PATH}/vendor/neat",
]

compile_css_with_sourcemaps(scss_file, "honeycrisp.css", load_paths)
compile_css_with_sourcemaps(scss_file, "honeycrisp.min.css", load_paths, compressed: true)
end

def compile_js
sprockets = create_sprockets_env
js_assets = "#{Dir.pwd}/app/assets/javascripts/cfa_styleguide_main.js"
assets = sprockets.find_asset(js_assets)
assets.write_to("#{JS_PATH}/honeycrisp.js")

sprockets = create_sprockets_env(compress: true)
assets = sprockets.find_asset(js_assets)
assets.write_to("#{JS_PATH}/honeycrisp.min.js")
end

def jquery_path
$LOAD_PATH.detect { |path| path.match(/jquery-rails(.*)\/vendor/) }
end

def create_sprockets_env(compress: false)
Sprockets::Environment.new do |env|
env.js_compressor = :uglify_with_source_maps if compress
env.append_path("#{jquery_path}/assets/javascripts/") # Can't find the method when inside ASSET_PATHS?
ASSET_PATHS.each do |path|
env.append_path(path)
end
env.context_class.class_eval do
def asset_path(path, options = {})
case options[:type]
when :image
"/dist/images/#{path}"
when :font
"/dist/fonts/#{path}"
end
end
end
end
end

def install_dependencies
`bourbon install --path dist/vendor && neat install`
FileUtils.move("#{Dir.pwd}/neat", "#{DIST_PATH}/vendor")

Sprockets.register_compressor(
"application/javascript",
:uglify_with_source_maps,
UglifierSourceMapsCompressor,
)
end

def compile_css_with_sourcemaps(scss_file, css_filename, load_paths, compressed: false)
options = { filename: css_filename,
output_path: "#{CSS_PATH}/#{css_filename}",
source_map_file: "#{CSS_PATH}/#{css_filename}.map",
load_paths: load_paths }

options[:style] = :compressed if compressed

engine = SassC::Engine.new(scss_file, options)
css = engine.render
File.write("#{CSS_PATH}/#{css_filename}", css)

map = engine.source_map
File.write("#{CSS_PATH}/#{css_filename}.map", map)
end
end
46 changes: 46 additions & 0 deletions spec/system/distribution_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
require "spec_helper"
require "tasks/distribution"

describe "Distribution" do
context "#new" do
it "creates a dist folder" do
Distribution.new
expect(Dir.exist?(Dir.pwd + "/dist")).to be(true)
end

it "creates css from assets" do
Distribution.new
expect(File.exist?(Dir.pwd + "/dist/css/honeycrisp.css")).to be(true)
end

it "creates css sourcemaps from assets" do
Distribution.new
expect(File.exist?(Dir.pwd + "/dist/css/honeycrisp.css.map")).to be(true)
end

it "creates minified css from assets" do
Distribution.new
expect(File.exist?(Dir.pwd + "/dist/css/honeycrisp.min.css")).to be(true)
end

it "creates css sourcemaps from assets" do
Distribution.new
expect(File.exist?(Dir.pwd + "/dist/css/honeycrisp.min.css.map")).to be(true)
end

it "copies js from assets" do
Distribution.new
expect(File.exist?(Dir.pwd + "/dist/js/honeycrisp.js")).to be(true)
end

it "creates minified js from assets" do
Distribution.new
expect(File.exist?(Dir.pwd + "/dist/js/honeycrisp.min.js")).to be(true)
end

it "creates js source map from assets" do
Distribution.new
expect(File.exist?(Dir.pwd + "/dist/js/honeycrisp.min.js.map")).to be(true)
end
end
end