emacs.d/clones/lisp/www.cliki.net/cl-markup.html
2022-10-07 15:47:14 +02:00

182 lines
No EOL
6.6 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>CLiki: cl-markup</title>
<link rel="alternate" type="application/atom+xml" title="ATOM feed of edits to current article"
href="https://www.cliki.net/site/feed/article.atom?title=cl-markup">
<link rel="stylesheet" href="static/css/style.css">
<link rel="stylesheet" href="static/css/colorize.css">
</head>
<body>
<span class="hidden">CLiki - cl-markup</span>
<div id="content"><div id="content-area"><div id="article-title">cl-markup</div><div id="article">CL-MARKUP - Modern <a href="HTML&#32;generator.html" class="category">HTML generator</a> library for Common Lisp.<p><ul>
<li>Fast (even faster if you compile it)
</li>
<li>Safety
</li>
<li>Support multiple document types (markup, xml, html, xhtml)
</li>
<li>Output with doctype
</li>
<li>Direct output to stream
</li>
</ul><p>Homepage: <a href="https://github.com/arielnetworks/cl-markup">https://github.com/arielnetworks/cl-markup</a><p>License: <a href="LLGPL.html" class="category">LLGPL</a><p><h2>Some experiments:</h2><p><pre>(defpackage :cl-markup-test (use :cl))
(in-package :cl-markup-test)
;; central feature is MARKUP:
(markup (:p 123))
=&gt; &quot;&lt;p&gt;123&lt;/p&gt;&quot;
;; MARKUP expects list arguments, atoms are being rejected
(markup &quot;abc&quot;)
=&gt; The value &quot;abc&quot; is not of type LIST.
[Condition of type TYPE-ERROR]
;; arguments can be multiple lists
(markup (:p 123) (:p 234))
=&gt; &quot;&lt;p&gt;123&lt;/p&gt;&lt;p&gt;234&lt;/p&gt;&quot;
;; first element of list is used as tag, not bothering what type it is
;; and wether it smells like HTML
(markup (&quot;p&quot; 123))
=&gt; &quot;&lt;p&gt;123&lt;/p&gt;&quot;
(markup (p 123))
=&gt; &quot;&lt;p&gt;123&lt;/p&gt;&quot;
(markup (&#039;p 123))
=&gt; &quot;&lt;&#039;p&gt;123&lt;/&#039;p&gt;&quot; ; oops
(markup (123 p))
=&gt; error: The variable P is unbound.
[Condition of type UNBOUND-VARIABLE]
(markup (123 &quot;p&quot;))
=&gt; &quot;&lt;123&gt;p&lt;/123&gt;&quot; ; !!
;; whole HTML pages can be produced with cl-markup macros HTML, HTML5,
;; XHTML and XML.
(html5 (:p 42))
=&gt; &quot;&lt;!DOCTYPE html&gt;&lt;html&gt;&lt;p&gt;42&lt;/p&gt;&lt;/html&gt;&quot;
;; lisp expressions can be inserted everywhere except first position of list
(markup (:p (concatenate &#039;string &quot;1&quot; &quot;2&quot; &quot;3&quot;)))
=&gt; &quot;&lt;p&gt;123&lt;/p&gt;&quot;
;; these expressions are considered good citizens when they produce
;; string results, else:
(markup (:p (+ 100 20 3)))
=&gt; The value 123 is not of type STRING.
[Condition of type TYPE-ERROR]
;; weird things seem to happen when combining snippets
(let ((snip (markup (:p &quot;abc&quot;))))
(markup (:div snip)))
=&gt; &quot;&lt;div&gt;&amp;lt;p&amp;gt;abc&amp;lt;/p&amp;gt;&lt;/div&gt;&quot; ; !!
;; This is a feature called auto-escape and it provides correct
;; solutions for these kind of tasks:
(markup (:p &quot;1&lt;3&quot;))
=&gt; &quot;&lt;p&gt;1&amp;lt;3&lt;/p&gt;&quot;
(markup (:p &quot;R&amp;B&quot;))
=&gt; &quot;&lt;p&gt;R&amp;amp;B&lt;/p&gt;&quot;
;; auto-escaping can be turned off like this
(let* ((*auto-escape* nil)
(snip (markup (:p &quot;abc&quot;))))
(markup (:div snip)))
=&gt; &quot;&lt;div&gt;&lt;p&gt;abc&lt;/p&gt;&lt;/div&gt;&quot;
;; another way to shelter strings against greedy auto-escape
;; is wrapping them in a list
(let ((snip (markup (:p &quot;abc&quot;))))
(markup (:div (list snip))))
=&gt; &quot;&lt;div&gt;&lt;p&gt;abc&lt;/p&gt;&lt;/div&gt;&quot;
;; same result using backquote syntax
(let ((snip (markup (:p &quot;abc&quot;))))
(markup (:div `(,snip))))
=&gt; &quot;&lt;div&gt;&lt;p&gt;abc&lt;/p&gt;&lt;/div&gt;&quot;
;; and this can also be done with CL-MARKUPs RAW macro. RAW sounds
;; like a kind of strange name for a list-wrapping feature. Maybe the
;; name tries to express that this procedure treats the string
;; like the raw markup from which it evolved.
(let ((snip (markup (:p &quot;abc&quot;))))
(markup (:div (raw snip))))
=&gt; &quot;&lt;div&gt;&lt;p&gt;abc&lt;/p&gt;&lt;/div&gt;&quot;
;; and now for the best of all: it is possible to write cl macros
;; producing HTML snippets.
(defmacro snip (name)
`(markup (:p ,name)))
(snip &quot;foo&quot;)
=&gt; &quot;&lt;p&gt;foo&lt;/p&gt;&quot;
;; It is save to handle string results.
;; Trying to pass markup asks for trouble
(defmacro snip-markup (name)
`(:p ,name))
(markup (snip-markup &quot;foo&quot;))
=&gt; &quot;&lt;snip-markup&gt;foo&lt;/snip-markup&gt;&quot; ;; oops
;; MARKUP is a macro, it does not evaluate its arguments</pre></div></div>
<div id="footer" class="buttonbar"><ul><li><a href="cl-markup.html">Current version</a></li>
<li><a href="https://www.cliki.net/site/history?article=cl-markup">History</a></li>
<li><a href="https://www.cliki.net/site/backlinks?article=cl-markup">Backlinks</a></li><li><a href="https://www.cliki.net/site/edit-article?title=cl-markup&amp;from-revision=3655983279">Edit</a></li><li><a href="https://www.cliki.net/site/edit-article?create=t">Create</a></li></ul></div>
</div>
<div id="header-buttons" class="buttonbar">
<ul>
<li><a href="https://www.cliki.net/">Home</a></li>
<li><a href="https://www.cliki.net/site/recent-changes">Recent Changes</a></li>
<li><a href="CLiki.html">About</a></li>
<li><a href="Text&#32;Formatting.html">Text Formatting</a></li>
<li><a href="https://www.cliki.net/site/tools">Tools</a></li>
</ul>
<div id="search">
<form action="https://www.cliki.net/site/search">
<label for="search_query" class="hidden">Search CLiki</label>
<input type="text" name="query" id="search_query" value="" />
<input type="submit" value="search" />
</form>
</div>
</div>
<div id="pageheader">
<div id="header">
<span id="logo">CLiki</span>
<span id="slogan">the common lisp wiki</span>
<div id="login"><form method="post" action="https://www.cliki.net/site/login">
<label for="login_name" class="hidden">Account name</label>
<input type="text" name="name" id="login_name" class="login_input" />
<label for= "login_password" class="hidden">Password</label>
<input type="password" name="password" id="login_password" class="login_input" />
<input type="submit" name="login" value="login" id="login_submit" /><br />
<div id="register"><a href="https://www.cliki.net/site/register">register</a></div>
<input type="submit" name="reset-pw" value="reset password" id="reset_pw" />
</form>
</div>
</div>
</div>
</body></html>