pith 0.0.6 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +28 -6
- data/bin/pith +35 -9
- data/features/metadata.feature +2 -2
- data/features/relative_linking.feature +67 -0
- data/features/{verbatim.feature → resources.feature} +18 -4
- data/features/step_definitions/build_steps.rb +8 -0
- data/lib/pith/console_logger.rb +0 -4
- data/lib/pith/input/abstract.rb +5 -5
- data/lib/pith/input/{verbatim.rb → resource.rb} +1 -1
- data/lib/pith/input/template.rb +4 -0
- data/lib/pith/input/template.rb~ +3 -7
- data/lib/pith/input.rb +2 -2
- data/lib/pith/pathname_ext.rb +14 -0
- data/lib/pith/project.rb +23 -7
- data/lib/pith/reference_error.rb +5 -0
- data/lib/pith/render_context.rb +29 -23
- data/lib/pith/render_context.rb~ +7 -6
- data/lib/pith/server.rb +17 -12
- data/lib/pith/version.rb +1 -1
- data/lib/pith/version.rb~ +1 -1
- data/spec/pith/input/template_spec.rb +48 -0
- data/spec/pith/project_spec.rb +28 -6
- data/spec/spec_helper.rb +0 -10
- metadata +11 -9
- data/spec/pith/input/abstract_spec.rb +0 -31
data/README.markdown
CHANGED
@@ -6,15 +6,10 @@ Pith is a static website generator, written in Ruby.
|
|
6
6
|
Using Pith, you can:
|
7
7
|
|
8
8
|
* Lay-out your page designs in [Haml][haml], ERb, or Liquid.
|
9
|
-
|
10
9
|
* Style things up using [Sass][sass].
|
11
|
-
|
12
10
|
* Succintly add content using Markdown or Textile.
|
13
|
-
|
14
11
|
* Encapsulate common markup in "layout" and "partial" templates.
|
15
|
-
|
16
12
|
* Easily link pages (and resources) using relative links.
|
17
|
-
|
18
13
|
* Test changes quickly using the built-in web-server.
|
19
14
|
|
20
15
|
Install it
|
@@ -35,7 +30,7 @@ Create an input directory for your site (wherever you want), and pop some files
|
|
35
30
|
logo.png
|
36
31
|
index.html.haml
|
37
32
|
|
38
|
-
The only requirement is the existance of a sub-directory called "`_pith`". Pith checks that it's present, to prevent you accidently treating
|
33
|
+
The only requirement is the existance of a sub-directory called "`_pith`". Pith checks that it's present, to prevent you accidently treating your entire home-directory as website input.
|
39
34
|
|
40
35
|
Next, use the `pith build` command to convert your inputs into a functioning website.
|
41
36
|
|
@@ -55,6 +50,25 @@ Any input file with an extension recognised by [Tilt][tilt] is considered to be
|
|
55
50
|
|
56
51
|
Anything else is just copied verbatim into the generated site.
|
57
52
|
|
53
|
+
Page metadata
|
54
|
+
-------------
|
55
|
+
|
56
|
+
A YAML header can be provided at the top of any template, defining page metadata. The header is introduced by a first line containing three dashes, and terminated by a line containing three dots.
|
57
|
+
|
58
|
+
---
|
59
|
+
title: "All about fish"
|
60
|
+
...
|
61
|
+
|
62
|
+
Metadata provided in the header can be referenced by template content, via the "`page`" object:
|
63
|
+
|
64
|
+
%html
|
65
|
+
%head
|
66
|
+
%title= page.title
|
67
|
+
%body
|
68
|
+
%h1= page.title
|
69
|
+
|
70
|
+
This is especially useful in "layout" templates (see below).
|
71
|
+
|
58
72
|
Partials
|
59
73
|
--------
|
60
74
|
|
@@ -92,6 +106,14 @@ Use "`yield`" to embed the block's content within the layout:
|
|
92
106
|
.main
|
93
107
|
= yield
|
94
108
|
|
109
|
+
Layouts can also be specified using a "`layout`" entry in the page header, e.g.
|
110
|
+
|
111
|
+
---
|
112
|
+
layout: "/_mylayout.haml"
|
113
|
+
...
|
114
|
+
|
115
|
+
Some content
|
116
|
+
|
95
117
|
Relative links
|
96
118
|
--------------
|
97
119
|
|
data/bin/pith
CHANGED
@@ -8,15 +8,17 @@ require "pathname"
|
|
8
8
|
require "pith/version"
|
9
9
|
|
10
10
|
$input_dir = Pathname(".")
|
11
|
+
$interval = 2
|
12
|
+
$port = 4321
|
11
13
|
|
12
14
|
BANNER = <<EOF
|
13
15
|
usage: pith [OPTIONS] [COMMAND]
|
14
16
|
|
15
17
|
Commands: (default: "build")
|
16
18
|
|
17
|
-
build Generate the website into OUTPUT_DIR
|
18
|
-
|
19
|
-
serve Serve the website
|
19
|
+
build Generate the website (into OUTPUT_DIR)
|
20
|
+
watch Monitor INPUT_DIR, and incrementally rebuild OUTPUT_DIR
|
21
|
+
serve Serve the generated website at "http://localhost:#{$port}"
|
20
22
|
|
21
23
|
EOF
|
22
24
|
|
@@ -24,12 +26,18 @@ OptionParser.new do |opts|
|
|
24
26
|
opts.banner = BANNER
|
25
27
|
opts.version = Pith::VERSION
|
26
28
|
opts.separator " Options:"
|
27
|
-
opts.on("-i", "--input INPUT_DIR",
|
29
|
+
opts.on("-i", "--input INPUT_DIR", %[Input directory (default: ".")]) do |dir|
|
28
30
|
$input_dir = Pathname(dir)
|
29
31
|
end
|
30
|
-
opts.on("-o", "--output OUTPUT_DIR",
|
32
|
+
opts.on("-o", "--output OUTPUT_DIR", %[Output directory (default: "INPUT_DIR/_out")]) do |dir|
|
31
33
|
$output_dir = Pathname(dir)
|
32
34
|
end
|
35
|
+
opts.on("-n", "--interval N", Integer, %[Rebuild interval (default: #{$interval})]) do |n|
|
36
|
+
$interval = n
|
37
|
+
end
|
38
|
+
opts.on("-p", "--port N", Integer, %[Web-server port (default: #{$port})]) do |port|
|
39
|
+
$port = port
|
40
|
+
end
|
33
41
|
opts.on_tail("-h", "--help", "Show this message") do
|
34
42
|
puts opts
|
35
43
|
exit
|
@@ -46,6 +54,8 @@ unless $output_dir
|
|
46
54
|
$output_dir = $input_dir + "_out"
|
47
55
|
end
|
48
56
|
|
57
|
+
puts %{Generating to "#{$output_dir}"}
|
58
|
+
|
49
59
|
require "pith/project"
|
50
60
|
require "pith/console_logger"
|
51
61
|
|
@@ -53,16 +63,32 @@ require "pith/console_logger"
|
|
53
63
|
@project.logger = Pith::ConsoleLogger.new
|
54
64
|
|
55
65
|
def build
|
56
|
-
puts %{Generating to "#{$output_dir}"}
|
57
66
|
@project.build
|
58
67
|
end
|
59
68
|
|
69
|
+
def watch
|
70
|
+
loop do
|
71
|
+
begin
|
72
|
+
build
|
73
|
+
rescue Exception => e
|
74
|
+
$stderr.puts "ERROR: #{e}"
|
75
|
+
e.backtrace.each { |line| $stderr.puts line }
|
76
|
+
end
|
77
|
+
sleep($interval)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
60
81
|
def serve
|
82
|
+
|
61
83
|
require "pith/server"
|
62
|
-
|
84
|
+
server = Pith::Server.new(@project)
|
85
|
+
|
63
86
|
build
|
64
|
-
|
65
|
-
|
87
|
+
Thread.new { watch }
|
88
|
+
|
89
|
+
puts %{>>> Now taking the Pith at "http://localhost:#{$port}"}
|
90
|
+
Rack::Handler.default.run(server, :Port => $port)
|
91
|
+
|
66
92
|
end
|
67
93
|
|
68
94
|
action = ARGV.shift || "build"
|
data/features/metadata.feature
CHANGED
@@ -10,7 +10,7 @@ Scenario: use meta-data from YAML comment
|
|
10
10
|
---
|
11
11
|
title: PAGE TITLE
|
12
12
|
---
|
13
|
-
%h1= meta["title"]
|
13
|
+
%h1= page.meta["title"]
|
14
14
|
"""
|
15
15
|
|
16
16
|
When I build the site
|
@@ -24,7 +24,7 @@ Scenario: corrupt meta-data
|
|
24
24
|
Given input file "page.html.haml" contains
|
25
25
|
"""
|
26
26
|
---
|
27
|
-
title: "This" is
|
27
|
+
title: "This" is not well-formed YAML
|
28
28
|
...
|
29
29
|
%p PAGE BODY
|
30
30
|
"""
|
@@ -3,6 +3,11 @@ Feature: linking between files
|
|
3
3
|
I want to be able to generate relative reference to other pages
|
4
4
|
So that the generated site is re-locateable
|
5
5
|
|
6
|
+
Background:
|
7
|
+
|
8
|
+
Given the "assume_content_negotiation" flag is disabled
|
9
|
+
And the "assume_directory_index" flag is disabled
|
10
|
+
|
6
11
|
Scenario: link from one top-level page to another
|
7
12
|
|
8
13
|
Given input file "index.html.haml" contains
|
@@ -107,3 +112,65 @@ Scenario: use "title" meta-data attribute in link
|
|
107
112
|
"""
|
108
113
|
<a href="page.html">Title from meta-data</a>
|
109
114
|
"""
|
115
|
+
|
116
|
+
Scenario: link to an Input object
|
117
|
+
|
118
|
+
Given input file "subdir/page.html.haml" contains
|
119
|
+
"""
|
120
|
+
= link(project.input("help.html"))
|
121
|
+
"""
|
122
|
+
|
123
|
+
And input file "help.html.haml" contains
|
124
|
+
"""
|
125
|
+
---
|
126
|
+
title: "Help!"
|
127
|
+
...
|
128
|
+
"""
|
129
|
+
|
130
|
+
When I build the site
|
131
|
+
Then output file "subdir/page.html" should contain
|
132
|
+
"""
|
133
|
+
<a href="../help.html">Help!</a>
|
134
|
+
"""
|
135
|
+
|
136
|
+
Scenario: link to a missing resource
|
137
|
+
|
138
|
+
Given input file "index.html.haml" contains
|
139
|
+
"""
|
140
|
+
= link("missing_page.html")
|
141
|
+
"""
|
142
|
+
|
143
|
+
When I build the site
|
144
|
+
Then output file "index.html" should contain
|
145
|
+
"""
|
146
|
+
<a href="missing_page.html">???</a>
|
147
|
+
"""
|
148
|
+
|
149
|
+
Scenario: assume content negotiation
|
150
|
+
|
151
|
+
Given the "assume_content_negotiation" flag is enabled
|
152
|
+
And input file "index.html.haml" contains
|
153
|
+
"""
|
154
|
+
= link("page.html", "Page")
|
155
|
+
"""
|
156
|
+
|
157
|
+
When I build the site
|
158
|
+
Then output file "index.html" should contain
|
159
|
+
"""
|
160
|
+
<a href="page">Page</a>
|
161
|
+
"""
|
162
|
+
|
163
|
+
Scenario: link to an index page
|
164
|
+
|
165
|
+
Given the "assume_directory_index" flag is enabled
|
166
|
+
|
167
|
+
And input file "page.html.haml" contains
|
168
|
+
"""
|
169
|
+
= link("stuff/index.html", "Stuff")
|
170
|
+
"""
|
171
|
+
|
172
|
+
When I build the site
|
173
|
+
Then output file "page.html" should contain
|
174
|
+
"""
|
175
|
+
<a href="stuff/">Stuff</a>
|
176
|
+
"""
|
@@ -5,28 +5,42 @@ Feature: unrecognised input files are copied into output intact
|
|
5
5
|
|
6
6
|
Scenario: text file
|
7
7
|
|
8
|
-
Given input file "
|
8
|
+
Given input file "resource.txt" contains
|
9
9
|
"""
|
10
10
|
Blah de blah
|
11
11
|
"""
|
12
12
|
|
13
13
|
When I build the site
|
14
14
|
|
15
|
-
Then output file "
|
15
|
+
Then output file "resource.txt" should contain
|
16
16
|
"""
|
17
17
|
Blah de blah
|
18
18
|
"""
|
19
19
|
|
20
20
|
Scenario: file in subdirectory
|
21
21
|
|
22
|
-
Given input file "blah/
|
22
|
+
Given input file "blah/resource.txt" contains
|
23
23
|
"""
|
24
24
|
Blah de blah
|
25
25
|
"""
|
26
26
|
|
27
27
|
When I build the site
|
28
28
|
|
29
|
-
Then output file "blah/
|
29
|
+
Then output file "blah/resource.txt" should contain
|
30
30
|
"""
|
31
31
|
Blah de blah
|
32
32
|
"""
|
33
|
+
|
34
|
+
Scenario: dot-file
|
35
|
+
|
36
|
+
Given input file ".htaccess" contains
|
37
|
+
"""
|
38
|
+
DirectoryIndex index.html
|
39
|
+
"""
|
40
|
+
|
41
|
+
When I build the site
|
42
|
+
|
43
|
+
Then output file ".htaccess" should contain
|
44
|
+
"""
|
45
|
+
DirectoryIndex index.html
|
46
|
+
"""
|
@@ -14,6 +14,14 @@ Given "the site is up-to-date" do
|
|
14
14
|
When "I build the site"
|
15
15
|
end
|
16
16
|
|
17
|
+
Given /^the "([^\"]*)" flag is enabled$/ do |flag|
|
18
|
+
@project.send("#{flag}=", true)
|
19
|
+
end
|
20
|
+
|
21
|
+
Given /^the "([^\"]*)" flag is disabled$/ do |flag|
|
22
|
+
@project.send("#{flag}=", false)
|
23
|
+
end
|
24
|
+
|
17
25
|
When /^I change input file "([^\"]*)" to contain "([^\"]*)"$/ do |path, content|
|
18
26
|
@inputs[path] = content
|
19
27
|
end
|
data/lib/pith/console_logger.rb
CHANGED
data/lib/pith/input/abstract.rb
CHANGED
@@ -20,11 +20,15 @@ module Pith
|
|
20
20
|
project.input_dir + path
|
21
21
|
end
|
22
22
|
|
23
|
+
# Public: Get the file-system location of the corresponding output file.
|
24
|
+
#
|
25
|
+
# Returns a fully-qualified Pathname.
|
26
|
+
#
|
23
27
|
def output_file
|
24
28
|
project.output_dir + output_path
|
25
29
|
end
|
26
30
|
|
27
|
-
# Public: Generate
|
31
|
+
# Public: Generate an output file.
|
28
32
|
#
|
29
33
|
def build
|
30
34
|
return false if ignorable? || uptodate?
|
@@ -59,10 +63,6 @@ module Pith
|
|
59
63
|
end
|
60
64
|
|
61
65
|
protected
|
62
|
-
|
63
|
-
def default_title
|
64
|
-
path.to_s.sub(/\..*/, '').tr('_-', ' ').capitalize
|
65
|
-
end
|
66
66
|
|
67
67
|
def logger
|
68
68
|
project.logger
|
data/lib/pith/input/template.rb
CHANGED
data/lib/pith/input/template.rb~
CHANGED
@@ -28,7 +28,7 @@ module Pith
|
|
28
28
|
# Return true unless output needs to be re-generated.
|
29
29
|
#
|
30
30
|
def uptodate?
|
31
|
-
|
31
|
+
dependencies && FileUtils.uptodate?(output_file, dependencies)
|
32
32
|
end
|
33
33
|
|
34
34
|
# Generate output for this template
|
@@ -39,7 +39,7 @@ module Pith
|
|
39
39
|
output_file.open("w") do |out|
|
40
40
|
out.puts(render_context.render(self))
|
41
41
|
end
|
42
|
-
|
42
|
+
@dependencies = render_context.dependencies
|
43
43
|
end
|
44
44
|
|
45
45
|
# Render this input using Tilt
|
@@ -112,11 +112,7 @@ module Pith
|
|
112
112
|
end
|
113
113
|
end
|
114
114
|
|
115
|
-
|
116
|
-
@all_input_files = referenced_inputs.map { |input| input.file }
|
117
|
-
end
|
118
|
-
|
119
|
-
attr_accessor :all_input_files
|
115
|
+
attr_accessor :dependencies
|
120
116
|
|
121
117
|
end
|
122
118
|
|
data/lib/pith/input.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
require "pith/input/template"
|
2
|
-
require "pith/input/
|
2
|
+
require "pith/input/resource"
|
3
3
|
|
4
4
|
module Pith
|
5
5
|
module Input
|
@@ -9,7 +9,7 @@ module Pith
|
|
9
9
|
def new(project, path)
|
10
10
|
Template.new(project, path)
|
11
11
|
rescue Template::UnrecognisedType
|
12
|
-
|
12
|
+
Resource.new(project, path)
|
13
13
|
end
|
14
14
|
|
15
15
|
end
|
data/lib/pith/project.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
|
-
require "pathname"
|
2
1
|
require "logger"
|
3
2
|
require "pith/input"
|
3
|
+
require "pith/pathname_ext"
|
4
|
+
require "pith/reference_error"
|
4
5
|
require "tilt"
|
5
6
|
|
6
7
|
module Pith
|
@@ -13,8 +14,20 @@ module Pith
|
|
13
14
|
end
|
14
15
|
end
|
15
16
|
|
16
|
-
|
17
|
+
attr_reader :input_dir
|
17
18
|
|
19
|
+
attr_accessor :output_dir
|
20
|
+
attr_accessor :assume_content_negotiation
|
21
|
+
attr_accessor :assume_directory_index
|
22
|
+
|
23
|
+
def input_dir=(dir)
|
24
|
+
@input_dir = Pathname(dir)
|
25
|
+
end
|
26
|
+
|
27
|
+
def output_dir=(dir)
|
28
|
+
@output_dir = Pathname(dir)
|
29
|
+
end
|
30
|
+
|
18
31
|
# Public: get inputs
|
19
32
|
#
|
20
33
|
# Returns Pith::Input objects representing the files in the input_dir.
|
@@ -23,7 +36,7 @@ module Pith
|
|
23
36
|
# call #refresh to discard the cached data.
|
24
37
|
#
|
25
38
|
def inputs
|
26
|
-
@inputs ||=
|
39
|
+
@inputs ||= input_dir.glob_all("**/*").map do |input_file|
|
27
40
|
next if input_file.directory?
|
28
41
|
path = input_file.relative_path_from(input_dir)
|
29
42
|
find_or_create_input(path)
|
@@ -42,7 +55,7 @@ module Pith
|
|
42
55
|
inputs.each do |input|
|
43
56
|
return input if input.path == path || input.output_path == path
|
44
57
|
end
|
45
|
-
|
58
|
+
nil
|
46
59
|
end
|
47
60
|
|
48
61
|
# Public: build the project, generating output files.
|
@@ -53,6 +66,7 @@ module Pith
|
|
53
66
|
inputs.each do |input|
|
54
67
|
input.build
|
55
68
|
end
|
69
|
+
output_dir.touch
|
56
70
|
end
|
57
71
|
|
58
72
|
# Public: discard cached data that is out-of-sync with the file-system.
|
@@ -62,6 +76,10 @@ module Pith
|
|
62
76
|
@config_files = nil
|
63
77
|
end
|
64
78
|
|
79
|
+
def last_built_at
|
80
|
+
output_dir.mtime
|
81
|
+
end
|
82
|
+
|
65
83
|
def logger
|
66
84
|
@logger ||= Logger.new(nil)
|
67
85
|
end
|
@@ -78,7 +96,7 @@ module Pith
|
|
78
96
|
|
79
97
|
def config_files
|
80
98
|
@config_files ||= begin
|
81
|
-
|
99
|
+
input_dir.glob_all("_pith/**")
|
82
100
|
end.to_set
|
83
101
|
end
|
84
102
|
|
@@ -105,7 +123,5 @@ module Pith
|
|
105
123
|
end
|
106
124
|
|
107
125
|
end
|
108
|
-
|
109
|
-
class ReferenceError < StandardError; end
|
110
126
|
|
111
127
|
end
|
data/lib/pith/render_context.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
|
-
require "
|
1
|
+
require "ostruct"
|
2
2
|
require "pathname"
|
3
|
+
require "pith/reference_error"
|
4
|
+
require "set"
|
3
5
|
require "tilt"
|
4
6
|
|
5
7
|
module Pith
|
@@ -17,7 +19,7 @@ module Pith
|
|
17
19
|
|
18
20
|
attr_reader :project
|
19
21
|
|
20
|
-
def
|
22
|
+
def page
|
21
23
|
@input_stack.first
|
22
24
|
end
|
23
25
|
|
@@ -28,7 +30,7 @@ module Pith
|
|
28
30
|
def render(input, locals = {}, &block)
|
29
31
|
with_input(input) do
|
30
32
|
result = input.render(self, locals, &block)
|
31
|
-
layout_ref =
|
33
|
+
layout_ref = input.meta["layout"]
|
32
34
|
result = render_ref(layout_ref) { result } if layout_ref
|
33
35
|
result
|
34
36
|
end
|
@@ -50,37 +52,42 @@ module Pith
|
|
50
52
|
@content_for_hash ||= Hash.new { "" }
|
51
53
|
end
|
52
54
|
|
53
|
-
def
|
54
|
-
|
55
|
+
def relative_url_to(target_path)
|
56
|
+
url = target_path.relative_path_from(page.path.parent)
|
57
|
+
url = url.sub(/index\.html$/, "") if project.assume_directory_index
|
58
|
+
url = url.sub(/\.html$/, "") if project.assume_content_negotiation
|
59
|
+
url
|
55
60
|
end
|
56
61
|
|
57
62
|
def href(target_ref)
|
58
|
-
|
63
|
+
relative_url_to(resolve_reference(target_ref))
|
59
64
|
end
|
60
65
|
|
61
66
|
def link(target_ref, label = nil)
|
62
|
-
target_path =
|
63
|
-
label ||= begin
|
64
|
-
|
65
|
-
rescue
|
66
|
-
"???"
|
67
|
+
target_path = resolve_reference(target_ref)
|
68
|
+
label ||= begin
|
69
|
+
input(target_path).title
|
70
|
+
rescue ReferenceError
|
71
|
+
"???"
|
67
72
|
end
|
68
|
-
|
73
|
+
url = relative_url_to(target_path)
|
74
|
+
%{<a href="#{url}">#{label}</a>}
|
69
75
|
end
|
70
76
|
|
71
77
|
private
|
72
78
|
|
73
|
-
def
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
+
def resolve_reference(ref)
|
80
|
+
if ref.respond_to?(:output_path)
|
81
|
+
ref.output_path
|
82
|
+
else
|
83
|
+
current_input.resolve_path(ref)
|
84
|
+
end
|
79
85
|
end
|
80
86
|
|
81
|
-
def
|
87
|
+
def input(path)
|
82
88
|
input = project.input(path)
|
83
|
-
|
89
|
+
raise(ReferenceError, %{Can't find "#{path}"}) if input.nil?
|
90
|
+
@dependencies << input.file
|
84
91
|
input
|
85
92
|
end
|
86
93
|
|
@@ -95,9 +102,8 @@ module Pith
|
|
95
102
|
end
|
96
103
|
|
97
104
|
def render_ref(template_ref, locals = {}, &block)
|
98
|
-
|
99
|
-
|
100
|
-
render(template, locals, &block)
|
105
|
+
template_input = input(resolve_reference(template_ref))
|
106
|
+
render(template_input, locals, &block)
|
101
107
|
end
|
102
108
|
|
103
109
|
end
|
data/lib/pith/render_context.rb~
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require "set"
|
2
2
|
require "pathname"
|
3
|
+
require "ostruct"
|
3
4
|
require "tilt"
|
4
5
|
|
5
6
|
module Pith
|
@@ -11,7 +12,7 @@ module Pith
|
|
11
12
|
def initialize(project)
|
12
13
|
@project = project
|
13
14
|
@input_stack = []
|
14
|
-
@
|
15
|
+
@dependencies = project.config_files.dup
|
15
16
|
self.extend(project.helper_module)
|
16
17
|
end
|
17
18
|
|
@@ -34,7 +35,7 @@ module Pith
|
|
34
35
|
end
|
35
36
|
end
|
36
37
|
|
37
|
-
attr_reader :
|
38
|
+
attr_reader :dependencies
|
38
39
|
|
39
40
|
def include(template_ref, locals = {}, &block)
|
40
41
|
content_block = if block_given?
|
@@ -50,8 +51,8 @@ module Pith
|
|
50
51
|
@content_for_hash ||= Hash.new { "" }
|
51
52
|
end
|
52
53
|
|
53
|
-
def
|
54
|
-
initial_input.meta
|
54
|
+
def page
|
55
|
+
@page ||= OpenStruct.new(initial_input.meta)
|
55
56
|
end
|
56
57
|
|
57
58
|
def href(target_ref)
|
@@ -80,12 +81,12 @@ module Pith
|
|
80
81
|
|
81
82
|
def find_input(path)
|
82
83
|
input = project.input(path)
|
83
|
-
@
|
84
|
+
@dependencies << input.file if input
|
84
85
|
input
|
85
86
|
end
|
86
87
|
|
87
88
|
def with_input(input)
|
88
|
-
@
|
89
|
+
@dependencies << input.file
|
89
90
|
@input_stack.push(input)
|
90
91
|
begin
|
91
92
|
yield
|
data/lib/pith/server.rb
CHANGED
@@ -7,31 +7,36 @@ module Pith
|
|
7
7
|
|
8
8
|
def new(project)
|
9
9
|
Rack::Builder.new do
|
10
|
-
use Rack::CommonLogger
|
10
|
+
use Rack::CommonLogger
|
11
11
|
use Rack::ShowExceptions
|
12
12
|
use Rack::Lint
|
13
|
-
use Pith::Server::AutoBuild, project
|
14
13
|
use Adsf::Rack::IndexFileFinder, :root => project.output_dir
|
14
|
+
use Pith::Server::DefaultToHtml, project.output_dir
|
15
15
|
run Rack::Directory.new(project.output_dir)
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
def run(project, options = {})
|
20
|
-
Rack::Handler.get("thin").run(new(project), options)
|
21
|
-
end
|
22
|
-
|
23
19
|
extend self
|
24
|
-
|
25
|
-
class AutoBuild
|
26
20
|
|
27
|
-
|
28
|
-
|
29
|
-
|
21
|
+
class DefaultToHtml
|
22
|
+
|
23
|
+
def initialize(app, root)
|
24
|
+
@app = app
|
25
|
+
@root = root
|
30
26
|
end
|
31
27
|
|
32
28
|
def call(env)
|
33
|
-
|
29
|
+
|
30
|
+
path_info = ::Rack::Utils.unescape(env["PATH_INFO"])
|
31
|
+
file = "#{@root}#{path_info}"
|
32
|
+
unless File.exist?(file)
|
33
|
+
if File.exist?("#{file}.html")
|
34
|
+
env["PATH_INFO"] += ".html"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
34
38
|
@app.call(env)
|
39
|
+
|
35
40
|
end
|
36
41
|
|
37
42
|
end
|
data/lib/pith/version.rb
CHANGED
data/lib/pith/version.rb~
CHANGED
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require "pith/input/abstract"
|
3
|
+
require "pith/project"
|
4
|
+
|
5
|
+
describe Pith::Input::Template do
|
6
|
+
|
7
|
+
before do
|
8
|
+
$input_dir.mkpath
|
9
|
+
@project = Pith::Project.new(:input_dir => $input_dir)
|
10
|
+
end
|
11
|
+
|
12
|
+
def make_input(path)
|
13
|
+
input_file = $input_dir + path
|
14
|
+
input_file.parent.mkpath
|
15
|
+
input_file.open("w") do |io|
|
16
|
+
yield io if block_given?
|
17
|
+
end
|
18
|
+
@project.input(path)
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "#title" do
|
22
|
+
|
23
|
+
it "is based on last component of filename" do
|
24
|
+
@input = make_input("dir/some_page.html.haml")
|
25
|
+
@input.title.should == "Some page"
|
26
|
+
end
|
27
|
+
|
28
|
+
it "can be over-ridden in metadata" do
|
29
|
+
@input = make_input("dir/some_page.html.haml") do |i|
|
30
|
+
i.puts "---"
|
31
|
+
i.puts "title: Blah blah"
|
32
|
+
i.puts "..."
|
33
|
+
end
|
34
|
+
@input.title.should == "Blah blah"
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "#output_path" do
|
40
|
+
|
41
|
+
it "excludes the template-type extension" do
|
42
|
+
@input = make_input("dir/some_page.html.haml")
|
43
|
+
@input.output_path.should == Pathname("dir/some_page.html")
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
data/spec/pith/project_spec.rb
CHANGED
@@ -17,9 +17,9 @@ describe Pith::Project do
|
|
17
17
|
@input_file.touch
|
18
18
|
end
|
19
19
|
|
20
|
-
it "constructs an
|
20
|
+
it "constructs an Resource object" do
|
21
21
|
@input = @project.input("input.txt")
|
22
|
-
@input.should be_kind_of(Pith::Input::
|
22
|
+
@input.should be_kind_of(Pith::Input::Resource)
|
23
23
|
@input.file.should == @input_file
|
24
24
|
end
|
25
25
|
|
@@ -55,10 +55,8 @@ describe Pith::Project do
|
|
55
55
|
|
56
56
|
describe "(with an invalid input path)" do
|
57
57
|
|
58
|
-
it "
|
59
|
-
|
60
|
-
@project.input("bogus.path")
|
61
|
-
end.should raise_error(Pith::ReferenceError)
|
58
|
+
it "returns nil" do
|
59
|
+
@project.input("bogus.path").should be_nil
|
62
60
|
end
|
63
61
|
|
64
62
|
end
|
@@ -112,4 +110,28 @@ describe Pith::Project do
|
|
112
110
|
|
113
111
|
end
|
114
112
|
|
113
|
+
describe "when an input file is removed" do
|
114
|
+
|
115
|
+
before do
|
116
|
+
@input_file = $input_dir + "input.html.haml"
|
117
|
+
@input_file.touch(Time.now - 10)
|
118
|
+
end
|
119
|
+
|
120
|
+
describe "a second call to #input" do
|
121
|
+
it "returns nil" do
|
122
|
+
|
123
|
+
first_time = @project.input("input.html.haml")
|
124
|
+
first_time.should_not be_nil
|
125
|
+
|
126
|
+
FileUtils.rm(@input_file)
|
127
|
+
|
128
|
+
@project.refresh
|
129
|
+
second_time = @project.input("input.html.haml")
|
130
|
+
second_time.should be_nil
|
131
|
+
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
136
|
+
|
115
137
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,16 +1,6 @@
|
|
1
1
|
require "rubygems"
|
2
2
|
|
3
3
|
require "fileutils"
|
4
|
-
require "pathname"
|
5
|
-
|
6
|
-
class Pathname
|
7
|
-
|
8
|
-
def touch(mtime = nil)
|
9
|
-
FileUtils.touch(self.to_s)
|
10
|
-
utime(mtime, mtime) if mtime
|
11
|
-
end
|
12
|
-
|
13
|
-
end
|
14
4
|
|
15
5
|
$project_dir = Pathname(__FILE__).expand_path.parent.parent
|
16
6
|
$tmp_dir = $project_dir + "tmp"
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pith
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 17
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 7
|
10
|
+
version: 0.0.7
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Mike Williams
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-09-
|
18
|
+
date: 2010-09-09 00:00:00 +10:00
|
19
19
|
default_executable: pith
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -96,15 +96,17 @@ files:
|
|
96
96
|
- lib/pith/console_logger.rb~
|
97
97
|
- lib/pith/input/abstract.rb
|
98
98
|
- lib/pith/input/abstract.rb~
|
99
|
+
- lib/pith/input/resource.rb
|
99
100
|
- lib/pith/input/template.rb
|
100
101
|
- lib/pith/input/template.rb~
|
101
|
-
- lib/pith/input/verbatim.rb
|
102
102
|
- lib/pith/input/verbatim.rb~
|
103
103
|
- lib/pith/input.rb
|
104
104
|
- lib/pith/input.rb~
|
105
105
|
- lib/pith/metadata.rb~
|
106
|
+
- lib/pith/pathname_ext.rb
|
106
107
|
- lib/pith/project.rb
|
107
108
|
- lib/pith/project.rb~
|
109
|
+
- lib/pith/reference_error.rb
|
108
110
|
- lib/pith/render_context.rb
|
109
111
|
- lib/pith/render_context.rb~
|
110
112
|
- lib/pith/server.rb
|
@@ -122,8 +124,8 @@ files:
|
|
122
124
|
- sample/stylesheets/app.css.sass
|
123
125
|
- README.markdown
|
124
126
|
- Rakefile
|
125
|
-
- spec/pith/input/abstract_spec.rb
|
126
127
|
- spec/pith/input/abstract_spec.rb~
|
128
|
+
- spec/pith/input/template_spec.rb
|
127
129
|
- spec/pith/metadata_spec.rb~
|
128
130
|
- spec/pith/project_spec.rb
|
129
131
|
- spec/pith/project_spec.rb~
|
@@ -148,6 +150,7 @@ files:
|
|
148
150
|
- features/metadata.feature~
|
149
151
|
- features/relative_linking.feature
|
150
152
|
- features/relative_linking.feature~
|
153
|
+
- features/resources.feature
|
151
154
|
- features/step_definitions/build_steps.rb
|
152
155
|
- features/step_definitions/build_steps.rb~
|
153
156
|
- features/support/env.rb
|
@@ -156,7 +159,6 @@ files:
|
|
156
159
|
- features/support/rspec_matchers.rb~
|
157
160
|
- features/textile.feature
|
158
161
|
- features/textile.feature~
|
159
|
-
- features/verbatim.feature
|
160
162
|
- features/verbatim.feature~
|
161
163
|
- cucumber.yml
|
162
164
|
- bin/pith
|
@@ -196,8 +198,8 @@ specification_version: 3
|
|
196
198
|
summary: A static website generator
|
197
199
|
test_files:
|
198
200
|
- Rakefile
|
199
|
-
- spec/pith/input/abstract_spec.rb
|
200
201
|
- spec/pith/input/abstract_spec.rb~
|
202
|
+
- spec/pith/input/template_spec.rb
|
201
203
|
- spec/pith/metadata_spec.rb~
|
202
204
|
- spec/pith/project_spec.rb
|
203
205
|
- spec/pith/project_spec.rb~
|
@@ -222,6 +224,7 @@ test_files:
|
|
222
224
|
- features/metadata.feature~
|
223
225
|
- features/relative_linking.feature
|
224
226
|
- features/relative_linking.feature~
|
227
|
+
- features/resources.feature
|
225
228
|
- features/step_definitions/build_steps.rb
|
226
229
|
- features/step_definitions/build_steps.rb~
|
227
230
|
- features/support/env.rb
|
@@ -230,6 +233,5 @@ test_files:
|
|
230
233
|
- features/support/rspec_matchers.rb~
|
231
234
|
- features/textile.feature
|
232
235
|
- features/textile.feature~
|
233
|
-
- features/verbatim.feature
|
234
236
|
- features/verbatim.feature~
|
235
237
|
- cucumber.yml
|
@@ -1,31 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require "pith/input/abstract"
|
3
|
-
require "pith/project"
|
4
|
-
|
5
|
-
describe Pith::Input::Abstract do
|
6
|
-
|
7
|
-
before do
|
8
|
-
$input_dir.mkpath
|
9
|
-
@project = Pith::Project.new(:input_dir => $input_dir)
|
10
|
-
@input_file = $input_dir + "some_page.html.haml"
|
11
|
-
@input_file.touch
|
12
|
-
end
|
13
|
-
|
14
|
-
describe "#title" do
|
15
|
-
|
16
|
-
it "is based on last component of filename" do
|
17
|
-
@project.input("some_page.html").title.should == "Some page"
|
18
|
-
end
|
19
|
-
|
20
|
-
it "can be over-ridden in metadata" do
|
21
|
-
@input_file.open("w") do |i|
|
22
|
-
i.puts "---"
|
23
|
-
i.puts "title: Blah blah"
|
24
|
-
i.puts "..."
|
25
|
-
end
|
26
|
-
@project.input("some_page.html").title.should == "Blah blah"
|
27
|
-
end
|
28
|
-
|
29
|
-
end
|
30
|
-
|
31
|
-
end
|