clevercss-0.2.4: documentation.html
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
<title>CleverCSS (Haskell) Documentation</title>
<style type="text/css">
body {
margin: 0;
padding: 0 10% 0 10%;
background-color: #5985de;
font-family: "Bitstream Vera Sans", sans-serif;
}
.document {
background-color: white;
padding: 1px 20px 1px 20px;
border-left: 5px solid #aaaaff;
border-right: 5px solid #aaaaff;
}
h1 a, h2 a, h3 a, h4 a, h5 a, h6 a {
color: #002277;
}
h1, h2, h3, h4, h5, h6 {
font-family: "Arial", sans-serif;
margin-top: 1em;
}
h1.title {
font-size: 2.5em;
color: #333333;
margin-top: 10px;
margin-left: -20px;
margin-right: -20px;
padding-left: 20px;
padding-right: 20px;
padding-bottom: 10px;
border-bottom: 2px solid #cccccc;
}
pre {
background-color: #d8f5c0;
padding: 5px;
border-top: 1px solid #cccccc;
border-bottom: 1px solid #cccccc;
}
a {
color: #003399;
}
table td {
padding: 2px;
}
table {
border-collapse: collapse;
border-color: #999999;
}
</style>
</head>
<body>
<div class="document" id="clevercss-haskell-documentation">
<h1 class="title">CleverCSS (Haskell) Documentation</h1>
<div class="section" id="introduction">
<h1>Introduction</h1>
<p>CleverCSS is a system for writing templates that are translated into CSS,
allowing to build style sheets in a clean and structured way, following the DRY
(don't repeat yourself) principle.</p>
<p>The syntax is slightly different from CSS in that it relies on indentation
instead of braces to indicate grouping, like the Python language does.</p>
<p>The two things that enable DRY are <em>variables</em> and <em>nesting</em>. Variables are
names for CSS values; nesting prevents repeating selectors all over. Here is an
example template file:</p>
<pre class="literal-block">
bgcolor = #f0f0e4
ul#comments, ol#comments:
background-color: $bgcolor
li:
background-color: $bgcolor
font-size: 1.2em
</pre>
<p>It would translate to (an equivalent of) this CSS stylesheet:</p>
<pre class="literal-block">
ul#comments, ol#comments {
background-color: #f0f0e4;
}
ul#comments li, ol#comments li {
background-color: #f0f0e4;
font-size: 1.2em;
}
</pre>
<p>You can already see that the template doesn't repeat the <tt class="docutils literal">ul#comments</tt> and
<tt class="docutils literal">ol#comments</tt> selectors. Also, should the desired background color ever
change, you won't need to replace a zillion references to it, but only one
variable assignment.</p>
<p>Other than that, CleverCSS allows expressions involving CSS values as well as
grouping of similar property names, as shown below.</p>
</div>
<div class="section" id="syntax">
<h1>Syntax</h1>
<p>As you have already seen, you use indentation and colons to express grouping.
There are also other small syntactic differences to CSS that make writing
templates less pain:</p>
<ul class="simple">
<li>Semicolons at line ends are optional.</li>
<li>There are no <tt class="docutils literal">/* ... */</tt> multiline comments, but Java-style <tt class="docutils literal">//</tt> line
comments.</li>
<li>A line consisting only of <tt class="docutils literal">__END__</tt> means "end of template". Everything
after that line is completely ignored by CleverCSS.</li>
</ul>
</div>
<div class="section" id="constructs">
<h1>Constructs</h1>
<div class="section" id="variable-assignments">
<h2>Variable assignments</h2>
<p>You can assign to variables with an equals sign. Variable assignments are not
allowed inside blocks, only at the toplevel. Variables can be assigned to
multiple times.</p>
<pre class="literal-block">
foo = 1px
body:
margin: $foo
foo = 2px
p:
margin: $foo
</pre>
<p>would result in <tt class="docutils literal">body { margin: 1px }</tt> and <tt class="docutils literal">p { margin: 2px }</tt>. Referencing
variables before they are defined is an error.</p>
<p>There's also another assignment operator, <tt class="docutils literal"><span class="pre">?=</span></tt>. It only has an effect if the
variable is not assigned to yet. This is helpful to provide defaults that can
be overridden by e.g. command line definitions. For example, after</p>
<pre class="literal-block">
foo = 1px
bar = 1px
foo = 2px
bar ?= 2px
</pre>
<p><tt class="docutils literal">$foo</tt> would be replaced by <tt class="docutils literal">2px</tt>, while <tt class="docutils literal">$bar</tt> would be replaced by
<tt class="docutils literal">1px</tt>.</p>
</div>
<div class="section" id="selectors">
<h2>Selectors</h2>
<p>CleverCSS does not process selectors in a special way, but as shown above you
can nest selector blocks instead of repeating parent selectors in individual
blocks:</p>
<pre class="literal-block">
ul, ol:
foo
li, p:
bar
strong, em:
baz
</pre>
<p>would result in</p>
<pre class="literal-block">
ul, ol { foo }
ul li, ul p, ol li, ol p { bar }
ul li strong, ul li em, ul p strong, ul p em,
ol li strong, ol li em, ol p strong, ol p em { baz }
</pre>
<p>To achieve this, the selectors are currently bluntly split at commas, so
extended selectors involving string matching with a comma will be handled
incorrectly at the moment.</p>
<p>As you see, the above handles basic parent-child relations by joining parent and
child selectors with a space. However, you can also explicitly determine where
to put the parent selector, using the <tt class="docutils literal">&</tt> character:</p>
<pre class="literal-block">
strong, em:
a &, #&:
bar
</pre>
<p>would result in</p>
<pre class="literal-block">
a strong, #strong, a em, #em { bar }
</pre>
<p>Using this technique, you can construct selectors quite freely. Multiple
occurrences of the ampersand are replaced.</p>
</div>
<div class="section" id="properties">
<h2>Properties</h2>
<p>Property specifications work like in CSS: just put a colon after the property
name. You can use expressions or variable references (see below) only in
property values, not in property names.</p>
<div class="note">
<p class="first admonition-title">Note</p>
<p>Due to the current limited parsing of CSS selectors, CleverCSS can confuse
the <tt class="docutils literal">://</tt> in URLs occurring in property values with a selector and a
following comment. Use a variable for the URL (or at least a part of it
that includes the <tt class="docutils literal">://</tt>) to work around that:</p>
<pre class="last literal-block">
// bad - will cause parsing error
div:
background-image: url("http://www.example.com/image.png")
// workaround
host = "http://www.example.com/"
div:
background-image: url($host + "image.png")
</pre>
</div>
</div>
<div class="section" id="property-groups">
<h2>Property groups</h2>
<p>Since CSS has many property names with common prefixes, CleverCSS includes one
more shortening notation, best described by an example:</p>
<pre class="literal-block">
#main p:
font->
family: Verdana, sans-serif
size: 1.1em
style: italic
</pre>
<p>would result in</p>
<pre class="literal-block">
#main p {
font-family: Verdana, sans-serif;
font-size: 1.1em;
font-style: italic;
}
</pre>
<p>The <tt class="docutils literal"><span class="pre">-></span></tt> symbol, followed by a block of properties, concatenates the name
before it with each of the property names in the block.</p>
</div>
<div class="section" id="macros">
<h2>Macros</h2>
<p>Macros can help you writing often used groups of properties and sub-blocks only
once. Define macros like this:</p>
<pre class="literal-block">
@define mymacro(arg1, arg2):
font-family: $arg1
p:
display: inline
color: $arg2
</pre>
<p>Macros can have zero or more arguments. Inside a macro definition, the
arguments are accessible like normal variables. Macros must be defined at
top-level, and their names live in a different namespace than variables.</p>
<p>Use ("substitute") them like this:</p>
<pre class="literal-block">
body:
%mymacro("Verdana", blue)
font-size: 1.1em
</pre>
<p>Macro substitutions are handled as if the macro's contents are placed at the
exact location of the substitution, with the argument variables replaced by the
given expressions.</p>
</div>
<div class="section" id="includes">
<h2>Includes</h2>
<p>Including a file:</p>
<pre class="literal-block">
@include "filename.ccs"
</pre>
<p>The contents of the included file are treated as if they occurred in the
including file at the point of the include command.</p>
</div>
</div>
<div class="section" id="values-and-expressions">
<h1>Values and expressions</h1>
<p>CleverCSS property values are of multiple types which also exist in CSS:</p>
<table border="1" class="docutils">
<colgroup>
<col width="51%" />
<col width="42%" />
<col width="7%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">Type</th>
<th class="head">Example property</th>
<th class="head">Note</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>barewords (also called identifiers)</td>
<td><tt class="docutils literal"><span class="pre">font-size:</span> small</tt></td>
<td> </td>
</tr>
<tr><td>strings (double or single quoted)</td>
<td><tt class="docutils literal"><span class="pre">font-family:</span> "Times"</tt></td>
<td> </td>
</tr>
<tr><td>numbers (integral or floating)</td>
<td><tt class="docutils literal"><span class="pre">line-height:</span> 2</tt></td>
<td> </td>
</tr>
<tr><td>dimensions (number + unit)</td>
<td><tt class="docutils literal"><span class="pre">margin-left:</span> 2px</tt></td>
<td> </td>
</tr>
<tr><td>hexadecimal colors</td>
<td><tt class="docutils literal">color: #f0f0f0</tt></td>
<td> </td>
</tr>
<tr><td>colors as color names</td>
<td><tt class="docutils literal">color: black</tt></td>
<td>(1)</td>
</tr>
<tr><td>colors via the RGB function</td>
<td><tt class="docutils literal">color: rgb(10%, 20%, 30%)</tt></td>
<td> </td>
</tr>
<tr><td>value sequences (separated by whitespace)</td>
<td><tt class="docutils literal">margin: 2px 0 2px 0</tt></td>
<td> </td>
</tr>
<tr><td>value lists (separated by commas)</td>
<td><tt class="docutils literal"><span class="pre">font-family:</span> "Times", serif</tt></td>
<td>(2)</td>
</tr>
<tr><td>function calls</td>
<td><tt class="docutils literal">content: attr(id)</tt></td>
<td>(3)</td>
</tr>
</tbody>
</table>
<p>Notes:</p>
<ol class="arabic simple">
<li>Color names are also valid identifiers. CleverCSS recognizes the 140 common
Netscape color names and treats them as values of type color, but does not
convert them to RGB format until you do arithmetic with them. That way, you
can have barewords that are color names without a problem.</li>
<li>This is only used in CSS for the <tt class="docutils literal"><span class="pre">font-family</span></tt> property, but you are free
to use value lists anywhere and convert them to other values using their
methods, see below.</li>
<li>The functions recognized by CleverCSS, in addition to <tt class="docutils literal">rgb</tt>, are <tt class="docutils literal">attr</tt>,
<tt class="docutils literal">counter</tt> and <tt class="docutils literal">url</tt>.</li>
</ol>
<p>CleverCSS extends CSS in that it allows writing not only these literal values,
but also expressions involving these values. These expressions can contain
these elements, in addition to the literal expressions described above:</p>
<table border="1" class="docutils">
<colgroup>
<col width="48%" />
<col width="45%" />
<col width="7%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">Type</th>
<th class="head">Example(s)</th>
<th class="head">Note</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>Arithmetic on numbers and values;
operators are <tt class="docutils literal">+</tt>, <tt class="docutils literal">-</tt>, <tt class="docutils literal">*</tt>, <tt class="docutils literal">/</tt>
and <tt class="docutils literal">%</tt> (modulo)</td>
<td><tt class="docutils literal">4 % 3 = 1</tt>, <tt class="docutils literal">2px + 4px = 6px</tt>,
<tt class="docutils literal">2 * 2px = 4px</tt></td>
<td>(1)</td>
</tr>
<tr><td>Arithmetic on colors with <tt class="docutils literal">+</tt> and <tt class="docutils literal">-</tt></td>
<td><tt class="docutils literal">#f0f000 + #000030 = #f0f030</tt>,
<tt class="docutils literal">#808080 + 16 = #909090</tt></td>
<td>(2)</td>
</tr>
<tr><td>Concatenation of strings with <tt class="docutils literal">+</tt></td>
<td><tt class="docutils literal">"hello " + "world" = "hello world"</tt></td>
<td>(3)</td>
</tr>
<tr><td>String multiplication</td>
<td><tt class="docutils literal">"a " * 3 = "a a a "</tt></td>
<td> </td>
</tr>
<tr><td>Expression grouping with parentheses</td>
<td><tt class="docutils literal">(2 + 3) * 5px</tt></td>
<td> </td>
</tr>
<tr><td>Method calls</td>
<td><tt class="docutils literal">#303030.brighten(40%) = #434343</tt>,
<tt class="docutils literal"><span class="pre">"hello".bare()</span> = hello</tt></td>
<td>(4)</td>
</tr>
<tr><td>Variable references</td>
<td><tt class="docutils literal">$foo = <whatever foo was assigned></tt></td>
<td> </td>
</tr>
</tbody>
</table>
<p>More explanations:</p>
<ol class="arabic">
<li><p class="first">Arithmetic on numbers works as expected.</p>
<p>You can mix one number and one value in arithmetic expressions, the result
will automatically be given the unit of the value. This is natural with
multiplication and division but can feel weird with addition and subtraction.</p>
<p>You can add and subtract two dimensions provided their units are the same or
convertable to one another, but you cannot multiply or divide them.</p>
</li>
<li><p class="first">If two colors are added or subtracted, their individual channels will be
added or subtracted. If one operand is a number, it will be applied to all
channels.</p>
</li>
<li><p class="first">Barewords cannot be added, but you can convert strings to barewords with the
<tt class="docutils literal">bare()</tt> method afterwards.</p>
</li>
<li><p class="first">For a list of available methods, see below.</p>
</li>
</ol>
<div class="section" id="methods">
<h2>Methods</h2>
<p>On values of all types:</p>
<ul class="simple">
<li><strong>string()</strong>: convert to a string.</li>
</ul>
<p>On strings:</p>
<ul class="simple">
<li><strong>bare()</strong>: convert the string to a bareword. It is not checked that it has the
required format!</li>
<li><strong>length()</strong>: return the string's length.</li>
<li><strong>upper()</strong>, <strong>lower()</strong>: convert the string to uppercase/lowercase.</li>
<li><strong>strip()</strong>: return the string with all trailing and leading whitespace removed.</li>
<li><strong>split(delim)</strong>: return a list with substrings, split at the string <em>delim</em>.</li>
<li><strong>eval()</strong>: evaluate the contents as a CleverCSS expression and return the result.</li>
</ul>
<p>On numbers and dimensions:</p>
<ul class="simple">
<li><strong>round([places])</strong>: return the number or dimension rounded to <em>places</em> decimal
places; <em>places</em> defaults to 0.</li>
<li><strong>abs()</strong>: return the absolute value.</li>
</ul>
<p>On colors:</p>
<ul class="simple">
<li><strong>brighten([amount])</strong>: return the color brightened by the specified amount,
which should be a percent dimension. <em>amount</em> defaults to 10%.</li>
<li><strong>darken([amount])</strong>: return the color darkened by the specified amount, which
should be a percent dimension. <em>amount</em> defaults to 10%.</li>
</ul>
<p>On lists and sequences:</p>
<ul class="simple">
<li><strong>length()</strong>: return the list or sequence's length.</li>
<li><strong>join([delim])</strong>: return a string consisting the items converted to strings
and joined by <em>delim</em>, which defaults to <tt class="docutils literal">", "</tt> for lists and <tt class="docutils literal">" "</tt> for
sequences.</li>
<li><strong>list()</strong>: return the sequence as a list, or the list unchanged.</li>
<li><strong>seq()</strong>: return the list as a sequence, or the sequence unchanged.</li>
</ul>
</div>
</div>
<div class="section" id="library-usage">
<h1>Library usage</h1>
<p>Using the CleverCSS library is straightforward, just import <tt class="docutils literal">Text.CSS.CleverCSS</tt>
and use the <tt class="docutils literal">cleverCSSConvert</tt> function, which is defined as</p>
<pre class="literal-block">
cleverCSSConvert :: SourceName -> String -> [(String, String)] -> Either String String
</pre>
<p>The arguments are:</p>
<ul class="simple">
<li>name of input (normally file name, only used for error messages)</li>
<li>input template</li>
<li>initial variable assignments as <tt class="docutils literal">(name, value)</tt> pairs; the value is evaluated
as a CleverCSS expression when used</li>
</ul>
<p>The return value is either <tt class="docutils literal">Left errormessage</tt> or <tt class="docutils literal">Right stylesheet</tt>.</p>
</div>
<div class="section" id="command-line-usage">
<h1>Command-line usage</h1>
<p>CleverCSS also can be compiled as a standalone command-line program. It can be
called with no arguments, in which case it will convert standard input to
standard output, or with file names as arguments, in which case it will convert
the files named to CSS and store them in a file with the same name, but the
extension replaced with <tt class="docutils literal">.css</tt> (e.g., <tt class="docutils literal">example.clevercss</tt> is converted to
<tt class="docutils literal">example.css</tt>).</p>
<p>You can use the <tt class="docutils literal"><span class="pre">-D</span> name=value</tt> command line option to assign initial
variables. The value is evaluated as a CleverCSS expression when used.</p>
</div>
<div class="section" id="how-to-get-and-install-it">
<h1>How to get and install it</h1>
<p>CleverCSS can be downloaded from
<a class="reference external" href="http://hackage.haskell.org/cgi-bin/hackage-scripts/package/clevercss">Hackage</a>
or checked out from Mercurial at <<a class="reference external" href="http://dev.pocoo.org/hg/clevercss-hs-main">http://dev.pocoo.org/hg/clevercss-hs-main</a>>.
It is a cabalized package, so the usual</p>
<pre class="literal-block">
runhaskell Setup.lhs configure
runhaskell Setup.lhs build
sudo runhaskell Setup.lhs install
</pre>
<p>should be enough to get the <tt class="docutils literal">clevercss</tt> binary and the <tt class="docutils literal">Text.CSS.CleverCSS</tt>
library installed.</p>
</div>
<div class="section" id="authors">
<h1>Authors</h1>
<p>The Haskell CleverCSS library is written by Georg Brandl <<a class="reference external" href="mailto:georg@python.org">georg@python.org</a>>.
Bug reports and suggestions are welcome!</p>
<p>The CleverCSS template language was initially devised and implemented in Python
by Armin Ronacher, see <<a class="reference external" href="http://sandbox.pocoo.org/clevercss">http://sandbox.pocoo.org/clevercss</a>>.</p>
</div>
</div>
</body>
</html>