From 6e02499111871aa59042fc30e57b522f18be6e22 Mon Sep 17 00:00:00 2001 From: Paul Duncan Date: Wed, 9 Mar 2016 01:13:48 -0500 Subject: add /tags support --- src/guff/handlers/blog.cr | 149 +++++++++++++++++++++++++++++++++++++++------- src/guff/post.cr | 4 ++ 2 files changed, 131 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?\/(?(?:[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: " +
+
Tags
+
+
    %{tags}
+
+
+ ", + + tag: " +
  • + + %{name} (%{num_posts} posts) + +
  • + ", + }) + + 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 diff --git a/src/guff/post.cr b/src/guff/post.cr index 703ed55..3a63163 100644 --- a/src/guff/post.cr +++ b/src/guff/post.cr @@ -14,6 +14,10 @@ class Guff::Post }).to_json(io) end + def name : String + @row["name"] as String + end + private def tags : Array(String) @tags ||= if @row.has_key?("tags") && (@row["tags"] as String).size > 0 (@row["tags"] as String).split('|') -- cgit v1.2.3