henshin 0.4.2 → 1.0.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENCE +18 -0
- data/README.md +133 -0
- data/Rakefile +6 -51
- data/bin/henshin +127 -134
- data/lib/henshin.rb +163 -38
- data/lib/henshin/compressor.rb +31 -0
- data/lib/henshin/compressors/css.rb +20 -0
- data/lib/henshin/compressors/js.rb +20 -0
- data/lib/henshin/core_ext.rb +69 -0
- data/lib/henshin/error.rb +28 -0
- data/lib/henshin/file.rb +67 -0
- data/lib/henshin/files/abstract.rb +102 -0
- data/lib/henshin/files/attributes.rb +31 -0
- data/lib/henshin/files/empty_template.rb +24 -0
- data/lib/henshin/files/physical.rb +117 -0
- data/lib/henshin/files/post.rb +64 -0
- data/lib/henshin/files/templatable.rb +29 -0
- data/lib/henshin/files/template.rb +45 -0
- data/lib/henshin/files/tilt.rb +50 -0
- data/lib/henshin/files/tilt_template.rb +45 -0
- data/lib/henshin/package.rb +27 -0
- data/lib/henshin/packages/script.rb +23 -0
- data/lib/henshin/packages/style.rb +20 -0
- data/lib/henshin/path.rb +143 -0
- data/lib/henshin/publisher.rb +42 -0
- data/lib/henshin/publishers/sftp.rb +79 -0
- data/lib/henshin/reader.rb +68 -0
- data/lib/henshin/safety.rb +74 -0
- data/lib/henshin/scope.rb +55 -0
- data/lib/henshin/site.rb +291 -228
- data/lib/henshin/ui.rb +35 -0
- data/lib/henshin/version.rb +3 -0
- data/lib/henshin/writer.rb +43 -0
- data/lib/rack/henshin.rb +113 -0
- data/site/assets/scripts/config.js +11 -0
- data/site/assets/styles/_mixins.sass +16 -0
- data/site/assets/styles/screen.sass +198 -0
- data/site/config.yml +13 -0
- data/site/drafts/a-work-in-progress.md +5 -0
- data/site/feed.xml.slim +19 -0
- data/site/index.html.slim +28 -0
- data/site/init.rb +33 -0
- data/site/posts/1-hello-world.md +46 -0
- data/site/posts/2-code-testing.md +36 -0
- data/site/posts/3-style-test.md +80 -0
- data/site/templates/default.slim +11 -0
- data/site/templates/post.slim +30 -0
- data/site/test.html.md +7 -0
- data/spec/helper.rb +70 -0
- data/spec/henshin/compressor_spec.rb +25 -0
- data/spec/henshin/compressors/css_spec.rb +22 -0
- data/spec/henshin/compressors/js_spec.rb +22 -0
- data/spec/henshin/core_ext_spec.rb +59 -0
- data/spec/henshin/error_spec.rb +22 -0
- data/spec/henshin/file_spec.rb +28 -0
- data/spec/henshin/files/abstract_spec.rb +98 -0
- data/spec/henshin/files/attributes_spec.rb +25 -0
- data/spec/henshin/files/empty_template_spec.rb +11 -0
- data/spec/henshin/files/physical_spec.rb +55 -0
- data/spec/henshin/files/post_spec.rb +66 -0
- data/spec/henshin/files/template_spec.rb +53 -0
- data/spec/henshin/files/tilt_spec.rb +59 -0
- data/spec/henshin/package_spec.rb +24 -0
- data/spec/henshin/packages/script_spec.rb +17 -0
- data/spec/henshin/packages/style_spec.rb +17 -0
- data/spec/henshin/path_spec.rb +56 -0
- data/spec/henshin/publisher_spec.rb +44 -0
- data/spec/henshin/publishers/sftp_spec.rb +21 -0
- data/spec/henshin/reader_spec.rb +55 -0
- data/spec/henshin/safety_spec.rb +66 -0
- data/spec/henshin/scope_spec.rb +33 -0
- data/spec/henshin/site_spec.rb +142 -0
- data/spec/henshin/ui_spec.rb +26 -0
- data/spec/henshin/writer_spec.rb +26 -0
- metadata +352 -197
- data/.gitignore +0 -27
- data/LICENSE +0 -20
- data/README.markdown +0 -35
- data/VERSION +0 -1
- data/henshin.gemspec +0 -121
- data/lib/henshin/archive.rb +0 -133
- data/lib/henshin/exec/files.rb +0 -46
- data/lib/henshin/ext.rb +0 -55
- data/lib/henshin/gen.rb +0 -154
- data/lib/henshin/labels.rb +0 -144
- data/lib/henshin/plugin.rb +0 -100
- data/lib/henshin/plugins/highlight.rb +0 -24
- data/lib/henshin/plugins/liquid.rb +0 -61
- data/lib/henshin/plugins/maruku.rb +0 -18
- data/lib/henshin/plugins/sass.rb +0 -24
- data/lib/henshin/plugins/textile.rb +0 -18
- data/lib/henshin/post.rb +0 -156
- data/lib/henshin/static.rb +0 -33
- data/test/helper.rb +0 -44
- data/test/site/css/_reset.sass +0 -34
- data/test/site/css/print.css +0 -12
- data/test/site/css/screen.sass +0 -70
- data/test/site/includes/head.html +0 -1
- data/test/site/index.html +0 -23
- data/test/site/layouts/archive_date.html +0 -20
- data/test/site/layouts/archive_month.html +0 -24
- data/test/site/layouts/archive_year.html +0 -26
- data/test/site/layouts/category_index.html +0 -27
- data/test/site/layouts/category_page.html +0 -20
- data/test/site/layouts/main.html +0 -13
- data/test/site/layouts/post.html +0 -36
- data/test/site/layouts/tag_index.html +0 -27
- data/test/site/layouts/tag_page.html +0 -20
- data/test/site/options.yaml +0 -17
- data/test/site/plugins/test.rb +0 -3
- data/test/site/posts/Testing-Stuff.markdown +0 -14
- data/test/site/posts/Textile-Test.textile +0 -7
- data/test/site/posts/cat/test.markdown +0 -6
- data/test/site/posts/lorem-ipsum.markdown +0 -7
- data/test/site/posts/same-date.markdown +0 -7
- data/test/site/static.html +0 -19
- data/test/suite.rb +0 -4
- data/test/test_gen.rb +0 -98
- data/test/test_options.rb +0 -73
- data/test/test_post.rb +0 -67
- data/test/test_site.rb +0 -197
- data/test/test_static.rb +0 -13
data/lib/henshin/gen.rb
DELETED
@@ -1,154 +0,0 @@
|
|
1
|
-
module Henshin
|
2
|
-
|
3
|
-
# This is the main class for files which need to be rendered with plugins
|
4
|
-
class Gen
|
5
|
-
|
6
|
-
attr_accessor :path, :data, :content, :site, :to_inject, :generators
|
7
|
-
|
8
|
-
# Creates a new instance of Gen
|
9
|
-
#
|
10
|
-
# @param [Pathname] path to the file
|
11
|
-
# @param [Site] the site the gen belongs to
|
12
|
-
# @param [Hash] an optional payload to add when rendered
|
13
|
-
def initialize(path, site, to_inject=nil)
|
14
|
-
@path = path
|
15
|
-
@site = site
|
16
|
-
@data = {}
|
17
|
-
@content = ''
|
18
|
-
@to_inject = to_inject
|
19
|
-
@generators = []
|
20
|
-
|
21
|
-
@data['input'] = @path.extension
|
22
|
-
end
|
23
|
-
|
24
|
-
|
25
|
-
##
|
26
|
-
# Reads the file if it exists, if not gets generators and layout, then cleans up @data
|
27
|
-
def read
|
28
|
-
self.read_file if @path.exist?
|
29
|
-
self.get_generators
|
30
|
-
self.get_layout
|
31
|
-
|
32
|
-
# tidy up data
|
33
|
-
@data['output'] ||= @data['input']
|
34
|
-
self
|
35
|
-
end
|
36
|
-
|
37
|
-
# Opens the file and reads the yaml frontmatter if any exists, and
|
38
|
-
# also gets the contents of the file.
|
39
|
-
def read_file
|
40
|
-
file = @path.read
|
41
|
-
|
42
|
-
if file =~ /^(---\s*\n.*?\n?^---\s*$\n?)/m
|
43
|
-
override = YAML.load_file(@path)
|
44
|
-
@data = @data.merge(override)
|
45
|
-
@content = file[$1.size..-1]
|
46
|
-
else
|
47
|
-
@content = file
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
# Finds the correct plugins to render this gen and sets output
|
52
|
-
def get_generators
|
53
|
-
@site.plugins[:generators].each do |k, v|
|
54
|
-
if k == @data['input'] || k == '*'
|
55
|
-
@generators << v
|
56
|
-
@data['output'] ||= v.extensions[:output]
|
57
|
-
@data['ignore_layout'] ||= (v.config['ignore_layouts'] ? true : false)
|
58
|
-
end
|
59
|
-
end
|
60
|
-
@generators.sort!
|
61
|
-
end
|
62
|
-
|
63
|
-
# Gets the correct layout for the gen, or the default if none exists.
|
64
|
-
# It gets the default layout from options.yaml or looks for one called
|
65
|
-
# 'main' or 'default'.
|
66
|
-
def get_layout
|
67
|
-
if @data['layout']
|
68
|
-
@data['layout'] = site.layouts[ @data['layout'] ]
|
69
|
-
else
|
70
|
-
# get default layout
|
71
|
-
@data['layout'] = site.layouts[(site.config['layout'] || 'main' || 'default')]
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
##
|
76
|
-
# Renders the files content using the generators from #get_generators and all layout parsers.
|
77
|
-
# Passed through layout parser twice so that markup in the gen is processed.
|
78
|
-
def render
|
79
|
-
@generators.each do |plugin|
|
80
|
-
@content = plugin.generate(@content)
|
81
|
-
end
|
82
|
-
|
83
|
-
unless @data['ignore_layout'] || @data['layout'].nil?
|
84
|
-
@site.plugins[:layoutors].each do |plugin|
|
85
|
-
@content = plugin.generate(@data['layout'], self.payload)
|
86
|
-
@content = plugin.generate(@content, self.payload)
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
end
|
91
|
-
|
92
|
-
# Creates the data to be sent to the layout engine. Adds optional data if available.
|
93
|
-
#
|
94
|
-
# @return [Hash] the payload for the layout engine
|
95
|
-
def payload
|
96
|
-
hash = {
|
97
|
-
'yield' => @content,
|
98
|
-
'gen' => self.to_hash,
|
99
|
-
'site' => @site.payload['site']
|
100
|
-
}
|
101
|
-
hash[ @to_inject[:name] ] = @to_inject[:payload] if @to_inject
|
102
|
-
hash
|
103
|
-
end
|
104
|
-
|
105
|
-
# Turns all of the gens data into a hash.
|
106
|
-
#
|
107
|
-
# @return [Hash]
|
108
|
-
def to_hash
|
109
|
-
@data['content'] = @content
|
110
|
-
@data['url'] = self.url
|
111
|
-
@data['permalink'] = self.permalink
|
112
|
-
@data
|
113
|
-
end
|
114
|
-
|
115
|
-
|
116
|
-
##
|
117
|
-
# Writes the file to the correct place
|
118
|
-
def write
|
119
|
-
FileUtils.mkdir_p(self.write_path.dirname)
|
120
|
-
file = File.new(self.write_path, "w")
|
121
|
-
file.puts(@content)
|
122
|
-
end
|
123
|
-
|
124
|
-
# @return [String] the permalink of the gen
|
125
|
-
def permalink
|
126
|
-
rel = @path.relative_path_from(@site.root).to_s
|
127
|
-
rel.gsub!(".#{@data['input']}", ".#{@data['output']}")
|
128
|
-
File.join(@site.base, rel)
|
129
|
-
end
|
130
|
-
|
131
|
-
# @return [String] the pretty url for the gen
|
132
|
-
def url
|
133
|
-
if @site.config['permalink'].include?("/index.html") && @data['output'] == 'html'
|
134
|
-
self.permalink.to_p.dirname.to_s
|
135
|
-
else
|
136
|
-
self.permalink
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
# @return [Pathname] path to write the file to
|
141
|
-
def write_path
|
142
|
-
@site.target + self.permalink[1..-1]
|
143
|
-
end
|
144
|
-
|
145
|
-
# Sorts gens based on permalink only
|
146
|
-
def <=>( other )
|
147
|
-
self.permalink <=> other.permalink
|
148
|
-
end
|
149
|
-
|
150
|
-
def inspect
|
151
|
-
"#<Gen:#{@path}>"
|
152
|
-
end
|
153
|
-
end
|
154
|
-
end
|
data/lib/henshin/labels.rb
DELETED
@@ -1,144 +0,0 @@
|
|
1
|
-
module Henshin
|
2
|
-
|
3
|
-
# This is basically a front for tags and categories, because they are so similar
|
4
|
-
# it makes sense to condense them into one class!
|
5
|
-
#
|
6
|
-
class Labels < Array
|
7
|
-
|
8
|
-
attr_accessor :base, :site
|
9
|
-
|
10
|
-
# Creates a new instance of labels
|
11
|
-
#
|
12
|
-
# @param [String] base the base part of the urls, eg. category, tag
|
13
|
-
# @param [Site] site that the labels belong to
|
14
|
-
def initialize(base, site)
|
15
|
-
@base = base
|
16
|
-
@site = site
|
17
|
-
end
|
18
|
-
|
19
|
-
# Adds the given post to the correct category object in the array
|
20
|
-
# or creates the category and adds the post to that
|
21
|
-
#
|
22
|
-
# @param [Post] post to be added
|
23
|
-
# @param [String, Array] k label(s) to be added to
|
24
|
-
#
|
25
|
-
# @todo Make it a bit more abstract, actually hard coding stuff in will
|
26
|
-
# lead to problems!
|
27
|
-
def <<(post)
|
28
|
-
k = nil
|
29
|
-
if base == 'tag'
|
30
|
-
k = post.data['tags']
|
31
|
-
elsif base == 'category'
|
32
|
-
k = [post.data['category']]
|
33
|
-
end
|
34
|
-
|
35
|
-
k.each do |j|
|
36
|
-
unless self.map{|i| i.name}.include?(j)
|
37
|
-
super Henshin::Label.new(j, @base, @site)
|
38
|
-
end
|
39
|
-
i = self.find_index {|i| i.name == j}
|
40
|
-
self[i].posts << post
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
# Converts the labels to a hash for use in a layout parser
|
45
|
-
def to_hash
|
46
|
-
r = []
|
47
|
-
self.each do |i|
|
48
|
-
r << i.to_hash
|
49
|
-
end
|
50
|
-
r
|
51
|
-
end
|
52
|
-
|
53
|
-
# @return [String] permalink for label index
|
54
|
-
def permalink
|
55
|
-
File.join(@site.base, @base, "index.html")
|
56
|
-
end
|
57
|
-
|
58
|
-
# @return [String] base url for label
|
59
|
-
def url
|
60
|
-
File.join(@site.base, @base)
|
61
|
-
end
|
62
|
-
|
63
|
-
# Need a fake path where the file would have been so as to
|
64
|
-
# trick the gen into constructing the correct paths
|
65
|
-
#
|
66
|
-
# @return [Pathname] the path for the gen
|
67
|
-
def fake_write_path
|
68
|
-
@site.root + self.permalink[1..-1]
|
69
|
-
end
|
70
|
-
|
71
|
-
# Writes the category index, then writes the individual
|
72
|
-
# category pages
|
73
|
-
def write
|
74
|
-
if @site.layouts["#{@base}_index"]
|
75
|
-
page = Gen.new(self.fake_write_path, @site)
|
76
|
-
page.read
|
77
|
-
page.data['layout'] = @site.layouts["#{@base}_index"]
|
78
|
-
|
79
|
-
page.render
|
80
|
-
page.write
|
81
|
-
end
|
82
|
-
if @site.layouts["#{@base}_page"]
|
83
|
-
self.each {|label| label.write }
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
end
|
88
|
-
|
89
|
-
class Label
|
90
|
-
attr_accessor :name, :posts, :site
|
91
|
-
|
92
|
-
# Creates a new instance of label
|
93
|
-
#
|
94
|
-
# @param [String] name of the label
|
95
|
-
# @param [String] base of the url for the label (see Labels#initialize)
|
96
|
-
# @param [Site] site that the label belongs to
|
97
|
-
def initialize(name, base, site)
|
98
|
-
@name = name
|
99
|
-
@base = base
|
100
|
-
@site = site
|
101
|
-
@posts = []
|
102
|
-
end
|
103
|
-
|
104
|
-
# Converts the label to a hash
|
105
|
-
def to_hash
|
106
|
-
hash = {
|
107
|
-
'name' => @name,
|
108
|
-
'posts' => @posts.sort.collect {|i| i.to_hash},
|
109
|
-
'url' => self.url
|
110
|
-
}
|
111
|
-
end
|
112
|
-
|
113
|
-
# @return [String] permalink for the label
|
114
|
-
def permalink
|
115
|
-
File.join(@site.base, @base, "#{@name.slugify}/index.html")
|
116
|
-
end
|
117
|
-
|
118
|
-
# @return [String] url for the label
|
119
|
-
def url
|
120
|
-
File.join(@site.base, @base, "#{@name.slugify}")
|
121
|
-
end
|
122
|
-
|
123
|
-
# @see Labels#fake_write_path
|
124
|
-
def fake_write_path
|
125
|
-
@site.root + self.permalink[1..-1]
|
126
|
-
end
|
127
|
-
|
128
|
-
# Writes the label page
|
129
|
-
def write
|
130
|
-
payload = {:name => @base, :payload => self.to_hash}
|
131
|
-
page = Gen.new(self.fake_write_path, @site, payload)
|
132
|
-
page.read
|
133
|
-
page.data['layout'] = @site.layouts["#{@base}_page"]
|
134
|
-
|
135
|
-
page.render
|
136
|
-
page.write
|
137
|
-
end
|
138
|
-
|
139
|
-
def inspect
|
140
|
-
"#<Label:#{@base}/#{@name}>"
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
|
-
end
|
data/lib/henshin/plugin.rb
DELETED
@@ -1,100 +0,0 @@
|
|
1
|
-
module Henshin
|
2
|
-
|
3
|
-
class Plugin
|
4
|
-
|
5
|
-
# @return [Hash{:input, :output => Array, String}]
|
6
|
-
# the file extensions that can be read by the plugin and the extension
|
7
|
-
# of the output
|
8
|
-
#
|
9
|
-
# @example
|
10
|
-
#
|
11
|
-
# @extensions = {:input => ['md', 'markdown'],
|
12
|
-
# :output => 'html'}
|
13
|
-
attr_accessor :extensions
|
14
|
-
|
15
|
-
# @return [Hash{Symbol => Object}]
|
16
|
-
# the config for the plugin
|
17
|
-
attr_accessor :config
|
18
|
-
|
19
|
-
# @return [Integer]
|
20
|
-
# The plugins are sorted on priority, high priority plugins are called first.
|
21
|
-
# You could really use any number, but stick to 1 to 5.
|
22
|
-
attr_accessor :priority
|
23
|
-
|
24
|
-
# Create a new instance of Plugin
|
25
|
-
#
|
26
|
-
# @param [Site] site that the plugin belongs to
|
27
|
-
def initialize(site)
|
28
|
-
@extensions = {:input => [],
|
29
|
-
:output => ''}
|
30
|
-
@config = {}
|
31
|
-
@priority = 3
|
32
|
-
end
|
33
|
-
|
34
|
-
# Finds all classes that subclass this particular class
|
35
|
-
#
|
36
|
-
# @return [Array] an array of class objects
|
37
|
-
# @see http://www.ruby-forum.com/topic/163430
|
38
|
-
# modified from the answer given on ruby-forum by black eyes
|
39
|
-
def self.subclasses
|
40
|
-
r = Henshin.constants.find_all do |c_klass|
|
41
|
-
if (c_klass != c_klass.upcase) && (Henshin.const_get(c_klass).is_a?(Class))
|
42
|
-
self > Henshin.const_get(c_klass)
|
43
|
-
else
|
44
|
-
nil
|
45
|
-
end
|
46
|
-
end
|
47
|
-
r.collect {|k| Henshin.const_get(k)}
|
48
|
-
end
|
49
|
-
|
50
|
-
# Plugins are sorted by priority
|
51
|
-
def <=>(other)
|
52
|
-
self.priority <=> other.priority
|
53
|
-
end
|
54
|
-
|
55
|
-
end
|
56
|
-
|
57
|
-
# Generator is the plugin type for processing things like markdown
|
58
|
-
#
|
59
|
-
# @example
|
60
|
-
#
|
61
|
-
# class MyMarkupPlugin < Henshin::Generator
|
62
|
-
# def generate(content)
|
63
|
-
# MyMarkup.do_stuff(content)
|
64
|
-
# end
|
65
|
-
# end
|
66
|
-
#
|
67
|
-
class Generator < Plugin
|
68
|
-
|
69
|
-
# This is the method that is called when rendering content
|
70
|
-
#
|
71
|
-
# @param [String] content to be rendered
|
72
|
-
# @return [String]
|
73
|
-
def generate( content )
|
74
|
-
end
|
75
|
-
|
76
|
-
end
|
77
|
-
|
78
|
-
# Layoutor is the plugin type for things like liquid
|
79
|
-
#
|
80
|
-
# @example
|
81
|
-
#
|
82
|
-
# class MyLayoutPlugin < Henshin::Layoutor
|
83
|
-
# def generate(content, data)
|
84
|
-
# MyLayout.do_stuff(content).render(data)
|
85
|
-
# end
|
86
|
-
# end
|
87
|
-
#
|
88
|
-
class Layoutor < Plugin
|
89
|
-
|
90
|
-
# This is the method called when rendering content
|
91
|
-
#
|
92
|
-
# @param [String] content to be rendered
|
93
|
-
# @param [Hash] data to be put into the content
|
94
|
-
# @return [String]
|
95
|
-
def generate( content, data )
|
96
|
-
end
|
97
|
-
|
98
|
-
end
|
99
|
-
|
100
|
-
end
|
@@ -1,24 +0,0 @@
|
|
1
|
-
require 'simplabs/highlight'
|
2
|
-
|
3
|
-
module Henshin
|
4
|
-
class HighlightPlugin < Generator
|
5
|
-
|
6
|
-
def initialize(site)
|
7
|
-
@extensions = {:input => ['*']}
|
8
|
-
@config = {}
|
9
|
-
@priority = 1
|
10
|
-
end
|
11
|
-
|
12
|
-
def generate( content )
|
13
|
-
content =~ /(\$highlight)\s+(.+)((\n.*)+)(\$end)/
|
14
|
-
if $1
|
15
|
-
lang = $2.to_sym
|
16
|
-
code = $3[1..-1] # removes first new line
|
17
|
-
insert = '<pre><code>' + Simplabs::Highlight.highlight(lang, code) + '</code></pre>'
|
18
|
-
content.gsub(/(\$highlight.*\$end)/m, insert)
|
19
|
-
else
|
20
|
-
content
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
@@ -1,61 +0,0 @@
|
|
1
|
-
require 'liquid'
|
2
|
-
|
3
|
-
module Henshin
|
4
|
-
class LiquidPlugin < Layoutor
|
5
|
-
|
6
|
-
def initialize(site)
|
7
|
-
@config = {}
|
8
|
-
|
9
|
-
if site.config['liquid']
|
10
|
-
@config = site.config['liquid']
|
11
|
-
@config['include_dir'] = File.join(site.root, @config['include_dir'])
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def generate( content, data )
|
16
|
-
reg = {:include_dir => @config['include_dir']}
|
17
|
-
Liquid::Template.parse(content).render(data, :registers => reg)
|
18
|
-
end
|
19
|
-
|
20
|
-
module Filters
|
21
|
-
def date_to_string(dt)
|
22
|
-
dt.strftime "%d %b %Y"
|
23
|
-
end
|
24
|
-
|
25
|
-
def date_to_long(dt)
|
26
|
-
dt.strftime "%d %B %Y at %H:%M"
|
27
|
-
end
|
28
|
-
|
29
|
-
def time_to_string(dt)
|
30
|
-
dt.strtime "%H:%M"
|
31
|
-
end
|
32
|
-
|
33
|
-
def titlecase(str)
|
34
|
-
str.upcase
|
35
|
-
end
|
36
|
-
|
37
|
-
def escape(str)
|
38
|
-
CGI::escape str
|
39
|
-
end
|
40
|
-
|
41
|
-
def escape_html(str)
|
42
|
-
CGI::escapeHTML str
|
43
|
-
end
|
44
|
-
end
|
45
|
-
Liquid::Template.register_filter(Filters)
|
46
|
-
|
47
|
-
class Include < Liquid::Tag
|
48
|
-
def initialize(tag_name, file, tokens)
|
49
|
-
super
|
50
|
-
@file = file.strip
|
51
|
-
end
|
52
|
-
|
53
|
-
def render(context)
|
54
|
-
include = File.join(context.registers[:include_dir], @file)
|
55
|
-
File.open(include, 'r') {|f| f.read}
|
56
|
-
end
|
57
|
-
end
|
58
|
-
Liquid::Template.register_tag('include', Include)
|
59
|
-
|
60
|
-
end
|
61
|
-
end
|