Extended example
svn: r12550
This commit is contained in:
parent
bea2297421
commit
daff0abe15
|
@ -0,0 +1,4 @@
|
||||||
|
<h2>@|title|</h2>
|
||||||
|
<p>@|body|</p>
|
||||||
|
|
||||||
|
<h1><a href="@|k-url|">Continue</a></h1>
|
16
collects/tests/web-server/template/examples/blog-posts.html
Normal file
16
collects/tests/web-server/template/examples/blog-posts.html
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
@in[p posts]{
|
||||||
|
<h2>@(post-title p)</h2>
|
||||||
|
<p>@(post-body p)</p>
|
||||||
|
<ul>
|
||||||
|
@in[c (post-comments p)]{
|
||||||
|
<li>@|c|</li>
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
}
|
||||||
|
|
||||||
|
<h1>New Post</h1>
|
||||||
|
<form action="@|k-url|">
|
||||||
|
<input name="title" />
|
||||||
|
<input name="body" />
|
||||||
|
<input type="submit" />
|
||||||
|
</form>
|
93
collects/tests/web-server/template/examples/blog-xexpr.ss
Normal file
93
collects/tests/web-server/template/examples/blog-xexpr.ss
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
#lang scheme
|
||||||
|
(require web-server/servlet
|
||||||
|
xml
|
||||||
|
web-server/servlet-env)
|
||||||
|
|
||||||
|
(define-struct post (title body comments))
|
||||||
|
|
||||||
|
(define posts
|
||||||
|
(list
|
||||||
|
(make-post
|
||||||
|
"(Y Y) Works: The Why of Y"
|
||||||
|
"..."
|
||||||
|
(list
|
||||||
|
"First post! - A.T."
|
||||||
|
"Didn't I write this? - Matthias"))
|
||||||
|
(make-post
|
||||||
|
"Church and the States"
|
||||||
|
"As you may know, I grew up in DC, not technically a state..."
|
||||||
|
(list
|
||||||
|
"Finally, A Diet That Really Works! As Seen On TV"))))
|
||||||
|
|
||||||
|
(define (template section body)
|
||||||
|
`(html
|
||||||
|
(head (title "Alonzo's Church: " ,section)
|
||||||
|
(style ([type "text/css"])
|
||||||
|
,(make-cdata #f #f "
|
||||||
|
body {
|
||||||
|
margin: 0px;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main {
|
||||||
|
background: #dddddd;
|
||||||
|
}")))
|
||||||
|
(body
|
||||||
|
(script ([type "text/javascript"])
|
||||||
|
,(make-cdata #f #f "
|
||||||
|
var gaJsHost = ((\"https:\" == document.location.protocol) ?
|
||||||
|
\"https://ssl.\" : \"http://www.\");
|
||||||
|
document.write(unescape(\"%3Cscript src='\" + gaJsHost +
|
||||||
|
\"google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E\"));
|
||||||
|
"))
|
||||||
|
(script ([type "text/javascript"])
|
||||||
|
,(make-cdata #f #f "
|
||||||
|
var pageTracker = _gat._getTracker(\"UA-YYYYYYY-Y\");
|
||||||
|
pageTracker._trackPageview();
|
||||||
|
"))
|
||||||
|
|
||||||
|
(h1 "Alonzo's Church: " ,section)
|
||||||
|
(div ([id "main"])
|
||||||
|
,@body))))
|
||||||
|
|
||||||
|
(define (blog-posted title body k-url)
|
||||||
|
`((h2 ,title)
|
||||||
|
(p ,body)
|
||||||
|
(h1 (a ([href ,k-url]) "Continue"))))
|
||||||
|
|
||||||
|
(define (extract-post req)
|
||||||
|
(define title (extract-binding/single 'title (request-bindings req)))
|
||||||
|
(define body (extract-binding/single 'body (request-bindings req)))
|
||||||
|
(set! posts
|
||||||
|
(list* (make-post title body empty)
|
||||||
|
posts))
|
||||||
|
(send/suspend
|
||||||
|
(lambda (k-url)
|
||||||
|
(template "Posted" (blog-posted title body k-url))))
|
||||||
|
(display-posts))
|
||||||
|
|
||||||
|
(define (blog-posts k-url)
|
||||||
|
(append
|
||||||
|
(apply append
|
||||||
|
(for/list ([p posts])
|
||||||
|
`((h2 ,(post-title p))
|
||||||
|
(p ,(post-body p))
|
||||||
|
(ul
|
||||||
|
,@(for/list ([c (post-comments p)])
|
||||||
|
`(li ,c))))))
|
||||||
|
`((h1 "New Post")
|
||||||
|
(form ([action ,k-url])
|
||||||
|
(input ([name "title"]))
|
||||||
|
(input ([name "body"]))
|
||||||
|
(input ([type "submit"]))))))
|
||||||
|
|
||||||
|
(define (display-posts)
|
||||||
|
(extract-post
|
||||||
|
(send/suspend
|
||||||
|
(lambda (k-url)
|
||||||
|
(template "Posts" (blog-posts k-url))))))
|
||||||
|
|
||||||
|
(define (start req)
|
||||||
|
(display-posts))
|
||||||
|
|
||||||
|
(serve/servlet start)
|
32
collects/tests/web-server/template/examples/blog.html
Normal file
32
collects/tests/web-server/template/examples/blog.html
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Alonzo's Church: @|section|</title>
|
||||||
|
<style type="text/css">
|
||||||
|
body {
|
||||||
|
margin: 0px;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main {
|
||||||
|
background: #dddddd;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script type="text/javascript">
|
||||||
|
var gaJsHost = (("https:" == document.location.protocol) ?
|
||||||
|
"https://ssl." : "http://www.");
|
||||||
|
document.write(unescape("%3Cscript src='" + gaJsHost +
|
||||||
|
"google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
|
||||||
|
</script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
var pageTracker = _gat._getTracker("UA-YYYYYYY-Y");
|
||||||
|
pageTracker._trackPageview();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<h1>Alonzo's Church: @|section|</h1>
|
||||||
|
<div id="main">
|
||||||
|
@body
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
46
collects/tests/web-server/template/examples/blog.ss
Normal file
46
collects/tests/web-server/template/examples/blog.ss
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
#lang scheme
|
||||||
|
(require web-server/templates
|
||||||
|
web-server/servlet
|
||||||
|
web-server/servlet-env)
|
||||||
|
|
||||||
|
(define-struct post (title body comments))
|
||||||
|
|
||||||
|
(define posts
|
||||||
|
(list
|
||||||
|
(make-post
|
||||||
|
"(Y Y) Works: The Why of Y"
|
||||||
|
"..."
|
||||||
|
(list
|
||||||
|
"First post! - A.T."
|
||||||
|
"Didn't I write this? - Matthias"))
|
||||||
|
(make-post
|
||||||
|
"Church and the States"
|
||||||
|
"As you may know, I grew up in DC, not technically a state..."
|
||||||
|
(list
|
||||||
|
"Finally, A Diet That Really Works! As Seen On TV"))))
|
||||||
|
|
||||||
|
(define (template section body)
|
||||||
|
(list TEXT/HTML-MIME-TYPE
|
||||||
|
(include-template "blog.html")))
|
||||||
|
|
||||||
|
(define (extract-post req)
|
||||||
|
(define title (extract-binding/single 'title (request-bindings req)))
|
||||||
|
(define body (extract-binding/single 'body (request-bindings req)))
|
||||||
|
(set! posts
|
||||||
|
(list* (make-post title body empty)
|
||||||
|
posts))
|
||||||
|
(send/suspend
|
||||||
|
(lambda (k-url)
|
||||||
|
(template "Posted" (include-template "blog-posted.html"))))
|
||||||
|
(display-posts))
|
||||||
|
|
||||||
|
(define (display-posts)
|
||||||
|
(extract-post
|
||||||
|
(send/suspend
|
||||||
|
(lambda (k-url)
|
||||||
|
(template "Posts" (include-template "blog-posts.html"))))))
|
||||||
|
|
||||||
|
(define (start req)
|
||||||
|
(display-posts))
|
||||||
|
|
||||||
|
(serve/servlet start)
|
|
@ -2,11 +2,13 @@
|
||||||
@(require "web-server.ss")
|
@(require "web-server.ss")
|
||||||
@(require (for-label web-server/servlet
|
@(require (for-label web-server/servlet
|
||||||
web-server/templates
|
web-server/templates
|
||||||
|
scheme/promise
|
||||||
scheme/list
|
scheme/list
|
||||||
xml))
|
xml))
|
||||||
|
|
||||||
@(define xexpr @tech[#:doc '(lib "xml/xml.scrbl")]{X-expression})
|
@(define xexpr @tech[#:doc '(lib "xml/xml.scrbl")]{X-expression})
|
||||||
@(define at-reader-ref @secref[#:doc '(lib "scribblings/scribble/scribble.scrbl")]{reader})
|
@(define at-reader-ref @secref[#:doc '(lib "scribblings/scribble/scribble.scrbl")]{reader})
|
||||||
|
@(define text-ref @secref[#:doc '(lib "scribblings/scribble/scribble.scrbl")]{preprocessor})
|
||||||
|
|
||||||
@title[#:tag "templates"]{Templates}
|
@title[#:tag "templates"]{Templates}
|
||||||
|
|
||||||
|
@ -15,6 +17,9 @@
|
||||||
The @web-server provides a powerful Web template system for separating the presentation logic of a Web application
|
The @web-server provides a powerful Web template system for separating the presentation logic of a Web application
|
||||||
and enabling non-programmers to contribute to PLT-based Web applications.
|
and enabling non-programmers to contribute to PLT-based Web applications.
|
||||||
|
|
||||||
|
@margin-note{Although all the examples here generate HTML, the template language and the @text-ref it is based on can
|
||||||
|
be used to generate any text-based format: C, SQL, form emails, reports, etc.}
|
||||||
|
|
||||||
@local-table-of-contents[]
|
@local-table-of-contents[]
|
||||||
|
|
||||||
@section{Static}
|
@section{Static}
|
||||||
|
@ -62,8 +67,8 @@ Then
|
||||||
]
|
]
|
||||||
evaluates to the same content as the static example.
|
evaluates to the same content as the static example.
|
||||||
|
|
||||||
There is no constraints on the values, the way they are used, or the way they are defined, that are made accessible to the template.
|
There are no constraints on how the lexical context of the template is populated. For instance, you can built template abstractions
|
||||||
For example,
|
by wrapping the inclusion of a template in a function:
|
||||||
@schemeblock[
|
@schemeblock[
|
||||||
(define (fast-template thing)
|
(define (fast-template thing)
|
||||||
(include-template "simple.html"))
|
(include-template "simple.html"))
|
||||||
|
@ -94,18 +99,71 @@ and
|
||||||
</html>
|
</html>
|
||||||
}|
|
}|
|
||||||
|
|
||||||
|
Furthermore, there are no constraints on the Scheme used by templates: they can use macros, structs, continuation marks, threads, etc.
|
||||||
|
However, Scheme values that are ultimately returned must be printable by the @text-ref@"."
|
||||||
|
For example, consider the following outputs of the
|
||||||
|
title line of different calls to @scheme[fast-template]:
|
||||||
|
|
||||||
|
@itemize{
|
||||||
|
|
||||||
|
@item{
|
||||||
|
@schemeblock[
|
||||||
|
(fast-template 'Templates)
|
||||||
|
]
|
||||||
|
@verbatim[#:indent 2]|{
|
||||||
|
<head><title>Fastest Templates in the West!</title></head>
|
||||||
|
}|
|
||||||
|
}
|
||||||
|
|
||||||
|
@item{
|
||||||
|
@schemeblock[
|
||||||
|
(fast-template 42)
|
||||||
|
]
|
||||||
|
@verbatim[#:indent 2]|{
|
||||||
|
<head><title>Fastest 42 in the West!</title></head>
|
||||||
|
}|
|
||||||
|
}
|
||||||
|
|
||||||
|
@item{
|
||||||
|
@schemeblock[
|
||||||
|
(fast-template (list "Noo" "dles"))
|
||||||
|
]
|
||||||
|
@verbatim[#:indent 2]|{
|
||||||
|
<head><title>Fastest Noodles in the West!</title></head>
|
||||||
|
}|
|
||||||
|
}
|
||||||
|
|
||||||
|
@item{
|
||||||
|
@schemeblock[
|
||||||
|
(fast-template (lambda () "Thunks"))
|
||||||
|
]
|
||||||
|
@verbatim[#:indent 2]|{
|
||||||
|
<head><title>Fastest Thunks in the West!</title></head>
|
||||||
|
}|
|
||||||
|
}
|
||||||
|
|
||||||
|
@item{
|
||||||
|
@schemeblock[
|
||||||
|
(fast-template (delay "Laziness"))
|
||||||
|
]
|
||||||
|
@verbatim[#:indent 2]|{
|
||||||
|
<head><title>Fastest Laziness in the West!</title></head>
|
||||||
|
}|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@section{Gotchas}
|
@section{Gotchas}
|
||||||
|
|
||||||
One of the most important things to remember about the @at-reader-ref syntax is that the @"@" symbol must be escaped in content:
|
To obtain an @"@" symbol in template output, you must escape the @"@" symbol, because it is the escape character of the @at-reader-ref syntax.
|
||||||
|
For example, to obtain:
|
||||||
@verbatim[#:indent 2]|{
|
@verbatim[#:indent 2]|{
|
||||||
<html>
|
<head><title>Fastest @s in the West!</title></head>
|
||||||
<head><title>Fastest @"@"s in the West!</title></head>
|
|
||||||
<body>
|
|
||||||
<h1>Bang!</h1>
|
|
||||||
<h2>Bang!</h2>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
}|
|
}|
|
||||||
|
You must write:
|
||||||
|
@verbatim[#:indent 2]|{
|
||||||
|
<head><title>Fastest @"@"s in the West!</title></head>
|
||||||
|
}|
|
||||||
|
as your template: literal @"@"s must be replaced with @"@\"@\"".
|
||||||
|
|
||||||
The other gotcha is that since the template is compiled into a Scheme program, only its results will be printed. For example, suppose
|
The other gotcha is that since the template is compiled into a Scheme program, only its results will be printed. For example, suppose
|
||||||
we have the template:
|
we have the template:
|
||||||
|
@ -117,7 +175,7 @@ we have the template:
|
||||||
</table>
|
</table>
|
||||||
}|
|
}|
|
||||||
|
|
||||||
If this is included in a lexical context with @scheme[clients] bound to @scheme[(list (cons "Young" "Brigham") (cons "Smith" "Joseph"))],
|
If this is included in a lexical context with @scheme[clients] bound to @schemeblock[(list (cons "Young" "Brigham") (cons "Smith" "Joseph"))]
|
||||||
then the template will be printed as:
|
then the template will be printed as:
|
||||||
@verbatim[#:indent 2]|{
|
@verbatim[#:indent 2]|{
|
||||||
<table>
|
<table>
|
||||||
|
@ -226,3 +284,217 @@ the template to be unescaped, then create a @scheme[cdata] structure:
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@section{Conversion Example}
|
||||||
|
|
||||||
|
Alonzo Church has been maintaining a blog with PLT Scheme for some years and would like to convert to @schememodname[web-server/templates].
|
||||||
|
|
||||||
|
Here's the code he starts off with:
|
||||||
|
@schememod[
|
||||||
|
scheme
|
||||||
|
(require xml
|
||||||
|
web-server/servlet
|
||||||
|
web-server/servlet-env)
|
||||||
|
|
||||||
|
(code:comment "He actually Church-encodes them, but we'll use structs.")
|
||||||
|
(define-struct post (title body comments))
|
||||||
|
|
||||||
|
(define posts
|
||||||
|
(list
|
||||||
|
(make-post
|
||||||
|
"(Y Y) Works: The Why of Y"
|
||||||
|
"..."
|
||||||
|
(list
|
||||||
|
"First post! - A.T."
|
||||||
|
"Didn't I write this? - Matthias"))
|
||||||
|
(make-post
|
||||||
|
"Church and the States"
|
||||||
|
"As you may know, I grew up in DC, not technically a state..."
|
||||||
|
(list
|
||||||
|
"Finally, A Diet That Really Works! As Seen On TV"))))
|
||||||
|
|
||||||
|
(code:comment "A function that is the generic template for the site")
|
||||||
|
(define (template section body)
|
||||||
|
`(html
|
||||||
|
(head (title "Alonzo's Church: " ,section)
|
||||||
|
(style ([type "text/css"])
|
||||||
|
(code:comment "CDATA objects were useful for returning raw data")
|
||||||
|
,(make-cdata #f #f "\n body {\n margin: 0px;\n padding: 10px;\n }\n\n #main {\n background: #dddddd;\n }")))
|
||||||
|
(body
|
||||||
|
(script ([type "text/javascript"])
|
||||||
|
(code:comment "Which is particularly useful for JavaScript")
|
||||||
|
,(make-cdata #f #f "\n var gaJsHost = ((\"https:\" == document.location.protocol) ?\n \"https://ssl.\" : \"http://www.\");\n document.write(unescape(\"%3Cscript src='\" + gaJsHost +\n \"google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E\"));\n"))
|
||||||
|
(script ([type "text/javascript"])
|
||||||
|
,(make-cdata #f #f "\n var pageTracker = _gat._getTracker(\"UA-YYYYYYY-Y\");\n pageTracker._trackPageview();\n"))
|
||||||
|
|
||||||
|
(h1 "Alonzo's Church: " ,section)
|
||||||
|
(div ([id "main"])
|
||||||
|
(code:comment "He had to be careful to use splicing here")
|
||||||
|
,@body))))
|
||||||
|
|
||||||
|
(define (blog-posted title body k-url)
|
||||||
|
`((h2 ,title)
|
||||||
|
(p ,body)
|
||||||
|
(h1 (a ([href ,k-url]) "Continue"))))
|
||||||
|
|
||||||
|
(define (extract-post req)
|
||||||
|
(define binds
|
||||||
|
(request-bindings req))
|
||||||
|
(define title
|
||||||
|
(extract-binding/single 'title binds))
|
||||||
|
(define body
|
||||||
|
(extract-binding/single 'body binds))
|
||||||
|
(set! posts
|
||||||
|
(list* (make-post title body empty)
|
||||||
|
posts))
|
||||||
|
(send/suspend
|
||||||
|
(lambda (k-url)
|
||||||
|
(template "Posted" (blog-posted title body k-url))))
|
||||||
|
(display-posts))
|
||||||
|
|
||||||
|
(define (blog-posts k-url)
|
||||||
|
(code:comment "append or splicing is needed")
|
||||||
|
(append
|
||||||
|
(code:comment "Each element of the list is another list")
|
||||||
|
(apply append
|
||||||
|
(for/list ([p posts])
|
||||||
|
`((h2 ,(post-title p))
|
||||||
|
(p ,(post-body p))
|
||||||
|
(ul
|
||||||
|
,@(for/list ([c (post-comments p)])
|
||||||
|
`(li ,c))))))
|
||||||
|
`((h1 "New Post")
|
||||||
|
(form ([action ,k-url])
|
||||||
|
(input ([name "title"]))
|
||||||
|
(input ([name "body"]))
|
||||||
|
(input ([type "submit"]))))))
|
||||||
|
|
||||||
|
(define (display-posts)
|
||||||
|
(extract-post
|
||||||
|
(send/suspend
|
||||||
|
(lambda (k-url)
|
||||||
|
(template "Posts" (blog-posts k-url))))))
|
||||||
|
|
||||||
|
(define (start req)
|
||||||
|
(display-posts))
|
||||||
|
|
||||||
|
(serve/servlet start)
|
||||||
|
]
|
||||||
|
|
||||||
|
Luckily, Alonzo has great software engineering skills, so he's already separated the presentation logic into the functions
|
||||||
|
@scheme[blog-posted], @scheme[blog-posts], and @scheme[template]. Each one of these will turn into a different
|
||||||
|
template.
|
||||||
|
|
||||||
|
@filepath{blog.html}:
|
||||||
|
@verbatim[#:indent 2]|{
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Alonzo's Church: @|section|</title>
|
||||||
|
<style type="text/css">
|
||||||
|
body {
|
||||||
|
margin: 0px;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main {
|
||||||
|
background: #dddddd;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script type="text/javascript">
|
||||||
|
var gaJsHost = (("https:" == document.location.protocol) ?
|
||||||
|
"https://ssl." : "http://www.");
|
||||||
|
document.write(unescape("%3Cscript src='" + gaJsHost +
|
||||||
|
"google-analytics.com/ga.js'
|
||||||
|
type='text/javascript'%3E%3C/script%3E"));
|
||||||
|
</script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
var pageTracker = _gat._getTracker("UA-YYYYYYY-Y");
|
||||||
|
pageTracker._trackPageview();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<h1>Alonzo's Church: @|section|</h1>
|
||||||
|
<div id="main">
|
||||||
|
@body
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
}|
|
||||||
|
|
||||||
|
Notice that this part of the presentation is much simpler, because the CSS and JavaScript
|
||||||
|
can be included verbatim, without resorting to any special escape-escaping patterns.
|
||||||
|
Similarly, since the @scheme[body] is represented as a string, there is no need to
|
||||||
|
remember if splicing is necessary.
|
||||||
|
|
||||||
|
@filepath{blog-posts.html}:
|
||||||
|
@verbatim[#:indent 2]|{
|
||||||
|
@in[p posts]{
|
||||||
|
<h2>@(post-title p)</h2>
|
||||||
|
<p>@(post-body p)</p>
|
||||||
|
<ul>
|
||||||
|
@in[c (post-comments p)]{
|
||||||
|
<li>@|c|</li>
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
}
|
||||||
|
|
||||||
|
<h1>New Post</h1>
|
||||||
|
<form action="@|k-url|">
|
||||||
|
<input name="title" />
|
||||||
|
<input name="body" />
|
||||||
|
<input type="submit" />
|
||||||
|
</form>
|
||||||
|
}|
|
||||||
|
|
||||||
|
This template is even simpler, because there is no list management whatsoever. The defaults "just work".
|
||||||
|
For completeness, we show the final template:
|
||||||
|
|
||||||
|
@filepath{blog-posted.html}:
|
||||||
|
@verbatim[#:indent 2]|{
|
||||||
|
<h2>@|title|</h2>
|
||||||
|
<p>@|body|</p>
|
||||||
|
|
||||||
|
<h1><a href="@|k-url|">Continue</a></h1>
|
||||||
|
}|
|
||||||
|
|
||||||
|
The code associated with these templates is very simple as well:
|
||||||
|
@schememod[
|
||||||
|
scheme
|
||||||
|
(require web-server/templates
|
||||||
|
web-server/servlet
|
||||||
|
web-server/servlet-env)
|
||||||
|
|
||||||
|
(define-struct post (title body comments))
|
||||||
|
|
||||||
|
(define posts ...)
|
||||||
|
|
||||||
|
(define (template section body)
|
||||||
|
(list TEXT/HTML-MIME-TYPE
|
||||||
|
(include-template "blog.html")))
|
||||||
|
|
||||||
|
(define (extract-post req)
|
||||||
|
(define binds
|
||||||
|
(request-bindings req))
|
||||||
|
(define title
|
||||||
|
(extract-binding/single 'title binds))
|
||||||
|
(define body
|
||||||
|
(extract-binding/single 'body binds))
|
||||||
|
(set! posts
|
||||||
|
(list* (make-post title body empty)
|
||||||
|
posts))
|
||||||
|
(send/suspend
|
||||||
|
(lambda (k-url)
|
||||||
|
(template "Posted" (include-template "blog-posted.html"))))
|
||||||
|
(display-posts))
|
||||||
|
|
||||||
|
(define (display-posts)
|
||||||
|
(extract-post
|
||||||
|
(send/suspend
|
||||||
|
(lambda (k-url)
|
||||||
|
(template "Posts" (include-template "blog-posts.html"))))))
|
||||||
|
|
||||||
|
(define (start req)
|
||||||
|
(display-posts))
|
||||||
|
|
||||||
|
(serve/servlet start)
|
||||||
|
]
|
Loading…
Reference in New Issue
Block a user