aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/guff/handlers/blog.cr149
-rw-r--r--src/guff/post.cr4
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('|')