Convert SASS to CSS using SASS gem - ruby

I am trying to create a CSS file from SASS file.
I tried to do this at first.
sass_filename = "#{Rails.root}/app/assets/stylesheets/application.sass"
css = Sass::Engine.for_file(sass_filename).render
File.open("#{render_path}/stylesheets/application.css", "wb") {|f| f.write(css) }
I got error wrong number of arguments (1 for 2) on Sass::Engine.for_file() because I didn't put anything for options field.
I am not sure how I can set the options field.
I tried
css = Sass::Engine.for_file(sass_filename, :syntax => :sass).render
but I got undefined method[]' for nil:NilClass` error.
How do I set the default option for converting SASS to CSS ?

If you are not passing any options try using an empty hash, e.g. '{}', for options:
sass_filename = "#{Rails.root}/app/assets/stylesheets/application.sass"
css = Sass::Engine.for_file(sass_filename, {}).render
File.open("#{render_path}/stylesheets/application.css", "wb") {|f| f.write(css) }

Related

Add CSS minifier to Sprockets

I have a web application which uses rack.
The code:
set :assets, (Sprockets::Environment.new { |env|
env.js_compressor = Uglifier.new({
:output => {
:preserve_line => true,
:bracketize => true,
:beautify => true,
:indent_level => 4,
:semicolons => true,
},
:mangle => false
})
env.append_path(APP_ROOT + "/app/assets/images")
env.append_path(APP_ROOT + "/app/assets/javascripts")
env.append_path(APP_ROOT + "/app/assets/stylesheets")
})
I now want to add a CSS minifier to it.
Can someone explain why only javascript files are taken into the JS compressor above?
Can I add something like env.css_compressor = YUI::CssCompressor.new() after the JS_compressor to get my requirement done
UPDATE: Well the second actually worked. But I have no clue how it worked :)
You hadn't set up the Sprockets::Environment.css_compressor variable, so there was no compressor available to run on text/css assets.
puts Sprockets::Environment.methods.inspect
#=> [...#css_compressor, #css_compressor=, #js_compressor, #js_compressor=,...]
To answer your question about how assets are loaded, yes the default is to point to one load path and you can as well manipulate that to include others.
https://github.com/sstephenson/sprockets
The load path is an ordered list of directories that Sprockets uses to
search for assets. To add a directory to your environment's load path, use the append_path and prepend_path methods.

Passing liquid file to Liquid::Template.parse

Right now I am able to do this:
#template = Liquid::Template.parse("hi {{name}}") # Parses and compiles the template
p #template.render('name' => 'tobi')
However, how can I call Liquid::Template with a file that I have called template.liquid that has the content:
hi {{name}}
File.read() returns the whole file as a string, so you can write:
template = Liquid::Template.parse(
File.read("template.liquid")
)

Add image from URL to Excel with Axlsx

I'm using the (Axlsx gem and it's working great, but I need to add an image to a cell.
I know it can be done with an image file (see Adding image to Excel file generated by Axlsx.?), but I'm having a lot of trouble using our images stored in S3 (through Carrierwave).
Things I've tried:
# image.url = 'http://.../test.jpg'
ws.add_image(:image_src => image.url,:noSelect => true, :noMove => true) do |image|
# ArgumentError: File does not exist
or
ws.add_image(:image_src => image,:noSelect => true, :noMove => true) do |image|
# Invalid Data #<Object ...>
Not sure how to proceed
Try using read to pull the contents into a tempfile and use that location:
t = Tempfile.new('my_image')
t.binmode
t.write image.read
t.close
ws.add_image(:image_src => t.path, ...
To add an alternative answer for Paperclip & S3 as I couldn't find a reference for that besides this answer.
I'm using Rails 5.0.2 and Paperclip 4.3.1.
With image URLs like: http://s3.amazonaws.com/prod/accounts/logos/000/000/001/original/logo.jpg?87879987987987
#logo = #account.company_logo
if #logo.present?
#logo_image = Tempfile.new(['', ".#{#logo.url.split('.').last.split('?').first}"])
#logo_image.binmode # note that our tempfile must be in binary mode
#logo_image.write open(#logo.url).read
#logo_image.rewind
end
In the .xlsx file
sheet.add_image(image_src: #logo_image.path, noSelect: true, noMove: true, hyperlink: "#") do |image|...
Reference link: http://mensfeld.pl/tag/tempfile/ for more reading.
The .split('.').last.split('?').first is to get .jpg from logo.jpg? 87879987987987.

Nanoc + Bower = Error - Found 2 content files for

I'm using nanoc to generate an static site.
Recently I added Bower to manage front end dependencies.
When I add Bootstrap via Bower I place the package in /assets/bower/
The Bootstrap package contains multiple files, including:
bootstrap/js/tests/vendor/qunit.css
bootstrap/js/tests/vendor/qunit.js
My Rules file has these rules:
route '/assets/*' do
extension = item[:extension]
if extension == 'coffee'
extension = 'js'
end
item.identifier.chop + '.' + extension
end
compile '*', :rep => :spec do
if !item[:spec_files].nil? && !item.binary?
filter :erb
layout 'spec'
end
end
route '*', :rep => :spec do
if !item[:spec_files].nil? && !item.binary?
'/specs' + #item.identifier[0..-2] + '.html'
end
end
compile '*' do
if !item.binary?
filter :erb
layout_name = item[:layout] || 'default'
layout layout_name
end
end
route '*' do
if item.binary?
item.identifier.chop + '.' + item[:extension]
else
item.identifier[0..-2] + '.html'
end
end
When running nanoc I get the following error:
RuntimeError: Found 2 content files for
content/assets/bower/bootstrap/js/tests/vendor/qunit; expected 0 or 1
I tried adding 2 new 'empty' rules for the /assets/bower/ folder but still getting the error.
route '/assets/bower/*' do
end
compile '/assets/bower/*' do
end
Any suggestions?
Later edit:
Looks like nanoc supports a static datasource that also takes in consideration the file extension.
https://github.com/nanoc/nanoc-site/blob/master/content/docs/troubleshooting.md
Still not sure if I can use both data sources in parallel.
Unfortunately, you can't have two files in the same directory with the same name before the last extension. For nanoc 4.0 it'll be rewritten to change that.
You can definitely have multiple data sources used at once, but that means you can't apply filters to the qunit files, only redirect the output.
Do you explicitly have to be able to organise files the same as Bower installs them? It might be a better idea to split them up into scripts and styles if you can, anyway - you'll almost certainly be filtering based on filetype, anyway, and that means in Rules you can just go
compile '/whatever-path/scripts/' do
filter :concatenate
filter :uglify_js
end
rather than
compile '/whatever-path/ do
case item[:extension]
when 'js'
filter :uglify_js
when 'scss'
filter :sass
end
end

Shopify Theme with Compass and Sass

Does anyone have a workflow for developing Shopify themes with Compass and Sass? I am really close, I just need to figure out how to not make Sass barf on the CSS liquid tags.
Here's what I've got:
A sass/compass project in directory (ex:, "/newwebsite/)
A subdirectory containing my Shopify theme ("/newwebsite/newwebsite-theme/")
A Compass config.rb that points the css,_dir images_dir and javascripts_dir all to the them's assets folder ("/newwebsite/newwebsite-theme/assets/")
Compass watch on
shopify_theme gem also watch on, uploading theme files to shopify (https://github.com/Shopify/shopify_theme)
EDIT Sass interpolations (see anser below)
EDIT Compass callback to rename to .css.liquid
The problem: Compass barf's when you need to use Shopify's liquid templating tags, for example, a background image - example, background: url( "{{ "splash-1.jpg" | asset_url }}")
Does anyone know how to instruct Compass / Sass to spit out the liquid template tags as they are into the CSS? If I have that, then I have a solid workflow of editing Sass locally, and realizing the changes momentarily after on the shopify shop.
Thanks
EDIT:
By using Hopper's answer below for the liquid tags in Sass, and renaming the Compass output .css file to .css.liquid, I now have an instantaneous workflow for designing a Shopify theme with Compass and Sass!
Here is the code for the Compass callback that goes in the config.rb:
on_stylesheet_saved do |filename|
s = filename + ".liquid"
puts "copying to: " + s
FileUtils.cp(filename, s)
puts "removing: " + filename
end
I'm not familiar with Shopify or liquid tags, but I do know that in SASS you can use interpolations to output plain CSS as-is. For example, the SASS here:
.test {
background: url( #{'{{ "splash-1.jpg" | asset_url }}'} )
}
Would be compiled to:
.test {
background: url({{ "splash-1.jpg" | asset_url }}); }
Does that get you close to what you're looking for?
How do you keep Compass from barfing on liquid logic between properties? E.g. any time there's a liquid if statement I get errors, and using #{'...'} doesn't seem to help.
This is a test I can't get to work:
#container {
width:884px;
margin:0px auto;
min-height:500px;
position:relative;
padding:0 40px;
{% if settings.page_bg_transparent %}
background:transparent;
{% else %}
background:{{ settings.page_bg_color }};
{% endif %}
}
UPDATE weirdly, commenting liquid logic works:
#container {
width:884px;
margin:0px auto;
min-height:500px;
position:relative;
padding:0 40px;
/* {% if settings.page_bg_transparent %} */
background:transparent;
/* {% else %} */
background:#{'{{ settings.page_bg_color }}'};
/* {% endif %} */
}
For asset url you can also use SCSS custom functions.
Put this in your config.rb file
module Sass::Script::Functions
def shopify_image_url(string)
assert_type string, :String
Sass::Script::String.new("url({{'#{string.value}' | asset_url}})")
end
end
And then use it in your styles.scss like this
background: shopify_image_url('image.png');
I found it useful to remove the original output file after save so you don't have that extra, non liquid file floating in the assets dir.
on_stylesheet_saved do |filename|
s = filename + ".liquid"
puts "copying to: " + s
FileUtils.cp(filename, s)
puts "removing: " + filename
FileUtils.remove_file(filename)
end
Building on hopper's answer, for anyone using autoprefixer to process sass output, you would need to add an additional pair of quotes because url( {{ ... }} ) causes autoprefixer's parser to choke.
Do this:
background: url( "#{'{{ "splash-1.jpg" | asset_url }}'}" )
Which becomes this in the *.css.liquid file :
background: url( '{{ "splash-1.jpg" | asset_url }}' )
If you wish to preserve the ".scss.liquid" extension for the new responsive checkout use:
on_stylesheet_saved do |filename|
FileUtils.mv filename, "#{File.dirname(filename)}/#{File.basename(filename,'.*')}.scss.liquid"
end
It renames the files instead of copying and then removing.
I wrote an article describing the methods I used to get Compass and Sass working well with Shopify. This is the same approach of DOMUSNETWORK's answer. I go into a little more detail on file structure.
http://www.mealeydev.com/blog/shopify-and-sass/
This worked for me, partially - however I found that the Shopify Theme app a lot of times didn't want to upload my edited .css.liquid file, because apparently it didn't recognize that the file had been edited.
What solved it for me was to use the following code in my config.rb, instead of the code in the question above:
on_stylesheet_saved do |filename|
move_to = filename + ".liquid"
puts "Moving from #{filename} to #{move_to}"
FileUtils.mv(filename, move_to)
end
Shameless plug...
I think #nick is on the right track.
scss is better when it's compiled before sending to Shopify.
For others who find this answer, I think Quickshot is the tool you are looking for.
You will still need to interpolate for asset urls, but quickshot will automatically recompile your scss and upload the result to shopify in one step. Which also gives you the ability to use #include in your scss files.
http://quickshot.io/
https://github.com/internalfx/quickshot

Resources