howl 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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