howl 0.1.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/.gitignore +21 -0
- data/Gemfile +2 -0
- data/LICENSE +14 -0
- data/README.markdown +31 -0
- data/Rakefile +54 -0
- data/VERSION +1 -0
- data/howl.gemspec +69 -0
- data/lib/howl.rb +102 -0
- data/test/fixtures/pages/has_template.html +4 -0
- data/test/fixtures/pages/no_yaml.html +1 -0
- data/test/fixtures/pages/simple.html +3 -0
- data/test/fixtures/site/has_template.html +9 -0
- data/test/fixtures/site/no_yaml.html +1 -0
- data/test/fixtures/site/simple.html +1 -0
- data/test/fixtures/templates/alt.html +1 -0
- data/test/fixtures/templates/default.html +6 -0
- data/test/fixtures/templates/site.html +4 -0
- data/test/howl_test.rb +55 -0
- data/test/teststrap.rb +16 -0
- metadata +123 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
Copyright (c) 2009 Clinton R. Nixon <crnixon@gmail.com>
|
2
|
+
|
3
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
4
|
+
purpose with or without fee is hereby granted, provided that the above
|
5
|
+
copyright notice and this permission notice appear in all copies.
|
6
|
+
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
8
|
+
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
9
|
+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
10
|
+
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
11
|
+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
12
|
+
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
13
|
+
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
14
|
+
|
data/README.markdown
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# Howl
|
2
|
+
|
3
|
+
Howl is a tiny static site generator.
|
4
|
+
|
5
|
+
## File structure
|
6
|
+
|
7
|
+
/pages
|
8
|
+
index.html
|
9
|
+
about.html
|
10
|
+
/posts
|
11
|
+
first-post.html
|
12
|
+
my-cat-died.html
|
13
|
+
/templates
|
14
|
+
default.html
|
15
|
+
alternate.html
|
16
|
+
/site
|
17
|
+
<generated files go here>
|
18
|
+
|
19
|
+
## Note on Patches/Pull Requests
|
20
|
+
|
21
|
+
* Fork the project.
|
22
|
+
* Make your feature addition or bug fix.
|
23
|
+
* Add tests for it. This is important so I don't break it in a
|
24
|
+
future version unintentionally.
|
25
|
+
* Commit, do not mess with rakefile, version, or history.
|
26
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
27
|
+
* Send me a pull request. Bonus points for topic branches.
|
28
|
+
|
29
|
+
## Copyright
|
30
|
+
|
31
|
+
Copyright (c) 2010 Clinton R. Nixon. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "howl"
|
8
|
+
gem.summary = %Q{A tiny static website/blog generator.}
|
9
|
+
gem.description = %Q{Howl is a tiny static website/blog generator.}
|
10
|
+
gem.email = "crnixon@gmail.com"
|
11
|
+
gem.homepage = "http://github.com/crnixon/howl"
|
12
|
+
gem.authors = ["Clinton R. Nixon"]
|
13
|
+
gem.add_development_dependency "riot", ">= 0.11"
|
14
|
+
gem.add_runtime_dependency 'rdiscount'
|
15
|
+
gem.add_runtime_dependency 'mustache'
|
16
|
+
end
|
17
|
+
Jeweler::GemcutterTasks.new
|
18
|
+
rescue LoadError
|
19
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
20
|
+
end
|
21
|
+
|
22
|
+
require 'rake/testtask'
|
23
|
+
Rake::TestTask.new(:test) do |test|
|
24
|
+
test.libs << 'lib' << 'test'
|
25
|
+
test.pattern = 'test/**/*_test.rb'
|
26
|
+
test.verbose = true
|
27
|
+
end
|
28
|
+
|
29
|
+
begin
|
30
|
+
require 'rcov/rcovtask'
|
31
|
+
Rcov::RcovTask.new do |test|
|
32
|
+
test.libs << 'test'
|
33
|
+
test.pattern = 'test/**/*_test.rb'
|
34
|
+
test.verbose = true
|
35
|
+
end
|
36
|
+
rescue LoadError
|
37
|
+
task :rcov do
|
38
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install rcov"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
task :test => :check_dependencies
|
43
|
+
|
44
|
+
task :default => :test
|
45
|
+
|
46
|
+
require 'rake/rdoctask'
|
47
|
+
Rake::RDocTask.new do |rdoc|
|
48
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
49
|
+
|
50
|
+
rdoc.rdoc_dir = 'rdoc'
|
51
|
+
rdoc.title = "howl #{version}"
|
52
|
+
rdoc.rdoc_files.include('README*')
|
53
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
54
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
data/howl.gemspec
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{howl}
|
8
|
+
s.version = "0.1.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Clinton R. Nixon"]
|
12
|
+
s.date = %q{2010-10-15}
|
13
|
+
s.description = %q{Howl is a tiny static website/blog generator.}
|
14
|
+
s.email = %q{crnixon@gmail.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.markdown"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".gitignore",
|
21
|
+
"Gemfile",
|
22
|
+
"LICENSE",
|
23
|
+
"README.markdown",
|
24
|
+
"Rakefile",
|
25
|
+
"VERSION",
|
26
|
+
"howl.gemspec",
|
27
|
+
"lib/howl.rb",
|
28
|
+
"test/fixtures/pages/has_template.html",
|
29
|
+
"test/fixtures/pages/no_yaml.html",
|
30
|
+
"test/fixtures/pages/simple.html",
|
31
|
+
"test/fixtures/site/has_template.html",
|
32
|
+
"test/fixtures/site/no_yaml.html",
|
33
|
+
"test/fixtures/site/simple.html",
|
34
|
+
"test/fixtures/templates/alt.html",
|
35
|
+
"test/fixtures/templates/default.html",
|
36
|
+
"test/fixtures/templates/site.html",
|
37
|
+
"test/howl_test.rb",
|
38
|
+
"test/teststrap.rb"
|
39
|
+
]
|
40
|
+
s.homepage = %q{http://github.com/crnixon/howl}
|
41
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
42
|
+
s.require_paths = ["lib"]
|
43
|
+
s.rubygems_version = %q{1.3.7}
|
44
|
+
s.summary = %q{A tiny static website/blog generator.}
|
45
|
+
s.test_files = [
|
46
|
+
"test/howl_test.rb",
|
47
|
+
"test/teststrap.rb"
|
48
|
+
]
|
49
|
+
|
50
|
+
if s.respond_to? :specification_version then
|
51
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
52
|
+
s.specification_version = 3
|
53
|
+
|
54
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
55
|
+
s.add_development_dependency(%q<riot>, [">= 0.11"])
|
56
|
+
s.add_runtime_dependency(%q<rdiscount>, [">= 0"])
|
57
|
+
s.add_runtime_dependency(%q<mustache>, [">= 0"])
|
58
|
+
else
|
59
|
+
s.add_dependency(%q<riot>, [">= 0.11"])
|
60
|
+
s.add_dependency(%q<rdiscount>, [">= 0"])
|
61
|
+
s.add_dependency(%q<mustache>, [">= 0"])
|
62
|
+
end
|
63
|
+
else
|
64
|
+
s.add_dependency(%q<riot>, [">= 0.11"])
|
65
|
+
s.add_dependency(%q<rdiscount>, [">= 0"])
|
66
|
+
s.add_dependency(%q<mustache>, [">= 0"])
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
data/lib/howl.rb
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'rdiscount'
|
3
|
+
require 'mustache'
|
4
|
+
require 'pathname'
|
5
|
+
require 'fileutils'
|
6
|
+
|
7
|
+
$:.unshift File.dirname(__FILE__)
|
8
|
+
|
9
|
+
module Howl
|
10
|
+
class Site
|
11
|
+
attr_accessor :root
|
12
|
+
|
13
|
+
def initialize(root)
|
14
|
+
@root = Pathname.new(root)
|
15
|
+
end
|
16
|
+
|
17
|
+
def path(path)
|
18
|
+
root + path
|
19
|
+
end
|
20
|
+
|
21
|
+
def pages
|
22
|
+
@pages ||= Dir[path "pages/*"].map { |path| Page.new(path, self) }
|
23
|
+
end
|
24
|
+
|
25
|
+
def templates
|
26
|
+
@templates ||= Hash[Dir[root + "templates/*"].map { |path|
|
27
|
+
[Pathname.new(path).relative_path_from(path "templates").to_s,
|
28
|
+
Template.new(path, self)]
|
29
|
+
}]
|
30
|
+
end
|
31
|
+
|
32
|
+
def write_to_disk
|
33
|
+
FileUtils.rm_r(path "site") if File.exist?(path "site")
|
34
|
+
FileUtils.makedirs(path "site")
|
35
|
+
pages.each do |page|
|
36
|
+
page.output_path.open("w") do |fh|
|
37
|
+
fh.write page.render
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class Template
|
44
|
+
attr_accessor :data, :content, :site
|
45
|
+
|
46
|
+
def initialize(path, site)
|
47
|
+
@site = site
|
48
|
+
@path = Pathname.new(path)
|
49
|
+
@extension = @path.extname
|
50
|
+
load_file
|
51
|
+
end
|
52
|
+
|
53
|
+
def ==(other)
|
54
|
+
self.path == other.path && self.class == other.class
|
55
|
+
end
|
56
|
+
|
57
|
+
def render(render_data = {})
|
58
|
+
render_data.merge!(@data)
|
59
|
+
rendered = Mustache.render(@content, render_data)
|
60
|
+
template = render_data.delete("template")
|
61
|
+
if template
|
62
|
+
rendered = @site.templates[template + @extension].render(render_data.merge("content" => rendered))
|
63
|
+
end
|
64
|
+
|
65
|
+
rendered
|
66
|
+
end
|
67
|
+
private
|
68
|
+
|
69
|
+
def load_file
|
70
|
+
content = @path.read
|
71
|
+
data, content = content.split("\n\n", 2)
|
72
|
+
|
73
|
+
if test_for_yaml(data)
|
74
|
+
@data = YAML.load(data)
|
75
|
+
@content = content
|
76
|
+
else
|
77
|
+
@data = {}
|
78
|
+
@content = "#{data}\n\n#{content}".strip
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_for_yaml(data)
|
83
|
+
begin
|
84
|
+
data = YAML.load(data)
|
85
|
+
data.is_a?(Hash)
|
86
|
+
rescue ArgumentError
|
87
|
+
false
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
class Page < Template
|
93
|
+
attr_accessor :path
|
94
|
+
|
95
|
+
def output_path
|
96
|
+
site.path("site") + path.relative_path_from(site.path "pages")
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
class Post < Template
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
This page has no YAML front-matter.
|
@@ -0,0 +1 @@
|
|
1
|
+
This page has no YAML front-matter.
|
@@ -0,0 +1 @@
|
|
1
|
+
<h1>This is a simple page</h1>
|
@@ -0,0 +1 @@
|
|
1
|
+
alternate
|
data/test/howl_test.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'teststrap'
|
2
|
+
include Howl
|
3
|
+
|
4
|
+
context "Site" do
|
5
|
+
setup { Site.new(fixture_path) }
|
6
|
+
|
7
|
+
should("find all pages") {
|
8
|
+
topic.pages == Dir[fixture_path("pages/*")].map { |path| Page.new(path, topic) }
|
9
|
+
}
|
10
|
+
|
11
|
+
should("write out all pages") {
|
12
|
+
topic.write_to_disk
|
13
|
+
topic.pages.map { |page|
|
14
|
+
File.exist?(page.output_path)
|
15
|
+
}.all?
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
context "Page" do
|
20
|
+
setup { @site = Site.new(fixture_path) }
|
21
|
+
|
22
|
+
context "simple.html" do
|
23
|
+
setup { Page.new(fixture_path("pages/simple.html"), @site) }
|
24
|
+
|
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>"
|
28
|
+
|
29
|
+
should("be able to find its output path") {
|
30
|
+
topic.output_path == (topic.site.path "site/simple.html")
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
context "no_yaml.html" do
|
35
|
+
setup { Page.new(fixture_path("pages/no_yaml.html"), @site) }
|
36
|
+
|
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
|
41
|
+
|
42
|
+
context "has_template.html" do
|
43
|
+
setup { Page.new(fixture_path("pages/has_template.html"), @site) }
|
44
|
+
|
45
|
+
asserts("#rendered") { topic.render.clean }.equals %Q[
|
46
|
+
<html>
|
47
|
+
<head><title>This page has a template</title></head>
|
48
|
+
<h1>This page has a template</h1>
|
49
|
+
<div>
|
50
|
+
Hello world!
|
51
|
+
</div>
|
52
|
+
</html>
|
53
|
+
].clean
|
54
|
+
end
|
55
|
+
end
|
data/test/teststrap.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'riot'
|
3
|
+
|
4
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
5
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
6
|
+
require 'howl'
|
7
|
+
|
8
|
+
def fixture_path(path = ".")
|
9
|
+
Pathname.new(File.dirname(__FILE__)) + 'fixtures' + path
|
10
|
+
end
|
11
|
+
|
12
|
+
class String
|
13
|
+
def clean
|
14
|
+
self.strip.gsub(/\n+/, "\n")
|
15
|
+
end
|
16
|
+
end
|
metadata
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: howl
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
version: 0.1.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Clinton R. Nixon
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-10-15 00:00:00 -04:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: riot
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
segments:
|
29
|
+
- 0
|
30
|
+
- 11
|
31
|
+
version: "0.11"
|
32
|
+
type: :development
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: rdiscount
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
none: false
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
segments:
|
43
|
+
- 0
|
44
|
+
version: "0"
|
45
|
+
type: :runtime
|
46
|
+
version_requirements: *id002
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: mustache
|
49
|
+
prerelease: false
|
50
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
segments:
|
56
|
+
- 0
|
57
|
+
version: "0"
|
58
|
+
type: :runtime
|
59
|
+
version_requirements: *id003
|
60
|
+
description: Howl is a tiny static website/blog generator.
|
61
|
+
email: crnixon@gmail.com
|
62
|
+
executables: []
|
63
|
+
|
64
|
+
extensions: []
|
65
|
+
|
66
|
+
extra_rdoc_files:
|
67
|
+
- LICENSE
|
68
|
+
- README.markdown
|
69
|
+
files:
|
70
|
+
- .gitignore
|
71
|
+
- Gemfile
|
72
|
+
- LICENSE
|
73
|
+
- README.markdown
|
74
|
+
- Rakefile
|
75
|
+
- VERSION
|
76
|
+
- howl.gemspec
|
77
|
+
- lib/howl.rb
|
78
|
+
- test/fixtures/pages/has_template.html
|
79
|
+
- test/fixtures/pages/no_yaml.html
|
80
|
+
- test/fixtures/pages/simple.html
|
81
|
+
- test/fixtures/site/has_template.html
|
82
|
+
- test/fixtures/site/no_yaml.html
|
83
|
+
- test/fixtures/site/simple.html
|
84
|
+
- test/fixtures/templates/alt.html
|
85
|
+
- test/fixtures/templates/default.html
|
86
|
+
- test/fixtures/templates/site.html
|
87
|
+
- test/howl_test.rb
|
88
|
+
- test/teststrap.rb
|
89
|
+
has_rdoc: true
|
90
|
+
homepage: http://github.com/crnixon/howl
|
91
|
+
licenses: []
|
92
|
+
|
93
|
+
post_install_message:
|
94
|
+
rdoc_options:
|
95
|
+
- --charset=UTF-8
|
96
|
+
require_paths:
|
97
|
+
- lib
|
98
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
99
|
+
none: false
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
segments:
|
104
|
+
- 0
|
105
|
+
version: "0"
|
106
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
107
|
+
none: false
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
segments:
|
112
|
+
- 0
|
113
|
+
version: "0"
|
114
|
+
requirements: []
|
115
|
+
|
116
|
+
rubyforge_project:
|
117
|
+
rubygems_version: 1.3.7
|
118
|
+
signing_key:
|
119
|
+
specification_version: 3
|
120
|
+
summary: A tiny static website/blog generator.
|
121
|
+
test_files:
|
122
|
+
- test/howl_test.rb
|
123
|
+
- test/teststrap.rb
|