]> HSS: a Compiler for Cascading Style Sheets
HSS: a Compiler for Cascading Style Sheets
Manuel Serrano Inria Sophia Antipolis Manuel.Serrano@inria.fr http://www.inria.fr/indes/Manuel.Serrano
@InProceedings{ serrano:ppdp10,
  author = {Serrano, M.},
  title = {HSS: a Compiler for Cascading Style Sheets},
  booktitle = {10th ACM Sigplan Int'l Conference on 
               Principles and Practice of Declarative Programming (PPDP'2010)},
  year = 2010,
  month = jul,
  address = {Hagenberg, Austria},
  url = {http://www-sop.inria.fr/members/Manuel.Serrano/publi/serrano-ppdf10.pdf};
}

This ar­ti­cle pre­sents HSS1

This work is supported in part by the French ANR agency, grant ANR­-09­-EMER­-009­-01.
, a com­pil­er for CSS. It is first ar­gued that gen­er­at­ing CSS im­proves porta­bil­i­ty and main­tain­abil­i­ty of CSS files. This claim is sup­port­ed by re­al­is­tic ex­am­ples. Then, the HSS com­pi­la­tion al­go­rithm is pre­sent­ed. It is sim­ple enough to be eas­i­ly adapt­ed to most web de­vel­op­ment kit­s.

HSS can be used as a stand-alone HSS-­to-C­SS com­pil­er in the goal of en­rich­ing CSS with user de­fined vari­ables, func­tions, and el­e­ment type­s. It can also be used with the Hop web de­vel­op­ment kit in which case, work­ing hand in hand with the Hop pro­gram­ming lan­guage, it can be used to im­ple­ment skinning or theming of web ap­pli­ca­tion­s.

1 Introduction

Cas­cad­ing Style Sheets (hence­forth CSS) is used to ex­press for­mat­ting in HTML and XHTM­L. It is a declar­a­tive lan­guage that can­not ex­press com­pu­ta­tion. The cor­rect­ness of CSS files can be checked stat­i­cal­ly by CSS parsers (named validators in the web jar­gon). The W3C for ex­am­ple, pro­vides one on-­line (see http://jigsaw.w3.org/css-validator/).

CSS is es­sen­tial for de­vel­op­ing Web user in­ter­face (hence­forth UI). It is used for fine graph­i­cal tun­ings as well as for man­ag­ing UIs glob­al lay­out­s. As pro­mot­ed by stan­dard en­gi­neer­ing method­olo­gies, CSS en­forces a strong sep­a­ra­tion be­tween the im­ple­men­ta­tion of the ap­pli­ca­tion and its UI.

CSS is de­fined by a W3C spec­i­fi­ca­tion 9

9Cascading Style Sheets level 2 Revision 1 CSS2.1 Specificationhttp://www.w3.org/TR/2009/CR-CSS2-20090423/CR-CSS2-20090423W3C Recommendation.
. A re­vised ver­sion is in prepa­ra­tion (CSS lev­el 3) that sup­ports ad­di­tion­al graph­i­cal tun­ings such as opac­i­ty, shad­ed box­es, or round bor­der­s. Few browsers al­ready sup­port CSS lev­el 3 but most browsers sup­port var­i­ous ex­ten­sions of CSS lev­el 2 for pro­vid­ing sim­i­lar fan­cy graph­i­cal fea­tures (for in­stance, Mozil­la ex­ten­sions are de­scribed at https://developer.mozilla.org).

Two re­stric­tions of CSS have mo­ti­vat­ed the pre­sent work.

Our con­tri­bu­tion, HSS, a com­pil­er for CSS, im­proves over these two as­pect­s. It brings com­put­ing fa­cil­i­ties to CSS and it al­lows users to ex­tend CSS. A HSS file is com­posed of a list of dec­la­ra­tions and rules. Dec­la­ra­tions de­fine new HTML el­e­ments, new prop­er­ty at­tributes, new prop­er­ty func­tions, or vari­ables. Rules are CSS rules where prop­er­ty val­ues can be dy­nam­i­cal­ly com­put­ed. The HSS com­pil­er can be used of­f-­line to stat­i­cal­ly trans­late HSS source files into CSS files that can be used by any HTML doc­u­ments, in­de­pen­dent­ly of any par­tic­u­lar web pro­gram­ming en­vi­ron­men­t. HSS files can also be used on-­line by Hop, a de­vel­op­ment kit for the dif­fuse Web, that em­beds HSS in its run­time sys­tem 8

8HOP, a language for programming the Web 2.0http://www.inria.fr/mimosa/Manuel.Serrano/publi/dls06/article.htmlProceedings of the First Dynamic Languages SymposiumPortland, Oregon, USA.
, 1
1Towards Reasoning for Web Applications: an Operational Semantics for HopProceedings of the first Workshop on Analysis and Programming Languages for Web Applications and Cloud ApplicationsToronto, Canada.
. HSS ac­tu­al­ly stands for Hop-C­SS.

Sec­tion 2 pre­sents the min­i­mum CSS back­ground need­ed to un­der­stand the pa­per. Sec­tion 3 pre­sents the HSS lan­guage. It shows ex­am­ples that il­lus­trate the HSS ex­ten­sion­s. Sec­tion 4 pre­sents the com­pi­la­tion pro­cess that trans­lates a HSS source file into a CSS file. Sec­tion 5 pre­sents fu­ture work. Sec­tion 6 com­pares HSS with oth­er sys­tems that gen­er­ate CSS files.

2 Background

In the mid 90s the web first start­ed with plain HTML doc­u­ments that were used to ex­press both struc­ture and vi­su­al as­pect­s. In or­der to sim­pli­fy au­thor­ing and site main­te­nance, the struc­tur­ing and the pre­sen­ta­tion of the doc­u­ments have then been sep­a­rat­ed: nowa­days HTML is used for struc­tur­ing and CSS (Cascading Style Sheets) is used to at­tach vi­su­al styles. In this sec­tion we pre­sent a brief CSS tu­to­ri­al. Read­ers fa­mil­iar with CSS may skip this sec­tion.

A web page is de­scribed by a HTML tree whose nodes have chil­dren and at­tributes such iden­ti­fiers, class­es, or ac­tions to be ex­e­cut­ed when the mouse flies over them. CSS is a declar­a­tive lan­guage that let pro­gram­mers spec­i­fy the graph­i­cal ren­der­ing of HTML nodes. For in­stance, a CSS dec­la­ra­tion may spec­i­fy that a node is red, that it uses a large bold font, and that it is dec­o­rat­ed with a dot­ted blue bor­der.

A CSS file is com­posed of CSS dec­la­ra­tions which have two parts:

  1. a pat­tern, also known as a selector, that dis­tin­guish­es the nodes on which the dec­la­ra­tion ap­plies.
  2. a list of properties that ex­press the graph­i­cal con­fig­u­ra­tions.

The syn­tax of CSS dec­la­ra­tions mim­ics those of C struc­tures. In the fol­low­ing dec­la­ra­tion:

div.example {
  color: blue;
}

div.example is the se­lec­tor and color is the spec­i­fied prop­er­ty. This dec­la­ra­tion reads as fol­lows: all the HTML div el­e­ments (a div is a plain box) that be­long to the example class are paint­ed in blue. The fol­low­ing HTML snip­pet shows how such an el­e­ment can be de­clared:

<DIV class="example" id="ex1">
  This is an example
 </DIV>

Us­ing the Hop pro­gram­ming lan­guage, one would write:

(<DIV> :class "example" :id "ex1" 
   "This is an example")

Var­i­ous se­lec­tors al­low CSS dec­la­ra­tions to se­lect nodes. In ad­di­tion to the class se­lec­tor pre­sent­ed above, three oth­er se­lec­tors are fre­quent­ly used all along this pa­per:

The se­lec­tors, may range from sim­ple el­e­ment such as above to rich con­tex­tu­al pat­tern­s. If all con­di­tions in the pat­tern are true for a cer­tain el­e­ment, the se­lec­tor match­es the el­e­men­t. Con­tex­tu­al pat­terns ex­press prop­er­ties of part of doc­u­ments. For in­stance, the se­lec­tor of the fol­low­ing dec­la­ra­tion:

div.example span.important { ... }

match­es span el­e­ments of the class important whose an­ces­tor (di­rect or not in the HTML tree) is a div of the class example. In the fol­low­ing ex­am­ple:

(<DIV> :class "tutorial"
   (<DIV> :class "example" 
      (<SPAN> :class "important" :id "span1"
         (<SPAN> :class "important" :id "span2")))
   (<SPAN> :class "important" :id "span3"))

only the el­e­ments span1 and span2 are se­lect­ed by the pat­tern. The el­e­ment span3 does not match be­cause its only an­ces­tor is a div of the class tutorial, as op­posed to example.

An el­e­ment may match sev­er­al se­lec­tors. For in­stance, if we add the fol­low­ing dec­la­ra­tion to our pre­vi­ous ex­am­ple:

span.important {
  color: green;
}

all the span el­e­ments of the class important that are chil­dren of div of the class example match­es the two se­lec­tors. To re­solve this am­bi­gu­i­ty, which means here choos­ing be­tween green and blue for paint­ing the span, CSS re­sorts on a nor­mal­ized al­go­rithm that se­lects amongst all the match­ing rules the most specific one.

Read­ers keen to un­der­stand the full tech­ni­cal de­tails and sub­tleties of CSS may re­fer to the W3C spec­i­fi­ca­tions 9

9Cascading Style Sheets level 2 Revision 1 CSS2.1 Specificationhttp://www.w3.org/TR/2009/CR-CSS2-20090423/CR-CSS2-20090423W3C Recommendation.
.

3 The HSS language

HSS is both a declar­a­tive lan­guage built on top of CSS and a com­pil­er that trans­lates the HSS lan­guage into CSS. Any cor­rect CSS file is a cor­rect HSS source file. Ad­di­tion­al­ly, HSS sup­ports four syn­tac­tic ex­ten­sions:

The for­mal syn­tax of HSS is de­scribed by the H syn­tax pre­sent­ed in Fig­ures 1, 2, 3, 4, 5 and 6.

H::=XHSS definition
|$exprHop expression
|S1,,Sn {D1;Dm; } rule set
X::=Hpropproperty definition
|Hfunfunction definition
|Htypetype definition
1Grammar for HSS.

The def­i­ni­tions of Hprop Hfun, and Htype will be pre­sent­ed in the rest of this sec­tion along with ex­am­ples.

S::=S'1 opop S'kcompound selector
S'::=IDENTelement type
|S' . STRINGclass
|S' : STRINGpseudo-element
op::=' ' | <child of
|>descendant of
|+sibling
|[ IDENT opa STRING ]attribute
opa::==match exact
|~=match member
||=match start
2Grammar for HSS selectors.

The ac­tu­al con­crete syn­tax of child of op­er­a­tor is only the emp­ty string. For the sake of read­abil­i­ty of the pa­per, we have added here the ter­mi­nal <.

D::=IDENT : Edeclaration
E::=$exprHop expression
|IDENT(E1,,Ep)function call
|STRINGliteral
3Grammar for HSS declarations.

In this sec­tion we pre­sent suc­ces­sive­ly the HSS ex­ten­sions, each ac­com­pa­nied with a re­al­is­tic mo­ti­vat­ing ex­am­ple.

31 HSS user-defined properties

A reg­u­lar CSS dec­la­ra­tion as­signs a val­ue to a prop­er­ty. Its syn­tax con­sists of a prop­er­ty name fol­lowed by colon fol­lowed by a val­ue. Ex­am­ples:

border: 1px solid red;
font-size: 120%;
background: rgb(100,50,200);

The set of prop­er­ty names that can be used in an as­sign­ment is closed, i.e., users can­not de­fine their own prop­er­ties.

311 HSS properties

HSS ex­tends CSS by al­low­ing de­vel­op­ers to de­clare their own new CSS prop­er­ties. HSS pro­gram­mers de­clare property compilers that rewrite a dec­la­ra­tion into a list of new HSS dec­la­ra­tions. These new dec­la­ra­tions are them­selves com­piled. This pro­cess it­er­ates un­til the dec­la­ra­tions pro­duced by com­pi­la­tion only con­cern prim­i­tive CSS-2 prop­er­ties.

HSS views a prop­er­ty as con­sist­ing of a list of strings (the pa­ram­e­ters) plus a dis­tin­guished string (the pri­or­i­ty); the user may de­fine a func­tion, a property compiler, that takes these and re­turns a string that re­places the prop­er­ty cal­l. In the ex­am­ple:

border: 1px solid red ! important;

The prop­er­ty com­pil­er is the user-de­fined func­tion as­so­ci­at­ed with border, the value pa­ram­e­ter is bound to the list "1px" "solid" "red" and the priority is the string "important". The re­sult of a prop­er­ty com­pil­er is a string that is in­sert­ed in the gen­er­at­ed file, in re­place­ment of the prop­er­ty cal­l.

Hprop::=(define-hss-property (IDENT IDENT IDENT) expr)
4Grammar for HSS property compilers.

Prop­er­ty com­pil­ers are de­fined by the define-hss-property form whose syn­tax is giv­en Fig­ure 4. Their sig­na­ture is as fol­lows:

property compiler: string list × string → string

The body of the prop­er­ty com­pil­er is giv­en by the ex­pres­sion expr that be­longs to the pro­gram­ming lan­guage used with HSS. The cur­rent ac­tu­al HSS im­ple­men­ta­tion uses Hop so the rest of the pa­per.

The fol­low­ing ex­am­ple de­fines a new black-and-white prop­er­ty that con­trols the back­ground and fore­ground col­ors of HTML el­e­ments. It ac­cepts two pos­si­ble val­ues regular and invert. It might be de­fined as:

(define-hss-property (black-and-white val prio)
   (if (string=? (car val) "regular")
       "color: black; background: white;"
       "color: white; background: black;"))

and might be used in rules such as:

div.box {
  black-and-white: invert;
}

Note: it might be not­ed that a prop­er­ty com­pil­er re­turns a new HSS frag­ment that is in­sert­ed in the style sheet. Be­cause it is deemed sim­pler to gen­er­ate ac­tu­al HSS ex­ter­nal syn­tax than any in­ter­nal for­mat, it has been de­cid­ed that prop­er­ty com­pil­ers re­turn strings in­stead of ab­stract syn­tax trees. As pre­sent­ed in Sec­tion 4 these strings are parsed back by the HSS com­pil­er in or­der to com­plete the com­pi­la­tion pro­cess.

312 Motivating example: browser compatibility

The ac­tu­al CSS prop­er­ties set is spe­cif­ic to each brows­er. All main­stream browsers sup­port a su­per­set of CSS-2.1 prop­er­ties. Ven­dor-spe­cif­ic prop­er­ties have name pre­fixed with a dis­tin­guish­ing mark, e.g., -moz-, -webkit-, or -o-. Im­ple­ment­ing CSS files com­pat­i­ble with all the ma­jor browsers is then te­dious be­cause clut­tered with many ven­dor-spe­cif­ic re­dun­dant dec­la­ra­tions. For in­stance, spec­i­fy­ing round bor­ders for box­es could yield to:

pre.example {
  -moz-border-radius: 1em 2em 1em 2em;
  -webkit-border-top-left-radius: 1em;
  -webkit-border-top-right-radius: 2em;
  -webkit-border-bottom-right-radius: 1em;
  -webkit-border-bottom-left-radius: 2em;
  border-top-left-radius: 1em;
  border-top-right-radius: 2em;
  border-bottom-right-radius: 1em;
  border-bottom-left-radius: 2em;
}

HSS prop­er­ties can be used to en­sure brows­er com­pat­i­bil­i­ty au­to­mat­i­cal­ly. For in­stance, the com­pat­i­bil­i­ty rule for round bor­ders could be de­fined as:

(define-hss-property (border-radius v p)
   (match-case v
     ((?tl ?tr ?br ?bl)
      (format "-moz-border-radius: ~a ~a ~a ~a;
          -webkit-border-top-left-radius: ~a;
          -webkit-border-top-right-radius: ~a;
          -webkit-border-bottom-right-radius: ~a;
          -webkit-border-bottom-left-radius: ~a;
          border-top-left-radius: ~a;
          border-top-right-radius: ~a;
          border-bottom-right-radius: ~a;
          border-bottom-left-radius: ~a;"
          tl tr br bl tl tr br bl tl tr br bl))
     ((?r)
      (format "-moz-border-radius: ~a;
          -webkit-border-radius: ~a;
          border-radius: ~a;" 
          r r r))
     (else
      (error 'border-radius "wrong number of args" v))))

The HSS prop­er­ty border-radius can be giv­en ei­ther four val­ues (one for each of the four cor­ners) or only one val­ue (that is used for all the four cor­ners). Pro­vid­ed with this def­i­ni­tion, the pre­vi­ous pre.example ex­am­ple can be re-writ­ten us­ing the fol­low­ing com­pact dec­la­ra­tion:

pre.example {
  border-radius: 1em 2em 1em 2em;
}

This ex­am­ple il­lus­trates two ad­van­tages of HSS over CSS dec­la­ra­tions:

  1. HSS source files are more compact than their cor­re­spond­ing CSS files;
  2. HSS files are easier to maintain be­cause if a new brows­er shows up with its own syn­tax for sup­port­ing a pop­u­lar ex­ten­sion, only the HSS rule declar­ing that ex­ten­sion has to be mod­i­fied, not the user HSS sources. HSS helps ap­pli­ca­tions de­vel­op­ers to write portable CSS files.

32 HSS user-defined functions

A CSS val­ue may be a lit­er­al (a string, a num­ber, a col­or, etc.), a URI, or a func­tion cal­l. Ex­am­ples:

color: red;
background: rgb(20%,40%,15%);
content: attr(bg);

As prop­er­ties, func­tions can­not be de­fined by users and main­stream browsers ex­tend the set de­fined by CSS-2. As prop­er­ties, these ex­ten­sions raise porta­bil­i­ty is­sues.

321 HSS functions

HSS sup­ports user-de­fined func­tion­s. They are in­tro­duced by the define-hss-function form whose syn­tax is giv­en Fig­ure 5.

Hfun::=(define-hss-function (IDENT IDENT ...) expr)
5Function definition.

The sig­na­ture of a HSS func­tion is:

value function: string × ... → string

The for­mal pa­ram­e­ters of HSS func­tions are bound to strings rep­re­sent­ing the ac­tu­al val­ues spec­i­fied at the call sites. For in­stance, in the prop­er­ty as­sign­ment:

background: rgb(20%,40%,15%);

The three for­mal pa­ram­e­ters of the rgb func­tion are bound to 20%, 40%, and 15%.

322 Motivating example: specification compatibility

CSS-3 ex­tends CSS-2 in many di­rec­tion­s. In par­tic­u­lar, the col­or mod­ule has been sig­nif­i­cant­ly aug­ment­ed. CSS-3 col­ors may be spec­i­fied us­ing RGB com­po­nents as well as HSL or HSLA com­po­nents. For in­stance

div.highlight {
  background: rgb(255,0,0);
  opacity: 0.9;
}

may also be writ­ten us­ing CSS-3 spec­i­fi­ca­tion as:

div.highlight {
  background: hsla(0,100%,50%,90%);
}

The CSS-3 hsla func­tion can be de­fined as a HSS val­ue func­tion and calls to hsla con­vert­ed into CSS-2 at­tribute val­ues dur­ing the HSS com­pi­la­tion. With HSS, hsla can be de­fined as:

(define-hss-function (hsla h s l a)
   (multiple-value-bind (r g b)
      (hsl->rgb (string->number h) 
                (string->number s)
                (string->number l))
      (format "rgb(~a,~a,~a); opacity:~a;" 
              r g b 
              (percentage->real a))))

This def­i­ni­tion uses the Hop li­brary func­tion hsl->rgb that re­turns the RGB com­po­nents of a HSL col­or spec­i­fi­ca­tion. This func­tion re­turns three val­ues that are bound to lo­cal vari­ables (r, g, and b) by the multiple-value-bind for­m. The a com­po­nent is com­piled into an CSS2 opacity at­tribute. Pro­vid­ed with this def­i­ni­tion of hsla, the ex­am­ple above us­ing the HSLA com­po­nents will be com­piled into an equiv­a­lent CSS-2 com­pat­i­ble RGB for­m.

This ex­am­ple shows that HSS can be used to en­sure back­ward com­pat­i­bil­i­ty of CSS files. Us­ing HSS func­tions, a CSS-3 source file can be com­piled into an equiv­a­lent CSS-2 file. This com­pi­la­tion can be au­to­mat­i­cal­ly trig­gered by clients-­side pro­grams for which an au­to-­con­fig­u­ra­tion test shows a lack of CSS-3 sup­port.

33 HSS user-defined types

HTML types (e.g., DIV, TABLE, ...) are cen­tral to the pat­tern match­ing rules that de­ter­mine which style rules ap­ply to each el­e­ment of a doc­u­ment tree. HTML is not ex­ten­si­ble, i.e., users can­not de­fine new types, as is CSS. HSS al­lows pro­gram­mers to de­fine new types that are used in the se­lec­tor rules as any prim­i­tive type. This is one of the main HSS con­tri­bu­tion­s.

331 HSS types

Types are de­fined by the define-hss-type form whose syn­tax is:

Htype::=(define-hss-type IDENT S [ :body S ] Hprop* )
6HSS types.

The rest of this sec­tion il­lus­trates type def­i­ni­tions with var­i­ous ex­am­ples. The first one shows that define-hss-type can be used to as­sign names to se­lec­tors. For in­stance, pro­vid­ed with the fol­low­ing dec­la­ra­tion,

(define-hss-type warning "span.warning")

the new type warning can be used as a sub­sti­tute of span.warning. Hence, one may write:

/* global warning's borders */
warning { 
  border: 4px dotted red;
}
/* "important" warning's color */
div.important warning {
  color: red;
}
/* buttons embedded inside warnings */
div.important warning button {
  background: yellow;
}

The first rule (glob­al warn­ing) spec­i­fies the gen­er­al graph­i­cal as­pect of a warning span (a span with a wide red dot­ted bor­der). The sec­ond rule (im­port warn­ing) over­rides warning spans by spec­i­fy­ing that important warning spans, e.g., amongst the warning spans those that are in­clud­ed in­side important divs, in ad­di­tion to be red-bor­dered, are writ­ten in red. The third rule spec­i­fies that but­tons that might be em­bed­ded in­side import warning spans en­joy a yel­low back­ground.

HSS types may be ac­com­pa­nied with type­-spe­cif­ic prop­er­ties. For in­stance it can be found con­ve­nient to as­so­ci­ate a level to the warn­ing el­e­ments de­fined above. The high­er the lev­el, the more vis­i­ble the graph­i­cal ren­der­ing. The level prop­er­ty of warn­ing el­e­ments can be im­ple­ment­ed as:

(define-hss-type warning "span.warning"
   (define-hss-property (level l)
      (cond
         ((string=? l "benign")
          "border: 2px solid red;")
         ((string=? l "important")
          "border: 4px dotted red;")
         ((string=? l "critical")
          "border: 4px dotted red; 
           color: red;")
         (else
          "border: 4px dotted red; 
           color: red; 
           background: yellow"))))

ro­vid­ed with these dec­la­ra­tions, warning can be used in ex­pres­sions such as:

warning#disk-failure {
  level: critical;
}

As seen in Sec­tion 2 the # pat­tern op­er­a­tor match­es el­e­ments ac­cord­ing to their iden­ti­fi­er (here disk-failure). Then, the se­lec­tor warning#disk-failure match­es any el­e­ment that be­longs to the warning class and whose iden­ti­fi­er is disk-failure. Such an el­e­ment can be build with a Hop ex­pres­sion such as:

(<SPAN> :class "warning" :id "disk-failure" 
   "Unable to read disk /dev/sda1")

332 Motivating example: abstraction

Many mod­ern web frame­works ab­stract over HTML by propos­ing ad­di­tion­al sets of wid­get­s. JQuery or the Dojo toolk­it are two pop­u­lar rep­re­sen­ta­tives of this kind. These frame­works con­sist of JavaScript APIs that amongst oth­er things im­ple­ment wid­get con­struc­tors.

The Hop 8

8HOP, a language for programming the Web 2.0http://www.inria.fr/mimosa/Manuel.Serrano/publi/dls06/article.htmlProceedings of the First Dynamic Languages SymposiumPortland, Oregon, USA.
de­vel­op­ment kit pro­vides sim­i­lar fa­cil­i­ties with an im­por­tant dif­fer­ence :

For in­stance, in Hop, one might cre­ate labelled frames with two fol­low­ing dec­la­ra­tions:

(define-tag <LFRAME> (body)
   (<DIV> :hssclass "hop-lframe"
      (<DIV> :hssclass "hop-lfborder"
         (<DIV> :hssclass "hop-lfbody" body))))
  
(define-tag <LFLABEL> (body)
   (<DIV> :hssclass "hop-lflabel"
      (<SPAN> body)))

These two user-de­fined markups can be used as any HTML el­e­ments such as:

(<LFRAME> :class "lframe-left"
   (<LFLABEL> "A Label")
   (<DIV> :id "a-lfbody" "The lframe body."))

Hop com­piles this ex­pres­sion into:

<DIV> class="lframe-left" hssclass="hop-lframe">
 <DIV hssclass="hop-lfborder">
  <DIV hssclass="hop-lfbody">
   <DIV hssclass="hop-lflabel">
    <SPAN>A Label</SPAN>
   </DIV>
   <DIV id='a-lfbody'>The lframe body.</DIV>
  </DIV>
 </DIV>
</DIV>

Be­ing able to de­fine new wid­gets is es­sen­tial to web de­vel­op­ment kit­s. It al­lows de­vel­op­ers to cre­ate abstractions on top of HTML in or­der to help cre­at­ing rich user in­ter­faces on the web. Web de­vel­op­ers then no longer di­rect­ly use HTML DIV, SPAN, or TABLE but NOTEPAD, TREE, or DATEPICKER in­stead.

Un­for­tu­nate­ly, CSS does not sup­port type ab­strac­tion. Thus, graph­i­cal tun­ings can only be ap­plied to prim­i­tive HTML el­e­ments even when they are only used to im­ple­ment high­-lev­el ab­strac­tion­s. For in­stance, the JQuery's API doc­u­men­ta­tion ac­knowl­edges that a DATEPICKER is im­ple­ment­ed as a HTML DIV of the class ui-datepicker. Un­veil­ing these im­ple­men­ta­tion de­tails is op­posed to elab­o­rat­ing safe and sound ab­strac­tions on top of a min­i­mal core ker­nel.

HSS user-de­fined types can pre­vent CSS con­fig­u­ra­tions to break ab­strac­tions of high­-lev­el APIs. This is il­lus­trat­ed with the HSS spec­i­fi­ca­tion of LFRAME pre­sent­ed Fig­ure 7. It shows the def­i­ni­tion of the type el­e­ment and its spe­cif­ic prop­er­ties.

(define-hss-type lframe "div[hssclass=hop-lframe]"
   :body "div[hssclass=hop-lfbody]"
   (define-hss-property (-hop-label-margin v)
      (format "padding: ~l;" v))
   (define-hss-property (-hop-label-border v)
      (format "div[hssclass=hop-lfborder] { 
                  border: ~l; }" v))
   (define-hss-property (padding v)
      (format "div[hssclass=hop-lfbody] { 
                  padding: ~l; }" v))
   (define-hss-property (-hop-label-border-radius v)
      (format "div[hssclass=hop-lfborder] { 
                  border-radius: ~l; }" v))
   (define-hss-property (-hop-label-align v)
      (format "div[hssclass=hop-lflabel] { 
                  text-align: ~l; }" v))
   (define-hss-property (-hop-label-offset v)
      (format "div[hssclass=hop-lflabel] { 
                  top: -~l; }" v))
   (define-hss-property (background v)
      (list (format "background: ~a;" (car v))
            (format "div[hssclass=hop-lflabel] > span { 
                       background: ~a; 
                     }" 
                    (car v)))))
  
(define-hss-type lflabel 
   "div[hssclass=hop-lframe] 
      div[hssclass=hop-lflabel] 
        span")
7Definition of the new lframe type element

HSS type­-spe­cif­ic prop­er­ties are nest­ed in­side a HSS type dec­la­ra­tion. They are sim­i­lar to glob­al prop­er­ties as pre­sent­ed Sec­tion 31 with two dif­fer­ences:

The sig­na­ture of a type­-spe­cif­ic prop­er­ty com­pil­er is:

type property compiler:
  string list × string → string + string list

When the re­turned val­ue is a list, any of the con­tained strings can ei­ther be a HSS prop­er­ty as­sign­ment or a plain HSS rule. The first case is used to con­fig­ure the HTML el­e­ment as­so­ci­at­ed with the de­fined HTML el­e­men­t. The sec­ond case is used to con­fig­ure HTML el­e­ments em­bed­ded in­side the HTML el­e­men­t. In the ex­am­ple of Fig­ure 7, -hop-label-margin is ap­plied to HTML DIV whose hssclass is hop-lframe. The -hop-label-border is ap­plied to HTML DIV whose hssclass is hop-lfborder and that are chil­dren of LFRAME el­e­ments. Sec­tion 4 shows how these prop­er­ties are com­piled into CSS.

The :body ar­gu­ment is bound to a se­lec­tor string. It is used to change the HSS com­pil­er alias­ing res­o­lu­tion. The :body ar­gu­ment is added to a se­lec­tor rule when the type el­e­ment is not used in the right-­most po­si­tion or when it is used with a pseu­do-s­e­lec­tor such as :first-child.

The de­fault con­fig­u­ra­tion of LFRAME that is giv­en by:

lframe {
  background: #edeceb;
  border: 1px solid black;
  padding: 2px;
  box-shadow: 5px 5px 5px #888;
  -hop-label-margin: 10px;
  -hop-label-border: 2px groove #ddd;
  -hop-label-border-radius: 4px;
  -hop-label-align: left;
  -hop-label-offset: 12px;
}
lflabel {
  font-style: roman;
}

It pro­duces the fol­low­ing ren­der­ing:

A Label
The lframe body.

Chang­ing the graph­i­cal as­pects of a LFRAME no longer re­quires to be aware of its im­ple­men­ta­tion. For in­stance

lframe.lframe-right {
  -hop-label-align: right;
  -hop-label-border-radius: 0;
  -hop-label-border: 2px ridge green;
}
lframe.lframe-right lflabel {
  font-variant: small-caps;
}

changes the de­fault ren­der­ing. It flush­es right the frame la­bel writ­ten us­ing a small caps font and used a green ridge bor­der. It is ren­dered as:

A Label
The lframe body.

34 Computed values

CSS is a pure­ly declar­a­tive lan­guage. It can­not be used to ex­press com­pu­ta­tion­s. CSS val­ues are thus lit­er­al­s. The fourth ex­ten­sion sup­port­ed by HSS al­lows com­put­ed val­ues to be injected in­side gen­er­at­ed CSS files.

341 The $-form

HSS ex­tends CSS state­ments and val­ues with one ad­di­tion­al syn­tax that inject com­pile-­time val­ues in the gen­er­at­ed CSS file. The $-form per­mits HSS source files to de­clare lo­cal vari­ables or im­port vari­ables or to bind val­ues to prop­er­ties. The fol­low­ing ex­am­ple

$(module hss-example)

$(define bg "#999")
$(define (light-color v) ...not given here...)
 
button {
  background: $bg;
}
button:hover {
  background: $(light-color bg);
}

de­fines a Hop mod­ule hss-example that de­clares one glob­al vari­able bg and one func­tion light-color. The glob­al vari­able is used twice in the ex­am­ple to spec­i­fy the back­ground col­or of but­ton­s.

342 Motivating example: skins

In­ject­ing dy­nam­ic val­ues roots HSS in­side the de­vel­op­ment kit that em­beds it. As demon­strat­ed by the ex­am­ples, it al­lows the vari­ables and the val­ues of the pro­gram­ming lan­guage to be used in­side HSS files. This may be used to cus­tomize HSS files. For in­stance, as­sum­ing a Hop data struc­ture that im­ple­ments skins:

(module skinning
  (export (class skin
             button-border
             button-background
             button-font
             toolbar-icon-size
             toolbar-style
             ...)
          (get-current-skin::skin)))

Then, HSS files may use these skins in source files such as:

$(module hss-example
   (import skinning))

$(define skin (get-current-skin))

button {
  border: $(skin-border skin);
  background: $(skin-button-bg skin);
  font: $(skin-font skin);
}
button:hover {
  background: $(light-color (skin-button-bg skin));
}
...

This tech­nique for im­ple­ment­ing skins al­lows ap­pli­ca­tions con­ceived and im­ple­ment­ed in­de­pen­dent­ly to share graph­i­cal con­fig­u­ra­tions. Glob­al­ly co­her­ent vi­su­al as­pect can thus be en­forced at the en­vi­ron­ment lev­el.

4 The HSS compiler

This sec­tion pre­sents the whole HSS com­pil­er. The com­pi­la­tions al­go­rithms are giv­en Fig­ures 10 through 15. They use the syn­tac­tic no­ta­tions pre­sent­ed Fig­ure 9. Read­ers only in­ter­est­ed by the HSS de­sign and not con­cerned by the tech­ni­cal as­pects of its im­ple­men­ta­tion can safe­ly skip this sec­tion.

The first step of the com­pi­la­tion normalizes HSS pro­gram­s. It pro­duces rules that con­tain only one se­lec­tor and it eval­u­ates glob­al Hop ex­pres­sion­s. Af­ter that stage pro­grams are de­scribed by the gram­mar H0 giv­en in Fig­ure 8.

H0::=S {D1;Dm; } rule
8Grammar for normalized HSS.

H, the com­plete syn­tax for HSS and H0 are re­lat­ed by:

H0H

In ad­di­tion, C, the ac­tu­al CSS syn­tax is re­lat­ed to H by:

CH

C, the com­pi­la­tion func­tion that trans­forms a HSS pro­gram into a CSS pro­gram, has the fol­low­ing pro­to­type:

C : H0 × τ × ρ × φ → C

H0 is the pro­gram to be com­piled, τ is the el­e­ment type en­vi­ron­ment that is ex­tend­ed by define-hss-type, ρ is the prop­er­ty en­vi­ron­ment that is ex­tend­ed by define-hss-property, and φ is the func­tion en­vi­ron­ment that is ex­tend­ed by define-hss-function.

The com­pi­la­tion al­go­rithm han­dles each rule sep­a­rate­ly. It re­solves type el­e­ment alias­ing and it in­vokes prop­er­ty and val­ue com­pil­er­s.

In this pre­sen­ta­tion, the com­pi­la­tion of the rule

S1 op1opn-1 Sn {D1; … Dm;}

in the type en­vi­ron­ment τ, the prop­er­ty en­vi­ron­ment ρ, and the func­tion en­vi­ron­ment φ is writ­ten:

CS1 op1opn-1 Sn {D1; … Dm;}⟧τρφ
Stypethe type of a selector S. e.g., div#footype = div
Sρthe property set of the type of the sector S. Sρρ (Stype).
τ(IDENT)selectorthe selector of user-defined types e.g., τ(lframe)selector = div[hssclass=hop-lframe]
τ(IDENT)bodythe optional body of user-defined types e.g., τ(lframe)body = div[hssclass=hop-lfbody]
ρ(IDENT)selectorthe selector of a type property.
ρ(IDENT)compilerthe compiler of user-defined property.
T1 and T2the first and second projection. e.g., ⟨a × b⟩2 = b
§the concatenation of lists.
9Notations. This figure presents the notations used by the compilation algorithms.

Sn drives the com­pi­la­tion of rules such as:

CS1 op1opn-1 Sn {D1; … Dm;}⟧
CS1 op1opn-1 Sn {D1; … Dm;}⟧τρφ = 
  if Sntype ∉ τ or pseudo(Sn) 
      then CsimpleS1 op1opn-1 Sn {D1; … Dm;}⟧τρφ
      then CuserS1 op1opn-1 Sn {D1; … Dm;}⟧τρφ
10Dispatching rules

41 Compiling Simple Rules

The func­tion Csimple com­piles simple rules by re­solv­ing type alias­ing and ex­pand­ing at­tributes name and val­ue. Sec­tion 33 of­fers a first ex­am­ple for Csimple that is de­tailed be­low. In the rule:

div.important warning button {
  background: yellow;
}

warning is a user de­fined type but not used in the right-­most po­si­tion of the se­lec­tor. So it does not drive the rule prop­er­ties ex­pan­sion. That rule ac­tu­al­ly con­fig­ures but­tons, not warn­ings. Hence, its com­pi­la­tion mere­ly con­sists in re­solv­ing se­lec­tor alias­ing. It then pro­duces:

div.important span.warning button {
  background: yellow;
}

This ex­am­ple il­lus­trates type alias­ing, the Sec­tion 311 pro­vides an ex­am­ple of at­tribute alias­ing and val­ue ex­pan­sion. In that Sec­tion a black-and-white prop­er­ty has been de­fined. It can be used in rules such as:

div.box {
  black-and-white: invert;
}

Ex­pand­ing the at­tribute black-and-white pro­duces:

div.box {
  color: white;
  background: black;
}

The func­tion Csimple, in charge of this trans­for­ma­tion, is pre­sent­ed in Fig­ure 11.

CsimpleS1 op1opn-1 Sn {D1; … Dm;}⟧τρφ = 
  CaliasS1τ op1opn-1 CaliasSnτ { 
     CdeclD1τρφ2; … CdeclDmτρφ2; 
  }
11Compiling simple rule

411 Compiling Selectors

The com­pi­la­tion of sim­ple se­lec­tors is giv­en by the func­tion Calias giv­en in Fig­ure 12. As shown in the warning ex­am­ple, it re­places user-de­fined types, i.e., types bound in the τ en­vi­ron­ment, with the se­lec­tor ex­pres­sion giv­en at the type dec­la­ra­tion.

Calias⟦IDENT⟧τ = 
  if IDENT ∈ τ 
     then Calias⟦τ(IDENT)selectorτ 
     else IDENT
Calias⟦IDENT.STRING⟧τ = 
  if IDENT ∈ τ 
     then Calias⟦τ(IDENT)selector.STRING⟧τ 
     else IDENT.STRING
Calias⟦IDENT:STRING⟧τ = 
  if IDENT ∈ τ 
     then let i = τ(IDENT) in
            if ibody 
               then Calias⟦iselector < ibody:STRING⟧τ 
               else Calias⟦iselector:STRING⟧τ
     else IDENT:STRING
12Compilation of selectors

One sub­tle­ty is in­tro­duced by pseu­do-ele­ments that ac­tu­al­ly change the alias res­o­lu­tion. This is il­lus­trat­ed by the fol­low­ing ex­am­ple that uses the lframe el­e­ment pre­sent­ed in Fig­ure 7:

lframe:first-child {
  border: 1px solid red;
}

The in­ten­tion of this rule is to set a bor­der to the first user child of lframe el­e­ments by op­po­si­tion to the child of the el­e­ment that im­ple­ments the out­er box of the lframe. This in­ten­tion is spec­i­fied in HSS by adding a :body ar­gu­ment to the type dec­la­ra­tion. The :body ar­gu­ment is bound to a se­lec­tor string which is used to change the HSS com­pil­er alias­ing res­o­lu­tion. The :body ar­gu­ment is added to a se­lec­tor rule when the type el­e­ment is not used in the right-­most po­si­tion or when it is used with a pseu­do-s­e­lec­tor such as :first-child.

In this ex­am­ple, since the dec­la­ra­tion of lframe spec­i­fies a :body ar­gu­ment, then :first-child must be re­solved against that el­e­ment, not against the el­e­ment im­ple­ment­ing the out­er lframe box. Hence, re­mem­ber­ing that lframe's :body at­tribute is div[hssclass=hop-lfbody], Calias com­piles the pre­vi­ous dec­la­ra­tion into:

div[hssclass=hop-lframe] 
   div[hssclass=hop-lfbody]:first-child {
  border: 1px solid red;
}

With­out the :body op­tion­al ar­gu­ment it would have been com­piled into:

div[hssclass=hop-lframe]:first-child {
  border: 1px solid red;
}

412 Compiling Declarations

Dec­la­ra­tions are com­piled by the func­tion Cdecl (see Fig­ure 13). The en­vi­ron­ment ρ binds prop­er­ty iden­ti­fier­s. For each iden­ti­fi­er it as­so­ci­ates a se­lec­tor and a com­pil­er.

Cdecl⟦IDENT : E⟧τρφ = 
  if IDENT ∈ ρ
     then let s = ρ(IDENT)selector
              c = ρ(IDENT)compiler in
            ⟨s × c(E)⟩
     else ⟨false × IDENT : Cexpr⟦E⟧φ
13Compiling declarations

The sec­ond func­tion need­ed to com­pile HSS dec­la­ra­tions is Cexpr (see Fig­ure 14). It takes in charge the com­pi­la­tion of ex­pres­sion­s. It re­solves $-forms and user-de­fined func­tions bound in the en­vi­ron­ment φ.

Cexpr⟦STRING⟧φ = STRING
Cexpr⟦$expr⟧φ = HOP(expr)
Cexpr⟦IDENT(expr)⟧φ = 
   let e = Cexpr⟦expr⟧φ in
     if IDENT ∈ φ 
        then let f = φ(IDENT) in f(e) 
        else IDENT(e)
14Compiling property values

42 Compiling User Rules

The right most el­e­ment type of a se­lec­tor spec­i­fies the el­e­ments the rule ap­plied to. The left el­e­ments lim­it the set of el­e­ments the rule ap­plies to so they do not im­pact the com­pi­la­tion of rule at­tributes. In the rest of this sec­tion, rules where the right most el­e­ment is a user de­clared type are re­ferred to as user rules. This sec­tion pre­sents the HSS com­pi­la­tion func­tion Cuser that han­dles them.

As shown in Sec­tion 33 and in par­tic­u­lar in the lframe ex­am­ple pre­sent­ed in Fig­ure 7, prop­er­ties of user de­fined types may be as­so­ci­at­ed with se­lec­tors. For in­stance, the padding prop­er­ty of the user de­fined lframe type is as­so­ci­at­ed with the se­lec­tor div[hssclass=hop-lfbody]. HSS has to gen­er­ate new se­lec­tors that ac­com­mo­dates the se­lec­tor used in the user type dec­la­ra­tion and the se­lec­tor used in the prop­er­ty dec­la­ra­tion. This is il­lus­trat­ed with two ex­am­ples. The first one il­lus­trates the com­pi­la­tion frame­work when the prop­er­ty does not come with its se­lec­tor. The sec­ond il­lus­trates the com­pi­la­tion when a se­lec­tor is as­so­ci­at­ed to a prop­er­ty.

To ac­com­plish this trans­for­ma­tion, the func­tion Cuser first splits the ini­tial rule into m rules where m is the num­ber of prop­er­ties held by the rule. Sec­ond, it com­putes the se­lec­tor of these new rules ac­cord­ing to prop­er­ty dec­la­ra­tions. The whole def­i­ni­tion of C is giv­en in Fig­ure 15 where, for sim­pli­fy­ing the pre­sen­ta­tion, it is as­sumed that type prop­er­ty com­pil­ers only re­turn sin­gle strings.

CuserS1 op1opn-1 Sn {D1; … Dm;}⟧τρφ = 
  let ρ' = Snρ § ρ in
      d1 = CdeclD1in 
    if d11 
       then CS1 op1opn-1 Sn < d11 {d12;}⟧τρφ
       else CaliasS1τ op1opn-1 CaliasSnτ {d12;}
    …
    let dm = CdeclDmin
15User rules compilation

5 Limits and Future work

HSS sup­ports a high­er lev­el of ab­strac­tion than CSS be­cause it can be used to hide wid­gets im­ple­men­ta­tion de­tail­s. How­ev­er, not all HTML style spec­i­fi­ca­tions are giv­en in CSS files. Some are spec­i­fied stat­i­cal­ly via the HTML :style at­tribute and oth­ers are even com­put­ed dy­nam­i­cal­ly on the clien­t-­side code. In all these cas­es, HSS is hope­less.

It could be ap­peal­ing to re­sort on the Hop dual com­pil­er that al­lows a same source code to be com­piled for the serv­er (via na­tive code com­pi­la­tion) as well as com­piled for the client (via JavaScript code com­pi­la­tion 4

4Trends in Functional ProgrammingHop Client-Side CompilationSeton Hall University, Intellect Bristol, ed. Morazán, M. T.UK/Chicago, USA141--158.
) to run the HSS com­pil­er on the server-­side and on the clien­t-­side of web ap­pli­ca­tion­s. How­ev­er, we think that this would be un­re­al­is­tic be­cause the HSS im­ple­men­ta­tion is too big. It is un­de­cid­able if HSS is need­ed or not on the client side, then HSS would have to be in­clud­ed in the reg­u­lar clien­t-­side run­time sys­tem, that is shipped with all the web pages de­liv­ered to clients. This would dra­mat­i­cal­ly en­large the load time of all Hop ap­pli­ca­tions as it would clut­ter the mem­o­ry of the web browsers than ex­e­cute them.

User-de­fined HTML el­e­ments can be as­signed names us­ing the define-hss-type for­m. De­vel­op­ers re­fer to these names for spec­i­fy­ing graph­i­cal tun­ings, in­de­pen­dent­ly of the im­ple­men­ta­tion de­tail­s. Un­for­tu­nate­ly this name bind­ing fails at to­tal­ly hid­ing im­ple­men­ta­tion de­tails be­cause it does not pre­vent the ref­er­enced HTML se­quence to be im­pact­ed by gen­er­al CSS rules. For in­stance, a lframe as de­fined in Fig­ure 7 is ac­tu­al­ly an alias for div[hssclass=hop-lframe]. Then, lframe is im­pact­ed by any gen­er­al rule men­tion­ing DIV el­e­ment such as:

div {
  background-color: red;
}

Al­though users may re­fer to lframe by a ded­i­cat­ed type name, a lframe is still a HTML DIV that can be con­fig­ured di­rect­ly by a CSS file! This let users in­fer that a lframe is ac­tu­al­ly im­ple­ment­ed with a DIV. We see no so­lu­tion to this prob­lem.

The cur­rent ver­sion of HSS does not sup­port user-de­fined pseu­do-ele­ments. How­ev­er, this could help im­prov­ing the back­ward com­pat­i­bil­i­ty be­tween CSS-2 and CSS-3. CSS-3 de­fines ad­di­tion­al pseu­do-ele­ments such as :last-child or :nth. Some of these are es­sen­tial and can­not be sim­u­lat­ed. Some could. This will be sub­ject of a fu­ture HSS ex­ten­sion­s.

6 Related work

HSS has first been men­tioned but not de­tailed in an ear­ly pub­li­ca­tion 7

7The HOP Development Kithttp://www.inria.fr/mimosa/Manuel.Serrano/publi/sfp06/article.htmlInvited paper of the Seventh ACM sigplan Workshop on Scheme and Functional ProgrammingPortland, Oregon, USA.
. We have not been able to ob­serve oth­er ev­i­dence of aca­dem­ic stud­ies con­cern­ing CSS in the main­stream con­fer­ences and jour­nals ded­i­cat­ed to the web. For in­stance, we have found no men­tion of CSS stud­ies in any of the 10 last ACM WWW con­fer­ences. How­ev­er, we think that CSS play­ing an im­por­tant role in the pro­duc­tion of web ap­pli­ca­tions, it de­serves our at­ten­tion.

No ar­ti­cle has been writ­ten by the academies or by re­search in­sti­tutes but some tools have been pro­duced by pri­vate com­pa­nies or by the free soft­ware ac­tors. In this sec­tion they are com­pared to HSS.

16This table summarizes the main characteristics of CSS compilers. Syntax denotes the input syntax of the compilers. The "Host" column gives indication on how the tool can be used. The column "Utype" shows which system allows users to define HTML elements. The column "Uprop" shows which system implements user properties. "Nesting" denotes the support of nested selectors declaration. "Var." denotes the possibility to declare variables inside style files. "Fun." denotes the possibility to develop private functions and, for those systems that support this feature, the programming language used for defining functions. "Block" denotes the possibility for a variable to contain a CSS value or a complete CSS block. "Expr." denotes the possibility to embedded expressions in property declarations and the language used for these expressions.

All these sys­tems, in­clud­ing HSS, share many fea­tures that help writ­ing more com­pact and portable CSS files. Fig­ure 16 sum­ma­rizes their main char­ac­ter­is­tic­s. As HSS some of these oth­er sys­tems raise the ab­strac­tion lev­el used in CSS files by sup­port­ing func­tions and vari­ables. How­ev­er, we think that HSS goes one step fur­ther by pre­sent­ing a co­her­ent ex­ten­sion frame­work that let de­vel­op­ers de­clare func­tions, and vari­ables as well as new el­e­ment prop­er­ties and new el­e­ment type­s.

7 Conclusion

This pa­per has pre­sent­ed HSS that ex­tends CSS with user de­fined vari­ables, func­tions, and el­e­ment type­s. The pa­per has shown that gen­er­at­ing CSS files im­proves porta­bil­i­ty and main­tain­abil­i­ty and rais­es the ab­strac­tion lev­el of CSS.

The pa­per has pre­sent­ed the HSS com­pi­la­tion al­go­rithm which is sim­ple enough to be re-im­ple­ment­ed with any we­b-ded­i­cat­ed pro­gram­ming lan­guage.

The cur­rent HSS source code is shipped with Hop whose de­vel­op­ment kit is avail­able at http://hop.inria.fr.

8 Acknowledgments

Thanks for the anonymous PPDP'10 referees whose help greatly improved this paper.

9References

1Towards Reasoning for Web Applications: an Operational Semantics for HopProceedings of the first Workshop on Analysis and Programming Languages for Web Applications and Cloud ApplicationsToronto, Canada.
2Haxe HSShttp://ncannasse.fr/projects/hss.
3Sass -- Syntactically Awesome StyleSheetshttp://sass-lang.com/.
4Trends in Functional ProgrammingHop Client-Side CompilationSeton Hall University, Intellect Bristol, ed. Morazán, M. T.UK/Chicago, USA141--158.
5CleverCSShttp://sandbox.pocoo.org/clevercss/.
6Lesshttp://lesscss.org/index.html.
7The HOP Development Kithttp://www.inria.fr/mimosa/Manuel.Serrano/publi/sfp06/article.htmlInvited paper of the Seventh ACM sigplan Workshop on Scheme and Functional ProgrammingPortland, Oregon, USA.
8HOP, a language for programming the Web 2.0http://www.inria.fr/mimosa/Manuel.Serrano/publi/dls06/article.htmlProceedings of the First Dynamic Languages SymposiumPortland, Oregon, USA.
9Cascading Style Sheets level 2 Revision 1 CSS2.1 Specificationhttp://www.w3.org/TR/2009/CR-CSS2-20090423/CR-CSS2-20090423W3C Recommendation.
HOP home pageHopTeX