2008-03-03

XCS Syntax

Extended Cascading Stylesheets (XCS) is a facilitating extension to standard CSS language. Since it is handled by a preprocessor before it is handed out to a CSS-fluent client (in a way similar to, say, how C sources are handled), it is useful to think of it as a macro language, rather then as of an actual extension of the standard. As noted in The List, new keywords and semantics are introduced, and I tried hard to keep the syntax as close to the spirit of CSS as possible.

A new @ rule - @require keyword

Much as in PHP, the new keyword includes the referenced file inline, during the preprocessing. A parenthesized string representing a valid path is required either immediately after the keyword, or preceded with any number of whitespace characters. Example:

@require(../etc/defines.css);

The parenthesized string is examined as a PHP path string - so, slashes will work in Windows environment as well.

Single-line comments

When the string // is encountered anywhere within an stylesheet, the rest of the line, up to ending newline character will be considered an XCS comment, and will be converted to standard CSS /* ... */ comment in place.

Constants

XCS understands the concept of constants rather then variables, declared through assigning. Once declared, the values can be cascaded overshadowing each other. However, the actual value is expanded in the stylesheet only after the cascading is done with. Variable names must be preceded by a variable-indicator string or character (! by default, but that can be changed) in order to be identified by the preprocessor. The value is always in global scope. The assigning is done by tying a variable name to a value:

!green = #0000FF;
!heavy = 4em;
!light = 0.5em;
!green = #FF0000;

It is important to note that all occurrences of !green in the rules within a stylesheet will be replaced with the string #FF0000 (red), because of value cascading. The assignment must be done within a single line, and the ending semicolon must not be omitted.

Simple math

Simple math calculations involving either two declared variables or a variable and a CSS value (or a numeric constant) can be conducted either in variable assignment, or in a rule itself. These simple expressions automatically inherit the CSS unit from the second operand (or from the first, in case the second operand is a numeric constant). Examples:

!red = #ff0000;
!green = #0000FF;
!border = !heavy-!light solid !green;
!heavy = 4em;
!light = 0.5em;

body{
   color: !red-!green; // Colors can be calculated as well
   border: !border;
   bla: !heavy/2;
}

expr Expressions

A more complex form of value expansion is the expr keyword, denoting a required parenthesized expression' value. The expression can contain any number of XCS constants, and even PHP variables. Note: since that is a security disaster just begging to happen in an uncontrolled environment, the expression evaluation can be entirely disabled. The expr keyword must always be followed by a parenthesized expression, either immediately, or after any number of whitespace characters. Examples:

!const = 12;
!size = expr((!const * 2)/24)em; // expands to '1'
!date = expr('10 Dec 2007');
!server = expr($_SERVER['SCRIPT_FILENAME']);
!newSize = expr(!const*22)px; // Can NOT use `expr` values in expr

It is important to note that the values assigned by expression expanding can not be used within expressions recursively, as seen in the last line of the example. The expanded values can be either strings or numerics, whatever, the preprocessor doesn't care, as long as they can be expanded to a finite value.

Rule inheritance

Just like CSS understands element inheritance, XCS understands rule inheritance as well. Rule inheritance can be triggered by using an extends keyword in the selector part of the rule. The extends must be followed by a parenthesized existing rule selector string, either immediately, or after any number of whitespace characters. The rule indicated by the parenthesized selector string is then prepended to the current rule, thus allowing any cascading effect to take place. Example:

p.emphasis {
   font-style: italic;
}
p.strong-emphasis extends (p.emphasis) {
   font-weight: bold;
}

All HTML p elements with class strong-emphasis will be rendered in both bold and italic font.

Defined preprocessor behavior in erroneous situations

The preprocessor acts as suggested by the CSS standard specification for compliant engines: as long as a stylesheet is syntactically correct, the preprocessor will attempt to understand it's semantics, leaving as-is anything it can't understand, or can't understand fully. So, as long as everything looks OK to the parser, the preprocessor won't barf at you - however, there might be, as in CSS, semantic errors that sneaked in.

2 comments: