Provide sass variables definitions on command-line - sass

Is there a standard, or simple, way to define sass variables on the command line, or pass them from the environment? What I am doing is trying to create to different CSS files from a single SCSS source file. Each output file will be specialized for a certain target device and included from the HTML page with media queries.
Update: It looks like this may not be enough. The #if syntax doesn't actually allow conditional sass blocks, only conditional CSS blocks. This means even if I can define a variable it wouldn't allow me to do different processing in the file. Any ideas?

Use SASS custom functions. A complete working example below.
styles.sass:
$primary_color: getenv("SASS_VAR_PRIMARY_COLOR", white)
body
background: $primary_color
sass_functions.rb:
module Sass::Script::Functions
def getenv(name, default)
assert_type name, :String
value = ENV.fetch(name.value, nil)
if not value
return default
end
begin
Sass::Script::Parser.parse(value, 0, 0)
rescue
Sass::Script::String.new(value)
end
end
end
Command line:
SASS_VAR_PRIMARY_COLOR='#123456' sass -r ./sass_functions.rb styles.sass styles.css
If you use Compass, you may put module Sass::Script::Functions directly into config.rb and compile the styles with:
SASS_VAR_PRIMARY_COLOR='#123456' sass --compass styles.sass styles.css

The facility I needed is simply not in SASS. Even if you could define variables on the command-line the "if" facility is insufficient to actually do conditional blocks in the style sheet.
Instead I've resorted to the old stand-by of M4. I simply preprocess the SASS with M4, doing command-line options and full conditional blocks.

I couldn’t find a way to specify sass variables from the command line but you can mimic this behaviour by creating multiple specialized SCSS files that import a base SCSS file.
For example:
// base_style.scss
#debug "* Format = #{$format} *";
#if $format == 1
{
$body-font-family: "Palatino" !global;
}
#else if $format == 2
{
$body-font-family: "Arial" !global;
}
#else
{
#warn "Undefined format";
}
body
{
font-family: $body-font-family;
}
// style_1.scss
$format: 1;
#import "base_style.scss";
// style_2.scss
$format: 2;
#import "base_style.scss";
Then from the command line:
sass style_1.scss style_1.css
sass style_2.scss style_2.css
Note that you can also specify the rules for different target media in one single (S)CSS file with distinct media queries in it. In this case, you only need one source file.

I'm pretty sure I understand what you're saying. Sometimes it's good to group things together in a .scss file that would end up in conditional stylesheets so you can find them easier.
At the moment there's still not the ability to compile a sass stylesheet in to separate stylesheets without grouping all your conditional rules in to a partial.
However, using Paul Irish's suggestion to conditionally add a class name to the html tag: http://paulirish.com/2008/conditional-stylesheets-vs-css-hacks-answer-neither/
<!--[if lt IE 7 ]> <html class="ie6"> <![endif]-->
<!--[if IE 7 ]> <html class="ie7"> <![endif]-->
<!--[if IE 8 ]> <html class="ie8"> <![endif]-->
<!--[if IE 9 ]> <html class="ie9"> <![endif]-->
<!--[if (gt IE 9)|!(IE)]><!--> <html class=""> <!--<![endif]-->
You could do something like this:
.something {
regular rules...
.ie8 & {
conditional rules...
}
}
That way you can still have organization as well as conditional styling. I hope this helps!

Related

Target case-insensitive schemes with URI::regexp?

I have this code to remove URIs using these schemes:
htmldoc.gsub(/#{URI::regexp(['http', 'https', 'ftp', 'mailto'])}/, '')
However, it won't detect a capitalized URI like HTTP or Http unless I add them to the array.
I tried adding the case-insensitive flag i to the regex, but it didn't work.
Any idea how I could achieve this?
URI::regexp calls the default parser's make_regexp which in turn passes the given arguments to Regexp::union and according to its docs: (emphasis mine)
The patterns can be Regexp objects, in which case their options will be preserved, or Strings.
Applied to your problem:
pattern = URI::regexp([/http/i, /https/i, /ftp/i, /mailto/i])
htmldoc = <<-HTML
<html>
<body>
here
here
</body>
</html>
HTML
puts htmldoc.gsub(pattern, '')
Output:
<html>
<body>
here
here
</body>
</html>

Ruby slim inline if

I'm trying to do an inline if with Ruby Slim.
Given my example below...
- if #droppable
.panel data-draggable="true"
span More content here
- else
.panel
span More content here
In both cases, the only difference is the presence of the data-draggable attribute on the top-level .panel element. The contents of the .panel is identical, so I'd like to accomplish something like the following:
.panel (#droppable ? data-draggable="true")
span More content here
Is there a way of achieving this in Slim?
There is no need for an if here, and the ternary operator requires three operands, not two.
Both Slim and HAML are designed to omit attributes with nil/false values, intentionally letting you use the && operator to turn a truthy/falsy value to the presence of attribute with a specific value, or its absence:
In Slim:
.panel data-draggable=(#droppable && "true")
span Hello
In HAML:
.panel{data: {draggable: #droppable && "true"}}
%span Hello
In both cases, if #droppable is a truthy value, data-draggable="true" will be added, otherwise the attribute will be omitted.
Use dynamic tags:
ruby:
def panel!
{tag: 'panel'}.tap do |tag|
tag[:"data-draggable"] = true if #droppable
end
end
*panel!
span hello
You can't have an "inline if" , but you can get the behavior you want with slim in line html support
doing this:
<div class="cool_class"
- if conditional_is_met
| data="must_be_added"
| special_data="#{#my_data.to_json}"
|
</div>
consider that inside the html tag the slim identation is still followed.
and the final | is important to close the if.

SASS Literal Strings

I'm using Django with django-compressor and pySCSS to compile SASS to regular CSS.
In django-compressor there's a filter that can convert variables like {{ STATIC_URL }} to the actual value. Unfortunately that runs after the SASS precompiler.
When I put in that literal in the .sass file, it inserts whitespaces between the curly braces:
background-image: url('{{ STATIC_URL }}img/background-lines.png')
becomes
background-image:url(' { { STATIC_URL }}img/background-lines.png')
Is there a way to insert a literal string into SASS source files? Or a way to escape the curly braces so they're not changed?

Replacing part of text string with a page include in Classic ASP

Not 100% sure if this is possible, but hoping there is a workaround. Several hours of searching bring nothing up. I have a text string written to the page from a Db table. If it contains a specific string, I would like to add a page include - example below does write:
<!--#include file="members.asp"-->
into the text, but does not pull the included file content in.
<%=Replace(myQuery("Text"), "123456", "%><!--#include file="mypage.asp"--><% ")%>
Client wants it in the page rather than at the top or bottom of the output which would be so easy (and we already do that) The include has to go in at a specific point in the text.
I would appreciate any help, even if it is to confirm that it is not possible to do this.
Here is the main page:
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
</head>
<body onload="document.getElementById('placeholder').innerText = document.getElementById('alwaysfillme').innerText">
<p><%=Replace("ABCDEFGHIJKLMNOPQRSTUVWXYZ", "J", "<span id=""placeholder""></span>")%></p>
<span id="alwaysfillme" style="display:none;"><!--#include file="mypage.asp"--></span>
</body>
</html>
And here is what I stuck in "mypage.asp":
<% response.Write("--123--") %>
When a J is in the text, it displays:
ABCDEFGHI--123--KLMNOPQRSTUVWXYZ
When no J is in the text, it displays:
ABCDEFGHIKLMNOPQRSTUVWXYZ
<%=Replace(myQuery("Text"), "123456", ""&Server.Execute("mypage.asp")&"")%>

Smarty template inheritance only provides local scope variables?

Using the latest version of Smarty 3 with template inheritance I'd like to set a variable in a child template and use it in the parent:
list.tpl
{extends file="page.tpl"}
{block name="head"}
{$page_var = array("abc", "xyz")}
{/block}
{block name="content"}
<div>...</div>
{/block}
page.tpl
<!DOCTYPE html>
<html>
<head>
{block name="head"}
{$page_var = array()}
{/block}
{mytemplatefunc foo=array("bar") + $page_var}
...
The main page template initializes a variable and the child page sets the variable if needed. The main page template would then use that variable when calling a template function. But $page_var is always empty. It's as if the scope of the template variables are always local. Is going back to {include} the only solution?
I've tried {assign scope='global'} and {assign scope='parent'} even though they are intended for includes. I also tried using my own static class methods and variables (to hang onto the value) but it never works. And elsewhere it's been suggested trying to use variables outside of {block} but that goes directly against the documentation.
Why do you redefine $page_var in the Template Extension (list.tpl)?
Have you tried adding values to the original $page_var instead?
So instead of
$page_var = array("abc", "xyz")
you could do
array_push($page_var, "abc", "xyz")

Resources