I am working on a sort of CMS project where I am leveraging SCSS. I would like to allow the user to specify properties of a stylesheet in a simple way (enable a few color customization), and then generate a CSS file based on SCSS templates, and substitute some variables in the SCSS file using mustache or ERB evaluation.
Basically, I want an ERB file to be rendered as scss file, and then generate a css in my application, upload it to S3, and include in the user's layout.
If possible I would like to avoid using css.erb files :-)
I fact (I am answering my own question). What I am trying to do is really easy. I've made this really simple script:
#!/usr/bin/env ruby
#processs.rb file
require 'sass'
result = Sass.compile open(ARGV[0]).read
puts result
And it generates css out of a scss file she invoked like this:
ruby process.rb myfile.css.scss
And this works perfectly. The code documentation in sass source code helped me to find this out.
Related
Our application is a collection of 3 engines that make up our base gem. Other plugin gems, written specifically for our base gem, can be used to add functionality to the base.
Currently we have 2 custom sprockets directives and 1 custom Sass importer that attempts to pull in SCSS files from these plugins dynamically into the base manifest. A contrived example looks something like:
//= depend_on_gemfile # mimics default "depend_on" functionality
//= depend_on_stylesheets # mimics default "depend_on" functionality
...
#import 'engine/namespace/settings/global';
#import 'engine/namespace/settings/colors';
#import 'engine/namespace/settings/fonts';
#import '[engine-plugins]/namespace/settings'; # mimics Sass Filesystem importer
...
To be clear, this works. We're having problems with the way Sass is caching the files, that is a bit too complicated to get into and not really my goal at the moment.
The point is that we realized that removing the custom Sprockets directives and Sass importer, in favor of using a Rails helper, would also solve our problem, since the ERB would be compiled before the SCSS, we'd be able to find and format all of the paths needed in all included plugins into a string and dump it out into the manifest. Something like:
#import 'engine/namespace/settings/global';
#import 'engine/namespace/settings/colors';
#import 'engine/namespace/settings/fonts';
<%= load_plugin_stylesheets_for('settings'); %>
...
This seems like a much more simple solution, since all we are doing is finding each path and converting those paths to strings.
The problem seems to be that Rails helpers are outside of domain of Sprockets entirely.
I've found some resources, but they all seem to pertain to Rails 3.
Add custom methods to Rails 3.1 asset pipeline?
https://github.com/rails/rails/issues/3282
I'm curious if anyone has had this problem with Rails 4, if they solved it and how. Or if I'm just thinking about this all wrong and there is a better way to approach the problem without a similar over-complication like we had before.
TL;DR
I'd like to use regular Rails helpers inside of a Sprockets manifest file. The Rails version is 4.2.4. We're running engines. Is this possible?
EDIT:
This comment answered my question.
After implementing this solution in an initializer within our engine.rb file, all of the Rails ActionView Helpers were available, including my custom written helper.
We had a similar issue a while ago.
application.scss (within gem) looks like this:
/*
*= require_tree .
*= require_self
*/
#import "c3.min";
#import "analytics";
and gemspec contains line for including all the code from app folder.
Gem::Specification.new do |s|
s.files = Dir['{app,config,db,lib}/**/*', 'MIT-LICENSE', 'Rakefile', 'README.rdoc']
end
Be sure to check that you don't have any caching enabled in env files as well.
I am using Ruby on Rails 4 on RubyMine 6. I have a somefile.css.scss.erb file in app/assets/stylesheets/somefolder. I am using SCSS and I need ERB to use asset_url helper to write paths for background properties.
The problem is that when I use both SCSS and ERB extensions I get "cannot find variable" warning everywhere I use SCSS variables(In uses but not in initializations). Is there any way to make RubyMine parse .scss.erb files correctly?
It works fine. I'm just not comfortable with these warnings.
You don't need to do that. Just rename the file to somefile.css.scss and use the SCSS image-url helper.
image-url("rails.png")
is translated into
url(/assets/rails.png)
Smarter minds than mine:
We have several SCSS partials which define mixins, variables, and other useful goodies. We now have need of using some embedded ruby in one of these partials, like so:
_partial.scss.erb
$text-color: #555555;
<%= "" %>
app.scss
#import "partial"
.text {color: $text-color;}
If the file is named _partial.scss it works fine (without any ruby, of course). When named .erb I get an error that the variable $text-color is not defined.
I'm using the sass_rails_patch gem. I can't say for sure, but I believe the _partial.scss.erb is being compiled all the way into _partial.css and then being imported into app.scss. This may be why $text-color is getting stripped out.
Any advice on how to get this flow working the way I expect? I would expect:
Evaluate ruby in .erb files, generate valid .scss.
Run #import statements on .scss
Do all the other SCSS compilation stuff, generate .css.
You most likely want to use Ruby script in your SCSS files in order to build asset paths (and that MUST be the only reason). If this is the reason, you can use SCSS functions to build them up :
Instead of:
background-image: url(<%= asset_path('general/side_shadow.png') %>);
Use this CSS/SCSS function instead:
background-image: url(asset-path("general/side_shadow.png", image));
Here's the doc for SCSS helpers : http://rubydoc.info/github/petebrowne/sprockets-sass/master/Sprockets/Sass/Functions
Hope this helps
I'm trying to allow the user to customize my application using YML files.
When the user updates certain things the CSS needs to be updated as well.
I'd like to solve this problem using dynamic CSS instead. The way I was planning on doing this is to have a settings SCSS file which the other css files import and use.
Here is what I have so far:
settings.scss.erb:
$width: <%= Rails.application.config.width %>px;
main.css.scss:
//= require settings
#import "settings";
#main {
width: $width;
}
But I get this error:
Invalid CSS after "$width: ": expected expression (e.g. 1px, bold), was "<%= Rails.appli..."`
So It seems that the settings are not being passed through the erb parser before being handed off to the SCSS parser, is there any way to solve this.
I'd rather not put everything in .erb files since my text editor doesn't support (syntax highlighting and commands) when having scss in erb files
Side stepping the problem where ERB is not being parsed, you are not going to be able to customize the CSS dynamically (I think the main file may require an erb extension). The asset pipeline is designed to serve assets in a way that tells browsers that the are static and are not going to change.
Assuming the erb parsing was working, the width would be rendered during the precompile phase, or on the first request. If you are using Sprockets far-future headers are set to tell the remote clients to cache the content for 1 year. And Sprockets only picks up changes if the timestamp of the file changes, so would never get any new values.
You could force Sprockets to dynamically serve every request, and to not send any headers, but it is not really designed for this and there are significant performance risks in doing so.
Is it possible to use haml within a coffeescript file in a rails 3.1 project?
What is the correct order of the file extensions?
My last try was that:
home.js.haml.coffescript
$ ->
alert '#{#count}'
where #count is a ruby variable.
The correct order would be home.js.coffeescript.haml—you want the file to first be evaluated as Haml to give you your variables, then compiled as CoffeeScript, then finally served as JavaScript.
However, I strongly suspect that the Haml processor will choke on some CoffeeScript syntax. It would probably be safer to use ERB, which should work for your example.