Updating tutorial for response/xexpr
This commit is contained in:
parent
16f8b3a2a6
commit
73749166ba
|
@ -29,9 +29,10 @@ We will be using the DrRacket Module language. Enter the following into the Defi
|
|||
@racketmod[
|
||||
web-server/insta
|
||||
(define (start request)
|
||||
'(html
|
||||
(head (title "My Blog"))
|
||||
(body (h1 "Under construction"))))
|
||||
(response/xexpr
|
||||
'(html
|
||||
(head (title "My Blog"))
|
||||
(body (h1 "Under construction")))))
|
||||
]
|
||||
|
||||
Press the @onscreen{Run} button. If a web browser comes up with an ``Under
|
||||
|
@ -88,17 +89,19 @@ application to show it.
|
|||
When a web browser visits our application's URL, the browser
|
||||
constructs a request structure and sends it off to our web
|
||||
application. Our start function will consume requests and produce
|
||||
responses. One basic kind of response is to show an HTML page.
|
||||
responses. One basic kind of response is to show an HTML page,
|
||||
represented as an X-expression in Racket, by using
|
||||
@racket[response/xexpr].
|
||||
|
||||
@racketblock[
|
||||
(define html-response/c
|
||||
(define xexpr/c
|
||||
(flat-rec-contract
|
||||
html-response
|
||||
xexpr
|
||||
(or/c string?
|
||||
(or/c (cons/c symbol? (listof html-response))
|
||||
(or/c (cons/c symbol? (listof xexpr))
|
||||
(cons/c symbol?
|
||||
(cons/c (listof (list/c symbol? string?))
|
||||
(listof html-response)))))))]
|
||||
(listof xexpr)))))))]
|
||||
|
||||
For example:
|
||||
|
||||
|
@ -116,7 +119,7 @@ The HTML @tt{hello} is represented as @racket["hello"]. Strings are automaticall
|
|||
|
||||
@racket['(p "This is " (div ((class "emph")) "another") " example.")].
|
||||
|
||||
We can produce these @racket[html-response]s by using @racket[cons] and @racket[list] directly.
|
||||
We can produce these @racket[xexpr]s by using @racket[cons] and @racket[list] directly.
|
||||
Doing so, however, can be notationally heavy. Consider:
|
||||
|
||||
@racketblock[
|
||||
|
@ -131,7 +134,7 @@ vs:
|
|||
(body (p "This is a simple static page.")))
|
||||
]
|
||||
|
||||
They both produce the same @racket[html-response], but the latter is a lot
|
||||
They both produce the same @racket[xexpr], but the latter is a lot
|
||||
easier to type and read. We've been using the extended list
|
||||
abbreviation form described in @link["http://htdp.org/2003-09-26/Book/curriculum-Z-H-17.html#node_chap_13"]{Section 13} of @link["http://htdp.org/"]{How to Design Programs}:
|
||||
by using a leading forward quote mark to concisely represent the list
|
||||
|
@ -139,7 +142,7 @@ structure, we can construct static html responses with aplomb.
|
|||
|
||||
However, we can run into a problem when we use simple list
|
||||
abbreviation with dynamic content. If we have expressions to inject
|
||||
into the @racket[html-response] structure, we can't use a simple list-abbreviation
|
||||
into the @racket[xexpr] structure, we can't use a simple list-abbreviation
|
||||
approach because those expressions will be treated literally as part
|
||||
of the list structure!
|
||||
|
||||
|
@ -157,17 +160,18 @@ prepend an unquoting comma in front of the subexpression. As an
|
|||
example:
|
||||
|
||||
@racketblock[
|
||||
@code:comment{render-greeting: string -> html-response}
|
||||
@code:comment{Consumes a name, and produces a dynamic html-response.}
|
||||
@code:comment{render-greeting: string -> response}
|
||||
@code:comment{Consumes a name, and produces a dynamic response.}
|
||||
(define (render-greeting a-name)
|
||||
`(html (head (title "Welcome"))
|
||||
(body (p ,(string-append "Hello " a-name)))))
|
||||
(response/xexpr
|
||||
`(html (head (title "Welcome"))
|
||||
(body (p ,(string-append "Hello " a-name))))))
|
||||
]
|
||||
|
||||
@bold{Exercise.} Write a function that consumes a @racket[post] and produces
|
||||
an @racket[html-response] representing that content.
|
||||
an @racket[xexpr] representing that content.
|
||||
|
||||
@defthing[render-post (post? . -> . html-response/c)]
|
||||
@defthing[render-post (post? . -> . xexpr/c)]
|
||||
|
||||
As an example, we want:
|
||||
|
||||
|
@ -186,33 +190,33 @@ to a post.
|
|||
|
||||
@centerline{------------}
|
||||
|
||||
If an expression produces a list of @racket[html-response] fragments, we may
|
||||
If an expression produces a list of @racket[xexpr] fragments, we may
|
||||
want to splice in the elements of a list into our template, rather
|
||||
plug in the whole list itself. In these situations, we can use the
|
||||
splicing form @racket[,@expression].
|
||||
|
||||
As an example, we may want a helper function that transforms a
|
||||
@racket[html-response] list into a fragment representing an unordered, itemized
|
||||
@racket[xexpr] list into a fragment representing an unordered, itemized
|
||||
HTML list:
|
||||
|
||||
@racketblock[
|
||||
@code:comment{render-as-itemized-list: (listof html-response) -> html-response}
|
||||
@code:comment{render-as-itemized-list: (listof xexpr) -> xexpr}
|
||||
@code:comment{Consumes a list of items, and produces a rendering}
|
||||
@code:comment{as an unordered list.}
|
||||
(define (render-as-itemized-list fragments)
|
||||
`(ul ,@(map render-as-item fragments)))
|
||||
|
||||
@code:comment{render-as-item: html-response -> html-response}
|
||||
@code:comment{Consumes an html-response, and produces a rendering}
|
||||
@code:comment{render-as-item: xexpr -> xexpr}
|
||||
@code:comment{Consumes an xexpr, and produces a rendering}
|
||||
@code:comment{as a list item.}
|
||||
(define (render-as-item a-fragment)
|
||||
`(li ,a-fragment))
|
||||
]
|
||||
|
||||
@bold{Exercise.} Write a function @racket[render-posts] that consumes a @racket[(listof post?)]
|
||||
and produces an @racket[html-response] for that content.
|
||||
and produces an @racket[xexpr] for that content.
|
||||
|
||||
@defthing[render-posts ((listof post?) . -> . html-response/c)]
|
||||
@defthing[render-posts ((listof post?) . -> . xexpr/c)]
|
||||
|
||||
As examples:
|
||||
|
||||
|
@ -245,7 +249,7 @@ should produce:
|
|||
|
||||
Now that we have the @racket[render-posts] function handy, let's revisit our
|
||||
web application and change our @racket[start] function to return an interesting
|
||||
@racket[html-response].
|
||||
@racket[response].
|
||||
|
||||
@external-file["iteration-1.rkt"]
|
||||
|
||||
|
@ -337,26 +341,28 @@ enter the following in the definition window.
|
|||
|
||||
@racketmod[
|
||||
web-server/insta
|
||||
@code:comment{start: request -> html-response}
|
||||
@code:comment{start: request -> response}
|
||||
(define (start request)
|
||||
(phase-1 request))
|
||||
|
||||
@code:comment{phase-1: request -> html-response}
|
||||
@code:comment{phase-1: request -> response}
|
||||
(define (phase-1 request)
|
||||
(local [(define (response-generator embed/url)
|
||||
`(html
|
||||
(body (h1 "Phase 1")
|
||||
(a ((href ,(embed/url phase-2)))
|
||||
"click me!"))))]
|
||||
(response/xexpr
|
||||
`(html
|
||||
(body (h1 "Phase 1")
|
||||
(a ((href ,(embed/url phase-2)))
|
||||
"click me!")))))]
|
||||
(send/suspend/dispatch response-generator)))
|
||||
|
||||
@code:comment{phase-2: request -> html-response}
|
||||
@code:comment{phase-2: request -> response}
|
||||
(define (phase-2 request)
|
||||
(local [(define (response-generator embed/url)
|
||||
`(html
|
||||
(body (h1 "Phase 2")
|
||||
(a ((href ,(embed/url phase-1)))
|
||||
"click me!"))))]
|
||||
(response/xexpr
|
||||
`(html
|
||||
(body (h1 "Phase 2")
|
||||
(a ((href ,(embed/url phase-1)))
|
||||
"click me!")))))]
|
||||
(send/suspend/dispatch response-generator)))
|
||||
]
|
||||
|
||||
|
@ -383,19 +389,20 @@ definition. Here's another loopy example:
|
|||
|
||||
@racketmod[
|
||||
web-server/insta
|
||||
@code:comment{start: request -> html-response}
|
||||
@code:comment{start: request -> response}
|
||||
(define (start request)
|
||||
(show-counter 0 request))
|
||||
|
||||
@code:comment{show-counter: number request -> html-response}
|
||||
@code:comment{show-counter: number request -> doesn't}
|
||||
@code:comment{Displays a number that's hyperlinked: when the link is pressed,}
|
||||
@code:comment{returns a new page with the incremented number.}
|
||||
(define (show-counter n request)
|
||||
(local [(define (response-generator embed/url)
|
||||
`(html (head (title "Counting example"))
|
||||
(body
|
||||
(a ((href ,(embed/url next-number-handler)))
|
||||
,(number->string n)))))
|
||||
(response/xexpr
|
||||
`(html (head (title "Counting example"))
|
||||
(body
|
||||
(a ((href ,(embed/url next-number-handler)))
|
||||
,(number->string n))))))
|
||||
|
||||
(define (next-number-handler request)
|
||||
(show-counter (+ n 1) request))]
|
||||
|
@ -602,7 +609,7 @@ our response.
|
|||
@racket['(style ((type "text/css")) "p { color: green }")]
|
||||
|
||||
It's tempting to directly embed this style information into our
|
||||
@racket[html-response]s. However, our source file is already quite busy. We
|
||||
@racket[response]s. However, our source file is already quite busy. We
|
||||
often want to separate the logical representation of our application
|
||||
from its presentation. Rather than directly embed the .css in the
|
||||
HTML response, let's instead add a link reference to an separate .css
|
||||
|
@ -630,13 +637,14 @@ following content:
|
|||
@racketmod[
|
||||
web-server/insta
|
||||
(define (start request)
|
||||
'(html (head (title "Testing"))
|
||||
(link ((rel "stylesheet")
|
||||
(href "/test-static.css")
|
||||
(type "text/css")))
|
||||
(body (h1 "Testing")
|
||||
(h2 "This is a header")
|
||||
(p "This is " (span ((class "hot")) "hot") "."))))
|
||||
(response/xexpr
|
||||
'(html (head (title "Testing"))
|
||||
(link ((rel "stylesheet")
|
||||
(href "/test-static.css")
|
||||
(type "text/css")))
|
||||
(body (h1 "Testing")
|
||||
(h2 "This is a header")
|
||||
(p "This is " (span ((class "hot")) "hot") ".")))))
|
||||
|
||||
(static-files-path "htdocs")
|
||||
]
|
||||
|
@ -1129,21 +1137,22 @@ web-server/insta
|
|||
We'll now go back to the application code. One of the poor design choices we made earlier is the loose connection between the names of form elements in the display and in the form processing code:
|
||||
|
||||
@racketblock[
|
||||
@code:comment{render-blog-page: blog request -> html-response}
|
||||
@code:comment{Produces an html-response page of the content of the}
|
||||
@code:comment{render-blog-page: blog request -> doesnt'}
|
||||
@code:comment{Send an HTML page of the content of the}
|
||||
@code:comment{blog.}
|
||||
(define (render-blog-page a-blog request)
|
||||
(local [(define (response-generator make-url)
|
||||
`(html (head (title "My Blog"))
|
||||
(body
|
||||
(h1 "My Blog")
|
||||
,(render-posts a-blog make-url)
|
||||
(form ((action
|
||||
,(make-url insert-post-handler)))
|
||||
@code:comment{"title" is used here}
|
||||
(input ((name "title")))
|
||||
(input ((name "body")))
|
||||
(input ((type "submit")))))))
|
||||
(local [(define (response-generator make-url)
|
||||
(response/xexpr
|
||||
`(html (head (title "My Blog"))
|
||||
(body
|
||||
(h1 "My Blog")
|
||||
,(render-posts a-blog make-url)
|
||||
(form ((action
|
||||
,(make-url insert-post-handler)))
|
||||
@code:comment{"title" is used here}
|
||||
(input ((name "title")))
|
||||
(input ((name "body")))
|
||||
(input ((type "submit"))))))))
|
||||
|
||||
(define (insert-post-handler request)
|
||||
(define bindings (request-bindings request))
|
||||
|
@ -1196,22 +1205,24 @@ And @racket[(formlet-process new-post-formlet _request)] where @racket[_request]
|
|||
|
||||
We can use @racket[new-post-formlet] in @racket[render-blog-page] as follows:
|
||||
@racketblock[
|
||||
@code:comment{render-blog-page: blog request -> html-response}
|
||||
@code:comment{Produces an html-response page of the content of the}
|
||||
@code:comment{render-blog-page: blog request -> doesn't}
|
||||
@code:comment{Sends an HTML page of the content of the}
|
||||
@code:comment{blog.}
|
||||
(define (render-blog-page a-blog request)
|
||||
(local [(define (response-generator make-url)
|
||||
`(html (head (title "My Blog"))
|
||||
(body
|
||||
(h1 "My Blog")
|
||||
,(render-posts a-blog make-url)
|
||||
(form ([action
|
||||
,(make-url insert-post-handler)])
|
||||
,@(formlet-display new-post-formlet)
|
||||
(input ([type "submit"]))))))
|
||||
(local [(define (response-generator make-url)
|
||||
(response/xexpr
|
||||
`(html (head (title "My Blog"))
|
||||
(body
|
||||
(h1 "My Blog")
|
||||
,(render-posts a-blog make-url)
|
||||
(form ([action
|
||||
,(make-url insert-post-handler)])
|
||||
,@(formlet-display new-post-formlet)
|
||||
(input ([type "submit"])))))))
|
||||
|
||||
(define (insert-post-handler request)
|
||||
(define-values (title body) (formlet-process new-post-formlet request))
|
||||
(define-values (title body)
|
||||
(formlet-process new-post-formlet request))
|
||||
(blog-insert-post! a-blog title body)
|
||||
(render-blog-page a-blog (redirect/get)))]
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
(require "dummy-3.rkt")
|
||||
|
||||
;; start: request -> html-response
|
||||
;; start: request -> doesn't
|
||||
;; Consumes a request and produces a page that displays
|
||||
;; all of the web content.
|
||||
(define (start request)
|
||||
|
@ -12,20 +12,21 @@
|
|||
"the-blog-data.sqlite"))
|
||||
request))
|
||||
|
||||
;; render-blog-page: blog request -> html-response
|
||||
;; Produces an html-response page of the content of the
|
||||
;; render-blog-page: blog request -> doesn't
|
||||
;; Produces an HTML page of the content of the
|
||||
;; blog.
|
||||
(define (render-blog-page a-blog request)
|
||||
(local [(define (response-generator make-url)
|
||||
`(html (head (title "My Blog"))
|
||||
(body
|
||||
(h1 "My Blog")
|
||||
,(render-posts a-blog make-url)
|
||||
(form ((action
|
||||
,(make-url insert-post-handler)))
|
||||
(input ((name "title")))
|
||||
(input ((name "body")))
|
||||
(input ((type "submit")))))))
|
||||
(local [(define (response-generator make-url)
|
||||
(response/xexpr
|
||||
`(html (head (title "My Blog"))
|
||||
(body
|
||||
(h1 "My Blog")
|
||||
,(render-posts a-blog make-url)
|
||||
(form ((action
|
||||
,(make-url insert-post-handler)))
|
||||
(input ((name "title")))
|
||||
(input ((name "body")))
|
||||
(input ((type "submit"))))))))
|
||||
|
||||
(define (insert-post-handler request)
|
||||
(define bindings (request-bindings request))
|
||||
|
@ -37,25 +38,26 @@
|
|||
|
||||
(send/suspend/dispatch response-generator)))
|
||||
|
||||
;; render-post-detail-page: post request -> html-response
|
||||
;; render-post-detail-page: post request -> doesn't
|
||||
;; Consumes a post and produces a detail page of the post.
|
||||
;; The user will be able to either insert new comments
|
||||
;; or go back to render-blog-page.
|
||||
(define (render-post-detail-page a-blog a-post request)
|
||||
(local [(define (response-generator make-url)
|
||||
`(html (head (title "Post Details"))
|
||||
(body
|
||||
(h1 "Post Details")
|
||||
(h2 ,(post-title a-post))
|
||||
(p ,(post-body a-post))
|
||||
,(render-as-itemized-list
|
||||
(post-comments a-post))
|
||||
(form ((action
|
||||
,(make-url insert-comment-handler)))
|
||||
(input ((name "comment")))
|
||||
(input ((type "submit"))))
|
||||
(a ((href ,(make-url back-handler)))
|
||||
"Back to the blog"))))
|
||||
(response/xexpr
|
||||
`(html (head (title "Post Details"))
|
||||
(body
|
||||
(h1 "Post Details")
|
||||
(h2 ,(post-title a-post))
|
||||
(p ,(post-body a-post))
|
||||
,(render-as-itemized-list
|
||||
(post-comments a-post))
|
||||
(form ((action
|
||||
,(make-url insert-comment-handler)))
|
||||
(input ((name "comment")))
|
||||
(input ((type "submit"))))
|
||||
(a ((href ,(make-url back-handler)))
|
||||
"Back to the blog")))))
|
||||
|
||||
(define (parse-comment bindings)
|
||||
(extract-binding/single 'comment bindings))
|
||||
|
@ -73,7 +75,7 @@
|
|||
(send/suspend/dispatch response-generator)))
|
||||
|
||||
;; render-confirm-add-comment-page :
|
||||
;; blog comment post request -> html-response
|
||||
;; blog comment post request -> doesn't
|
||||
;; Consumes a comment that we intend to add to a post, as well
|
||||
;; as the request. If the user follows through, adds a comment
|
||||
;; and goes back to the display page. Otherwise, goes back to
|
||||
|
@ -81,17 +83,18 @@
|
|||
(define (render-confirm-add-comment-page a-blog a-comment
|
||||
a-post request)
|
||||
(local [(define (response-generator make-url)
|
||||
`(html (head (title "Add a Comment"))
|
||||
(body
|
||||
(h1 "Add a Comment")
|
||||
"The comment: " (div (p ,a-comment))
|
||||
"will be added to "
|
||||
(div ,(post-title a-post))
|
||||
|
||||
(p (a ((href ,(make-url yes-handler)))
|
||||
"Yes, add the comment."))
|
||||
(p (a ((href ,(make-url cancel-handler)))
|
||||
"No, I changed my mind!")))))
|
||||
(response/xexpr
|
||||
`(html (head (title "Add a Comment"))
|
||||
(body
|
||||
(h1 "Add a Comment")
|
||||
"The comment: " (div (p ,a-comment))
|
||||
"will be added to "
|
||||
(div ,(post-title a-post))
|
||||
|
||||
(p (a ((href ,(make-url yes-handler)))
|
||||
"Yes, add the comment."))
|
||||
(p (a ((href ,(make-url cancel-handler)))
|
||||
"No, I changed my mind!"))))))
|
||||
|
||||
(define (yes-handler request)
|
||||
(post-insert-comment! a-blog a-post a-comment)
|
||||
|
@ -102,8 +105,8 @@
|
|||
|
||||
(send/suspend/dispatch response-generator)))
|
||||
|
||||
;; render-post: post (handler -> string) -> html-response
|
||||
;; Consumes a post, produces an html-response fragment of the post.
|
||||
;; render-post: post (handler -> string) -> xexpr
|
||||
;; Consumes a post, produces an xexpr fragment of the post.
|
||||
;; The fragment contains a link to show a detailed view of the post.
|
||||
(define (render-post a-blog a-post make-url)
|
||||
(local [(define (view-post-handler request)
|
||||
|
@ -115,8 +118,8 @@
|
|||
(div ,(number->string (length (post-comments a-post)))
|
||||
" comment(s)"))))
|
||||
|
||||
;; render-posts: blog (handler -> string) -> html-response
|
||||
;; Consumes a make-url, produces an html-response fragment
|
||||
;; render-posts: blog (handler -> string) -> xexpr
|
||||
;; Consumes a make-url, produces an xexpr fragment
|
||||
;; of all its posts.
|
||||
(define (render-posts a-blog make-url)
|
||||
(local [(define (render-post/make-url a-post)
|
||||
|
@ -124,14 +127,14 @@
|
|||
`(div ((class "posts"))
|
||||
,@(map render-post/make-url (blog-posts a-blog)))))
|
||||
|
||||
;; render-as-itemized-list: (listof html-response) -> html-response
|
||||
;; render-as-itemized-list: (listof xexpr) -> xexpr
|
||||
;; Consumes a list of items, and produces a rendering as
|
||||
;; an unorderered list.
|
||||
(define (render-as-itemized-list fragments)
|
||||
`(ul ,@(map render-as-item fragments)))
|
||||
|
||||
;; render-as-item: html-response -> html-response
|
||||
;; Consumes an html-response, and produces a rendering
|
||||
;; render-as-item: xexpr -> xexpr
|
||||
;; Consumes an xexpr, and produces a rendering
|
||||
;; as a list item.
|
||||
(define (render-as-item a-fragment)
|
||||
`(li ,a-fragment))
|
||||
|
|
|
@ -10,29 +10,30 @@
|
|||
(list (post "First Post" "This is my first post")
|
||||
(post "Second Post" "This is another post")))
|
||||
|
||||
;; start: request -> html-response
|
||||
;; start: request -> response
|
||||
;; Consumes a request, and produces a page that displays all of the
|
||||
;; web content.
|
||||
(define (start request)
|
||||
(render-blog-page BLOG request))
|
||||
|
||||
;; render-blog-page: blog request -> html-response
|
||||
;; Consumes a blog and a request, and produces an html-response page
|
||||
;; render-blog-page: blog request -> response
|
||||
;; Consumes a blog and a request, and produces an HTML page
|
||||
;; of the content of the blog.
|
||||
(define (render-blog-page a-blog request)
|
||||
`(html (head (title "My Blog"))
|
||||
(body (h1 "My Blog")
|
||||
,(render-posts a-blog))))
|
||||
(response/xexpr
|
||||
`(html (head (title "My Blog"))
|
||||
(body (h1 "My Blog")
|
||||
,(render-posts a-blog)))))
|
||||
|
||||
;; render-post: post -> html-response
|
||||
;; Consumes a post, produces an html-response fragment of the post.
|
||||
;; render-post: post -> xexpr
|
||||
;; Consumes a post, produces an xexpr fragment of the post.
|
||||
(define (render-post a-post)
|
||||
`(div ((class "post"))
|
||||
,(post-title a-post)
|
||||
(p ,(post-body a-post))))
|
||||
|
||||
;; render-posts: blog -> html-response
|
||||
;; Consumes a blog, produces an html-response fragment
|
||||
;; render-posts: blog -> xexpr
|
||||
;; Consumes a blog, produces an xexpr fragment
|
||||
;; of all its posts.
|
||||
(define (render-posts a-blog)
|
||||
`(div ((class "posts"))
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
(require "model-3.rkt")
|
||||
|
||||
;; start: request -> html-response
|
||||
;; start: request -> doesn't
|
||||
;; Consumes a request and produces a page that displays
|
||||
;; all of the web content.
|
||||
(define (start request)
|
||||
|
@ -12,20 +12,21 @@
|
|||
"the-blog-data.sqlite"))
|
||||
request))
|
||||
|
||||
;; render-blog-page: blog request -> html-response
|
||||
;; Produces an html-response page of the content of the
|
||||
;; render-blog-page: blog request -> doesn't
|
||||
;; Produces an HTML page of the content of the
|
||||
;; blog.
|
||||
(define (render-blog-page a-blog request)
|
||||
(local [(define (response-generator make-url)
|
||||
`(html (head (title "My Blog"))
|
||||
(body
|
||||
(h1 "My Blog")
|
||||
,(render-posts a-blog make-url)
|
||||
(form ((action
|
||||
,(make-url insert-post-handler)))
|
||||
(input ((name "title")))
|
||||
(input ((name "body")))
|
||||
(input ((type "submit")))))))
|
||||
(local [(define (response-generator make-url)
|
||||
(response/xexpr
|
||||
`(html (head (title "My Blog"))
|
||||
(body
|
||||
(h1 "My Blog")
|
||||
,(render-posts a-blog make-url)
|
||||
(form ((action
|
||||
,(make-url insert-post-handler)))
|
||||
(input ((name "title")))
|
||||
(input ((name "body")))
|
||||
(input ((type "submit"))))))))
|
||||
|
||||
(define (insert-post-handler request)
|
||||
(define bindings (request-bindings request))
|
||||
|
@ -37,25 +38,26 @@
|
|||
|
||||
(send/suspend/dispatch response-generator)))
|
||||
|
||||
;; render-post-detail-page: post request -> html-response
|
||||
;; render-post-detail-page: post request -> doesn't
|
||||
;; Consumes a post and produces a detail page of the post.
|
||||
;; The user will be able to either insert new comments
|
||||
;; or go back to render-blog-page.
|
||||
(define (render-post-detail-page a-blog a-post request)
|
||||
(local [(define (response-generator make-url)
|
||||
`(html (head (title "Post Details"))
|
||||
(body
|
||||
(h1 "Post Details")
|
||||
(h2 ,(post-title a-post))
|
||||
(p ,(post-body a-post))
|
||||
,(render-as-itemized-list
|
||||
(post-comments a-post))
|
||||
(form ((action
|
||||
,(make-url insert-comment-handler)))
|
||||
(input ((name "comment")))
|
||||
(input ((type "submit"))))
|
||||
(a ((href ,(make-url back-handler)))
|
||||
"Back to the blog"))))
|
||||
(response/xexpr
|
||||
`(html (head (title "Post Details"))
|
||||
(body
|
||||
(h1 "Post Details")
|
||||
(h2 ,(post-title a-post))
|
||||
(p ,(post-body a-post))
|
||||
,(render-as-itemized-list
|
||||
(post-comments a-post))
|
||||
(form ((action
|
||||
,(make-url insert-comment-handler)))
|
||||
(input ((name "comment")))
|
||||
(input ((type "submit"))))
|
||||
(a ((href ,(make-url back-handler)))
|
||||
"Back to the blog")))))
|
||||
|
||||
(define (parse-comment bindings)
|
||||
(extract-binding/single 'comment bindings))
|
||||
|
@ -73,7 +75,7 @@
|
|||
(send/suspend/dispatch response-generator)))
|
||||
|
||||
;; render-confirm-add-comment-page :
|
||||
;; blog comment post request -> html-response
|
||||
;; blog comment post request -> doesn't
|
||||
;; Consumes a comment that we intend to add to a post, as well
|
||||
;; as the request. If the user follows through, adds a comment
|
||||
;; and goes back to the display page. Otherwise, goes back to
|
||||
|
@ -81,17 +83,18 @@
|
|||
(define (render-confirm-add-comment-page a-blog a-comment
|
||||
a-post request)
|
||||
(local [(define (response-generator make-url)
|
||||
`(html (head (title "Add a Comment"))
|
||||
(body
|
||||
(h1 "Add a Comment")
|
||||
"The comment: " (div (p ,a-comment))
|
||||
"will be added to "
|
||||
(div ,(post-title a-post))
|
||||
|
||||
(p (a ((href ,(make-url yes-handler)))
|
||||
"Yes, add the comment."))
|
||||
(p (a ((href ,(make-url cancel-handler)))
|
||||
"No, I changed my mind!")))))
|
||||
(response/xexpr
|
||||
`(html (head (title "Add a Comment"))
|
||||
(body
|
||||
(h1 "Add a Comment")
|
||||
"The comment: " (div (p ,a-comment))
|
||||
"will be added to "
|
||||
(div ,(post-title a-post))
|
||||
|
||||
(p (a ((href ,(make-url yes-handler)))
|
||||
"Yes, add the comment."))
|
||||
(p (a ((href ,(make-url cancel-handler)))
|
||||
"No, I changed my mind!"))))))
|
||||
|
||||
(define (yes-handler request)
|
||||
(post-insert-comment! a-blog a-post a-comment)
|
||||
|
@ -102,8 +105,8 @@
|
|||
|
||||
(send/suspend/dispatch response-generator)))
|
||||
|
||||
;; render-post: post (handler -> string) -> html-response
|
||||
;; Consumes a post, produces an html-response fragment of the post.
|
||||
;; render-post: post (handler -> string) -> xexpr
|
||||
;; Consumes a post, produces an xexpr fragment of the post.
|
||||
;; The fragment contains a link to show a detailed view of the post.
|
||||
(define (render-post a-blog a-post make-url)
|
||||
(local [(define (view-post-handler request)
|
||||
|
@ -115,8 +118,8 @@
|
|||
(div ,(number->string (length (post-comments a-post)))
|
||||
" comment(s)"))))
|
||||
|
||||
;; render-posts: blog (handler -> string) -> html-response
|
||||
;; Consumes a make-url, produces an html-response fragment
|
||||
;; render-posts: blog (handler -> string) -> xexpr
|
||||
;; Consumes a make-url, produces an xexpr fragment
|
||||
;; of all its posts.
|
||||
(define (render-posts a-blog make-url)
|
||||
(local [(define (render-post/make-url a-post)
|
||||
|
@ -124,14 +127,14 @@
|
|||
`(div ((class "posts"))
|
||||
,@(map render-post/make-url (blog-posts a-blog)))))
|
||||
|
||||
;; render-as-itemized-list: (listof html-response) -> html-response
|
||||
;; render-as-itemized-list: (listof xexpr) -> xexpr
|
||||
;; Consumes a list of items, and produces a rendering as
|
||||
;; an unorderered list.
|
||||
(define (render-as-itemized-list fragments)
|
||||
`(ul ,@(map render-as-item fragments)))
|
||||
|
||||
;; render-as-item: html-response -> html-response
|
||||
;; Consumes an html-response, and produces a rendering
|
||||
;; render-as-item: xexpr -> xexpr
|
||||
;; Consumes an xexpr, and produces a rendering
|
||||
;; as a list item.
|
||||
(define (render-as-item a-fragment)
|
||||
`(li ,a-fragment))
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
(require web-server/formlets
|
||||
"model-3.rkt")
|
||||
|
||||
;; start: request -> html-response
|
||||
;; start: request -> doesn't
|
||||
;; Consumes a request and produces a page that displays
|
||||
;; all of the web content.
|
||||
(define (start request)
|
||||
|
@ -21,19 +21,20 @@
|
|||
,{input-string . => . body})
|
||||
(values title body)))
|
||||
|
||||
;; render-blog-page: blog request -> html-response
|
||||
;; Produces an html-response page of the content of the
|
||||
;; render-blog-page: blog request -> doesn't
|
||||
;; Produces an HTML page of the content of the
|
||||
;; blog.
|
||||
(define (render-blog-page a-blog request)
|
||||
(local [(define (response-generator make-url)
|
||||
`(html (head (title "My Blog"))
|
||||
(body
|
||||
(h1 "My Blog")
|
||||
,(render-posts a-blog make-url)
|
||||
(form ([action
|
||||
,(make-url insert-post-handler)])
|
||||
,@(formlet-display new-post-formlet)
|
||||
(input ([type "submit"]))))))
|
||||
(local [(define (response-generator make-url)
|
||||
(response/xexpr
|
||||
`(html (head (title "My Blog"))
|
||||
(body
|
||||
(h1 "My Blog")
|
||||
,(render-posts a-blog make-url)
|
||||
(form ([action
|
||||
,(make-url insert-post-handler)])
|
||||
,@(formlet-display new-post-formlet)
|
||||
(input ([type "submit"])))))))
|
||||
|
||||
(define (insert-post-handler request)
|
||||
(define-values (title body)
|
||||
|
@ -48,25 +49,26 @@
|
|||
(define new-comment-formlet
|
||||
input-string)
|
||||
|
||||
;; render-post-detail-page: post request -> html-response
|
||||
;; render-post-detail-page: post request -> doesn't
|
||||
;; Consumes a post and produces a detail page of the post.
|
||||
;; The user will be able to either insert new comments
|
||||
;; or go back to render-blog-page.
|
||||
(define (render-post-detail-page a-blog a-post request)
|
||||
(local [(define (response-generator make-url)
|
||||
`(html (head (title "Post Details"))
|
||||
(body
|
||||
(h1 "Post Details")
|
||||
(h2 ,(post-title a-post))
|
||||
(p ,(post-body a-post))
|
||||
,(render-as-itemized-list
|
||||
(post-comments a-post))
|
||||
(form ([action
|
||||
,(make-url insert-comment-handler)])
|
||||
,@(formlet-display new-comment-formlet)
|
||||
(input ([type "submit"])))
|
||||
(a ([href ,(make-url back-handler)])
|
||||
"Back to the blog"))))
|
||||
(response/xexpr
|
||||
`(html (head (title "Post Details"))
|
||||
(body
|
||||
(h1 "Post Details")
|
||||
(h2 ,(post-title a-post))
|
||||
(p ,(post-body a-post))
|
||||
,(render-as-itemized-list
|
||||
(post-comments a-post))
|
||||
(form ([action
|
||||
,(make-url insert-comment-handler)])
|
||||
,@(formlet-display new-comment-formlet)
|
||||
(input ([type "submit"])))
|
||||
(a ([href ,(make-url back-handler)])
|
||||
"Back to the blog")))))
|
||||
|
||||
(define (insert-comment-handler request)
|
||||
(render-confirm-add-comment-page
|
||||
|
@ -81,7 +83,7 @@
|
|||
(send/suspend/dispatch response-generator)))
|
||||
|
||||
;; render-confirm-add-comment-page :
|
||||
;; blog comment post request -> html-response
|
||||
;; blog comment post request -> doesn't
|
||||
;; Consumes a comment that we intend to add to a post, as well
|
||||
;; as the request. If the user follows through, adds a comment
|
||||
;; and goes back to the display page. Otherwise, goes back to
|
||||
|
@ -89,17 +91,18 @@
|
|||
(define (render-confirm-add-comment-page a-blog a-comment
|
||||
a-post request)
|
||||
(local [(define (response-generator make-url)
|
||||
`(html (head (title "Add a Comment"))
|
||||
(body
|
||||
(h1 "Add a Comment")
|
||||
"The comment: " (div (p ,a-comment))
|
||||
"will be added to "
|
||||
(div ,(post-title a-post))
|
||||
|
||||
(p (a ([href ,(make-url yes-handler)])
|
||||
"Yes, add the comment."))
|
||||
(p (a ([href ,(make-url cancel-handler)])
|
||||
"No, I changed my mind!")))))
|
||||
(response/xexpr
|
||||
`(html (head (title "Add a Comment"))
|
||||
(body
|
||||
(h1 "Add a Comment")
|
||||
"The comment: " (div (p ,a-comment))
|
||||
"will be added to "
|
||||
(div ,(post-title a-post))
|
||||
|
||||
(p (a ([href ,(make-url yes-handler)])
|
||||
"Yes, add the comment."))
|
||||
(p (a ([href ,(make-url cancel-handler)])
|
||||
"No, I changed my mind!"))))))
|
||||
|
||||
(define (yes-handler request)
|
||||
(post-insert-comment! a-blog a-post a-comment)
|
||||
|
@ -110,8 +113,8 @@
|
|||
|
||||
(send/suspend/dispatch response-generator)))
|
||||
|
||||
;; render-post: post (handler -> string) -> html-response
|
||||
;; Consumes a post, produces an html-response fragment of the post.
|
||||
;; render-post: post (handler -> string) -> xexpr
|
||||
;; Consumes a post, produces an xexpr fragment of the post.
|
||||
;; The fragment contains a link to show a detailed view of the post.
|
||||
(define (render-post a-blog a-post make-url)
|
||||
(local [(define (view-post-handler request)
|
||||
|
@ -123,8 +126,8 @@
|
|||
(div ,(number->string (length (post-comments a-post)))
|
||||
" comment(s)"))))
|
||||
|
||||
;; render-posts: blog (handler -> string) -> html-response
|
||||
;; Consumes a make-url, produces an html-response fragment
|
||||
;; render-posts: blog (handler -> string) -> xexpr
|
||||
;; Consumes a make-url, produces an xexpr fragment
|
||||
;; of all its posts.
|
||||
(define (render-posts a-blog make-url)
|
||||
(local [(define (render-post/make-url a-post)
|
||||
|
@ -132,14 +135,14 @@
|
|||
`(div ([class "posts"])
|
||||
,@(map render-post/make-url (blog-posts a-blog)))))
|
||||
|
||||
;; render-as-itemized-list: (listof html-response) -> html-response
|
||||
;; render-as-itemized-list: (listof xexpr) -> xexpr
|
||||
;; Consumes a list of items, and produces a rendering as
|
||||
;; an unorderered list.
|
||||
(define (render-as-itemized-list fragments)
|
||||
`(ul ,@(map render-as-item fragments)))
|
||||
|
||||
;; render-as-item: html-response -> html-response
|
||||
;; Consumes an html-response, and produces a rendering
|
||||
;; render-as-item: xexpr -> xexpr
|
||||
;; Consumes an xexpr, and produces a rendering
|
||||
;; as a list item.
|
||||
(define (render-as-item a-fragment)
|
||||
`(li ,a-fragment))
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
(list (post "First Post" "This is my first post")
|
||||
(post "Second Post" "This is another post")))
|
||||
|
||||
;; start: request -> html-response
|
||||
;; start: request -> response
|
||||
;; Consumes a request and produces a page that displays all of the
|
||||
;; web content.
|
||||
(define (start request)
|
||||
|
@ -36,29 +36,30 @@
|
|||
(post (extract-binding/single 'title bindings)
|
||||
(extract-binding/single 'body bindings)))
|
||||
|
||||
;; render-blog-page: blog request -> html-response
|
||||
;; Consumes a blog and a request, and produces an html-response page
|
||||
;; render-blog-page: blog request -> response
|
||||
;; Consumes a blog and a request, and produces an HTML page
|
||||
;; of the content of the blog.
|
||||
(define (render-blog-page a-blog request)
|
||||
`(html (head (title "My Blog"))
|
||||
(body
|
||||
(h1 "My Blog")
|
||||
,(render-posts a-blog)
|
||||
(form
|
||||
(input ((name "title")))
|
||||
(input ((name "body")))
|
||||
(input ((type "submit")))))))
|
||||
(response/xexpr
|
||||
`(html (head (title "My Blog"))
|
||||
(body
|
||||
(h1 "My Blog")
|
||||
,(render-posts a-blog)
|
||||
(form
|
||||
(input ((name "title")))
|
||||
(input ((name "body")))
|
||||
(input ((type "submit"))))))))
|
||||
|
||||
;; render-post: post -> html-response
|
||||
;; Consumes a post, produces an html-response fragment of the post.
|
||||
;; render-post: post -> xexpr
|
||||
;; Consumes a post, produces an xexpr fragment of the post.
|
||||
(define (render-post a-post)
|
||||
`(div ((class "post"))
|
||||
,(post-title a-post)
|
||||
(p ,(post-body a-post))))
|
||||
|
||||
|
||||
;; render-posts: blog -> html-response
|
||||
;; Consumes a blog, produces an html-response fragment
|
||||
;; render-posts: blog -> xexpr
|
||||
;; Consumes a blog, produces an xexpr fragment
|
||||
;; of all its posts.
|
||||
(define (render-posts a-blog)
|
||||
`(div ((class "posts"))
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
(list (post "First Post" "This is my first post")
|
||||
(post "Second Post" "This is another post")))
|
||||
|
||||
;; start: request -> html-response
|
||||
;; start: request -> doesn't
|
||||
;; Consumes a request and produces a page that displays all of the
|
||||
;; web content.
|
||||
(define (start request)
|
||||
|
@ -22,20 +22,21 @@
|
|||
(post (extract-binding/single 'title bindings)
|
||||
(extract-binding/single 'body bindings)))
|
||||
|
||||
;; render-blog-page: blog request -> html-response
|
||||
;; Consumes a blog and a request, and produces an html-response page
|
||||
;; render-blog-page: blog request -> doesn't
|
||||
;; Consumes a blog and a request, and produces an HTML page
|
||||
;; of the content of the blog.
|
||||
(define (render-blog-page a-blog request)
|
||||
(local [(define (response-generator make-url)
|
||||
`(html (head (title "My Blog"))
|
||||
(body
|
||||
(h1 "My Blog")
|
||||
,(render-posts a-blog)
|
||||
(form ((action
|
||||
,(make-url insert-post-handler)))
|
||||
(input ((name "title")))
|
||||
(input ((name "body")))
|
||||
(input ((type "submit")))))))
|
||||
(local [(define (response-generator make-url)
|
||||
(response/xexpr
|
||||
`(html (head (title "My Blog"))
|
||||
(body
|
||||
(h1 "My Blog")
|
||||
,(render-posts a-blog)
|
||||
(form ((action
|
||||
,(make-url insert-post-handler)))
|
||||
(input ((name "title")))
|
||||
(input ((name "body")))
|
||||
(input ((type "submit"))))))))
|
||||
|
||||
(define (insert-post-handler request)
|
||||
(render-blog-page
|
||||
|
@ -45,15 +46,15 @@
|
|||
|
||||
(send/suspend/dispatch response-generator)))
|
||||
|
||||
;; render-post: post -> html-response
|
||||
;; Consumes a post, produces an html-response fragment of the post.
|
||||
;; render-post: post -> xexpr
|
||||
;; Consumes a post, produces an xexpr fragment of the post.
|
||||
(define (render-post a-post)
|
||||
`(div ((class "post"))
|
||||
,(post-title a-post)
|
||||
(p ,(post-body a-post))))
|
||||
|
||||
;; render-posts: blog -> html-response
|
||||
;; Consumes a blog, produces an html-response fragment
|
||||
;; render-posts: blog -> xexpr
|
||||
;; Consumes a blog, produces an xexpr fragment
|
||||
;; of all its posts.
|
||||
(define (render-posts a-blog)
|
||||
`(div ((class "posts"))
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
(set-blog-posts! a-blog
|
||||
(cons a-post (blog-posts a-blog))))
|
||||
|
||||
;; start: request -> html-response
|
||||
;; start: request -> doesn't
|
||||
;; Consumes a request and produces a page that displays
|
||||
;; all of the web content.
|
||||
(define (start request)
|
||||
|
@ -33,19 +33,20 @@
|
|||
(post (extract-binding/single 'title bindings)
|
||||
(extract-binding/single 'body bindings)))
|
||||
|
||||
;; render-blog-page: request -> html-response
|
||||
;; Produces an html-response page of the content of the BLOG.
|
||||
;; render-blog-page: request -> doesn't
|
||||
;; Produces an HTML page of the content of the BLOG.
|
||||
(define (render-blog-page request)
|
||||
(local [(define (response-generator make-url)
|
||||
`(html (head (title "My Blog"))
|
||||
(body
|
||||
(h1 "My Blog")
|
||||
,(render-posts)
|
||||
(form ((action
|
||||
,(make-url insert-post-handler)))
|
||||
(input ((name "title")))
|
||||
(input ((name "body")))
|
||||
(input ((type "submit")))))))
|
||||
(local [(define (response-generator make-url)
|
||||
(response/xexpr
|
||||
`(html (head (title "My Blog"))
|
||||
(body
|
||||
(h1 "My Blog")
|
||||
,(render-posts)
|
||||
(form ((action
|
||||
,(make-url insert-post-handler)))
|
||||
(input ((name "title")))
|
||||
(input ((name "body")))
|
||||
(input ((type "submit"))))))))
|
||||
|
||||
(define (insert-post-handler request)
|
||||
(blog-insert-post!
|
||||
|
@ -54,15 +55,15 @@
|
|||
|
||||
(send/suspend/dispatch response-generator)))
|
||||
|
||||
;; render-post: post -> html-response
|
||||
;; Consumes a post, produces an html-response fragment of the post.
|
||||
;; render-post: post -> xexpr
|
||||
;; Consumes a post, produces an xexpr fragment of the post.
|
||||
(define (render-post a-post)
|
||||
`(div ((class "post"))
|
||||
,(post-title a-post)
|
||||
(p ,(post-body a-post))))
|
||||
|
||||
;; render-posts: -> html-response
|
||||
;; Consumes a blog, produces an html-response fragment
|
||||
;; render-posts: -> xexpr
|
||||
;; Consumes a blog, produces an xexpr fragment
|
||||
;; of all its posts.
|
||||
(define (render-posts)
|
||||
`(div ((class "posts"))
|
||||
|
|
|
@ -35,26 +35,27 @@
|
|||
a-post
|
||||
(append (post-comments a-post) (list a-comment))))
|
||||
|
||||
;; start: request -> html-response
|
||||
;; start: request -> doesn't
|
||||
;; Consumes a request, and produces a page that displays
|
||||
;; all of the web content.
|
||||
(define (start request)
|
||||
(render-blog-page request))
|
||||
|
||||
;; render-blog-page: request -> html-response
|
||||
;; Produces an html-response page of the content of the
|
||||
;; render-blog-page: request -> doesn't
|
||||
;; Produces an doesn't page of the content of the
|
||||
;; BLOG.
|
||||
(define (render-blog-page request)
|
||||
(local [(define (response-generator make-url)
|
||||
`(html (head (title "My Blog"))
|
||||
(body
|
||||
(h1 "My Blog")
|
||||
,(render-posts make-url)
|
||||
(form ((action
|
||||
,(make-url insert-post-handler)))
|
||||
(input ((name "title")))
|
||||
(input ((name "body")))
|
||||
(input ((type "submit")))))))
|
||||
(local [(define (response-generator make-url)
|
||||
(response/xexpr
|
||||
`(html (head (title "My Blog"))
|
||||
(body
|
||||
(h1 "My Blog")
|
||||
,(render-posts make-url)
|
||||
(form ((action
|
||||
,(make-url insert-post-handler)))
|
||||
(input ((name "title")))
|
||||
(input ((name "body")))
|
||||
(input ((type "submit"))))))))
|
||||
|
||||
;; parse-post: bindings -> post
|
||||
;; Extracts a post out of the bindings.
|
||||
|
@ -70,22 +71,23 @@
|
|||
|
||||
(send/suspend/dispatch response-generator)))
|
||||
|
||||
;; render-post-detail-page: post request -> html-response
|
||||
;; render-post-detail-page: post request -> doesn't
|
||||
;; Consumes a post and request, and produces a detail page
|
||||
;; of the post. The user will be able to insert new comments.
|
||||
(define (render-post-detail-page a-post request)
|
||||
(local [(define (response-generator make-url)
|
||||
`(html (head (title "Post Details"))
|
||||
(body
|
||||
(h1 "Post Details")
|
||||
(h2 ,(post-title a-post))
|
||||
(p ,(post-body a-post))
|
||||
,(render-as-itemized-list
|
||||
(post-comments a-post))
|
||||
(form ((action
|
||||
,(make-url insert-comment-handler)))
|
||||
(input ((name "comment")))
|
||||
(input ((type "submit")))))))
|
||||
(response/xexpr
|
||||
`(html (head (title "Post Details"))
|
||||
(body
|
||||
(h1 "Post Details")
|
||||
(h2 ,(post-title a-post))
|
||||
(p ,(post-body a-post))
|
||||
,(render-as-itemized-list
|
||||
(post-comments a-post))
|
||||
(form ((action
|
||||
,(make-url insert-comment-handler)))
|
||||
(input ((name "comment")))
|
||||
(input ((type "submit"))))))))
|
||||
|
||||
(define (parse-comment bindings)
|
||||
(extract-binding/single 'comment bindings))
|
||||
|
@ -99,8 +101,8 @@
|
|||
(send/suspend/dispatch response-generator)))
|
||||
|
||||
|
||||
;; render-post: post (handler -> string) -> html-response
|
||||
;; Consumes a post, produces an html-response fragment of the post.
|
||||
;; render-post: post (handler -> string) -> xexpr
|
||||
;; Consumes a post, produces an xexpr fragment of the post.
|
||||
;; The fragment contains a link to show a detailed view of the post.
|
||||
(define (render-post a-post make-url)
|
||||
(local [(define (view-post-handler request)
|
||||
|
@ -112,8 +114,8 @@
|
|||
(div ,(number->string (length (post-comments a-post)))
|
||||
" comment(s)"))))
|
||||
|
||||
;; render-posts: (handler -> string) -> html-response
|
||||
;; Consumes a make-url, and produces an html-response fragment
|
||||
;; render-posts: (handler -> string) -> xexpr
|
||||
;; Consumes a make-url, and produces an xexpr fragment
|
||||
;; of all its posts.
|
||||
(define (render-posts make-url)
|
||||
(local [(define (render-post/make-url a-post)
|
||||
|
@ -121,14 +123,14 @@
|
|||
`(div ((class "posts"))
|
||||
,@(map render-post/make-url (blog-posts BLOG)))))
|
||||
|
||||
;; render-as-itemized-list: (listof html-response) -> html-response
|
||||
;; render-as-itemized-list: (listof xexpr) -> xexpr
|
||||
;; Consumes a list of items, and produces a rendering as
|
||||
;; an unorderered list.
|
||||
(define (render-as-itemized-list fragments)
|
||||
`(ul ,@(map render-as-item fragments)))
|
||||
|
||||
;; render-as-item: html-response -> html-response
|
||||
;; Consumes an html-response, and produces a rendering
|
||||
;; render-as-item: xexpr -> xexpr
|
||||
;; Consumes an xexpr, and produces a rendering
|
||||
;; as a list item.
|
||||
(define (render-as-item a-fragment)
|
||||
`(li ,a-fragment))
|
||||
|
|
|
@ -35,26 +35,27 @@
|
|||
a-post
|
||||
(append (post-comments a-post) (list a-comment))))
|
||||
|
||||
;; start: request -> html-response
|
||||
;; start: request -> doesn't
|
||||
;; Consumes a request and produces a page that displays
|
||||
;; all of the web content.
|
||||
(define (start request)
|
||||
(render-blog-page request))
|
||||
|
||||
;; render-blog-page: request -> html-response
|
||||
;; Produces an html-response page of the content of the
|
||||
;; render-blog-page: request -> doesn't
|
||||
;; Produces an HTML page of the content of the
|
||||
;; BLOG.
|
||||
(define (render-blog-page request)
|
||||
(local [(define (response-generator make-url)
|
||||
`(html (head (title "My Blog"))
|
||||
(body
|
||||
(h1 "My Blog")
|
||||
,(render-posts make-url)
|
||||
(form ((action
|
||||
,(make-url insert-post-handler)))
|
||||
(input ((name "title")))
|
||||
(input ((name "body")))
|
||||
(input ((type "submit")))))))
|
||||
(local [(define (response-generator make-url)
|
||||
(response/xexpr
|
||||
`(html (head (title "My Blog"))
|
||||
(body
|
||||
(h1 "My Blog")
|
||||
,(render-posts make-url)
|
||||
(form ((action
|
||||
,(make-url insert-post-handler)))
|
||||
(input ((name "title")))
|
||||
(input ((name "body")))
|
||||
(input ((type "submit"))))))))
|
||||
|
||||
;; parse-post: bindings -> post
|
||||
;; Extracts a post out of the bindings.
|
||||
|
@ -70,25 +71,26 @@
|
|||
|
||||
(send/suspend/dispatch response-generator)))
|
||||
|
||||
;; render-post-detail-page: post request -> html-response
|
||||
;; render-post-detail-page: post request -> doesn't
|
||||
;; Consumes a post and produces a detail page of the post.
|
||||
;; The user will be able to either insert new comments
|
||||
;; or go back to render-blog-page.
|
||||
(define (render-post-detail-page a-post request)
|
||||
(local [(define (response-generator make-url)
|
||||
`(html (head (title "Post Details"))
|
||||
(body
|
||||
(h1 "Post Details")
|
||||
(h2 ,(post-title a-post))
|
||||
(p ,(post-body a-post))
|
||||
,(render-as-itemized-list
|
||||
(post-comments a-post))
|
||||
(form ((action
|
||||
,(make-url insert-comment-handler)))
|
||||
(input ((name "comment")))
|
||||
(input ((type "submit"))))
|
||||
(a ((href ,(make-url back-handler)))
|
||||
"Back to the blog"))))
|
||||
(response/xexpr
|
||||
`(html (head (title "Post Details"))
|
||||
(body
|
||||
(h1 "Post Details")
|
||||
(h2 ,(post-title a-post))
|
||||
(p ,(post-body a-post))
|
||||
,(render-as-itemized-list
|
||||
(post-comments a-post))
|
||||
(form ((action
|
||||
,(make-url insert-comment-handler)))
|
||||
(input ((name "comment")))
|
||||
(input ((type "submit"))))
|
||||
(a ((href ,(make-url back-handler)))
|
||||
"Back to the blog")))))
|
||||
|
||||
(define (parse-comment bindings)
|
||||
(extract-binding/single 'comment bindings))
|
||||
|
@ -105,24 +107,25 @@
|
|||
(send/suspend/dispatch response-generator)))
|
||||
|
||||
;; render-confirm-add-comment-page :
|
||||
;; comment post request -> html-response
|
||||
;; comment post request -> doesn't
|
||||
;; Consumes a comment that we intend to add to a post, as well
|
||||
;; as the request. If the user follows through, adds a comment
|
||||
;; and goes back to the display page. Otherwise, goes back to
|
||||
;; the detail page of the post.
|
||||
(define (render-confirm-add-comment-page a-comment a-post request)
|
||||
(local [(define (response-generator make-url)
|
||||
`(html (head (title "Add a Comment"))
|
||||
(body
|
||||
(h1 "Add a Comment")
|
||||
"The comment: " (div (p ,a-comment))
|
||||
"will be added to "
|
||||
(div ,(post-title a-post))
|
||||
|
||||
(p (a ((href ,(make-url yes-handler)))
|
||||
"Yes, add the comment."))
|
||||
(p (a ((href ,(make-url cancel-handler)))
|
||||
"No, I changed my mind!")))))
|
||||
(response/xexpr
|
||||
`(html (head (title "Add a Comment"))
|
||||
(body
|
||||
(h1 "Add a Comment")
|
||||
"The comment: " (div (p ,a-comment))
|
||||
"will be added to "
|
||||
(div ,(post-title a-post))
|
||||
|
||||
(p (a ((href ,(make-url yes-handler)))
|
||||
"Yes, add the comment."))
|
||||
(p (a ((href ,(make-url cancel-handler)))
|
||||
"No, I changed my mind!"))))))
|
||||
|
||||
(define (yes-handler request)
|
||||
(post-insert-comment! a-post a-comment)
|
||||
|
@ -133,8 +136,8 @@
|
|||
|
||||
(send/suspend/dispatch response-generator)))
|
||||
|
||||
;; render-post: post (handler -> string) -> html-response
|
||||
;; Consumes a post, produces an html-response fragment of the post.
|
||||
;; render-post: post (handler -> string) -> xexpr
|
||||
;; Consumes a post, produces an xexpr fragment of the post.
|
||||
;; The fragment contains a link to show a detailed view of the post.
|
||||
(define (render-post a-post make-url)
|
||||
(local [(define (view-post-handler request)
|
||||
|
@ -146,8 +149,8 @@
|
|||
(div ,(number->string (length (post-comments a-post)))
|
||||
" comment(s)"))))
|
||||
|
||||
;; render-posts: (handler -> string) -> html-response
|
||||
;; Consumes a make-url, produces an html-response fragment
|
||||
;; render-posts: (handler -> string) -> xexpr
|
||||
;; Consumes a make-url, produces an xexpr fragment
|
||||
;; of all its posts.
|
||||
(define (render-posts make-url)
|
||||
(local [(define (render-post/make-url a-post)
|
||||
|
@ -155,14 +158,14 @@
|
|||
`(div ((class "posts"))
|
||||
,@(map render-post/make-url (blog-posts BLOG)))))
|
||||
|
||||
;; render-as-itemized-list: (listof html-response) -> html-response
|
||||
;; render-as-itemized-list: (listof xexpr) -> xexpr
|
||||
;; Consumes a list of items, and produces a rendering as
|
||||
;; an unorderered list.
|
||||
(define (render-as-itemized-list fragments)
|
||||
`(ul ,@(map render-as-item fragments)))
|
||||
|
||||
;; render-as-item: html-response -> html-response
|
||||
;; Consumes an html-response, and produces a rendering
|
||||
;; render-as-item: xexpr -> xexpr
|
||||
;; Consumes an xexpr, and produces a rendering
|
||||
;; as a list item.
|
||||
(define (render-as-item a-fragment)
|
||||
`(li ,a-fragment))
|
||||
|
|
|
@ -35,26 +35,27 @@
|
|||
a-post
|
||||
(append (post-comments a-post) (list a-comment))))
|
||||
|
||||
;; start: request -> html-response
|
||||
;; start: request -> doesn't
|
||||
;; Consumes a request and produces a page that displays
|
||||
;; all of the web content.
|
||||
(define (start request)
|
||||
(render-blog-page request))
|
||||
|
||||
;; render-blog-page: request -> html-response
|
||||
;; Produces an html-response page of the content of the
|
||||
;; render-blog-page: request -> doesn't
|
||||
;; Produces an doesn't page of the content of the
|
||||
;; BLOG.
|
||||
(define (render-blog-page request)
|
||||
(local [(define (response-generator make-url)
|
||||
`(html (head (title "My Blog"))
|
||||
(body
|
||||
(h1 "My Blog")
|
||||
,(render-posts make-url)
|
||||
(form ((action
|
||||
,(make-url insert-post-handler)))
|
||||
(input ((name "title")))
|
||||
(input ((name "body")))
|
||||
(input ((type "submit")))))))
|
||||
(local [(define (response-generator make-url)
|
||||
(response/xexpr
|
||||
`(html (head (title "My Blog"))
|
||||
(body
|
||||
(h1 "My Blog")
|
||||
,(render-posts make-url)
|
||||
(form ((action
|
||||
,(make-url insert-post-handler)))
|
||||
(input ((name "title")))
|
||||
(input ((name "body")))
|
||||
(input ((type "submit"))))))))
|
||||
|
||||
;; parse-post: bindings -> post
|
||||
;; Extracts a post out of the bindings.
|
||||
|
@ -70,25 +71,26 @@
|
|||
|
||||
(send/suspend/dispatch response-generator)))
|
||||
|
||||
;; render-post-detail-page: post request -> html-response
|
||||
;; render-post-detail-page: post request -> doesn't
|
||||
;; Consumes a post and produces a detail page of the post.
|
||||
;; The user will be able to either insert new comments
|
||||
;; or go back to render-blog-page.
|
||||
(define (render-post-detail-page a-post request)
|
||||
(local [(define (response-generator make-url)
|
||||
`(html (head (title "Post Details"))
|
||||
(body
|
||||
(h1 "Post Details")
|
||||
(h2 ,(post-title a-post))
|
||||
(p ,(post-body a-post))
|
||||
,(render-as-itemized-list
|
||||
(post-comments a-post))
|
||||
(form ((action
|
||||
,(make-url insert-comment-handler)))
|
||||
(input ((name "comment")))
|
||||
(input ((type "submit"))))
|
||||
(a ((href ,(make-url back-handler)))
|
||||
"Back to the blog"))))
|
||||
(response/xexpr
|
||||
`(html (head (title "Post Details"))
|
||||
(body
|
||||
(h1 "Post Details")
|
||||
(h2 ,(post-title a-post))
|
||||
(p ,(post-body a-post))
|
||||
,(render-as-itemized-list
|
||||
(post-comments a-post))
|
||||
(form ((action
|
||||
,(make-url insert-comment-handler)))
|
||||
(input ((name "comment")))
|
||||
(input ((type "submit"))))
|
||||
(a ((href ,(make-url back-handler)))
|
||||
"Back to the blog")))))
|
||||
|
||||
(define (parse-comment bindings)
|
||||
(extract-binding/single 'comment bindings))
|
||||
|
@ -105,24 +107,25 @@
|
|||
(send/suspend/dispatch response-generator)))
|
||||
|
||||
;; render-confirm-add-comment-page :
|
||||
;; comment post request -> html-response
|
||||
;; comment post request -> doesn't
|
||||
;; Consumes a comment that we intend to add to a post, as well
|
||||
;; as the request. If the user follows through, adds a comment
|
||||
;; and goes back to the display page. Otherwise, goes back to
|
||||
;; the detail page of the post.
|
||||
(define (render-confirm-add-comment-page a-comment a-post request)
|
||||
(local [(define (response-generator make-url)
|
||||
`(html (head (title "Add a Comment"))
|
||||
(body
|
||||
(h1 "Add a Comment")
|
||||
"The comment: " (div (p ,a-comment))
|
||||
"will be added to "
|
||||
(div ,(post-title a-post))
|
||||
|
||||
(p (a ((href ,(make-url yes-handler)))
|
||||
"Yes, add the comment."))
|
||||
(p (a ((href ,(make-url cancel-handler)))
|
||||
"No, I changed my mind!")))))
|
||||
(response/xexpr
|
||||
`(html (head (title "Add a Comment"))
|
||||
(body
|
||||
(h1 "Add a Comment")
|
||||
"The comment: " (div (p ,a-comment))
|
||||
"will be added to "
|
||||
(div ,(post-title a-post))
|
||||
|
||||
(p (a ((href ,(make-url yes-handler)))
|
||||
"Yes, add the comment."))
|
||||
(p (a ((href ,(make-url cancel-handler)))
|
||||
"No, I changed my mind!"))))))
|
||||
|
||||
(define (yes-handler request)
|
||||
(post-insert-comment! a-post a-comment)
|
||||
|
@ -133,8 +136,8 @@
|
|||
|
||||
(send/suspend/dispatch response-generator)))
|
||||
|
||||
;; render-post: post (handler -> string) -> html-response
|
||||
;; Consumes a post, produces an html-response fragment of the post.
|
||||
;; render-post: post (handler -> string) -> xexpr
|
||||
;; Consumes a post, produces an xexpr fragment of the post.
|
||||
;; The fragment contains a link to show a detailed view of the post.
|
||||
(define (render-post a-post make-url)
|
||||
(local [(define (view-post-handler request)
|
||||
|
@ -146,8 +149,8 @@
|
|||
(div ,(number->string (length (post-comments a-post)))
|
||||
" comment(s)"))))
|
||||
|
||||
;; render-posts: (handler -> string) -> html-response
|
||||
;; Consumes a make-url, produces an html-response fragment
|
||||
;; render-posts: (handler -> string) -> xexpr
|
||||
;; Consumes a make-url, produces an xexpr fragment
|
||||
;; of all its posts.
|
||||
(define (render-posts make-url)
|
||||
(local [(define (render-post/make-url a-post)
|
||||
|
@ -155,14 +158,14 @@
|
|||
`(div ((class "posts"))
|
||||
,@(map render-post/make-url (blog-posts BLOG)))))
|
||||
|
||||
;; render-as-itemized-list: (listof html-response) -> html-response
|
||||
;; render-as-itemized-list: (listof xexpr) -> xexpr
|
||||
;; Consumes a list of items, and produces a rendering as
|
||||
;; an unorderered list.
|
||||
(define (render-as-itemized-list fragments)
|
||||
`(ul ,@(map render-as-item fragments)))
|
||||
|
||||
;; render-as-item: html-response -> html-response
|
||||
;; Consumes an html-response, and produces a rendering
|
||||
;; render-as-item: xexpr -> xexpr
|
||||
;; Consumes an xexpr, and produces a rendering
|
||||
;; as a list item.
|
||||
(define (render-as-item a-fragment)
|
||||
`(li ,a-fragment))
|
||||
|
|
|
@ -2,26 +2,27 @@
|
|||
|
||||
(require "model.rkt")
|
||||
|
||||
;; start: request -> html-response
|
||||
;; start: request -> doesn't
|
||||
;; Consumes a request and produces a page that displays
|
||||
;; all of the web content.
|
||||
(define (start request)
|
||||
(render-blog-page request))
|
||||
|
||||
;; render-blog-page: request -> html-response
|
||||
;; Produces an html-response page of the content of the
|
||||
;; render-blog-page: request -> doesn't
|
||||
;; Produces an HTML page of the content of the
|
||||
;; BLOG.
|
||||
(define (render-blog-page request)
|
||||
(local [(define (response-generator make-url)
|
||||
`(html (head (title "My Blog"))
|
||||
(body
|
||||
(h1 "My Blog")
|
||||
,(render-posts make-url)
|
||||
(form ((action
|
||||
,(make-url insert-post-handler)))
|
||||
(input ((name "title")))
|
||||
(input ((name "body")))
|
||||
(input ((type "submit")))))))
|
||||
(local [(define (response-generator make-url)
|
||||
(response/xexpr
|
||||
`(html (head (title "My Blog"))
|
||||
(body
|
||||
(h1 "My Blog")
|
||||
,(render-posts make-url)
|
||||
(form ((action
|
||||
,(make-url insert-post-handler)))
|
||||
(input ((name "title")))
|
||||
(input ((name "body")))
|
||||
(input ((type "submit"))))))))
|
||||
|
||||
;; parse-post: bindings -> post
|
||||
;; Extracts a post out of the bindings.
|
||||
|
@ -37,25 +38,26 @@
|
|||
|
||||
(send/suspend/dispatch response-generator)))
|
||||
|
||||
;; render-post-detail-page: post request -> html-response
|
||||
;; render-post-detail-page: post request -> doesn't
|
||||
;; Consumes a post and produces a detail page of the post.
|
||||
;; The user will be able to either insert new comments
|
||||
;; or go back to render-blog-page.
|
||||
(define (render-post-detail-page a-post request)
|
||||
(local [(define (response-generator make-url)
|
||||
`(html (head (title "Post Details"))
|
||||
(body
|
||||
(h1 "Post Details")
|
||||
(h2 ,(post-title a-post))
|
||||
(p ,(post-body a-post))
|
||||
,(render-as-itemized-list
|
||||
(post-comments a-post))
|
||||
(form ((action
|
||||
,(make-url insert-comment-handler)))
|
||||
(input ((name "comment")))
|
||||
(input ((type "submit"))))
|
||||
(a ((href ,(make-url back-handler)))
|
||||
"Back to the blog"))))
|
||||
(response/xexpr
|
||||
`(html (head (title "Post Details"))
|
||||
(body
|
||||
(h1 "Post Details")
|
||||
(h2 ,(post-title a-post))
|
||||
(p ,(post-body a-post))
|
||||
,(render-as-itemized-list
|
||||
(post-comments a-post))
|
||||
(form ((action
|
||||
,(make-url insert-comment-handler)))
|
||||
(input ((name "comment")))
|
||||
(input ((type "submit"))))
|
||||
(a ((href ,(make-url back-handler)))
|
||||
"Back to the blog")))))
|
||||
|
||||
(define (parse-comment bindings)
|
||||
(extract-binding/single 'comment bindings))
|
||||
|
@ -72,24 +74,25 @@
|
|||
(send/suspend/dispatch response-generator)))
|
||||
|
||||
;; render-confirm-add-comment-page :
|
||||
;; comment post request -> html-response
|
||||
;; comment post request -> doesn't
|
||||
;; Consumes a comment that we intend to add to a post, as well
|
||||
;; as the request. If the user follows through, adds a comment
|
||||
;; and goes back to the display page. Otherwise, goes back to
|
||||
;; the detail page of the post.
|
||||
(define (render-confirm-add-comment-page a-comment a-post request)
|
||||
(local [(define (response-generator make-url)
|
||||
`(html (head (title "Add a Comment"))
|
||||
(body
|
||||
(h1 "Add a Comment")
|
||||
"The comment: " (div (p ,a-comment))
|
||||
"will be added to "
|
||||
(div ,(post-title a-post))
|
||||
|
||||
(p (a ((href ,(make-url yes-handler)))
|
||||
"Yes, add the comment."))
|
||||
(p (a ((href ,(make-url cancel-handler)))
|
||||
"No, I changed my mind!")))))
|
||||
(response/xexpr
|
||||
`(html (head (title "Add a Comment"))
|
||||
(body
|
||||
(h1 "Add a Comment")
|
||||
"The comment: " (div (p ,a-comment))
|
||||
"will be added to "
|
||||
(div ,(post-title a-post))
|
||||
|
||||
(p (a ((href ,(make-url yes-handler)))
|
||||
"Yes, add the comment."))
|
||||
(p (a ((href ,(make-url cancel-handler)))
|
||||
"No, I changed my mind!"))))))
|
||||
|
||||
(define (yes-handler request)
|
||||
(post-insert-comment! a-post a-comment)
|
||||
|
@ -100,8 +103,8 @@
|
|||
|
||||
(send/suspend/dispatch response-generator)))
|
||||
|
||||
;; render-post: post (handler -> string) -> html-response
|
||||
;; Consumes a post, produces an html-response fragment of the post.
|
||||
;; render-post: post (handler -> string) -> xexpr
|
||||
;; Consumes a post, produces an xexpr fragment of the post.
|
||||
;; The fragment contains a link to show a detailed view of the post.
|
||||
(define (render-post a-post make-url)
|
||||
(local [(define (view-post-handler request)
|
||||
|
@ -113,8 +116,8 @@
|
|||
(div ,(number->string (length (post-comments a-post)))
|
||||
" comment(s)"))))
|
||||
|
||||
;; render-posts: (handler -> string) -> html-response
|
||||
;; Consumes a make-url, produces an html-response fragment
|
||||
;; render-posts: (handler -> string) -> xexpr
|
||||
;; Consumes a make-url, produces an xexpr fragment
|
||||
;; of all its posts.
|
||||
(define (render-posts make-url)
|
||||
(local [(define (render-post/make-url a-post)
|
||||
|
@ -122,14 +125,14 @@
|
|||
`(div ((class "posts"))
|
||||
,@(map render-post/make-url (blog-posts BLOG)))))
|
||||
|
||||
;; render-as-itemized-list: (listof html-response) -> html-response
|
||||
;; render-as-itemized-list: (listof xexpr) -> xexpr
|
||||
;; Consumes a list of items, and produces a rendering as
|
||||
;; an unorderered list.
|
||||
(define (render-as-itemized-list fragments)
|
||||
`(ul ,@(map render-as-item fragments)))
|
||||
|
||||
;; render-as-item: html-response -> html-response
|
||||
;; Consumes an html-response, and produces a rendering
|
||||
;; render-as-item: xexpr -> xexpr
|
||||
;; Consumes an xexpr, and produces a rendering
|
||||
;; as a list item.
|
||||
(define (render-as-item a-fragment)
|
||||
`(li ,a-fragment))
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
(require "model-2.rkt")
|
||||
|
||||
;; start: request -> html-response
|
||||
;; start: request -> doesn't
|
||||
;; Consumes a request and produces a page that displays
|
||||
;; all of the web content.
|
||||
(define (start request)
|
||||
|
@ -12,20 +12,21 @@
|
|||
"the-blog-data.db"))
|
||||
request))
|
||||
|
||||
;; render-blog-page: blog request -> html-response
|
||||
;; Produces an html-response page of the content of the
|
||||
;; render-blog-page: blog request -> doesn't
|
||||
;; Produces an HTML page of the content of the
|
||||
;; blog.
|
||||
(define (render-blog-page a-blog request)
|
||||
(local [(define (response-generator make-url)
|
||||
`(html (head (title "My Blog"))
|
||||
(body
|
||||
(h1 "My Blog")
|
||||
,(render-posts a-blog make-url)
|
||||
(form ((action
|
||||
,(make-url insert-post-handler)))
|
||||
(input ((name "title")))
|
||||
(input ((name "body")))
|
||||
(input ((type "submit")))))))
|
||||
(local [(define (response-generator make-url)
|
||||
(response/xexpr
|
||||
`(html (head (title "My Blog"))
|
||||
(body
|
||||
(h1 "My Blog")
|
||||
,(render-posts a-blog make-url)
|
||||
(form ((action
|
||||
,(make-url insert-post-handler)))
|
||||
(input ((name "title")))
|
||||
(input ((name "body")))
|
||||
(input ((type "submit"))))))))
|
||||
|
||||
(define (insert-post-handler request)
|
||||
(define bindings (request-bindings request))
|
||||
|
@ -37,25 +38,26 @@
|
|||
|
||||
(send/suspend/dispatch response-generator)))
|
||||
|
||||
;; render-post-detail-page: post request -> html-response
|
||||
;; render-post-detail-page: post request -> doesn't
|
||||
;; Consumes a post and produces a detail page of the post.
|
||||
;; The user will be able to either insert new comments
|
||||
;; or go back to render-blog-page.
|
||||
(define (render-post-detail-page a-blog a-post request)
|
||||
(local [(define (response-generator make-url)
|
||||
`(html (head (title "Post Details"))
|
||||
(body
|
||||
(h1 "Post Details")
|
||||
(h2 ,(post-title a-post))
|
||||
(p ,(post-body a-post))
|
||||
,(render-as-itemized-list
|
||||
(post-comments a-post))
|
||||
(form ((action
|
||||
,(make-url insert-comment-handler)))
|
||||
(input ((name "comment")))
|
||||
(input ((type "submit"))))
|
||||
(a ((href ,(make-url back-handler)))
|
||||
"Back to the blog"))))
|
||||
(response/xexpr
|
||||
`(html (head (title "Post Details"))
|
||||
(body
|
||||
(h1 "Post Details")
|
||||
(h2 ,(post-title a-post))
|
||||
(p ,(post-body a-post))
|
||||
,(render-as-itemized-list
|
||||
(post-comments a-post))
|
||||
(form ((action
|
||||
,(make-url insert-comment-handler)))
|
||||
(input ((name "comment")))
|
||||
(input ((type "submit"))))
|
||||
(a ((href ,(make-url back-handler)))
|
||||
"Back to the blog")))))
|
||||
|
||||
(define (parse-comment bindings)
|
||||
(extract-binding/single 'comment bindings))
|
||||
|
@ -73,7 +75,7 @@
|
|||
(send/suspend/dispatch response-generator)))
|
||||
|
||||
;; render-confirm-add-comment-page :
|
||||
;; blog comment post request -> html-response
|
||||
;; blog comment post request -> doesn't
|
||||
;; Consumes a comment that we intend to add to a post, as well
|
||||
;; as the request. If the user follows through, adds a comment
|
||||
;; and goes back to the display page. Otherwise, goes back to
|
||||
|
@ -81,17 +83,18 @@
|
|||
(define (render-confirm-add-comment-page a-blog a-comment
|
||||
a-post request)
|
||||
(local [(define (response-generator make-url)
|
||||
`(html (head (title "Add a Comment"))
|
||||
(body
|
||||
(h1 "Add a Comment")
|
||||
"The comment: " (div (p ,a-comment))
|
||||
"will be added to "
|
||||
(div ,(post-title a-post))
|
||||
|
||||
(p (a ((href ,(make-url yes-handler)))
|
||||
"Yes, add the comment."))
|
||||
(p (a ((href ,(make-url cancel-handler)))
|
||||
"No, I changed my mind!")))))
|
||||
(response/xexpr
|
||||
`(html (head (title "Add a Comment"))
|
||||
(body
|
||||
(h1 "Add a Comment")
|
||||
"The comment: " (div (p ,a-comment))
|
||||
"will be added to "
|
||||
(div ,(post-title a-post))
|
||||
|
||||
(p (a ((href ,(make-url yes-handler)))
|
||||
"Yes, add the comment."))
|
||||
(p (a ((href ,(make-url cancel-handler)))
|
||||
"No, I changed my mind!"))))))
|
||||
|
||||
(define (yes-handler request)
|
||||
(post-insert-comment! a-blog a-post a-comment)
|
||||
|
@ -102,8 +105,8 @@
|
|||
|
||||
(send/suspend/dispatch response-generator)))
|
||||
|
||||
;; render-post: post (handler -> string) -> html-response
|
||||
;; Consumes a post, produces an html-response fragment of the post.
|
||||
;; render-post: post (handler -> string) -> xexpr
|
||||
;; Consumes a post, produces an xexpr fragment of the post.
|
||||
;; The fragment contains a link to show a detailed view of the post.
|
||||
(define (render-post a-blog a-post make-url)
|
||||
(local [(define (view-post-handler request)
|
||||
|
@ -115,8 +118,8 @@
|
|||
(div ,(number->string (length (post-comments a-post)))
|
||||
" comment(s)"))))
|
||||
|
||||
;; render-posts: blog (handler -> string) -> html-response
|
||||
;; Consumes a make-url, produces an html-response fragment
|
||||
;; render-posts: blog (handler -> string) -> xexpr
|
||||
;; Consumes a make-url, produces an xexpr fragment
|
||||
;; of all its posts.
|
||||
(define (render-posts a-blog make-url)
|
||||
(local [(define (render-post/make-url a-post)
|
||||
|
@ -124,14 +127,14 @@
|
|||
`(div ((class "posts"))
|
||||
,@(map render-post/make-url (blog-posts a-blog)))))
|
||||
|
||||
;; render-as-itemized-list: (listof html-response) -> html-response
|
||||
;; render-as-itemized-list: (listof xexpr) -> xexpr
|
||||
;; Consumes a list of items, and produces a rendering as
|
||||
;; an unorderered list.
|
||||
(define (render-as-itemized-list fragments)
|
||||
`(ul ,@(map render-as-item fragments)))
|
||||
|
||||
;; render-as-item: html-response -> html-response
|
||||
;; Consumes an html-response, and produces a rendering
|
||||
;; render-as-item: xexpr -> xexpr
|
||||
;; Consumes an xexpr, and produces a rendering
|
||||
;; as a list item.
|
||||
(define (render-as-item a-fragment)
|
||||
`(li ,a-fragment))
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
(require "model-2.rkt")
|
||||
|
||||
;; start: request -> html-response
|
||||
;; start: request -> doesn't
|
||||
;; Consumes a request and produces a page that displays
|
||||
;; all of the web content.
|
||||
(define (start request)
|
||||
|
@ -12,20 +12,21 @@
|
|||
"the-blog-data.db"))
|
||||
request))
|
||||
|
||||
;; render-blog-page: blog request -> html-response
|
||||
;; Produces an html-response page of the content of the
|
||||
;; render-blog-page: blog request -> doesn't
|
||||
;; Sends an HTML page of the content of the
|
||||
;; blog.
|
||||
(define (render-blog-page a-blog request)
|
||||
(define (response-generator make-url)
|
||||
`(html (head (title "My Blog"))
|
||||
(body
|
||||
(h1 "My Blog")
|
||||
,(render-posts a-blog make-url)
|
||||
(form ((action
|
||||
,(make-url insert-post-handler)))
|
||||
(input ((name "title")))
|
||||
(input ((name "body")))
|
||||
(input ((type "submit")))))))
|
||||
(define (response-generator make-url)
|
||||
(response/xexpr
|
||||
`(html (head (title "My Blog"))
|
||||
(body
|
||||
(h1 "My Blog")
|
||||
,(render-posts a-blog make-url)
|
||||
(form ((action
|
||||
,(make-url insert-post-handler)))
|
||||
(input ((name "title")))
|
||||
(input ((name "body")))
|
||||
(input ((type "submit"))))))))
|
||||
|
||||
(define (insert-post-handler request)
|
||||
(define bindings (request-bindings/raw request))
|
||||
|
@ -37,25 +38,26 @@
|
|||
|
||||
(send/suspend/dispatch response-generator))
|
||||
|
||||
;; render-post-detail-page: post request -> html-response
|
||||
;; render-post-detail-page: post request -> doesn't
|
||||
;; Consumes a post and produces a detail page of the post.
|
||||
;; The user will be able to either insert new comments
|
||||
;; or go back to render-blog-page.
|
||||
(define (render-post-detail-page a-blog a-post request)
|
||||
(define (response-generator make-url)
|
||||
`(html (head (title "Post Details"))
|
||||
(body
|
||||
(h1 "Post Details")
|
||||
(h2 ,(post-title a-post))
|
||||
(p ,(post-body a-post))
|
||||
,(render-as-itemized-list
|
||||
(post-comments a-post))
|
||||
(form ((action
|
||||
,(make-url insert-comment-handler)))
|
||||
(input ((name "comment")))
|
||||
(input ((type "submit"))))
|
||||
(a ((href ,(make-url back-handler)))
|
||||
"Back to the blog"))))
|
||||
(response/xexpr
|
||||
`(html (head (title "Post Details"))
|
||||
(body
|
||||
(h1 "Post Details")
|
||||
(h2 ,(post-title a-post))
|
||||
(p ,(post-body a-post))
|
||||
,(render-as-itemized-list
|
||||
(post-comments a-post))
|
||||
(form ((action
|
||||
,(make-url insert-comment-handler)))
|
||||
(input ((name "comment")))
|
||||
(input ((type "submit"))))
|
||||
(a ((href ,(make-url back-handler)))
|
||||
"Back to the blog")))))
|
||||
|
||||
(define (parse-comment bindings)
|
||||
(bytes->string/utf-8 (bindings-assq #"comment" bindings)))
|
||||
|
@ -73,7 +75,7 @@
|
|||
(send/suspend/dispatch response-generator))
|
||||
|
||||
;; render-confirm-add-comment-page :
|
||||
;; blog comment post request -> html-response
|
||||
;; blog comment post request -> doesn't
|
||||
;; Consumes a comment that we intend to add to a post, as well
|
||||
;; as the request. If the user follows through, adds a comment
|
||||
;; and goes back to the display page. Otherwise, goes back to
|
||||
|
@ -81,17 +83,18 @@
|
|||
(define (render-confirm-add-comment-page a-blog a-comment
|
||||
a-post request)
|
||||
(define (response-generator make-url)
|
||||
`(html (head (title "Add a Comment"))
|
||||
(body
|
||||
(h1 "Add a Comment")
|
||||
"The comment: " (div (p ,a-comment))
|
||||
"will be added to "
|
||||
(div ,(post-title a-post))
|
||||
|
||||
(p (a ((href ,(make-url yes-handler)))
|
||||
"Yes, add the comment."))
|
||||
(p (a ((href ,(make-url cancel-handler)))
|
||||
"No, I changed my mind!")))))
|
||||
(response/xexpr
|
||||
`(html (head (title "Add a Comment"))
|
||||
(body
|
||||
(h1 "Add a Comment")
|
||||
"The comment: " (div (p ,a-comment))
|
||||
"will be added to "
|
||||
(div ,(post-title a-post))
|
||||
|
||||
(p (a ((href ,(make-url yes-handler)))
|
||||
"Yes, add the comment."))
|
||||
(p (a ((href ,(make-url cancel-handler)))
|
||||
"No, I changed my mind!"))))))
|
||||
|
||||
(define (yes-handler request)
|
||||
(post-insert-comment! a-blog a-post a-comment)
|
||||
|
@ -102,8 +105,8 @@
|
|||
|
||||
(send/suspend/dispatch response-generator))
|
||||
|
||||
;; render-post: post (handler -> string) -> html-response
|
||||
;; Consumes a post, produces an html-response fragment of the post.
|
||||
;; render-post: post (handler -> string) -> xexpr
|
||||
;; Consumes a post, produces an xexpr fragment of the post.
|
||||
;; The fragment contains a link to show a detailed view of the post.
|
||||
(define (render-post a-blog a-post make-url)
|
||||
(define (view-post-handler request)
|
||||
|
@ -116,8 +119,8 @@
|
|||
(div ,(number->string (length (post-comments a-post)))
|
||||
" comment(s)")))
|
||||
|
||||
;; render-posts: blog (handler -> string) -> html-response
|
||||
;; Consumes a make-url, produces an html-response fragment
|
||||
;; render-posts: blog (handler -> string) -> xexpr
|
||||
;; Consumes a make-url, produces an xexpr fragment
|
||||
;; of all its posts.
|
||||
(define (render-posts a-blog make-url)
|
||||
(define (render-post/make-url a-post)
|
||||
|
@ -126,14 +129,14 @@
|
|||
`(div ((class "posts"))
|
||||
,@(map render-post/make-url (blog-posts a-blog))))
|
||||
|
||||
;; render-as-itemized-list: (listof html-response) -> html-response
|
||||
;; render-as-itemized-list: (listof xexpr) -> xexpr
|
||||
;; Consumes a list of items, and produces a rendering as
|
||||
;; an unorderered list.
|
||||
(define (render-as-itemized-list fragments)
|
||||
`(ul ,@(map render-as-item fragments)))
|
||||
|
||||
;; render-as-item: html-response -> html-response
|
||||
;; Consumes an html-response, and produces a rendering
|
||||
;; render-as-item: xexpr -> xexpr
|
||||
;; Consumes an xexpr, and produces a rendering
|
||||
;; as a list item.
|
||||
(define (render-as-item a-fragment)
|
||||
`(li ,a-fragment))
|
||||
|
|
|
@ -14,21 +14,22 @@
|
|||
|
||||
(define ROSTER (roster '("kathi" "shriram" "dan")))
|
||||
|
||||
;; start: request -> html-response
|
||||
;; start: request -> doesn't
|
||||
(define (start request)
|
||||
(show-roster request))
|
||||
|
||||
;; show-roster: request -> html-response
|
||||
;; show-roster: request -> doesn't
|
||||
(define (show-roster request)
|
||||
(local [(define (response-generator make-url)
|
||||
`(html (head (title "Roster"))
|
||||
(body (h1 "Roster")
|
||||
,(render-as-itemized-list
|
||||
(roster-names ROSTER))
|
||||
(form ((action
|
||||
,(make-url add-name-handler)))
|
||||
(input ((name "a-name")))
|
||||
(input ((type "submit")))))))
|
||||
(response/xexpr
|
||||
`(html (head (title "Roster"))
|
||||
(body (h1 "Roster")
|
||||
,(render-as-itemized-list
|
||||
(roster-names ROSTER))
|
||||
(form ((action
|
||||
,(make-url add-name-handler)))
|
||||
(input ((name "a-name")))
|
||||
(input ((type "submit"))))))))
|
||||
(define (parse-name bindings)
|
||||
(extract-binding/single 'a-name bindings))
|
||||
|
||||
|
@ -38,10 +39,10 @@
|
|||
(show-roster request))]
|
||||
(send/suspend/dispatch response-generator)))
|
||||
|
||||
;; render-as-itemized-list: (listof html-response) -> html-response
|
||||
;; render-as-itemized-list: (listof xexpr) -> xexpr
|
||||
(define (render-as-itemized-list fragments)
|
||||
`(ul ,@(map render-as-item fragments)))
|
||||
|
||||
;; render-as-item: html-response -> html-response
|
||||
;; render-as-item: xexpr -> xexpr
|
||||
(define (render-as-item a-fragment)
|
||||
`(li ,a-fragment))
|
||||
|
|
|
@ -1,20 +1,23 @@
|
|||
#lang web-server/insta
|
||||
|
||||
;; start: request -> html-response
|
||||
;; start: request -> response
|
||||
(define (start request)
|
||||
(send/suspend/dispatch
|
||||
(lambda (make-url)
|
||||
`(html
|
||||
(body
|
||||
(a ((href ,(make-url link-1))) "Link 1")
|
||||
(a ((href ,(make-url link-2))) "Link 2"))))))
|
||||
(response/xexpr
|
||||
`(html
|
||||
(body
|
||||
(a ((href ,(make-url link-1))) "Link 1")
|
||||
(a ((href ,(make-url link-2))) "Link 2")))))))
|
||||
|
||||
|
||||
;; link-1: request -> html-response
|
||||
;; link-1: request -> response
|
||||
(define (link-1 request)
|
||||
"This is link-1")
|
||||
(response/xexpr
|
||||
"This is link-1"))
|
||||
|
||||
|
||||
;; link-2: request -> html-response
|
||||
;; link-2: request -> response
|
||||
(define (link-2 request)
|
||||
"This is link-2")
|
||||
(response/xexpr
|
||||
"This is link-2"))
|
||||
|
|
|
@ -3,13 +3,14 @@
|
|||
(define (start request)
|
||||
(show-counter 0))
|
||||
|
||||
;; show-counter: number -> html-response
|
||||
;; show-counter: number -> doesn't
|
||||
(define (show-counter n)
|
||||
(send/suspend/dispatch
|
||||
(lambda (make-url)
|
||||
`(html (head (title "Counting example"))
|
||||
(body
|
||||
(a ((href ,(make-url
|
||||
(lambda (request)
|
||||
(show-counter (+ n 1))))))
|
||||
,(number->string n)))))))
|
||||
(response/xexpr
|
||||
`(html (head (title "Counting example"))
|
||||
(body
|
||||
(a ((href ,(make-url
|
||||
(lambda (request)
|
||||
(show-counter (+ n 1))))))
|
||||
,(number->string n))))))))
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
#lang web-server/insta
|
||||
(define (start request)
|
||||
'(html (head (title "Testing"))
|
||||
(link ((rel "stylesheet")
|
||||
(href "/test-static.css")
|
||||
(type "text/css")))
|
||||
(body (h1 "This is a header")
|
||||
(p "This is " (span ((class "hot")) "hot") "."))))
|
||||
(response/xexpr
|
||||
'(html (head (title "Testing"))
|
||||
(link ((rel "stylesheet")
|
||||
(href "/test-static.css")
|
||||
(type "text/css")))
|
||||
(body (h1 "This is a header")
|
||||
(p "This is " (span ((class "hot")) "hot") ".")))))
|
||||
(static-files-path "htdocs")
|
||||
|
|
|
@ -14,21 +14,22 @@
|
|||
|
||||
(define ROSTER (roster '("kathi" "shriram" "dan")))
|
||||
|
||||
;; start: request -> html-response
|
||||
;; start: request -> doesn't
|
||||
(define (start request)
|
||||
(show-roster request))
|
||||
|
||||
;; show-roster: request -> html-response
|
||||
;; show-roster: request -> doesn't
|
||||
(define (show-roster request)
|
||||
(local [(define (response-generator make-url)
|
||||
`(html (head (title "Roster"))
|
||||
(body (h1 "Roster")
|
||||
,(render-as-itemized-list
|
||||
(roster-names ROSTER))
|
||||
(form ((action
|
||||
,(make-url add-name-handler)))
|
||||
(input ((name "a-name")))
|
||||
(input ((type "submit")))))))
|
||||
(response/xexpr
|
||||
`(html (head (title "Roster"))
|
||||
(body (h1 "Roster")
|
||||
,(render-as-itemized-list
|
||||
(roster-names ROSTER))
|
||||
(form ((action
|
||||
,(make-url add-name-handler)))
|
||||
(input ((name "a-name")))
|
||||
(input ((type "submit"))))))))
|
||||
(define (parse-name bindings)
|
||||
(extract-binding/single 'a-name bindings))
|
||||
|
||||
|
@ -38,10 +39,10 @@
|
|||
(show-roster (redirect/get)))]
|
||||
(send/suspend/dispatch response-generator)))
|
||||
|
||||
;; render-as-itemized-list: (listof html-response) -> html-response
|
||||
;; render-as-itemized-list: (listof xexpr) -> xexpr
|
||||
(define (render-as-itemized-list fragments)
|
||||
`(ul ,@(map render-as-item fragments)))
|
||||
|
||||
;; render-as-item: html-response -> html-response
|
||||
;; render-as-item: xexpr -> xexpr
|
||||
(define (render-as-item a-fragment)
|
||||
`(li ,a-fragment))
|
||||
|
|
Loading…
Reference in New Issue
Block a user