pith 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/pith +6 -5
- data/features/error_handling.feature +5 -4
- data/features/step_definitions/build_steps.rb +4 -0
- data/lib/pith/input.rb +215 -11
- data/lib/pith/plugins/publication/input.rb +2 -14
- data/lib/pith/project.rb +26 -19
- data/lib/pith/version.rb +1 -1
- data/spec/pith/{input/template_spec.rb~ → input_spec.rb} +15 -28
- data/spec/pith/project_spec.rb +14 -29
- metadata +28 -41
- data/lib/pith/exception_ext.rb +0 -9
- data/lib/pith/input/abstract.rb +0 -78
- data/lib/pith/input/abstract.rb~ +0 -74
- data/lib/pith/input/base.rb~ +0 -74
- data/lib/pith/input/resource.rb +0 -39
- data/lib/pith/input/resource.rb~ +0 -41
- data/lib/pith/input/template.rb +0 -159
- data/lib/pith/input/template.rb~ +0 -126
- data/lib/pith/input/verbatim.rb~ +0 -31
- data/spec/pith/input/abstract_spec.rb~ +0 -31
- data/spec/pith/input/template_spec.rb +0 -70
data/lib/pith/input/abstract.rb~
DELETED
@@ -1,74 +0,0 @@
|
|
1
|
-
require "pathname"
|
2
|
-
|
3
|
-
module Pith
|
4
|
-
module Input
|
5
|
-
|
6
|
-
class Abstract
|
7
|
-
|
8
|
-
def initialize(project, path)
|
9
|
-
@project = project
|
10
|
-
@path = path
|
11
|
-
end
|
12
|
-
|
13
|
-
attr_reader :project, :path
|
14
|
-
|
15
|
-
# Public: Get the file-system location of this input.
|
16
|
-
#
|
17
|
-
# Returns a fully-qualified Pathname.
|
18
|
-
#
|
19
|
-
def file
|
20
|
-
project.input_dir + path
|
21
|
-
end
|
22
|
-
|
23
|
-
def output_file
|
24
|
-
project.output_dir + output_path
|
25
|
-
end
|
26
|
-
|
27
|
-
# Public: Generate a corresponding output file.
|
28
|
-
#
|
29
|
-
def build
|
30
|
-
return false if ignorable? || uptodate?
|
31
|
-
logger.info("%-14s%s" % ["--(#{type})-->", output_path])
|
32
|
-
generate_output
|
33
|
-
end
|
34
|
-
|
35
|
-
# Public: Resolve a reference relative to this input.
|
36
|
-
#
|
37
|
-
# ref - a String referencing another asset
|
38
|
-
#
|
39
|
-
# A ref starting with "/" is resolved relative to the project root;
|
40
|
-
# anything else is resolved relative to this input.
|
41
|
-
#
|
42
|
-
# Returns a fully-qualified Pathname of the asset.
|
43
|
-
#
|
44
|
-
def resolve_path(ref)
|
45
|
-
ref = ref.to_str
|
46
|
-
if ref[0,1] == "/"
|
47
|
-
Pathname(ref[1..-1])
|
48
|
-
else
|
49
|
-
path.parent + ref
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
# Consider whether this input can be ignored.
|
54
|
-
#
|
55
|
-
# Returns true if it can.
|
56
|
-
#
|
57
|
-
def ignorable?
|
58
|
-
path.to_s.split("/").any? { |component| component.to_s[0,1] == "_" }
|
59
|
-
end
|
60
|
-
|
61
|
-
protected
|
62
|
-
|
63
|
-
def default_title
|
64
|
-
path.to_s.sub(/\..*/, '').tr('_-', ' ').capitalize
|
65
|
-
end
|
66
|
-
|
67
|
-
def logger
|
68
|
-
project.logger
|
69
|
-
end
|
70
|
-
|
71
|
-
end
|
72
|
-
|
73
|
-
end
|
74
|
-
end
|
data/lib/pith/input/base.rb~
DELETED
@@ -1,74 +0,0 @@
|
|
1
|
-
require "pathname"
|
2
|
-
|
3
|
-
module Pith
|
4
|
-
module Input
|
5
|
-
|
6
|
-
class Abstract
|
7
|
-
|
8
|
-
def initialize(project, path)
|
9
|
-
@project = project
|
10
|
-
@path = path
|
11
|
-
end
|
12
|
-
|
13
|
-
attr_reader :project, :path
|
14
|
-
|
15
|
-
# Public: Get the file-system location of this input.
|
16
|
-
#
|
17
|
-
# Returns a fully-qualified Pathname.
|
18
|
-
#
|
19
|
-
def file
|
20
|
-
project.input_dir + path
|
21
|
-
end
|
22
|
-
|
23
|
-
# Public: Get the file-system location of the corresponding output file.
|
24
|
-
#
|
25
|
-
# Returns a fully-qualified Pathname.
|
26
|
-
#
|
27
|
-
def output_file
|
28
|
-
project.output_dir + output_path
|
29
|
-
end
|
30
|
-
|
31
|
-
# Public: Generate an output file.
|
32
|
-
#
|
33
|
-
def build
|
34
|
-
return false if ignorable? || uptodate?
|
35
|
-
logger.info("%-16s%s" % ["--(#{type})-->", output_path])
|
36
|
-
generate_output
|
37
|
-
end
|
38
|
-
|
39
|
-
# Public: Resolve a reference relative to this input.
|
40
|
-
#
|
41
|
-
# ref - a String referencing another asset
|
42
|
-
#
|
43
|
-
# A ref starting with "/" is resolved relative to the project root;
|
44
|
-
# anything else is resolved relative to this input.
|
45
|
-
#
|
46
|
-
# Returns a fully-qualified Pathname of the asset.
|
47
|
-
#
|
48
|
-
def resolve_path(ref)
|
49
|
-
ref = ref.to_str
|
50
|
-
if ref[0,1] == "/"
|
51
|
-
Pathname(ref[1..-1])
|
52
|
-
else
|
53
|
-
path.parent + ref
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
# Consider whether this input can be ignored.
|
58
|
-
#
|
59
|
-
# Returns true if it can.
|
60
|
-
#
|
61
|
-
def ignorable?
|
62
|
-
path.to_s.split("/").any? { |component| component.to_s[0,1] == "_" }
|
63
|
-
end
|
64
|
-
|
65
|
-
protected
|
66
|
-
|
67
|
-
def logger
|
68
|
-
project.logger
|
69
|
-
end
|
70
|
-
|
71
|
-
end
|
72
|
-
|
73
|
-
end
|
74
|
-
end
|
data/lib/pith/input/resource.rb
DELETED
@@ -1,39 +0,0 @@
|
|
1
|
-
require "fileutils"
|
2
|
-
require "pith/input/abstract"
|
3
|
-
|
4
|
-
module Pith
|
5
|
-
module Input
|
6
|
-
|
7
|
-
# Represents a non-template input.
|
8
|
-
#
|
9
|
-
class Resource < Abstract
|
10
|
-
|
11
|
-
def output_path
|
12
|
-
path
|
13
|
-
end
|
14
|
-
|
15
|
-
def uptodate?
|
16
|
-
FileUtils.uptodate?(output_file, [file])
|
17
|
-
end
|
18
|
-
|
19
|
-
# Copy this input verbatim into the output directory
|
20
|
-
#
|
21
|
-
def generate_output
|
22
|
-
output_file.parent.mkpath
|
23
|
-
FileUtils.copy(file, output_file)
|
24
|
-
end
|
25
|
-
|
26
|
-
# Render this input, for inclusion within templates
|
27
|
-
#
|
28
|
-
def render(context, locals = {})
|
29
|
-
file.read
|
30
|
-
end
|
31
|
-
|
32
|
-
def meta
|
33
|
-
{}
|
34
|
-
end
|
35
|
-
|
36
|
-
end
|
37
|
-
|
38
|
-
end
|
39
|
-
end
|
data/lib/pith/input/resource.rb~
DELETED
@@ -1,41 +0,0 @@
|
|
1
|
-
require "fileutils"
|
2
|
-
require "pith/input/abstract"
|
3
|
-
|
4
|
-
module Pith
|
5
|
-
module Input
|
6
|
-
|
7
|
-
class Resource < Abstract
|
8
|
-
|
9
|
-
def output_path
|
10
|
-
path
|
11
|
-
end
|
12
|
-
|
13
|
-
def type
|
14
|
-
"copy"
|
15
|
-
end
|
16
|
-
|
17
|
-
def uptodate?
|
18
|
-
FileUtils.uptodate?(output_file, [file])
|
19
|
-
end
|
20
|
-
|
21
|
-
# Copy this input verbatim into the output directory
|
22
|
-
#
|
23
|
-
def generate_output
|
24
|
-
output_file.parent.mkpath
|
25
|
-
FileUtils.copy(file, output_file)
|
26
|
-
end
|
27
|
-
|
28
|
-
# Render this input, for inclusion within templates
|
29
|
-
#
|
30
|
-
def render(context, locals = {})
|
31
|
-
file.read
|
32
|
-
end
|
33
|
-
|
34
|
-
def meta
|
35
|
-
{}
|
36
|
-
end
|
37
|
-
|
38
|
-
end
|
39
|
-
|
40
|
-
end
|
41
|
-
end
|
data/lib/pith/input/template.rb
DELETED
@@ -1,159 +0,0 @@
|
|
1
|
-
require "fileutils"
|
2
|
-
require "pathname"
|
3
|
-
require "pith/exception_ext"
|
4
|
-
require "pith/input/abstract"
|
5
|
-
require "pith/render_context"
|
6
|
-
require "tilt"
|
7
|
-
require "yaml"
|
8
|
-
|
9
|
-
module Pith
|
10
|
-
module Input
|
11
|
-
|
12
|
-
# Represents an input that should be evaluated as a template.
|
13
|
-
#
|
14
|
-
class Template < Abstract
|
15
|
-
|
16
|
-
def self.can_handle?(path)
|
17
|
-
!!Tilt[path.to_s]
|
18
|
-
end
|
19
|
-
|
20
|
-
def initialize(project, path)
|
21
|
-
raise(ArgumentError, "#{path} is not a template") unless Template.can_handle?(path)
|
22
|
-
super(project, path)
|
23
|
-
determine_pipeline
|
24
|
-
load
|
25
|
-
end
|
26
|
-
|
27
|
-
attr_reader :output_path
|
28
|
-
|
29
|
-
# Check whether output is up-to-date.
|
30
|
-
#
|
31
|
-
# Return true unless output needs to be re-generated.
|
32
|
-
#
|
33
|
-
def uptodate?
|
34
|
-
dependencies && FileUtils.uptodate?(output_file, dependencies)
|
35
|
-
end
|
36
|
-
|
37
|
-
# Generate output for this template
|
38
|
-
#
|
39
|
-
def generate_output
|
40
|
-
output_file.parent.mkpath
|
41
|
-
render_context = RenderContext.new(project)
|
42
|
-
output_file.open("w") do |out|
|
43
|
-
begin
|
44
|
-
out.puts(render_context.render(self))
|
45
|
-
rescue StandardError, SyntaxError => e
|
46
|
-
logger.warn e.summary(:max_backtrace => 5)
|
47
|
-
out.puts "<pre>"
|
48
|
-
out.puts e.summary
|
49
|
-
end
|
50
|
-
end
|
51
|
-
@dependencies = render_context.dependencies
|
52
|
-
end
|
53
|
-
|
54
|
-
# Render this input using Tilt
|
55
|
-
#
|
56
|
-
def render(context, locals = {}, &block)
|
57
|
-
@pipeline.inject(@template_text) do |text, processor|
|
58
|
-
template = processor.new(file.to_s, @template_start_line) { text }
|
59
|
-
template.render(context, locals, &block)
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
# Public: Get YAML metadata declared in the header of of a template.
|
64
|
-
#
|
65
|
-
# If the first line of the template starts with "---" it is considered to be
|
66
|
-
# the start of a YAML 'document', which is loaded and returned.
|
67
|
-
#
|
68
|
-
# Examples
|
69
|
-
#
|
70
|
-
# Given input starting with:
|
71
|
-
#
|
72
|
-
# ---
|
73
|
-
# published: 2008-09-15
|
74
|
-
# ...
|
75
|
-
# OTHER STUFF
|
76
|
-
#
|
77
|
-
# input.meta
|
78
|
-
# #=> { "published" => "2008-09-15" }
|
79
|
-
#
|
80
|
-
# Returns a Hash.
|
81
|
-
#
|
82
|
-
def meta
|
83
|
-
@meta
|
84
|
-
end
|
85
|
-
|
86
|
-
# Public: Get page title.
|
87
|
-
#
|
88
|
-
# The default title is based on the input file-name, sans-extension, capitalised,
|
89
|
-
# but can be overridden by providing a "title" in the metadata block.
|
90
|
-
#
|
91
|
-
# Examples
|
92
|
-
#
|
93
|
-
# input.path.to_s
|
94
|
-
# #=> "some_page.html.haml"
|
95
|
-
# input.title
|
96
|
-
# #=> "Some page"
|
97
|
-
#
|
98
|
-
def title
|
99
|
-
meta["title"] || default_title
|
100
|
-
end
|
101
|
-
|
102
|
-
private
|
103
|
-
|
104
|
-
def default_title
|
105
|
-
path.basename.to_s.sub(/\..*/, '').tr('_-', ' ').capitalize
|
106
|
-
end
|
107
|
-
|
108
|
-
def determine_pipeline
|
109
|
-
@pipeline = []
|
110
|
-
remaining_path = path.to_s
|
111
|
-
while remaining_path =~ /^(.+)\.(.+)$/
|
112
|
-
if Tilt[$2]
|
113
|
-
remaining_path = $1
|
114
|
-
@pipeline << Tilt[$2]
|
115
|
-
else
|
116
|
-
break
|
117
|
-
end
|
118
|
-
end
|
119
|
-
@output_path = Pathname(remaining_path)
|
120
|
-
end
|
121
|
-
|
122
|
-
# Read input file, extracting YAML meta-data header, and template content.
|
123
|
-
#
|
124
|
-
def load
|
125
|
-
file.open do |input|
|
126
|
-
load_meta(input)
|
127
|
-
load_template(input)
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
def load_meta(input)
|
132
|
-
@meta = {}
|
133
|
-
header = input.gets
|
134
|
-
if header =~ /^---/
|
135
|
-
while line = input.gets
|
136
|
-
break if line =~ /^(---|\.\.\.)/
|
137
|
-
header << line
|
138
|
-
end
|
139
|
-
begin
|
140
|
-
@meta = YAML.load(header)
|
141
|
-
rescue ArgumentError, SyntaxError
|
142
|
-
logger.warn "#{file}:1: badly-formed YAML header"
|
143
|
-
end
|
144
|
-
else
|
145
|
-
input.rewind
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
def load_template(input)
|
150
|
-
@template_start_line = input.lineno + 1
|
151
|
-
@template_text = input.read
|
152
|
-
end
|
153
|
-
|
154
|
-
attr_accessor :dependencies
|
155
|
-
|
156
|
-
end
|
157
|
-
|
158
|
-
end
|
159
|
-
end
|
data/lib/pith/input/template.rb~
DELETED
@@ -1,126 +0,0 @@
|
|
1
|
-
require "fileutils"
|
2
|
-
require "pathname"
|
3
|
-
require "pith/input/abstract"
|
4
|
-
require "pith/render_context"
|
5
|
-
require "tilt"
|
6
|
-
require "yaml"
|
7
|
-
|
8
|
-
module Pith
|
9
|
-
module Input
|
10
|
-
|
11
|
-
class Template < Abstract
|
12
|
-
|
13
|
-
def self.can_handle?(path)
|
14
|
-
path.to_str =~ /\.([^.]+)$/ && Tilt.registered?($1)
|
15
|
-
end
|
16
|
-
|
17
|
-
def initialize(project, path)
|
18
|
-
raise(ArgumentError, "#{path} is not a template") unless Template.can_handle?(path)
|
19
|
-
super(project, path)
|
20
|
-
path.to_str =~ /^(.+)\.(.+)$/ || raise("huh?")
|
21
|
-
@output_path = Pathname($1)
|
22
|
-
@type = $2
|
23
|
-
load
|
24
|
-
end
|
25
|
-
|
26
|
-
attr_reader :output_path, :type
|
27
|
-
|
28
|
-
# Check whether output is up-to-date.
|
29
|
-
#
|
30
|
-
# Return true unless output needs to be re-generated.
|
31
|
-
#
|
32
|
-
def uptodate?
|
33
|
-
dependencies && FileUtils.uptodate?(output_file, dependencies)
|
34
|
-
end
|
35
|
-
|
36
|
-
# Generate output for this template
|
37
|
-
#
|
38
|
-
def generate_output
|
39
|
-
output_file.parent.mkpath
|
40
|
-
render_context = RenderContext.new(project)
|
41
|
-
output_file.open("w") do |out|
|
42
|
-
out.puts(render_context.render(self))
|
43
|
-
end
|
44
|
-
@dependencies = render_context.dependencies
|
45
|
-
end
|
46
|
-
|
47
|
-
# Render this input using Tilt
|
48
|
-
#
|
49
|
-
def render(context, locals = {}, &block)
|
50
|
-
@tilt_template.render(context, locals, &block)
|
51
|
-
end
|
52
|
-
|
53
|
-
# Public: Get YAML metadata declared in the header of of a template.
|
54
|
-
#
|
55
|
-
# If the first line of the template starts with "---" it is considered to be
|
56
|
-
# the start of a YAML 'document', which is loaded and returned.
|
57
|
-
#
|
58
|
-
# Examples
|
59
|
-
#
|
60
|
-
# Given input starting with:
|
61
|
-
#
|
62
|
-
# ---
|
63
|
-
# published: 2008-09-15
|
64
|
-
# ...
|
65
|
-
# OTHER STUFF
|
66
|
-
#
|
67
|
-
# input.meta
|
68
|
-
# #=> { "published" => "2008-09-15" }
|
69
|
-
#
|
70
|
-
# Returns a Hash.
|
71
|
-
#
|
72
|
-
def meta
|
73
|
-
@meta
|
74
|
-
end
|
75
|
-
|
76
|
-
# Public: Get page title.
|
77
|
-
#
|
78
|
-
# The default title is based on the input file-name, sans-extension, capitalised,
|
79
|
-
# but can be overridden by providing a "title" in the metadata block.
|
80
|
-
#
|
81
|
-
# Examples
|
82
|
-
#
|
83
|
-
# input.path.to_s
|
84
|
-
# #=> "some_page.html.haml"
|
85
|
-
# input.title
|
86
|
-
# #=> "Some page"
|
87
|
-
#
|
88
|
-
def title
|
89
|
-
meta["title"] || default_title
|
90
|
-
end
|
91
|
-
|
92
|
-
private
|
93
|
-
|
94
|
-
def default_title
|
95
|
-
path.basename.to_s.sub(/\..*/, '').tr('_-', ' ').capitalize
|
96
|
-
end
|
97
|
-
|
98
|
-
# Read input file, extracting YAML meta-data header, and template content.
|
99
|
-
#
|
100
|
-
def load
|
101
|
-
@meta = {}
|
102
|
-
file.open do |input|
|
103
|
-
header = input.gets
|
104
|
-
if header =~ /^---/
|
105
|
-
while line = input.gets
|
106
|
-
break if line =~ /^(---|\.\.\.)/
|
107
|
-
header << line
|
108
|
-
end
|
109
|
-
begin
|
110
|
-
@meta = YAML.load(header)
|
111
|
-
rescue
|
112
|
-
logger.warn "#{file}:1: badly-formed YAML header"
|
113
|
-
end
|
114
|
-
else
|
115
|
-
input.rewind
|
116
|
-
end
|
117
|
-
@tilt_template = Tilt.new(file, input.lineno + 1) { input.read }
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
attr_accessor :dependencies
|
122
|
-
|
123
|
-
end
|
124
|
-
|
125
|
-
end
|
126
|
-
end
|