diff options
Diffstat (limited to 'src/guff/handlers')
-rw-r--r-- | src/guff/handlers/blog.cr | 149 |
1 files changed, 127 insertions, 22 deletions
diff --git a/src/guff/handlers/blog.cr b/src/guff/handlers/blog.cr index 2394354..89393c3 100644 --- a/src/guff/handlers/blog.cr +++ b/src/guff/handlers/blog.cr @@ -1,10 +1,11 @@ +require "html" require "../handler" require "../views/html/page" class Guff::Handlers::BlogHandler < Guff::Handler ROUTES = [{ - list: false, - blog: true, + type: :post, + tags: ["_blog"], re: %r{ ^/ @@ -21,8 +22,8 @@ class Guff::Handlers::BlogHandler < Guff::Handler $ }x, }, { - list: true, - blog: true, + type: :list, + tags: ["_blog"], re: %r{ ^/ @@ -37,8 +38,8 @@ class Guff::Handlers::BlogHandler < Guff::Handler $ }x, }, { - list: true, - blog: true, + type: :list, + tags: ["_blog"], re: %r{ ^/ @@ -51,8 +52,8 @@ class Guff::Handlers::BlogHandler < Guff::Handler $ }x, }, { - list: true, - blog: true, + type: :list, + tags: ["_blog"], re: %r{ ^/ @@ -63,8 +64,8 @@ class Guff::Handlers::BlogHandler < Guff::Handler $ }x, }, { - list: false, - blog: false, + type: :post, + tags: ["_post"], re: %r{ ^/ @@ -75,8 +76,30 @@ class Guff::Handlers::BlogHandler < Guff::Handler $ }x, }, { - list: true, - blog: true, + type: :list, + tags: ["_blog"], + re: %r{ + ^/ + + # match tags/foo/bar/baz + tags?\/(?<tags>(?:[a-z0-9._-]+)(?:/(?:[a-z0-9._-]+))*) + + /?$ + }x, + }, { + type: :tags, + tags: ["_blog"], + re: %r{ + ^/ + + # match tags + tags? + + /?$ + }x, + }, { + type: :list, + tags: ["_blog"], re: %r{ # match index ^/$ @@ -95,18 +118,41 @@ class Guff::Handlers::BlogHandler < Guff::Handler md.to_s ] - # search for matching posts - posts = @models.post.get_posts( - filters: get_filters(md), - tags: [["foo"]], - ) + # build tags + tags = route[:tags] as Array(String) + + case route[:type] + when :tags + # route to list of tags - if posts.size > 0 # mark as matched matched = true # draw result - draw(context, route, posts) + draw_tags(context, @models.tag.get_tags( + tags: tags, + )) + else + # route to post or list of posts + + # add tags from path + if md["tags"]? + tags += md["tags"].split('/') + end + + # search for matching posts + posts = @models.post.get_posts( + filters: get_post_filters(md), + tags: [tags], + ) + + if posts.size > 0 + # mark as matched + matched = true + + # draw result + draw_posts(context, route, posts) + end end end end @@ -122,16 +168,75 @@ class Guff::Handlers::BlogHandler < Guff::Handler slug: "slug", } - private def get_filters(md) : Hash(Symbol, String) + private def get_post_filters(md) : Hash(Symbol, String) FILTERS.reduce({} of Symbol => String) do |r, k, s| r[k] = md[s] if md[s]? r end end - private def draw(context, route, posts) + private def draw_posts(context, route, posts) + case route[:type] + when :list + name = "Posts" + rows = posts.rows + pager = true + when :post + post = posts.rows.first + name = post.name + rows = [post] + pager = false + else + # never reached + raise "unknown route type: #{route[:type]}" + end + + # create page + page = PageHTMLView.new( + title: name, + body: rows.map { |post| post.to_s }.join, + ) + + # render page + context.response.content_type = page.content_type + context.response.puts page + end + + TAG_TEMPLATES = TemplateCache.new({ + body: " + <div class='post'> + <div class='name'>Tags</div> + <div class='body'> + <ul class='tags'>%{tags}</ul> + </div> + </div> + ", + + tag: " + <li class='tag'> + <a + href='%{name}/' + title='View posts matching tag %{name}.' + > + %{name} (%{num_posts} posts) + </a> + </li> + ", + }) + + private def draw_tags(context, tags) # create page - page = PageHTMLView.new("Posts", posts.rows.map { |post| post.to_s }.join) + page = PageHTMLView.new( + title: "Tags", + body: TAG_TEMPLATES[:body].run({ + "tags": tags.map { |row| + TAG_TEMPLATES[:tag].run(row.reduce({} of String => String) do |r, k, v| + r[k] = HTML.escape(v.to_s) + r + end) + }.join, + }) + ) # render page context.response.content_type = page.content_type |