erbside 0.1.0 → 0.2.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/.gemspec +152 -0
- data/.gitignore +8 -0
- data/.ruby +48 -0
- data/.yardopts +6 -0
- data/{HISTORY → HISTORY.rdoc} +0 -0
- data/MANIFEST +33 -0
- data/NOTICE.rdoc +32 -0
- data/PROFILE +6 -3
- data/README.rdoc +76 -0
- data/VERSION +1 -1
- data/lib/erbside.rb +6 -2
- data/lib/erbside/context.rb +3 -3
- data/lib/erbside/gemspec.rb +19 -0
- data/lib/erbside/inline.rb +8 -5
- data/lib/erbside/inline/cpp.rb +7 -0
- data/lib/erbside/inline/css.rb +7 -0
- data/lib/erbside/inline/js.rb +7 -0
- data/lib/erbside/metadata.rb +86 -50
- data/lib/erbside/runner.rb +14 -5
- data/main.assembly +56 -0
- data/{test/functional → qed}/applique/env.rb +0 -0
- data/{test/functional → qed}/bash.rdoc +0 -0
- data/{test/functional → qed}/cli.rdoc +0 -0
- data/{test/functional → qed}/cpp.rdoc +0 -0
- data/{test/functional → qed}/css.rdoc +0 -0
- data/{test/functional → qed}/javascript.rdoc +0 -0
- data/{test/functional → qed}/ruby.rdoc +0 -0
- data/{test/functional → qed}/sgml.rdoc +0 -0
- data/site/.htaccess +2 -0
- data/site/.rsync-filter +7 -0
- data/site/assets/css/highlight.css +96 -0
- data/site/assets/css/reset.css +19 -0
- data/site/assets/css/site.css +52 -0
- data/site/assets/img/curb.jpg +0 -0
- data/site/assets/img/emeraled.png +0 -0
- data/site/assets/img/fade.png +0 -0
- data/site/assets/img/fork-me.png +0 -0
- data/site/assets/img/icon.jpg +0 -0
- data/site/assets/js/highlight.js +1 -0
- data/site/assets/js/jquery.js +19 -0
- data/site/assets/js/jquery.tabs.js +1 -0
- data/site/index.html +229 -0
- data/test/{unit/fixture → fixture}/inline.rb +3 -3
- data/test/{unit/fixture → fixture}/inline_complex.rb +0 -0
- data/test/inline_test.rb +15 -0
- data/work/defunct/css/color.css +45 -0
- data/work/defunct/css/font.css +39 -0
- data/work/defunct/css/struct.css +51 -0
- data/work/defunct/inline-old/bash.rb +36 -0
- data/work/defunct/inline-old/cpp.rb +39 -0
- data/work/defunct/inline-old/css.rb +32 -0
- data/work/defunct/inline-old/html.rb +32 -0
- data/work/defunct/inline-old/js.rb +85 -0
- data/work/defunct/inline-old/ruby.rb +147 -0
- data/work/defunct/inline-old/type.rb +91 -0
- data/work/defunct/inline.rb +202 -0
- data/work/defunct/plan.rb +37 -0
- data/work/defunct/tiller.rb +200 -0
- data/work/defunct/webme/options.yml +4 -0
- data/work/defunct/whole.rb +221 -0
- data/{lib → work}/plugins/syckle/erbside.rb +0 -0
- data/work/radio_earth.jpg +0 -0
- data/yard.watchr +12 -0
- metadata +94 -50
- data/LICENSE +0 -206
- data/README +0 -88
- data/test/unit/inline_test.rb +0 -14
@@ -0,0 +1,202 @@
|
|
1
|
+
module Till
|
2
|
+
|
3
|
+
# = Inline Templating
|
4
|
+
#
|
5
|
+
class Inline
|
6
|
+
|
7
|
+
# R E Q U I R E M E N T S
|
8
|
+
|
9
|
+
require 'erb'
|
10
|
+
require 'tilt'
|
11
|
+
require 'till/context'
|
12
|
+
|
13
|
+
|
14
|
+
# C O N S T A N T S
|
15
|
+
|
16
|
+
# Supported templating systems.
|
17
|
+
STENCILS = %w{ .erb .liquid .mustache }
|
18
|
+
|
19
|
+
|
20
|
+
# A T T R I B U T E S
|
21
|
+
|
22
|
+
# The file to receive inline templating.
|
23
|
+
attr :file
|
24
|
+
|
25
|
+
# The extname of the file.
|
26
|
+
attr :extension
|
27
|
+
|
28
|
+
# Location of the file.
|
29
|
+
attr :location
|
30
|
+
|
31
|
+
# The rendered result.
|
32
|
+
attr :result
|
33
|
+
|
34
|
+
# Rendering context/scope.
|
35
|
+
attr :context
|
36
|
+
|
37
|
+
# Extension name of stenciling template system
|
38
|
+
# to use. This determines with templating system to use,
|
39
|
+
# such as .erb, .liquid, etc. This defaults to '.erb',
|
40
|
+
# but can be changed in the file with:
|
41
|
+
#
|
42
|
+
# # :till.stencil: <ext>
|
43
|
+
#
|
44
|
+
attr :stencil
|
45
|
+
|
46
|
+
|
47
|
+
# I N I T I A L I Z E
|
48
|
+
|
49
|
+
#
|
50
|
+
def initialize(file)
|
51
|
+
@file = file
|
52
|
+
@extension = File.extname(file)
|
53
|
+
@location = File.dirname(File.expand_path(file))
|
54
|
+
|
55
|
+
self.stencil = '.erb'
|
56
|
+
|
57
|
+
@context = Context.new(@location)
|
58
|
+
end
|
59
|
+
|
60
|
+
#
|
61
|
+
def stencil=(ext)
|
62
|
+
ext = (ext[0,1] == '.' ? ext : ".#{ext}")
|
63
|
+
raise "unsupported stencil type -- #{ext}" unless STENCILS.include?(ext)
|
64
|
+
@stencil = ext
|
65
|
+
end
|
66
|
+
|
67
|
+
#
|
68
|
+
def root
|
69
|
+
context.metadata.root
|
70
|
+
end
|
71
|
+
|
72
|
+
#
|
73
|
+
def render
|
74
|
+
render_inline(file)
|
75
|
+
end
|
76
|
+
|
77
|
+
#
|
78
|
+
def render_inline(file)
|
79
|
+
#name = file.sub(Dir.pwd+'/', '')
|
80
|
+
save = false
|
81
|
+
text = ''
|
82
|
+
lines = File.readlines(file)
|
83
|
+
i = 0
|
84
|
+
while i < lines.size
|
85
|
+
line = lines[i]
|
86
|
+
if md = /^\s*#\s*:till.stencil:(.*?)/.match(line)
|
87
|
+
self.type = md[1].strip
|
88
|
+
text << line
|
89
|
+
elsif md = /^(\s*)#(\s*):till\+(\d*):/.match(line)
|
90
|
+
temp = md.post_match
|
91
|
+
code = md.post_match
|
92
|
+
line = lines[i+=1]
|
93
|
+
while i < lines.size && line =~ /^\s*^#/
|
94
|
+
temp << line
|
95
|
+
code << line
|
96
|
+
line = lines[i+=1]
|
97
|
+
end
|
98
|
+
res = render_template(code.gsub(/^\s*#*/,'').strip)
|
99
|
+
text << md[1] + "#" + md[2] + ":till+#{res.split("\n").size}:"
|
100
|
+
text << temp
|
101
|
+
text << res
|
102
|
+
text << "\n"
|
103
|
+
save = true
|
104
|
+
i += md[3].to_i
|
105
|
+
elsif md = /^(\s*).*?(\s*#\s*:till:)/.match(line)
|
106
|
+
pm = md.post_match.strip
|
107
|
+
if pm[0,1] == '^'
|
108
|
+
pm = pm[1..-1].strip
|
109
|
+
fm = pm[0...(pm.index('<')||-1)]
|
110
|
+
ri = line.index(fm)
|
111
|
+
if ri
|
112
|
+
text << line[0...ri] + render_template(pm) + md[2] + md.post_match
|
113
|
+
else
|
114
|
+
puts "waning: skipped line #{i} no match for #{fm}"
|
115
|
+
text << line
|
116
|
+
end
|
117
|
+
else
|
118
|
+
text << md[1] + render_template(pm) + md[2] + md.post_match
|
119
|
+
end
|
120
|
+
save = true
|
121
|
+
i += 1
|
122
|
+
else
|
123
|
+
text << line
|
124
|
+
i += 1
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
@result = text
|
129
|
+
end
|
130
|
+
|
131
|
+
#
|
132
|
+
|
133
|
+
def render_template(text)
|
134
|
+
template = Tilt[stencil]
|
135
|
+
unless template
|
136
|
+
warn "unknown template type #{stencil}"
|
137
|
+
template = Tilt::ERBTemplate
|
138
|
+
end
|
139
|
+
render_tilt(template.new{ text })
|
140
|
+
end
|
141
|
+
|
142
|
+
#
|
143
|
+
|
144
|
+
def render_tilt(template)
|
145
|
+
Dir.chdir(location) do
|
146
|
+
template.render(@context)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
#
|
151
|
+
|
152
|
+
def relative_output(dir=nil)
|
153
|
+
dir = dir || Dir.pwd
|
154
|
+
output.sub(dir+'/', '')
|
155
|
+
end
|
156
|
+
|
157
|
+
#
|
158
|
+
|
159
|
+
def exist?
|
160
|
+
File.exist?(output)
|
161
|
+
end
|
162
|
+
|
163
|
+
# Has the file changed?
|
164
|
+
|
165
|
+
def changed?
|
166
|
+
if exist?
|
167
|
+
File.read(output) != result
|
168
|
+
else
|
169
|
+
true
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
# Save result to file.
|
174
|
+
|
175
|
+
def save
|
176
|
+
File.open(output, 'w'){ |f| f << result }
|
177
|
+
end
|
178
|
+
|
179
|
+
# Output file (same as the input file).
|
180
|
+
|
181
|
+
def output
|
182
|
+
file
|
183
|
+
end
|
184
|
+
|
185
|
+
#
|
186
|
+
|
187
|
+
#def erb(text, file=nil)
|
188
|
+
# if file
|
189
|
+
# dir = File.dirname(file)
|
190
|
+
# Dir.chdir(dir) do
|
191
|
+
# context.erb(text)
|
192
|
+
# end
|
193
|
+
# else
|
194
|
+
# context.erb(text)
|
195
|
+
# end
|
196
|
+
#end
|
197
|
+
|
198
|
+
end
|
199
|
+
|
200
|
+
end
|
201
|
+
|
202
|
+
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Till
|
2
|
+
|
3
|
+
# = Tilling Plan
|
4
|
+
#
|
5
|
+
# A plan file is used to easily repeat a set of tills.
|
6
|
+
#
|
7
|
+
# myfile.html:
|
8
|
+
# source: templates/myfile.rdoc
|
9
|
+
# filter: erb, rdoc
|
10
|
+
#
|
11
|
+
class Plan
|
12
|
+
|
13
|
+
include Enumerable
|
14
|
+
|
15
|
+
#
|
16
|
+
|
17
|
+
def initialize(root)
|
18
|
+
file = Dir[File.join(root, '{.config,config}/till/plan.{yml,yaml}')].first
|
19
|
+
@plan = file ? YAML.load(File.new(file) : {}
|
20
|
+
end
|
21
|
+
|
22
|
+
#
|
23
|
+
|
24
|
+
def [](file)
|
25
|
+
@plan[file]
|
26
|
+
end
|
27
|
+
|
28
|
+
#
|
29
|
+
|
30
|
+
def each(&block)
|
31
|
+
@plan.each(&block)
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
@@ -0,0 +1,200 @@
|
|
1
|
+
require 'till/metadata'
|
2
|
+
require 'facets/kernel/ask'
|
3
|
+
require 'facets/string/tabto'
|
4
|
+
require 'erb'
|
5
|
+
|
6
|
+
module Till
|
7
|
+
|
8
|
+
# The Tiller class is used to generate files from
|
9
|
+
# embebbded ERB template files.
|
10
|
+
#
|
11
|
+
class Tiller
|
12
|
+
|
13
|
+
attr_accessor :files
|
14
|
+
|
15
|
+
attr_accessor :force
|
16
|
+
|
17
|
+
attr_accessor :skip
|
18
|
+
|
19
|
+
#attr_accessor :delete
|
20
|
+
|
21
|
+
#
|
22
|
+
def initialize(files, options)
|
23
|
+
files = files || Dir['**/*.til']
|
24
|
+
files = files.map do |file|
|
25
|
+
if File.directory?(file)
|
26
|
+
collect_usable_files(file)
|
27
|
+
else
|
28
|
+
file
|
29
|
+
end
|
30
|
+
end.flatten
|
31
|
+
@files = files
|
32
|
+
@force = options[:force]
|
33
|
+
@skip = options[:skip]
|
34
|
+
#@delete = options[:delete]
|
35
|
+
end
|
36
|
+
|
37
|
+
def collect_usable_files(dir)
|
38
|
+
Dir[File.join(dir,'**/*.{till,til,rb}')]
|
39
|
+
end
|
40
|
+
|
41
|
+
def delete? ; @delete ; end
|
42
|
+
def force? ; @force ; end
|
43
|
+
def skip? ; @skip ; end
|
44
|
+
|
45
|
+
def debug? ; $DEBUG ; end
|
46
|
+
def trial? ; $TRIAL ; end
|
47
|
+
|
48
|
+
#
|
49
|
+
#def tillfiles
|
50
|
+
# @tillfiles ||= Dir[File.join(@output, '**/*.till')].select{ |f| File.file?(f) }
|
51
|
+
#end
|
52
|
+
|
53
|
+
#
|
54
|
+
#def rubyfiles
|
55
|
+
# @rubyfiles ||= Dir[File.join(@output, '**/*.rb')].select{ |f| File.file?(f) }
|
56
|
+
#end
|
57
|
+
|
58
|
+
def till
|
59
|
+
files.each{ |file|
|
60
|
+
raise "unsupport file type -- #{file}" unless File.extname =~ /^\.(rb|til|till)$/
|
61
|
+
end
|
62
|
+
|
63
|
+
files.each do |file|
|
64
|
+
case File.extname(file)
|
65
|
+
when '.till', '.til'
|
66
|
+
till_template(file)
|
67
|
+
when '.rb'
|
68
|
+
till_inline(file)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Search for till templates (*.till) and render.
|
74
|
+
#
|
75
|
+
def till_template(file)
|
76
|
+
result = erb(File.read(file))
|
77
|
+
fname = file.chomp(File.extname(file))
|
78
|
+
write(fname, result)
|
79
|
+
#rm(file) if delete? # TODO
|
80
|
+
end
|
81
|
+
|
82
|
+
# Search through Ruby files for inline till templates.
|
83
|
+
def till_inline(file)
|
84
|
+
name = file.sub(Dir.pwd+'/', '')
|
85
|
+
save = false
|
86
|
+
text = ''
|
87
|
+
lines = File.readlines(file)
|
88
|
+
i = 0
|
89
|
+
while i < lines.size
|
90
|
+
line = lines[i]
|
91
|
+
if md = /^(\s*)#(\s*):till\+(\d*):/.match(line)
|
92
|
+
temp = md.post_match
|
93
|
+
code = md.post_match
|
94
|
+
line = lines[i+=1]
|
95
|
+
while i < lines.size && line =~ /^\s*^#/
|
96
|
+
temp << line
|
97
|
+
code << line
|
98
|
+
line = lines[i+=1]
|
99
|
+
end
|
100
|
+
res = erb(code.gsub(/^\s*#*/,'').strip, file)
|
101
|
+
text << md[1] + "#" + md[2] + ":till+#{res.split("\n").size}:"
|
102
|
+
text << temp
|
103
|
+
text << res
|
104
|
+
text << "\n"
|
105
|
+
save = true
|
106
|
+
i += md[3].to_i
|
107
|
+
elsif md = /^(\s*).*?(\s*#\s*:till:)/.match(line)
|
108
|
+
pm = md.post_match.strip
|
109
|
+
if pm[0,1] == '^'
|
110
|
+
pm = pm[1..-1].strip
|
111
|
+
fm = pm[0...(pm.index('<')||-1)]
|
112
|
+
ri = line.index(fm)
|
113
|
+
if ri
|
114
|
+
text << line[0...ri] + erb(pm, file) + md[2] + md.post_match
|
115
|
+
else
|
116
|
+
puts "waning: skipped line #{i} no match for #{fm}"
|
117
|
+
text << line
|
118
|
+
end
|
119
|
+
else
|
120
|
+
text << md[1] + erb(pm, file) + md[2] + md.post_match
|
121
|
+
end
|
122
|
+
save = true
|
123
|
+
i += 1
|
124
|
+
else
|
125
|
+
text << line
|
126
|
+
i += 1
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
if save
|
131
|
+
write(file, text)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
#
|
136
|
+
def write(fname, text)
|
137
|
+
name = fname.sub(Dir.pwd+'/', '')
|
138
|
+
if trial?
|
139
|
+
puts " #{name}"
|
140
|
+
else
|
141
|
+
if File.exist?(fname)
|
142
|
+
if skip? # TODO: skip before running erb ?
|
143
|
+
puts " skipped #{name}"
|
144
|
+
return
|
145
|
+
elsif File.read(fname) == text
|
146
|
+
puts " unchanged #{name}"
|
147
|
+
return
|
148
|
+
elsif !force?
|
149
|
+
case ask(" overwrite #{name}? ")
|
150
|
+
when 'y', 'yes'
|
151
|
+
else
|
152
|
+
return
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
File.open(fname, 'w'){ |f| f << text }
|
157
|
+
puts " written #{name}"
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
#
|
162
|
+
def context
|
163
|
+
@conext ||= Erb.new() #TODO: @output ?
|
164
|
+
end
|
165
|
+
|
166
|
+
def erb(text, file=nil)
|
167
|
+
if file
|
168
|
+
dir = File.dirname(file)
|
169
|
+
Dir.chdir(dir) do
|
170
|
+
context.erb(text)
|
171
|
+
end
|
172
|
+
else
|
173
|
+
context.erb(text)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
# Tiller's erb context
|
178
|
+
#
|
179
|
+
class Erb
|
180
|
+
|
181
|
+
def initialize(dir=nil)
|
182
|
+
@metadata = Metadata.new(dir)
|
183
|
+
end
|
184
|
+
|
185
|
+
def method_missing(s)
|
186
|
+
@metadata.send(s)
|
187
|
+
end
|
188
|
+
|
189
|
+
# Processes through erb.
|
190
|
+
def erb(text)
|
191
|
+
erb = ERB.new(text)
|
192
|
+
erb.result(binding)
|
193
|
+
end
|
194
|
+
|
195
|
+
end#class Context
|
196
|
+
|
197
|
+
end#class Tiller
|
198
|
+
|
199
|
+
end
|
200
|
+
|
@@ -0,0 +1,221 @@
|
|
1
|
+
module Till
|
2
|
+
|
3
|
+
# = Whole Template
|
4
|
+
#
|
5
|
+
class Whole
|
6
|
+
|
7
|
+
# R E Q U I R E M E N T S
|
8
|
+
|
9
|
+
# TODO: Load engines only if used?
|
10
|
+
|
11
|
+
begin ; require 'rubygems' ; rescue LoadError ; end # why?
|
12
|
+
begin ; require 'erb' ; rescue LoadError ; end
|
13
|
+
begin ; require 'redcloth' ; rescue LoadError ; end
|
14
|
+
begin ; require 'bluecloth' ; rescue LoadError ; end
|
15
|
+
begin ; require 'rdiscount' ; rescue LoadError ; end
|
16
|
+
|
17
|
+
begin
|
18
|
+
require 'liquid'
|
19
|
+
#Liquid::Template.register_filter(TemplateFilters)
|
20
|
+
rescue LoadError
|
21
|
+
end
|
22
|
+
|
23
|
+
begin
|
24
|
+
require 'haml'
|
25
|
+
#Haml::Template.options[:format] = :html5
|
26
|
+
rescue LoadError
|
27
|
+
end
|
28
|
+
|
29
|
+
begin
|
30
|
+
require 'rdoc/markup/simple_markup'
|
31
|
+
require 'rdoc/markup/simple_markup/to_html'
|
32
|
+
rescue LoadError
|
33
|
+
end
|
34
|
+
|
35
|
+
require 'tilt'
|
36
|
+
|
37
|
+
require 'till/context'
|
38
|
+
|
39
|
+
|
40
|
+
# A T T R I B U T E S
|
41
|
+
|
42
|
+
# File pathname of the template file.
|
43
|
+
attr :file
|
44
|
+
|
45
|
+
# Directory location of the template +file+.
|
46
|
+
attr :location
|
47
|
+
|
48
|
+
# Format of the template (in terms of extension names).
|
49
|
+
attr :format
|
50
|
+
|
51
|
+
# Where to save the rendered result (defaults to +file+ w/o it's extension).
|
52
|
+
# This is also often referred to as the *target*.
|
53
|
+
attr :output
|
54
|
+
|
55
|
+
# List of redering filters to processes file through (defaults to +extension+ plus +erb+).
|
56
|
+
attr :filters
|
57
|
+
|
58
|
+
# Stores the rendered result, after #render is called.
|
59
|
+
attr :result
|
60
|
+
|
61
|
+
# Body of file.
|
62
|
+
attr :content
|
63
|
+
|
64
|
+
# Context/scope of template rendering.
|
65
|
+
attr :context
|
66
|
+
|
67
|
+
|
68
|
+
# I N I T I A L I Z E
|
69
|
+
|
70
|
+
#
|
71
|
+
def initialize(file)
|
72
|
+
@file = file
|
73
|
+
|
74
|
+
case ext = File.extname(file)
|
75
|
+
when '.till', '.til'
|
76
|
+
fname = file.chomp(ext)
|
77
|
+
else
|
78
|
+
fname = file
|
79
|
+
end
|
80
|
+
|
81
|
+
#@format = File.extname(fname)
|
82
|
+
@location = File.dirname(File.expand_path(file))
|
83
|
+
|
84
|
+
text = File.read(file).rstrip
|
85
|
+
|
86
|
+
# front matter indicator
|
87
|
+
if text =~ /\A---/
|
88
|
+
text = text.sub(/---.*?\n/, '')
|
89
|
+
meta, body = *text.split(/^---/)
|
90
|
+
else
|
91
|
+
meta = nil
|
92
|
+
body = text
|
93
|
+
end
|
94
|
+
|
95
|
+
@content = body
|
96
|
+
|
97
|
+
fm = meta ? YAML.load(meta) : {}
|
98
|
+
|
99
|
+
self.filters = fm['filter'] || ['erb']
|
100
|
+
|
101
|
+
self.format = fm['format'] || File.extname(fname)
|
102
|
+
|
103
|
+
if fm['output']
|
104
|
+
self.output = fm['output']
|
105
|
+
else
|
106
|
+
self.output = fname #.chomp(extension) #+ DEFAULT_CONVERSIONS[filters.last]
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
|
111
|
+
#@context = Context.new(@location) # prime context/scope
|
112
|
+
end
|
113
|
+
|
114
|
+
#
|
115
|
+
|
116
|
+
def output=(path)
|
117
|
+
if path[0,1] == '/'
|
118
|
+
path = File.join(root, path[1..-1])
|
119
|
+
else
|
120
|
+
path = File.join(location, path)
|
121
|
+
end
|
122
|
+
@output = File.expand_path(path)
|
123
|
+
end
|
124
|
+
|
125
|
+
#
|
126
|
+
|
127
|
+
def format=(ext)
|
128
|
+
ext = ext.to_s
|
129
|
+
ext = (ext[0,1] == '.' ? ext : ".#{ext}")
|
130
|
+
case ext
|
131
|
+
when '.md'
|
132
|
+
ext = '.markdown'
|
133
|
+
when '.tt'
|
134
|
+
ext = '.textile'
|
135
|
+
end
|
136
|
+
@format = ext
|
137
|
+
end
|
138
|
+
|
139
|
+
#
|
140
|
+
|
141
|
+
def filters=(list)
|
142
|
+
@filters = [list].flatten.compact.map{ |f| f.sub(/^\./,'') }
|
143
|
+
end
|
144
|
+
|
145
|
+
#
|
146
|
+
|
147
|
+
def relative_output(dir=nil)
|
148
|
+
dir = dir || Dir.pwd
|
149
|
+
output.sub(dir+'/', '')
|
150
|
+
end
|
151
|
+
|
152
|
+
# Does the output file exist?
|
153
|
+
|
154
|
+
def exist?
|
155
|
+
File.exist?(output)
|
156
|
+
end
|
157
|
+
|
158
|
+
#
|
159
|
+
|
160
|
+
def context
|
161
|
+
@context ||= Context.new(location)
|
162
|
+
end
|
163
|
+
|
164
|
+
# TODO: maybe bring root discovery up a level or two ?
|
165
|
+
|
166
|
+
def root
|
167
|
+
context.metadata.root
|
168
|
+
end
|
169
|
+
|
170
|
+
# Render a whole template.
|
171
|
+
|
172
|
+
def render
|
173
|
+
context = Context.new(location) # prime context/scope
|
174
|
+
result = content
|
175
|
+
|
176
|
+
filters.each do |filter|
|
177
|
+
if filter == 'html' # TODO: +next+ if html format and html filter ?
|
178
|
+
engine = Tilt[format]
|
179
|
+
else
|
180
|
+
engine = Tilt[filter]
|
181
|
+
end
|
182
|
+
raise "unknown filter #{filter}" unless engine
|
183
|
+
result = Dir.chdir(location) do
|
184
|
+
engine.new{result}.render(context)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
@result = result
|
188
|
+
end
|
189
|
+
|
190
|
+
# Is the current rendering different then the output file's content?
|
191
|
+
# This will call #render if it hasn't been called yet.
|
192
|
+
|
193
|
+
def changed?
|
194
|
+
render unless result
|
195
|
+
if exist?
|
196
|
+
File.read(output) != result
|
197
|
+
else
|
198
|
+
true
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
# Save the rendering to the output file.
|
203
|
+
# This will call #render if it hasn't been called yet.
|
204
|
+
|
205
|
+
def save
|
206
|
+
render unless result
|
207
|
+
if File.exist?(output)
|
208
|
+
mode = File.stat(output).mode
|
209
|
+
File.chmod(mode | 0000220, output)
|
210
|
+
File.open(output, 'w'){ |f| f << result }
|
211
|
+
File.chmod(mode, output)
|
212
|
+
else
|
213
|
+
File.open(output, 'w'){ |f| f << result }
|
214
|
+
File.chmod(0440, output) # change to read-only mode
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
end
|
219
|
+
|
220
|
+
end
|
221
|
+
|