howl 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Rakefile CHANGED
@@ -13,6 +13,7 @@ begin
13
13
  gem.add_development_dependency "riot", ">= 0.11"
14
14
  gem.add_runtime_dependency 'rdiscount'
15
15
  gem.add_runtime_dependency 'mustache'
16
+ gem.add_runtime_dependency 'hashie'
16
17
  end
17
18
  Jeweler::GemcutterTasks.new
18
19
  rescue LoadError
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 0.2.0
data/howl.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{howl}
8
- s.version = "0.1.0"
8
+ s.version = "0.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Clinton R. Nixon"]
12
- s.date = %q{2010-10-15}
12
+ s.date = %q{2010-10-16}
13
13
  s.description = %q{Howl is a tiny static website/blog generator.}
14
14
  s.email = %q{crnixon@gmail.com}
15
15
  s.extra_rdoc_files = [
@@ -28,11 +28,16 @@ Gem::Specification.new do |s|
28
28
  "test/fixtures/pages/has_template.html",
29
29
  "test/fixtures/pages/no_yaml.html",
30
30
  "test/fixtures/pages/simple.html",
31
+ "test/fixtures/posts/first_post.html",
32
+ "test/fixtures/posts/no_date.html",
31
33
  "test/fixtures/site/has_template.html",
32
34
  "test/fixtures/site/no_yaml.html",
35
+ "test/fixtures/site/posts/2010/09/04/first_post.html",
36
+ "test/fixtures/site/posts/2010/10/16/no_date.html",
33
37
  "test/fixtures/site/simple.html",
34
38
  "test/fixtures/templates/alt.html",
35
39
  "test/fixtures/templates/default.html",
40
+ "test/fixtures/templates/post.html",
36
41
  "test/fixtures/templates/site.html",
37
42
  "test/howl_test.rb",
38
43
  "test/teststrap.rb"
@@ -55,15 +60,18 @@ Gem::Specification.new do |s|
55
60
  s.add_development_dependency(%q<riot>, [">= 0.11"])
56
61
  s.add_runtime_dependency(%q<rdiscount>, [">= 0"])
57
62
  s.add_runtime_dependency(%q<mustache>, [">= 0"])
63
+ s.add_runtime_dependency(%q<hashie>, [">= 0"])
58
64
  else
59
65
  s.add_dependency(%q<riot>, [">= 0.11"])
60
66
  s.add_dependency(%q<rdiscount>, [">= 0"])
61
67
  s.add_dependency(%q<mustache>, [">= 0"])
68
+ s.add_dependency(%q<hashie>, [">= 0"])
62
69
  end
63
70
  else
64
71
  s.add_dependency(%q<riot>, [">= 0.11"])
65
72
  s.add_dependency(%q<rdiscount>, [">= 0"])
66
73
  s.add_dependency(%q<mustache>, [">= 0"])
74
+ s.add_dependency(%q<hashie>, [">= 0"])
67
75
  end
68
76
  end
69
77
 
data/lib/howl.rb CHANGED
@@ -1,8 +1,10 @@
1
1
  require 'yaml'
2
2
  require 'rdiscount'
3
3
  require 'mustache'
4
+ require 'hashie'
4
5
  require 'pathname'
5
6
  require 'fileutils'
7
+ require 'time'
6
8
 
7
9
  $:.unshift File.dirname(__FILE__)
8
10
 
@@ -22,6 +24,10 @@ module Howl
22
24
  @pages ||= Dir[path "pages/*"].map { |path| Page.new(path, self) }
23
25
  end
24
26
 
27
+ def posts
28
+ @posts ||= Dir[path "posts/*"].map { |path| Post.new(path, self) }.sort
29
+ end
30
+
25
31
  def templates
26
32
  @templates ||= Hash[Dir[root + "templates/*"].map { |path|
27
33
  [Pathname.new(path).relative_path_from(path "templates").to_s,
@@ -31,8 +37,9 @@ module Howl
31
37
 
32
38
  def write_to_disk
33
39
  FileUtils.rm_r(path "site") if File.exist?(path "site")
34
- FileUtils.makedirs(path "site")
35
- pages.each do |page|
40
+ #raise (pages + posts).map(&:class).inspect
41
+ (pages + posts).each do |page|
42
+ FileUtils.makedirs(page.output_path.dirname)
36
43
  page.output_path.open("w") do |fh|
37
44
  fh.write page.render
38
45
  end
@@ -40,8 +47,11 @@ module Howl
40
47
  end
41
48
  end
42
49
 
50
+ class View < Hashie::Mash
51
+ end
52
+
43
53
  class Template
44
- attr_accessor :data, :content, :site
54
+ attr_accessor :view, :content, :site, :path
45
55
 
46
56
  def initialize(path, site)
47
57
  @site = site
@@ -54,35 +64,43 @@ module Howl
54
64
  self.path == other.path && self.class == other.class
55
65
  end
56
66
 
57
- def render(render_data = {})
58
- render_data.merge!(@data)
59
- rendered = Mustache.render(@content, render_data)
60
- template = render_data.delete("template")
67
+ def render(render_view = {})
68
+ render_view.merge!(@view)
69
+ rendered = Mustache.render(@content, render_view)
70
+ template = render_view.delete("template")
61
71
  if template
62
- rendered = @site.templates[template + @extension].render(render_data.merge("content" => rendered))
72
+ begin
73
+ rendered = @site.templates[template + @extension].render(render_view.merge("content" => rendered))
74
+ rescue NoMethodError => ex
75
+ puts "Warning: Template #{template + @extension} does not exist in file #{path}"
76
+ rendered
77
+ end
63
78
  end
64
79
 
65
80
  rendered
66
81
  end
82
+
67
83
  private
68
84
 
69
85
  def load_file
70
86
  content = @path.read
71
- data, content = content.split("\n\n", 2)
87
+ view, content = content.split("\n\n", 2)
72
88
 
73
- if test_for_yaml(data)
74
- @data = YAML.load(data)
89
+ if test_for_yaml(view)
75
90
  @content = content
91
+ view = YAML.load(view)
76
92
  else
77
- @data = {}
78
- @content = "#{data}\n\n#{content}".strip
93
+ @content = "#{view}\n\n#{content}".strip
94
+ view = {}
79
95
  end
96
+
97
+ @view = View.new(view.merge(:site => site))
80
98
  end
81
99
 
82
- def test_for_yaml(data)
100
+ def test_for_yaml(view)
83
101
  begin
84
- data = YAML.load(data)
85
- data.is_a?(Hash)
102
+ view = YAML.load(view)
103
+ view.is_a?(Hash)
86
104
  rescue ArgumentError
87
105
  false
88
106
  end
@@ -90,13 +108,24 @@ module Howl
90
108
  end
91
109
 
92
110
  class Page < Template
93
- attr_accessor :path
94
-
95
111
  def output_path
96
112
  site.path("site") + path.relative_path_from(site.path "pages")
97
113
  end
98
114
  end
99
115
 
100
116
  class Post < Template
117
+ include Comparable
118
+
119
+ def date
120
+ view.date? ? Time.parse(view.date) : File.mtime(path)
121
+ end
122
+
123
+ def output_path
124
+ site.path("site/posts") + date.strftime("%Y/%m/%d") + path.basename
125
+ end
126
+
127
+ def <=>(other)
128
+ self.date <=> other.date
129
+ end
101
130
  end
102
131
  end
@@ -0,0 +1,5 @@
1
+ date: 4 Sep 2010
2
+ title: First Post!
3
+ template: post
4
+
5
+ DANG
@@ -0,0 +1,3 @@
1
+ topic: I Have No Date
2
+
3
+ This post has no date in its YAML front-matter.
@@ -0,0 +1,11 @@
1
+ <html>
2
+ <head><title>First Post!</title></head>
3
+ <div class="post">
4
+ <h2>First Post!</h2>
5
+ <div class="post-content">
6
+ DANG
7
+
8
+ </div.
9
+ </div>
10
+
11
+ </html>
@@ -0,0 +1 @@
1
+ This post has no date in its YAML front-matter.
@@ -0,0 +1,8 @@
1
+ template: site
2
+
3
+ <div class="post">
4
+ <h2>{{title}}</h2>
5
+ <div class="post-content">
6
+ {{content}}
7
+ </div>
8
+ </div>
data/test/howl_test.rb CHANGED
@@ -2,7 +2,7 @@ require 'teststrap'
2
2
  include Howl
3
3
 
4
4
  context "Site" do
5
- setup { Site.new(fixture_path) }
5
+ setup { @site = Site.new(fixture_path) }
6
6
 
7
7
  should("find all pages") {
8
8
  topic.pages == Dir[fixture_path("pages/*")].map { |path| Page.new(path, topic) }
@@ -14,35 +14,43 @@ context "Site" do
14
14
  File.exist?(page.output_path)
15
15
  }.all?
16
16
  }
17
- end
18
17
 
19
- context "Page" do
20
- setup { @site = Site.new(fixture_path) }
18
+ should("write out all posts") {
19
+ topic.write_to_disk
20
+ topic.posts.map { |post|
21
+ Dir[topic.path("site/posts") + "**/*"].map { |path| File.basename(path) }.include?(post.path.basename.to_s)
22
+ }.all?
23
+ }
21
24
 
22
- context "simple.html" do
23
- setup { Page.new(fixture_path("pages/simple.html"), @site) }
25
+ context "Page" do
26
+ context "simple.html" do
27
+ setup { Page.new(fixture_path("pages/simple.html"), @site) }
24
28
 
25
- asserts(:data).equals({"title" => "This is a simple page"})
26
- asserts("#content") { topic.content.strip }.equals "<h1>{{title}}</h1>"
27
- asserts("#rendered") { topic.render.strip }.equals "<h1>This is a simple page</h1>"
29
+ asserts("#content") { topic.content.strip }.equals "<h1>{{title}}</h1>"
30
+ asserts("#view is correct") {
31
+ topic.view == View.new(:site => topic.site, :title => "This is a simple page")
32
+ }
33
+ asserts("#rendered") { topic.render.strip }.equals "<h1>This is a simple page</h1>"
28
34
 
29
- should("be able to find its output path") {
30
- topic.output_path == (topic.site.path "site/simple.html")
31
- }
32
- end
35
+ should("be able to find its output path") {
36
+ topic.output_path == (topic.site.path "site/simple.html")
37
+ }
38
+ end
33
39
 
34
- context "no_yaml.html" do
35
- setup { Page.new(fixture_path("pages/no_yaml.html"), @site) }
40
+ context "no_yaml.html" do
41
+ setup { Page.new(fixture_path("pages/no_yaml.html"), @site) }
36
42
 
37
- asserts(:data).equals({})
38
- asserts("#content") { topic.content.strip }.equals "This page has no YAML front-matter."
39
- asserts("#rendered") { topic.render.strip }.equals "This page has no YAML front-matter."
40
- end
43
+ asserts("#content") { topic.content.strip }.equals "This page has no YAML front-matter."
44
+ asserts("#view is correct") {
45
+ topic.view == View.new(:site => topic.site)
46
+ }
47
+ asserts("#rendered") { topic.render.strip }.equals "This page has no YAML front-matter."
48
+ end
41
49
 
42
- context "has_template.html" do
43
- setup { Page.new(fixture_path("pages/has_template.html"), @site) }
50
+ context "has_template.html" do
51
+ setup { Page.new(fixture_path("pages/has_template.html"), @site) }
44
52
 
45
- asserts("#rendered") { topic.render.clean }.equals %Q[
53
+ asserts("#rendered") { topic.render.clean }.equals %Q[
46
54
  <html>
47
55
  <head><title>This page has a template</title></head>
48
56
  <h1>This page has a template</h1>
@@ -50,6 +58,26 @@ context "Page" do
50
58
  Hello world!
51
59
  </div>
52
60
  </html>
53
- ].clean
61
+ ].clean
62
+ end
63
+ end
64
+
65
+ context "Post" do
66
+ setup { Post.new(fixture_path("posts/first_post.html"), @site) }
67
+
68
+ asserts("date is equal to date from front matter") {
69
+ topic.date == Time.parse("2010/09/04")
70
+ }
71
+
72
+ asserts(:output_path).equals {
73
+ topic.site.path("site/posts/2010/09/04") + "first_post.html"
74
+ }
75
+
76
+ context "without a date" do
77
+ setup { Post.new(fixture_path("posts/no_date.html"), @site) }
78
+
79
+ asserts("date is equal to file's mtime") { topic.date == File.mtime(topic.path) }
80
+ end
54
81
  end
55
82
  end
83
+
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 1
7
+ - 2
8
8
  - 0
9
- version: 0.1.0
9
+ version: 0.2.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Clinton R. Nixon
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-10-15 00:00:00 -04:00
17
+ date: 2010-10-16 00:00:00 -04:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -57,6 +57,19 @@ dependencies:
57
57
  version: "0"
58
58
  type: :runtime
59
59
  version_requirements: *id003
60
+ - !ruby/object:Gem::Dependency
61
+ name: hashie
62
+ prerelease: false
63
+ requirement: &id004 !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ segments:
69
+ - 0
70
+ version: "0"
71
+ type: :runtime
72
+ version_requirements: *id004
60
73
  description: Howl is a tiny static website/blog generator.
61
74
  email: crnixon@gmail.com
62
75
  executables: []
@@ -78,11 +91,16 @@ files:
78
91
  - test/fixtures/pages/has_template.html
79
92
  - test/fixtures/pages/no_yaml.html
80
93
  - test/fixtures/pages/simple.html
94
+ - test/fixtures/posts/first_post.html
95
+ - test/fixtures/posts/no_date.html
81
96
  - test/fixtures/site/has_template.html
82
97
  - test/fixtures/site/no_yaml.html
98
+ - test/fixtures/site/posts/2010/09/04/first_post.html
99
+ - test/fixtures/site/posts/2010/10/16/no_date.html
83
100
  - test/fixtures/site/simple.html
84
101
  - test/fixtures/templates/alt.html
85
102
  - test/fixtures/templates/default.html
103
+ - test/fixtures/templates/post.html
86
104
  - test/fixtures/templates/site.html
87
105
  - test/howl_test.rb
88
106
  - test/teststrap.rb