Created
November 28, 2011 20:55
-
-
Save dpk/1402006 to your computer and use it in GitHub Desktop.
Plan: the Mustache templating system
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; An implementation of the Mustache template system. (http://mustache.github.com/) | |
;; See http://mustache.github.com/mustache.5.html for the format documentation | |
;; | |
;; Usage: (mustache '{employees ({name "Bob" age "34"} {name "Jim" age "27"} {name "Sally" age "54"})} "{{#employees}}\n* {{name}} is {{age}} years old\n{{/employees}}") | |
;; ==> "\n* Bob is 34 years old\n\n* Jim is 27 years old\n\n* Sally is 54 years old\n" | |
(deffn (mustache-tokens tmpl) | |
(regexp-split (mustache-strip-comments tmpl) r“({{(?:{.+?}|[#&^/>]?.+?)}})”)) | |
(deffn (mustache-strip-comments tmpl) | |
(regexp-subst tmpl r/{{!.*?}}/ "" t)) | |
(deffn (mustache-token-kind tok) | |
(if (regexp-match tok r/^{{{/) | |
(list 'unescaped (symbol ((regexp-match tok r/^{{{\s*(.+)\s*}}}$/) 1))) | |
(regexp-match tok r“^{{[#&^/>]”) | |
(let m (regexp-match tok r“^{{([#&^/>])\s*(.+)\s*}}$”) | |
(list | |
(if (= (m 1) "#") 'open-sect | |
(= (m 1) "&") 'unescaped | |
(= (m 1) "^") 'open-neg-sect | |
(= (m 1) "/") 'close-sect | |
(= (m 1) ">") 'partial) | |
(symbol (m 2)))) | |
(regexp-match tok r/^{{/) | |
(list 'var (symbol ((regexp-match tok r/^{{\s*(.+)\s*}}$/) 1))) | |
(list 'str tok)))) | |
(deffn (mustache-group-sections toks) | |
(if (nil? toks) nil | |
(= (caar toks) 'open-sect) | |
(let group (mustache-build-section (cadar toks) (cdr toks)) | |
(cons (append (list 'sect (cadar toks)) (mustache-group-sections (car group))) (mustache-group-sections (cadr group)))) | |
(= (caar toks) 'open-neg-sect) | |
(let group (mustache-build-section (cadar toks) (cdr toks)) | |
(cons (append (list 'neg-sect (cadar toks)) (mustache-group-sections (car group))) (mustache-group-sections (cadr group)))) | |
(cons (car toks) (mustache-group-sections (cdr toks))))) | |
(deffn (mustache-build-section name toks) | |
(if (and (= (caar toks) 'close-sect) (= (cadar toks) name)) | |
(list nil (cdr toks)) | |
(let gd (mustache-build-section name (cdr toks)) | |
(list (cons (car toks) (car gd)) (cadr gd))))) | |
(deffn (mustache-do-section data sect) | |
(if (nil? data) nil | |
(cons? data) | |
(s (map (fn (datum) (mustache-do-tokens datum sect)) data)) | |
(dictionary? data) | |
(mustache-do-tokens data sect))) | |
(deffn (mustache-neg-section data sect) | |
(if (not data) (mustache-do-tokens data sect))) | |
(deffn (mustache-do-tokens data toks) | |
(s (map (fn (tok) | |
(let kind (car tok) | |
(if (= kind 'str) (cadr tok) | |
(= kind 'var) (escape-html (data (cadr tok))) | |
(= kind 'unescaped) (data (cadr tok)) | |
(= kind 'sect) (mustache-do-section (data (cadr tok)) (cddr tok)) | |
(= kind 'neg-sect) (mustache-neg-section (data (cadr tok)) (cddr tok)) | |
(= kind 'partial) 'nothing-here-yet))) toks))) | |
(deffn (mustache data tmpl) | |
(mustache-do-tokens data | |
(mustache-group-sections (map mustache-token-kind (mustache-tokens tmpl))))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment