Skip to content

paddymul/css-lite

Repository files navigation

css-lite is a library for generating CSS from an s-exp based syntax. When compiled with Parenscript loaded in the Lisp image, it also provides the same CSS generation facilities in Parenscript-generated JavaScript code.

Installation

First, install Quicklisp.

After that, type in your Lisp prompt the following:

(ql:quickload 'css-lite)

It should download and load css-lite. This download is only done once, after that Quicklisp will always load your local copy of css-lite.

Note: In previous versions of css-lite there was a bug where you sometimes couldn’t call (ql:quickload 'css-lite) without having previously called (ql:quickload 'parenscript). This bug has hopefully now been fixed.

Examples

After loading the css-lite library, you are now ready to try these examples.

First Example

Set the width of the “body” tag to be 70%

(css-lite:css
  (("body") (:width "70%")))

Output:

"
body {
width:70%;
}
"

By default, css-lite doesn’t indent the properties. If you wish to indent them, see the documentation for the variable css-lite:*indent-css*, or the section “Change the indentation” of this README. For example, if you change the value of the variable css-lite:*indent-css* to 4, this would be the output:

"
body {
    width:70%;
}
"

Second Example

Set the height of the ID “foo” to 50px and the width to 10em

(css-lite:css
  (("#foo")
    (:height "50px"
     :width "10em")))

Output:

"
#foo {
height:50px;
width:10em;
}
"

To do the same thing, but to a class “foo”, simply replace “#foo” with “.foo”.

(css-lite:css
  ((".foo")
    (:height "50px"
     :width "10em")))

Output:

"
.foo {
height:50px;
width:10em;
}
"

Third Example

Define the properties of rules “#foo” and “#foo li”

(css-lite:css
  (("#foo")
    (:length "50px"
     :margin "50 px 30 px"
     :border "1px solid red")
   (("li")
    (:width "50px"
     :float "left"
     :margin "50 px 30 px"
     :border "1px solid red"))))

Output:

"
#foo {
length:50px;
margin:50 px 30 px;
border:1px solid red;
}

#foo li {
width:50px;
float:left;
margin:50 px 30 px;
border:1px solid red;
}
"

Fourth Example

In the third example, the rules “margin:50 px 30 px;” and “border:1px solid red;” are repeated twice. css-lite has something called CSS variables that allow to abstract this.

You create a CSS variable by using the macro css-lite:make-css-var.

(css-lite:make-css-var my-favorite-border-var '(:border "1px solid red"))
(css-lite:make-css-var my-margin-var '(:margin "50px 30px"))

Then you could write the third example as this:

(css-lite:css
   (("#foo")
     (:length "50px"
      my-margin-var
      my-favorite-border-var)
    (("li")
     (:width "50px"
      :float "left"
      my-margin-var
      my-favorite-border-var))))

Output:

"
#foo {
length:50px;
margin:50px 30px;
border:1px solid red;
}

#foo li {
width:50px;
float:left;
margin:50px 30px;
border:1px solid red;
}
"

Fifth Example

In addition to the CSS variables, css-lite also provides the ability to define CSS functions. This allows you to perform arbitrary modifications on the rules.

This function is declared using the macro css-lite:make-css-func and can receive any number of arguments. However, it should return a list with 2 values, the first being the name of the property and the second its value.

For example, to create a function that receives the name of a property and its value in inches and converts that value into centimeters use this:

(css-lite:make-css-func convert-in-to-cm (property-name value)
  ;; Assumes that `value' is a string with the following
  ;; format: XXin, where XX represents a number greater than 0
  (let* ((inches (parse-integer
                   (string-right-trim "in " value)))
          (centimeters (round (* inches 2.54))))
    (list property-name
      (concatenate 'string
        (write-to-string centimeters)
        "cm"))))

So this call:

(convert-in-to-cm :width "10in")

Returns this list:

(:WIDTH "4cm")

So to use this function to convert the height of the identifier “#foo” from inches to centimeters, you would write this code:

(css-lite:css
  (("#foo")
    (:length "50px"
     my-margin-var
     (convert-in-to-cm :width "10in")
     my-favorite-border-var)))

Output:

"
#foo {
length:50px;
margin:50px 30px;
width:4cm;
border:1px solid red;
}
"

Sixth Example

To add a CSS comment use the function css-lite:comment

(css-lite:css
  (("body")
    ((css-lite:comment "These are the rules for the body tag")
     :width "80%"
     :float "left")))

Output:

"
body {
/*These are the rules for the body tag*/
width:80%;
float:left;
}
"

To see more examples, see the file example-usage.lisp

Change the indentation

As you can see be the above examples, by default, css-lite doesn’t indent the rules.

However you can customize this behaviour by changing the value of the variable css-lite:*indent-css*.

There are three possible values:

  • nil - The default value, indicates that no indentation should be performed
  • the symbol ‘tab - Indicates that the rules should be indented using a #\Tab character
  • a number greater than 0 - Indicates that the rules should be indented with that many #\Space characters.

For example, to indent the rules with 4 spaces, you would type:

(setf css-lite:*indent-css* 4)

The next time you call the css-lite:css function, the code will be indented with 4 spaces.

For example, calling the function css-lite:css with this value:

(css-lite:css
    (("body")
      ((css-lite:comment "These are the rules for the body tag")
       :width "80%"
       :float "left")))

Output:

"
body {
    /*These are the rules for the body tag*/
    width:80%;
    float:left;
}
"

Tests

Test implemented using the FiveAM test library.

Run tests via the ASDF :TEST-OP

(asdf:oos ':test-op 'css-lite/test)

Or using the FiveAM run command

(fiveam:run! :css-lite)

About

a css grammar for lisp

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published