diff options
author | Paul Duncan <pabs@pablotron.org> | 2016-03-09 01:13:48 -0500 |
---|---|---|
committer | Paul Duncan <pabs@pablotron.org> | 2016-03-09 01:13:48 -0500 |
commit | 6e02499111871aa59042fc30e57b522f18be6e22 (patch) | |
tree | 21e7d2a85b5c039ff700fe6ea2f5ac25d1a08f21 | |
parent | 804b034691f4c276090ee0d2a681dbf5b8b5a267 (diff) | |
download | old-guff-6e02499111871aa59042fc30e57b522f18be6e22.tar.bz2 old-guff-6e02499111871aa59042fc30e57b522f18be6e22.zip |
add /tags support
-rw-r--r-- | src/guff/handlers/blog.cr | 149 | ||||
-rw-r--r-- | 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?\/(?<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 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('|') |