Wiki
Download
Manual
Eggs
API
Tests
Bugs
show
edit
history
You can edit this page using
wiki syntax
for markup.
Article contents:
== Chiccup A modern HTML rendering system for CHICKEN Scheme with CSS selector integration. === Description Chiccup is a lightweight HTML rendering library that allows you to write HTML using Lisp syntax with CSS-inspired selectors. It converts simplified Chiccup-style lists to SXML and then to HTML using sxml-transforms, providing both security through automatic HTML escaping and flexibility for advanced transformations. === Requirements * CHICKEN Scheme 5.0 or later * Dependencies: srfi-1, srfi-13, sxml-transforms === Installation <enscript highlight="bash"> chicken-install chiccup </enscript> === Basic Usage <enscript highlight="scheme"> (import chiccup) ;; Simple elements (ccup->html `[h1 "Hello World"]) ;; => <h1>Hello World</h1> ;; CSS classes and IDs (ccup->html `[.container.mx-auto#main "Content"]) ;; => <div class="container mx-auto" id="main">Content</div> ;; Attributes (ccup->html `[a (@ (href "/page")) "Link"]) ;; => <a href="/page">Link</a> </enscript> === API <procedure>(ccup->html s-html)</procedure> Convert Chiccup list to HTML string. String content is automatically HTML-sanitized to prevent XSS attacks. <enscript highlight="scheme"> ;; Basic elements (ccup->html `[div "Hello World"]) ;; => <div>Hello World</div> ;; Automatic escaping for security (ccup->html `[div "< & >"]) ;; => <div>< & ></div> ;; CSS classes and IDs - default element is "div" ;; Note: ID (#id) must come after classes (ccup->html `[.container.mx-auto#main "Content"]) ;; => <div class="container mx-auto" id="main">Content</div> </enscript> <procedure>(ccup->sxml s-html)</procedure> Convert Chiccup list to SXML for advanced processing with the sxml-transforms ecosystem. <enscript highlight="scheme"> (ccup->sxml `[div.class "content"]) ;; => (div (@ (class "class")) "content") </enscript> ==== CSS Selector Syntax Chiccup supports CSS-style selectors in element names: '''Tag Names:''' Any valid HTML tag name <enscript highlight="scheme"> `[h1 "Title"] ; => <h1>Title</h1> `[button "Click"] ; => <button>Click</button> </enscript> '''Classes:''' Use dot notation, multiple classes allowed <enscript highlight="scheme"> `[.primary "Content"] ; => <div class="primary">Content</div> `[button.btn.btn-primary "OK"] ; => <button class="btn btn-primary">OK</button> </enscript> '''IDs:''' Use hash notation (must come after classes) <enscript highlight="scheme"> `[\#header "Title"] ; => <div id="header">Title</div> `[.container#main "Content"] ; => <div class="container" id="main">Content</div> </enscript> '''Note''': if you only specify the id, you need to escape the hash symbol. ==== Attributes Use the `@` syntax for explicit attributes: <enscript highlight="scheme"> ;; Basic attributes `[input (@ (type "text") (name "username"))] ;; => <input type="text" name="username"> ;; Boolean attributes (no values) `[input (@ (type "checkbox") (checked) (disabled))] ;; => <input type="checkbox" checked disabled> ;; Attribute values are automatically HTML-escaped `[div (@ (data-config "{\"theme\":\"dark\"}")) "Content"] ;; => <div data-config="{"theme":"dark"}">Content</div> ;; Conditional attributes (let ((is-disabled #t)) `[button (@ (type "submit") ,@(if is-disabled '((disabled)) '())) "Submit"]) ;; => <button type="submit" disabled>Submit</button> </enscript> When both CSS selector classes and explicit `@` attributes contain classes, they are merged: <enscript highlight="scheme"> `[div.container (@ (class "active")) "Content"] ;; => <div class="container active">Content</div> </enscript> ==== Dynamic Content <enscript highlight="scheme"> ;; Lists and iteration (let ((items '("Apple" "Banana" "Cherry"))) `[ul ,@(map (lambda (item) `[li ,item]) items)]) ;; => <ul><li>Apple</li><li>Banana</li><li>Cherry</li></ul> ;; Conditional content (let ((logged-in? #t)) `[div ,(if logged-in? `[p "Welcome back!"] `[a (@ (href "/login")) "Login"])]) </enscript> ==== Raw HTML Content For unescaped HTML content, use the `raw` marker: <enscript highlight="scheme"> `[div (raw "<em>emphasized</em>")] ;; => <div><em>emphasized</em></div> ;; Compare with normal escaped content: `[div "<em>emphasized</em>"] ;; => <div><em>emphasized</em></div> </enscript> ==== Void Elements Chiccup automatically handles HTML void elements (self-closing tags): <enscript highlight="scheme"> `[br] ; => <br> `[hr] ; => <hr> `[img (@ (src "/logo.png") (alt "Logo"))] ; => <img src="/logo.png" alt="Logo"> </enscript> Supported void elements: area, base, br, col, embed, hr, img, input, link, meta, param, source, track, wbr ==== Configuration Parameters <parameter>(ccup/doctype)</parameter> Controls the DOCTYPE declaration for HTML documents (default: "<!doctype html>"). <enscript highlight="scheme"> ;; Only applied when root element is 'html (ccup->html `[html [body "Hello"]]) ;; => <!doctype html><html><body>Hello</body></html> ;; Custom doctype (parameterize ((ccup/doctype "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0//EN\">")) (ccup->html `[html [body "Hello"]])) </enscript> <parameter>(ccup/raw-content-tags)</parameter> List of tags whose content should not be HTML-escaped (default: '(script style)). <enscript highlight="scheme"> `[script "alert('Hello');"] ; Content not escaped `[div "alert('Hello');"] ; Content escaped: alert('Hello'); ;; Add more raw content tags (parameterize ((ccup/raw-content-tags '(script style pre))) (ccup->html `[pre "<code>example</code>"])) ;; => <pre><code>example</code></pre> </enscript> === Complete Examples ==== Simple Page <enscript highlight="scheme"> (ccup->html `[html [head [title "My Page"] [meta (@ (charset "utf-8"))]] [body [.container [h1 "Welcome"] [p "This is a simple page."] [a (@ (href "/about")) "Learn more"]]]]) </enscript> ==== Form with Validation <enscript highlight="scheme"> (define (render-form errors) `[form (@ (method "POST") (action "/submit")) [.form-group [label (@ (for "email")) "Email:"] [input (@ (type "email") (name "email") (id "email") ,@(if (member 'email errors) '((class "error")) '()))] ,@(if (member 'email errors) `([.error-msg "Please enter a valid email"]) '())] [button.btn.btn-primary (@ (type "submit")) "Submit"]]) (ccup->html (render-form '(email))) </enscript> ==== Dynamic Navigation <enscript highlight="scheme"> (define (nav-item label url current?) `[li ,(if current? '(class "active") '()) [a (@ (href ,url)) ,label]]) (define (render-nav current-page) `[nav.navbar [ul.nav-list ,(nav-item "Home" "/" (eq? current-page 'home)) ,(nav-item "About" "/about" (eq? current-page 'about)) ,(nav-item "Contact" "/contact" (eq? current-page 'contact))]]) </enscript> === Security Chiccup automatically escapes string content to prevent XSS attacks, similar to modern frontend frameworks like React or Vue. Only use `raw` when you trust the content or have sanitized it yourself. <enscript highlight="scheme"> ;; Safe by default `[div ,user-input] ; Automatically escaped ;; Only when you trust the content `[div (raw ,trusted-html)] ; Not escaped - use with caution </enscript> === Integration with SXML Since Chiccup generates SXML, you can combine it with other SXML tools: <enscript highlight="scheme"> (import sxml-transforms) ;; Generate SXML and further process it (let ((sxml (ccup->sxml `[article [h1 "Title"] [p "Content"]]))) ;; Apply SXML transformations (SRV:send-reply (post-order sxml custom-rules))) </enscript> === License Copyright © 2025 Rolando Abarca. Released under BSD-3-Clause License. === Repository [[https://github.com/schematra/schematra|GitHub Repository]]
Description of your changes:
I would like to authenticate
Authentication
Username:
Password:
Spam control
What do you get when you multiply 2 by 5?