howl 0.2.0 → 0.3.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 +3 -0
- data/Gemfile.lock +34 -0
- data/Rakefile +2 -0
- data/VERSION +1 -1
- data/howl.gemspec +23 -7
- data/lib/howl/converter.rb +33 -0
- data/lib/howl/converters/markdown.rb +14 -0
- data/lib/howl/converters/sass.rb +13 -0
- data/lib/howl/core_ext.rb +13 -0
- data/lib/howl/page.rb +7 -0
- data/lib/howl/plugin.rb +49 -0
- data/lib/howl/post.rb +25 -0
- data/lib/howl/site.rb +39 -0
- data/lib/howl/template.rb +77 -0
- data/lib/howl/view.rb +19 -0
- data/lib/howl.rb +8 -120
- data/test/fixtures/pages/css/modules/colors.scss +3 -0
- data/test/fixtures/pages/css/screen.scss +7 -0
- data/test/fixtures/pages/index.html +10 -0
- data/test/fixtures/posts/markdown_post.md +5 -0
- data/test/howl_test.rb +23 -2
- data/test/teststrap.rb +7 -0
- metadata +48 -12
- data/test/fixtures/site/has_template.html +0 -9
- data/test/fixtures/site/no_yaml.html +0 -1
- data/test/fixtures/site/posts/2010/09/04/first_post.html +0 -11
- data/test/fixtures/site/posts/2010/10/16/no_date.html +0 -1
- data/test/fixtures/site/simple.html +0 -1
data/.gitignore
CHANGED
data/Gemfile.lock
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
howl (0.3.0)
|
5
|
+
haml
|
6
|
+
hashie
|
7
|
+
mustache
|
8
|
+
rdiscount
|
9
|
+
|
10
|
+
GEM
|
11
|
+
remote: http://rubygems.org/
|
12
|
+
specs:
|
13
|
+
haml (3.0.17)
|
14
|
+
hashie (0.4.0)
|
15
|
+
mustache (0.11.2)
|
16
|
+
nokogiri (1.4.3.1)
|
17
|
+
rdiscount (1.6.5)
|
18
|
+
riot (0.11.4)
|
19
|
+
rr
|
20
|
+
term-ansicolor
|
21
|
+
rr (1.0.0)
|
22
|
+
term-ansicolor (1.0.5)
|
23
|
+
|
24
|
+
PLATFORMS
|
25
|
+
ruby
|
26
|
+
|
27
|
+
DEPENDENCIES
|
28
|
+
haml
|
29
|
+
hashie
|
30
|
+
howl!
|
31
|
+
mustache
|
32
|
+
nokogiri
|
33
|
+
rdiscount
|
34
|
+
riot (>= 0.11)
|
data/Rakefile
CHANGED
@@ -11,9 +11,11 @@ begin
|
|
11
11
|
gem.homepage = "http://github.com/crnixon/howl"
|
12
12
|
gem.authors = ["Clinton R. Nixon"]
|
13
13
|
gem.add_development_dependency "riot", ">= 0.11"
|
14
|
+
gem.add_development_dependency "nokogiri"
|
14
15
|
gem.add_runtime_dependency 'rdiscount'
|
15
16
|
gem.add_runtime_dependency 'mustache'
|
16
17
|
gem.add_runtime_dependency 'hashie'
|
18
|
+
gem.add_runtime_dependency 'haml'
|
17
19
|
end
|
18
20
|
Jeweler::GemcutterTasks.new
|
19
21
|
rescue LoadError
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.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.
|
8
|
+
s.version = "0.3.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-
|
12
|
+
s.date = %q{2010-10-17}
|
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 = [
|
@@ -19,22 +19,32 @@ Gem::Specification.new do |s|
|
|
19
19
|
s.files = [
|
20
20
|
".gitignore",
|
21
21
|
"Gemfile",
|
22
|
+
"Gemfile.lock",
|
22
23
|
"LICENSE",
|
23
24
|
"README.markdown",
|
24
25
|
"Rakefile",
|
25
26
|
"VERSION",
|
26
27
|
"howl.gemspec",
|
27
28
|
"lib/howl.rb",
|
29
|
+
"lib/howl/converter.rb",
|
30
|
+
"lib/howl/converters/markdown.rb",
|
31
|
+
"lib/howl/converters/sass.rb",
|
32
|
+
"lib/howl/core_ext.rb",
|
33
|
+
"lib/howl/page.rb",
|
34
|
+
"lib/howl/plugin.rb",
|
35
|
+
"lib/howl/post.rb",
|
36
|
+
"lib/howl/site.rb",
|
37
|
+
"lib/howl/template.rb",
|
38
|
+
"lib/howl/view.rb",
|
39
|
+
"test/fixtures/pages/css/modules/colors.scss",
|
40
|
+
"test/fixtures/pages/css/screen.scss",
|
28
41
|
"test/fixtures/pages/has_template.html",
|
42
|
+
"test/fixtures/pages/index.html",
|
29
43
|
"test/fixtures/pages/no_yaml.html",
|
30
44
|
"test/fixtures/pages/simple.html",
|
31
45
|
"test/fixtures/posts/first_post.html",
|
46
|
+
"test/fixtures/posts/markdown_post.md",
|
32
47
|
"test/fixtures/posts/no_date.html",
|
33
|
-
"test/fixtures/site/has_template.html",
|
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",
|
37
|
-
"test/fixtures/site/simple.html",
|
38
48
|
"test/fixtures/templates/alt.html",
|
39
49
|
"test/fixtures/templates/default.html",
|
40
50
|
"test/fixtures/templates/post.html",
|
@@ -58,20 +68,26 @@ Gem::Specification.new do |s|
|
|
58
68
|
|
59
69
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
60
70
|
s.add_development_dependency(%q<riot>, [">= 0.11"])
|
71
|
+
s.add_development_dependency(%q<nokogiri>, [">= 0"])
|
61
72
|
s.add_runtime_dependency(%q<rdiscount>, [">= 0"])
|
62
73
|
s.add_runtime_dependency(%q<mustache>, [">= 0"])
|
63
74
|
s.add_runtime_dependency(%q<hashie>, [">= 0"])
|
75
|
+
s.add_runtime_dependency(%q<haml>, [">= 0"])
|
64
76
|
else
|
65
77
|
s.add_dependency(%q<riot>, [">= 0.11"])
|
78
|
+
s.add_dependency(%q<nokogiri>, [">= 0"])
|
66
79
|
s.add_dependency(%q<rdiscount>, [">= 0"])
|
67
80
|
s.add_dependency(%q<mustache>, [">= 0"])
|
68
81
|
s.add_dependency(%q<hashie>, [">= 0"])
|
82
|
+
s.add_dependency(%q<haml>, [">= 0"])
|
69
83
|
end
|
70
84
|
else
|
71
85
|
s.add_dependency(%q<riot>, [">= 0.11"])
|
86
|
+
s.add_dependency(%q<nokogiri>, [">= 0"])
|
72
87
|
s.add_dependency(%q<rdiscount>, [">= 0"])
|
73
88
|
s.add_dependency(%q<mustache>, [">= 0"])
|
74
89
|
s.add_dependency(%q<hashie>, [">= 0"])
|
90
|
+
s.add_dependency(%q<haml>, [">= 0"])
|
75
91
|
end
|
76
92
|
end
|
77
93
|
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Howl
|
2
|
+
class Converter < Plugin
|
3
|
+
def self.converts(hash = nil)
|
4
|
+
@converts ||= {}
|
5
|
+
if hash
|
6
|
+
@converts.merge!(hash)
|
7
|
+
else
|
8
|
+
@converts
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.matches?(ext)
|
13
|
+
@converts.keys.any? do |matcher|
|
14
|
+
matcher.match(ext)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
attr_accessor :extension
|
19
|
+
|
20
|
+
def initialize(template)
|
21
|
+
@template = template
|
22
|
+
ext_regexp = self.class.converts.find { |conversion| conversion[0].match(@template.extension) }
|
23
|
+
@extension = @template.extension.gsub(ext_regexp[0], ext_regexp[1])
|
24
|
+
end
|
25
|
+
|
26
|
+
def convert(text)
|
27
|
+
text
|
28
|
+
end
|
29
|
+
|
30
|
+
priority :lowest
|
31
|
+
converts /\..+$/ => '\0'
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'rdiscount'
|
2
|
+
|
3
|
+
module Howl
|
4
|
+
class MarkdownConverter < Converter
|
5
|
+
converts ".md" => ".html"
|
6
|
+
converts ".mdown" => ".html"
|
7
|
+
converts ".markdown" => ".html"
|
8
|
+
priority :highest
|
9
|
+
|
10
|
+
def convert(text)
|
11
|
+
RDiscount.new(text).to_html
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'sass'
|
2
|
+
|
3
|
+
module Howl
|
4
|
+
class SassConverter < Converter
|
5
|
+
converts /\.s[ac]ss/ => '.css'
|
6
|
+
|
7
|
+
def convert(text)
|
8
|
+
sass_args = { :syntax => @template.extension.drop(1).to_sym,
|
9
|
+
:load_paths => [@template.path.dirname] }
|
10
|
+
Sass::Engine.new(text, sass_args).render
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class String
|
2
|
+
def drop(num)
|
3
|
+
self.dup.split(//).drop(num).join
|
4
|
+
end
|
5
|
+
|
6
|
+
def slugify
|
7
|
+
string = self.dup
|
8
|
+
string.gsub!(/[^\x00-\x7F]+/, '') # Remove anything non-ASCII entirely (e.g. diacritics).
|
9
|
+
string.gsub!(/[^a-z0-9\-_]+/i, '-')
|
10
|
+
string.downcase
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
data/lib/howl/page.rb
ADDED
data/lib/howl/plugin.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# Adapted from Jekyll's Plugin class.
|
2
|
+
|
3
|
+
module Howl
|
4
|
+
class Plugin
|
5
|
+
PRIORITIES = { :lowest => -100,
|
6
|
+
:low => -10,
|
7
|
+
:normal => 0,
|
8
|
+
:high => 10,
|
9
|
+
:highest => 100 }
|
10
|
+
|
11
|
+
# Install a hook so that subclasses are recorded. This method is only
|
12
|
+
# ever called by Ruby itself.
|
13
|
+
#
|
14
|
+
# base - The Class subclass.
|
15
|
+
#
|
16
|
+
# Returns nothing.
|
17
|
+
def self.inherited(base)
|
18
|
+
subclasses << base
|
19
|
+
subclasses.sort!
|
20
|
+
end
|
21
|
+
|
22
|
+
# The list of Classes that have been subclassed.
|
23
|
+
#
|
24
|
+
# Returns an Array of Class objects.
|
25
|
+
def self.subclasses
|
26
|
+
@subclasses ||= []
|
27
|
+
end
|
28
|
+
|
29
|
+
# Get or set the priority of this plugin. When called without an
|
30
|
+
# argument it returns the priority. When an argument is given, it will
|
31
|
+
# set the priority.
|
32
|
+
#
|
33
|
+
# priority - The Symbol priority (default: nil). Valid options are:
|
34
|
+
# :lowest, :low, :normal, :high, :highest
|
35
|
+
#
|
36
|
+
# Returns the Symbol priority.
|
37
|
+
def self.priority(priority = nil)
|
38
|
+
if priority && PRIORITIES.has_key?(priority)
|
39
|
+
@priority = priority
|
40
|
+
end
|
41
|
+
@priority || :normal
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.<=>(other)
|
45
|
+
PRIORITIES[other.priority] <=> PRIORITIES[self.priority]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
data/lib/howl/post.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
module Howl
|
2
|
+
class Post < Template
|
3
|
+
include Comparable
|
4
|
+
|
5
|
+
def date
|
6
|
+
view.date? ? Time.parse(view.date) : File.mtime(path)
|
7
|
+
end
|
8
|
+
|
9
|
+
def <=>(other)
|
10
|
+
self.date <=> other.date
|
11
|
+
end
|
12
|
+
|
13
|
+
def output_path
|
14
|
+
site.path("site/posts") + date.strftime("%Y/%m/%d") + output_filename
|
15
|
+
end
|
16
|
+
|
17
|
+
def title
|
18
|
+
view.title || path.basename(extension).to_s
|
19
|
+
end
|
20
|
+
|
21
|
+
def dom_id
|
22
|
+
title.slugify
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/howl/site.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
module Howl
|
2
|
+
class Site
|
3
|
+
attr_accessor :root
|
4
|
+
|
5
|
+
def initialize(root)
|
6
|
+
@root = Pathname.new(root)
|
7
|
+
end
|
8
|
+
|
9
|
+
def path(path)
|
10
|
+
root + path
|
11
|
+
end
|
12
|
+
|
13
|
+
def pages
|
14
|
+
@pages ||= Dir[path "pages/**/*.*"].map { |path| Page.new(path, self) }
|
15
|
+
end
|
16
|
+
|
17
|
+
def posts
|
18
|
+
@posts ||= Dir[path "posts/**/*.*"].map { |path| Post.new(path, self) }.sort
|
19
|
+
end
|
20
|
+
|
21
|
+
def templates
|
22
|
+
@templates ||= Hash[Dir[root + "templates/*"].map { |path|
|
23
|
+
[Pathname.new(path).relative_path_from(path "templates").to_s,
|
24
|
+
Template.new(path, self)]
|
25
|
+
}]
|
26
|
+
end
|
27
|
+
|
28
|
+
def write_to_disk
|
29
|
+
FileUtils.rm_r(path "site") if File.exist?(path "site")
|
30
|
+
#raise (pages + posts).map(&:class).inspect
|
31
|
+
(pages + posts).each do |page|
|
32
|
+
FileUtils.makedirs(page.output_path.dirname)
|
33
|
+
page.output_path.open("w") do |fh|
|
34
|
+
fh.write page.render
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module Howl
|
2
|
+
class Template
|
3
|
+
attr_accessor :view, :content, :site, :path, :extension
|
4
|
+
|
5
|
+
def initialize(path, site)
|
6
|
+
@site = site
|
7
|
+
@path = Pathname.new(path)
|
8
|
+
@extension = @path.extname
|
9
|
+
load_file
|
10
|
+
end
|
11
|
+
|
12
|
+
def ==(other)
|
13
|
+
self.path == other.path && self.class == other.class
|
14
|
+
end
|
15
|
+
|
16
|
+
def output_filename
|
17
|
+
path.basename.sub(/#{extension}$/, converter.extension)
|
18
|
+
end
|
19
|
+
|
20
|
+
def converter
|
21
|
+
unless @converter
|
22
|
+
converter_class = Converter.subclasses.find do |converter|
|
23
|
+
converter.matches? @extension
|
24
|
+
end
|
25
|
+
converter_class ||= Converter
|
26
|
+
|
27
|
+
@converter = converter_class.new(self)
|
28
|
+
end
|
29
|
+
|
30
|
+
@converter
|
31
|
+
end
|
32
|
+
|
33
|
+
def render(render_view = View.new)
|
34
|
+
render_view.merge!(@view)
|
35
|
+
rendered = converter.convert(Mustache.render(@content, render_view))
|
36
|
+
template = render_view.delete("template")
|
37
|
+
|
38
|
+
if template
|
39
|
+
if @site.templates[template + @extension]
|
40
|
+
rendered = @site.templates[template + @extension].render(
|
41
|
+
render_view.merge("content" => rendered))
|
42
|
+
else
|
43
|
+
puts "Warning: Template #{template + @extension} does not exist in file #{path}"
|
44
|
+
rendered
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
rendered
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def load_file
|
54
|
+
content = @path.read
|
55
|
+
view, content = content.split("\n\n", 2)
|
56
|
+
|
57
|
+
if test_for_yaml(view)
|
58
|
+
@content = content
|
59
|
+
view = YAML.load(view)
|
60
|
+
else
|
61
|
+
@content = "#{view}\n\n#{content}".strip
|
62
|
+
view = {}
|
63
|
+
end
|
64
|
+
|
65
|
+
@view = View.new(view.merge(:site => site))
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_for_yaml(view)
|
69
|
+
begin
|
70
|
+
view = YAML.load(view)
|
71
|
+
view.is_a?(Hash)
|
72
|
+
rescue ArgumentError
|
73
|
+
false
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
data/lib/howl/view.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'hashie'
|
2
|
+
|
3
|
+
module Howl
|
4
|
+
class View < Hashie::Mash
|
5
|
+
def has_key?(key)
|
6
|
+
key?(key) || respond_to?(key)
|
7
|
+
end
|
8
|
+
|
9
|
+
def [](key)
|
10
|
+
super || (respond_to?(key) && send(key))
|
11
|
+
end
|
12
|
+
|
13
|
+
def posts
|
14
|
+
if site? && site.respond_to?(:posts)
|
15
|
+
site.posts
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/howl.rb
CHANGED
@@ -1,131 +1,19 @@
|
|
1
1
|
require 'yaml'
|
2
|
-
require 'rdiscount'
|
3
2
|
require 'mustache'
|
4
|
-
require 'hashie'
|
5
3
|
require 'pathname'
|
6
4
|
require 'fileutils'
|
7
5
|
require 'time'
|
8
6
|
|
9
7
|
$:.unshift File.dirname(__FILE__)
|
10
8
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
def initialize(root)
|
16
|
-
@root = Pathname.new(root)
|
17
|
-
end
|
18
|
-
|
19
|
-
def path(path)
|
20
|
-
root + path
|
21
|
-
end
|
22
|
-
|
23
|
-
def pages
|
24
|
-
@pages ||= Dir[path "pages/*"].map { |path| Page.new(path, self) }
|
25
|
-
end
|
26
|
-
|
27
|
-
def posts
|
28
|
-
@posts ||= Dir[path "posts/*"].map { |path| Post.new(path, self) }.sort
|
29
|
-
end
|
30
|
-
|
31
|
-
def templates
|
32
|
-
@templates ||= Hash[Dir[root + "templates/*"].map { |path|
|
33
|
-
[Pathname.new(path).relative_path_from(path "templates").to_s,
|
34
|
-
Template.new(path, self)]
|
35
|
-
}]
|
36
|
-
end
|
37
|
-
|
38
|
-
def write_to_disk
|
39
|
-
FileUtils.rm_r(path "site") if File.exist?(path "site")
|
40
|
-
#raise (pages + posts).map(&:class).inspect
|
41
|
-
(pages + posts).each do |page|
|
42
|
-
FileUtils.makedirs(page.output_path.dirname)
|
43
|
-
page.output_path.open("w") do |fh|
|
44
|
-
fh.write page.render
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
class View < Hashie::Mash
|
9
|
+
def require_all(path)
|
10
|
+
Dir[File.join(File.dirname(__FILE__), path, '*.rb')].each do |f|
|
11
|
+
require f
|
51
12
|
end
|
13
|
+
end
|
52
14
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
def initialize(path, site)
|
57
|
-
@site = site
|
58
|
-
@path = Pathname.new(path)
|
59
|
-
@extension = @path.extname
|
60
|
-
load_file
|
61
|
-
end
|
62
|
-
|
63
|
-
def ==(other)
|
64
|
-
self.path == other.path && self.class == other.class
|
65
|
-
end
|
66
|
-
|
67
|
-
def render(render_view = {})
|
68
|
-
render_view.merge!(@view)
|
69
|
-
rendered = Mustache.render(@content, render_view)
|
70
|
-
template = render_view.delete("template")
|
71
|
-
if template
|
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
|
78
|
-
end
|
79
|
-
|
80
|
-
rendered
|
81
|
-
end
|
82
|
-
|
83
|
-
private
|
84
|
-
|
85
|
-
def load_file
|
86
|
-
content = @path.read
|
87
|
-
view, content = content.split("\n\n", 2)
|
88
|
-
|
89
|
-
if test_for_yaml(view)
|
90
|
-
@content = content
|
91
|
-
view = YAML.load(view)
|
92
|
-
else
|
93
|
-
@content = "#{view}\n\n#{content}".strip
|
94
|
-
view = {}
|
95
|
-
end
|
96
|
-
|
97
|
-
@view = View.new(view.merge(:site => site))
|
98
|
-
end
|
99
|
-
|
100
|
-
def test_for_yaml(view)
|
101
|
-
begin
|
102
|
-
view = YAML.load(view)
|
103
|
-
view.is_a?(Hash)
|
104
|
-
rescue ArgumentError
|
105
|
-
false
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
class Page < Template
|
111
|
-
def output_path
|
112
|
-
site.path("site") + path.relative_path_from(site.path "pages")
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
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
|
130
|
-
end
|
15
|
+
%w(core_ext plugin converter site template page post view).each do |file|
|
16
|
+
require "howl/#{file}"
|
131
17
|
end
|
18
|
+
|
19
|
+
require_all "howl/converters"
|
data/test/howl_test.rb
CHANGED
@@ -5,7 +5,7 @@ context "Site" do
|
|
5
5
|
setup { @site = Site.new(fixture_path) }
|
6
6
|
|
7
7
|
should("find all pages") {
|
8
|
-
topic.pages == Dir[fixture_path("pages
|
8
|
+
topic.pages == Dir[fixture_path("pages/**/*.*")].map { |path| Page.new(path, topic) }
|
9
9
|
}
|
10
10
|
|
11
11
|
should("write out all pages") {
|
@@ -18,7 +18,9 @@ context "Site" do
|
|
18
18
|
should("write out all posts") {
|
19
19
|
topic.write_to_disk
|
20
20
|
topic.posts.map { |post|
|
21
|
-
Dir[topic.path("site/posts") + "
|
21
|
+
Dir[topic.path("site/posts") + "**/*.*"].map { |path|
|
22
|
+
File.basename(path, File.extname(path))
|
23
|
+
}.include?(post.path.basename(post.extension).to_s)
|
22
24
|
}.all?
|
23
25
|
}
|
24
26
|
|
@@ -60,6 +62,17 @@ context "Site" do
|
|
60
62
|
</html>
|
61
63
|
].clean
|
62
64
|
end
|
65
|
+
|
66
|
+
context "index.html" do
|
67
|
+
setup { Page.new(fixture_path("pages/index.html"), @site) }
|
68
|
+
|
69
|
+
should "show all posts" do
|
70
|
+
doc = Nokogiri.parse(topic.render)
|
71
|
+
@site.posts.map { |post|
|
72
|
+
doc.search("div##{post.dom_id}").empty?
|
73
|
+
}.none?
|
74
|
+
end
|
75
|
+
end
|
63
76
|
end
|
64
77
|
|
65
78
|
context "Post" do
|
@@ -79,5 +92,13 @@ context "Site" do
|
|
79
92
|
asserts("date is equal to file's mtime") { topic.date == File.mtime(topic.path) }
|
80
93
|
end
|
81
94
|
end
|
95
|
+
|
96
|
+
context "A Post in Markdown" do
|
97
|
+
setup { Post.new(fixture_path("posts/markdown_post.md"), @site) }
|
98
|
+
|
99
|
+
should "convert to HTML" do
|
100
|
+
topic.render == RDiscount.new(topic.content).to_html
|
101
|
+
end
|
102
|
+
end
|
82
103
|
end
|
83
104
|
|
data/test/teststrap.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'riot'
|
3
|
+
require 'nokogiri'
|
3
4
|
|
4
5
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
5
6
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
@@ -14,3 +15,9 @@ class String
|
|
14
15
|
self.strip.gsub(/\n+/, "\n")
|
15
16
|
end
|
16
17
|
end
|
18
|
+
|
19
|
+
class Mustache
|
20
|
+
def self.raise_on_context_miss?
|
21
|
+
true
|
22
|
+
end
|
23
|
+
end
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
7
|
+
- 3
|
8
8
|
- 0
|
9
|
-
version: 0.
|
9
|
+
version: 0.3.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-
|
17
|
+
date: 2010-10-17 00:00:00 -04:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -32,7 +32,7 @@ dependencies:
|
|
32
32
|
type: :development
|
33
33
|
version_requirements: *id001
|
34
34
|
- !ruby/object:Gem::Dependency
|
35
|
-
name:
|
35
|
+
name: nokogiri
|
36
36
|
prerelease: false
|
37
37
|
requirement: &id002 !ruby/object:Gem::Requirement
|
38
38
|
none: false
|
@@ -42,10 +42,10 @@ dependencies:
|
|
42
42
|
segments:
|
43
43
|
- 0
|
44
44
|
version: "0"
|
45
|
-
type: :
|
45
|
+
type: :development
|
46
46
|
version_requirements: *id002
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
|
-
name:
|
48
|
+
name: rdiscount
|
49
49
|
prerelease: false
|
50
50
|
requirement: &id003 !ruby/object:Gem::Requirement
|
51
51
|
none: false
|
@@ -58,7 +58,7 @@ dependencies:
|
|
58
58
|
type: :runtime
|
59
59
|
version_requirements: *id003
|
60
60
|
- !ruby/object:Gem::Dependency
|
61
|
-
name:
|
61
|
+
name: mustache
|
62
62
|
prerelease: false
|
63
63
|
requirement: &id004 !ruby/object:Gem::Requirement
|
64
64
|
none: false
|
@@ -70,6 +70,32 @@ dependencies:
|
|
70
70
|
version: "0"
|
71
71
|
type: :runtime
|
72
72
|
version_requirements: *id004
|
73
|
+
- !ruby/object:Gem::Dependency
|
74
|
+
name: hashie
|
75
|
+
prerelease: false
|
76
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
77
|
+
none: false
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
segments:
|
82
|
+
- 0
|
83
|
+
version: "0"
|
84
|
+
type: :runtime
|
85
|
+
version_requirements: *id005
|
86
|
+
- !ruby/object:Gem::Dependency
|
87
|
+
name: haml
|
88
|
+
prerelease: false
|
89
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
90
|
+
none: false
|
91
|
+
requirements:
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
segments:
|
95
|
+
- 0
|
96
|
+
version: "0"
|
97
|
+
type: :runtime
|
98
|
+
version_requirements: *id006
|
73
99
|
description: Howl is a tiny static website/blog generator.
|
74
100
|
email: crnixon@gmail.com
|
75
101
|
executables: []
|
@@ -82,22 +108,32 @@ extra_rdoc_files:
|
|
82
108
|
files:
|
83
109
|
- .gitignore
|
84
110
|
- Gemfile
|
111
|
+
- Gemfile.lock
|
85
112
|
- LICENSE
|
86
113
|
- README.markdown
|
87
114
|
- Rakefile
|
88
115
|
- VERSION
|
89
116
|
- howl.gemspec
|
90
117
|
- lib/howl.rb
|
118
|
+
- lib/howl/converter.rb
|
119
|
+
- lib/howl/converters/markdown.rb
|
120
|
+
- lib/howl/converters/sass.rb
|
121
|
+
- lib/howl/core_ext.rb
|
122
|
+
- lib/howl/page.rb
|
123
|
+
- lib/howl/plugin.rb
|
124
|
+
- lib/howl/post.rb
|
125
|
+
- lib/howl/site.rb
|
126
|
+
- lib/howl/template.rb
|
127
|
+
- lib/howl/view.rb
|
128
|
+
- test/fixtures/pages/css/modules/colors.scss
|
129
|
+
- test/fixtures/pages/css/screen.scss
|
91
130
|
- test/fixtures/pages/has_template.html
|
131
|
+
- test/fixtures/pages/index.html
|
92
132
|
- test/fixtures/pages/no_yaml.html
|
93
133
|
- test/fixtures/pages/simple.html
|
94
134
|
- test/fixtures/posts/first_post.html
|
135
|
+
- test/fixtures/posts/markdown_post.md
|
95
136
|
- test/fixtures/posts/no_date.html
|
96
|
-
- test/fixtures/site/has_template.html
|
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
|
100
|
-
- test/fixtures/site/simple.html
|
101
137
|
- test/fixtures/templates/alt.html
|
102
138
|
- test/fixtures/templates/default.html
|
103
139
|
- test/fixtures/templates/post.html
|
@@ -1 +0,0 @@
|
|
1
|
-
This page has no YAML front-matter.
|
@@ -1 +0,0 @@
|
|
1
|
-
This post has no date in its YAML front-matter.
|
@@ -1 +0,0 @@
|
|
1
|
-
<h1>This is a simple page</h1>
|