#cs
(module css mzscheme
(require "xml.ss"
"html.ss")
(require-for-syntax (lib "stx.ss" "syntax"))
(define-syntax (css-attr stx)
(syntax-case stx ()
((_ (name1 val1))
(syntax (string-append (symbol->string 'name1)
":"
val1
";")))
((_ (name1 val1) (name val) ...)
(syntax (string-append (string-append (symbol->string 'name1)
":"
val1
";")
(string-append " "
(symbol->string 'name)
":"
val
";")
...)))))
(define-syntax (css/html stx)
(syntax-case stx ()
((_ . rest)
(syntax (h4:style h4:type: "text/css" (css . rest))))))
(define (create-css decls)
(make-css-node decls))
(define (css-link url)
(h4:link h4:rel: "stylesheet"
h4:href: url
h4:type: "text/css"))
(define (css-link/xml url)
(make-xml-pi "xml-stylesheet"
(list (format "type=\"text/css\" href=~a media=\"screen\""
url))))
(define-syntax (css stx)
(syntax-case stx ()
((_ . lst)
(letrec ((parse-avp (lambda (avp)
(syntax-case* avp (!)
module-or-top-identifier=?
((! (name val))
#'(make-em-avp 'name val))
((name val)
#'(make-avp 'name val)))))
(parse-avp-list (lambda (lst)
(syntax-case* lst ()
module-or-top-identifier=?
((fst . rst)
#`(cons #,(parse-avp #'fst)
#,(parse-avp-list #'rst)))
(()
#'()))))
(parse-symbol-selector (lambda (sel)
(syntax-case sel ()
(i #'(quote i)))))
(parse-simple-selector (lambda (sel-item)
(syntax-case* sel-item (// pclass id)
module-or-top-identifier=?
(sel
(identifier? #'sel)
(parse-symbol-selector #'sel))
((sel)
#`(list #,(parse-simple-selector #'sel)))
((id sel)
#`(quote #,(string->symbol
(string-append "#"
(symbol->string (syntax-e #'sel))))))
((id typ sel)
#`(quote #,(string->symbol
(string-append (symbol->string (syntax-e #'typ))
"#"
(symbol->string (syntax-e #'sel))))))
((classx sel)
(eq? (syntax-object->datum #'classx) 'class)
#`(quote #,(string->symbol
(string-append "."
(symbol->string (syntax-e #'sel))))))
((classx typ sel)
(eq? (syntax-object->datum #'classx) 'class)
#`(quote #,(string->symbol
(string-append (symbol->string (syntax-e #'typ))
"."
(symbol->string (syntax-e #'sel))))))
((pclass sel)
#`(quote #,(string->symbol
(string-append ":"
(symbol->string (syntax-e #'sel))))))
((pclass typ sel)
#`(quote #,(string->symbol
(string-append (symbol->string (syntax-e #'typ))
":"
(symbol->string
(syntax-e #'sel))))))
((pclass (classx csel) sel)
(eq? (syntax-object->datum #'classx) 'class)
#`(quote #,(string->symbol
(string-append "."
(symbol->string
(syntax-e #'csel))
":"
(symbol->string
(syntax-e #'sel))))))
((pclass (classx typ csel) sel)
(eq? (syntax-object->datum #'classx) 'class)
#`(quote #,(string->symbol
(string-append (symbol->string
(syntax-e #'typ))
"."
(symbol->string
(syntax-e #'csel))
":"
(symbol->string (syntax-e #'sel))))))
((sel1 sel ...)
#`(cons #,(parse-symbol-selector #'sel1)
#,(parse-selector #'(sel ...)))))))
(parse-steps (lambda (lst)
(syntax-case lst ()
(() #'())
((sel) #`(list #,(parse-simple-selector #'sel)))
((sel1 . rst) #`(cons #,(parse-simple-selector #'sel1)
#,(parse-steps #'rst))))))
(parse-path-selector (lambda (sel-item)
(syntax-case* sel-item (//)
module-or-top-identifier=?
((// i ...)
#`(make-path-selector #,(parse-steps #'(i ...))))
(a (parse-simple-selector #'a)))))
(parse-selector (lambda (sel-item)
(syntax-case* sel-item (// pclass id)
module-or-top-identifier=?
(sel
(identifier? #'sel)
(parse-symbol-selector #'sel))
((// sel ...)
(parse-path-selector #'(// sel ...)))
((sel)
#`(list #,(parse-path-selector #'sel)))
((id sel)
(parse-simple-selector #'(id sel)))
((id typ sel)
(parse-simple-selector #'(id typ sel)))
((classx sel)
(eq? (syntax-object->datum #'classx) 'class)
(parse-simple-selector #'(classx sel)))
((classx typ sel)
(eq? (syntax-e #'class) 'class)
(parse-simple-selector #'(classx typ sel)))
((pclass sel)
(parse-simple-selector #'(pclass sel)))
((pclass (classx csel) sel)
(eq? (syntax-object->datum #'classx) 'class)
(parse-simple-selector #'(pclass (classx csel) sel)))
((pclass (classx typ csel) sel)
(eq? (syntax-object->datum #'classx) 'class)
(parse-simple-selector #'(pclass (classx typ csel) sel)))
((pclass typ sel)
(parse-simple-selector #'(pclass typ sel)))
((sel1 sel ...)
#`(cons #,(parse-simple-selector #'sel1)
#,(parse-selector #'(sel ...)))))))
(parse-rule (lambda (r)
(syntax-case r ()
((sel avp ...)
#`(make-css-rule #,(parse-selector #'sel)
#,(parse-avp-list #'(avp ...)))))))
(parse-rules (lambda (lst)
(syntax-case lst ()
((fst others ...)
#`(cons #,(parse-rule #'fst)
#,(parse-rules #'(others ...))))
((fst)
#`(list #,(parse-rule #'fst)))
(()
#'()))))
(parse-clause (lambda (c)
(syntax-case* c (import)
module-or-top-identifier=?
((import url)
#'(make-import-clause url)))))
(parse-clauses (lambda (lst)
(syntax-case* lst (import)
module-or-top-identifier=?
(((import . a) . rst)
(begin (write "parsing import")
(newline)
#`(cons #,(parse-clause #'(import . a))
#,(parse-clauses #'rst))))
(rst
(parse-rules #'rst))))))
#`(make-css-node #,(parse-clauses #'lst))))))
(provide css-attr
css
(rename css text/css)
css/html
(rename css/html text/css-html)
css-link
(rename css-link external-stylesheet/html)
css-link/xml
(rename css-link/xml external-stylesheet/xml)
css-node?)
)