bunto 3.0.0 → 3.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +124 -76
- data/README.markdown +49 -12
- data/{bin → exe}/bunto +18 -14
- data/lib/bunto.rb +83 -78
- data/lib/bunto/cleaner.rb +10 -8
- data/lib/bunto/collection.rb +33 -17
- data/lib/bunto/command.rb +19 -13
- data/lib/bunto/commands/build.rb +22 -14
- data/lib/bunto/commands/clean.rb +9 -8
- data/lib/bunto/commands/doctor.rb +10 -8
- data/lib/bunto/commands/help.rb +4 -3
- data/lib/bunto/commands/new.rb +30 -21
- data/lib/bunto/commands/new_theme.rb +36 -0
- data/lib/bunto/commands/serve.rb +26 -20
- data/lib/bunto/commands/serve/servlet.rb +4 -5
- data/lib/bunto/configuration.rb +187 -125
- data/lib/bunto/converters/markdown.rb +19 -9
- data/lib/bunto/converters/markdown/kramdown_parser.rb +12 -5
- data/lib/bunto/converters/markdown/rdiscount_parser.rb +4 -4
- data/lib/bunto/converters/markdown/redcarpet_parser.rb +90 -84
- data/lib/bunto/convertible.rb +38 -25
- data/lib/bunto/deprecator.rb +11 -6
- data/lib/bunto/desktop.ini +2 -0
- data/lib/bunto/document.rb +53 -51
- data/lib/bunto/drops/bunto_drop.rb +12 -0
- data/lib/bunto/drops/document_drop.rb +40 -5
- data/lib/bunto/drops/drop.rb +49 -10
- data/lib/bunto/drops/excerpt_drop.rb +15 -0
- data/lib/bunto/drops/site_drop.rb +4 -2
- data/lib/bunto/drops/url_drop.rb +4 -4
- data/lib/bunto/entry_filter.rb +64 -19
- data/lib/bunto/errors.rb +6 -3
- data/lib/bunto/excerpt.rb +4 -6
- data/lib/bunto/external.rb +4 -4
- data/lib/bunto/filters.rb +72 -39
- data/lib/bunto/frontmatter_defaults.rb +45 -38
- data/lib/bunto/hooks.rb +21 -21
- data/lib/bunto/layout.rb +4 -8
- data/lib/bunto/liquid_renderer.rb +14 -3
- data/lib/bunto/liquid_renderer/file.rb +5 -1
- data/lib/bunto/liquid_renderer/table.rb +11 -11
- data/lib/bunto/log_adapter.rb +2 -2
- data/lib/bunto/page.rb +10 -10
- data/lib/bunto/plugin.rb +5 -5
- data/lib/bunto/plugin_manager.rb +12 -8
- data/lib/bunto/publisher.rb +1 -1
- data/lib/bunto/reader.rb +11 -7
- data/lib/bunto/readers/data_reader.rb +9 -9
- data/lib/bunto/readers/layout_reader.rb +7 -7
- data/lib/bunto/readers/page_reader.rb +3 -1
- data/lib/bunto/readers/post_reader.rb +9 -10
- data/lib/bunto/readers/static_file_reader.rb +3 -1
- data/lib/bunto/regenerator.rb +50 -28
- data/lib/bunto/related_posts.rb +1 -1
- data/lib/bunto/renderer.rb +33 -23
- data/lib/bunto/site.rb +94 -51
- data/lib/bunto/static_file.rb +33 -26
- data/lib/bunto/stevenson.rb +6 -5
- data/lib/bunto/tags/highlight.rb +50 -35
- data/lib/bunto/tags/include.rb +42 -31
- data/lib/bunto/tags/link.rb +11 -4
- data/lib/bunto/tags/post_url.rb +8 -7
- data/lib/bunto/theme.rb +10 -8
- data/lib/bunto/theme_builder.rb +117 -0
- data/lib/bunto/url.rb +21 -14
- data/lib/bunto/utils.rb +57 -28
- data/lib/bunto/utils/ansi.rb +9 -9
- data/lib/bunto/utils/platforms.rb +2 -2
- data/lib/bunto/version.rb +1 -1
- data/lib/site_template/_config.yml +3 -1
- data/lib/site_template/_posts/0000-00-00-welcome-to-bunto.markdown.erb +3 -3
- data/lib/site_template/about.md +3 -3
- data/lib/site_template/css/main.scss +3 -17
- data/lib/theme_template/CODE_OF_CONDUCT.md.erb +74 -0
- data/lib/theme_template/Gemfile +2 -0
- data/lib/theme_template/LICENSE.txt.erb +21 -0
- data/lib/theme_template/README.md.erb +48 -0
- data/lib/theme_template/_layouts/default.html +1 -0
- data/lib/theme_template/_layouts/page.html +5 -0
- data/lib/theme_template/_layouts/post.html +5 -0
- data/lib/theme_template/example/_config.yml.erb +1 -0
- data/lib/theme_template/example/_post.md +12 -0
- data/lib/theme_template/example/index.html +14 -0
- data/lib/theme_template/example/style.scss +7 -0
- data/lib/theme_template/gitignore.erb +4 -0
- data/lib/theme_template/theme.gemspec.erb +18 -0
- metadata +40 -19
- data/lib/site_template/_includes/footer.html +0 -38
- data/lib/site_template/_includes/head.html +0 -12
- data/lib/site_template/_includes/header.html +0 -27
- data/lib/site_template/_includes/icon-github.html +0 -1
- data/lib/site_template/_includes/icon-github.svg +0 -1
- data/lib/site_template/_includes/icon-twitter.html +0 -1
- data/lib/site_template/_includes/icon-twitter.svg +0 -1
- data/lib/site_template/_layouts/default.html +0 -20
- data/lib/site_template/_layouts/page.html +0 -14
- data/lib/site_template/_layouts/post.html +0 -15
- data/lib/site_template/_sass/_base.scss +0 -200
- data/lib/site_template/_sass/_layout.scss +0 -242
- data/lib/site_template/_sass/_syntax-highlighting.scss +0 -71
@@ -24,11 +24,13 @@ module Bunto
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def html_pages
|
27
|
-
@site_html_pages ||= @obj.pages.select
|
27
|
+
@site_html_pages ||= @obj.pages.select do |page|
|
28
|
+
page.html? || page.url.end_with?("/")
|
29
|
+
end
|
28
30
|
end
|
29
31
|
|
30
32
|
def collections
|
31
|
-
@site_collections ||= @obj.collections.values.map(&:to_liquid)
|
33
|
+
@site_collections ||= @obj.collections.values.sort_by(&:label).map(&:to_liquid)
|
32
34
|
end
|
33
35
|
|
34
36
|
private
|
data/lib/bunto/drops/url_drop.rb
CHANGED
@@ -19,20 +19,20 @@ module Bunto
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def title
|
22
|
-
Utils.slugify(@obj.data[
|
22
|
+
Utils.slugify(@obj.data["slug"], :mode => "pretty", :cased => true) ||
|
23
23
|
Utils.slugify(@obj.basename_without_ext, :mode => "pretty", :cased => true)
|
24
24
|
end
|
25
25
|
|
26
26
|
def slug
|
27
|
-
Utils.slugify(@obj.data[
|
27
|
+
Utils.slugify(@obj.data["slug"]) || Utils.slugify(@obj.basename_without_ext)
|
28
28
|
end
|
29
29
|
|
30
30
|
def categories
|
31
31
|
category_set = Set.new
|
32
|
-
Array(@obj.data[
|
32
|
+
Array(@obj.data["categories"]).each do |category|
|
33
33
|
category_set << category.to_s.downcase
|
34
34
|
end
|
35
|
-
category_set.to_a.join(
|
35
|
+
category_set.to_a.join("/")
|
36
36
|
end
|
37
37
|
|
38
38
|
def year
|
data/lib/bunto/entry_filter.rb
CHANGED
@@ -1,12 +1,15 @@
|
|
1
1
|
module Bunto
|
2
2
|
class EntryFilter
|
3
|
-
SPECIAL_LEADING_CHARACTERS = ['.', '_', '#', '~'].freeze
|
4
|
-
|
5
3
|
attr_reader :site
|
4
|
+
SPECIAL_LEADING_CHARACTERS = [
|
5
|
+
".", "_", "#", "~"
|
6
|
+
].freeze
|
6
7
|
|
7
8
|
def initialize(site, base_directory = nil)
|
8
9
|
@site = site
|
9
|
-
@base_directory = derive_base_directory(
|
10
|
+
@base_directory = derive_base_directory(
|
11
|
+
@site, base_directory.to_s.dup
|
12
|
+
)
|
10
13
|
end
|
11
14
|
|
12
15
|
def base_directory
|
@@ -14,14 +17,14 @@ module Bunto
|
|
14
17
|
end
|
15
18
|
|
16
19
|
def derive_base_directory(site, base_dir)
|
17
|
-
if base_dir.start_with?(site.source)
|
18
|
-
base_dir[site.source] = ""
|
19
|
-
end
|
20
|
+
base_dir[site.source] = "" if base_dir.start_with?(site.source)
|
20
21
|
base_dir
|
21
22
|
end
|
22
23
|
|
23
24
|
def relative_to_source(entry)
|
24
|
-
File.join(
|
25
|
+
File.join(
|
26
|
+
base_directory, entry
|
27
|
+
)
|
25
28
|
end
|
26
29
|
|
27
30
|
def filter(entries)
|
@@ -33,7 +36,8 @@ module Bunto
|
|
33
36
|
end
|
34
37
|
|
35
38
|
def included?(entry)
|
36
|
-
glob_include?(site.include,
|
39
|
+
glob_include?(site.include,
|
40
|
+
entry)
|
37
41
|
end
|
38
42
|
|
39
43
|
def special?(entry)
|
@@ -42,34 +46,75 @@ module Bunto
|
|
42
46
|
end
|
43
47
|
|
44
48
|
def backup?(entry)
|
45
|
-
entry[-1..-1] ==
|
49
|
+
entry[-1..-1] == "~"
|
46
50
|
end
|
47
51
|
|
48
52
|
def excluded?(entry)
|
49
53
|
excluded = glob_include?(site.exclude, relative_to_source(entry))
|
50
|
-
|
54
|
+
if excluded
|
55
|
+
Bunto.logger.debug(
|
56
|
+
"EntryFilter:",
|
57
|
+
"excluded #{relative_to_source(entry)}"
|
58
|
+
)
|
59
|
+
end
|
51
60
|
excluded
|
52
61
|
end
|
53
62
|
|
63
|
+
# --
|
64
|
+
# Check if a file is a symlink.
|
65
|
+
# NOTE: This can be converted to allowing even in safe,
|
66
|
+
# since we use Pathutil#in_path? now.
|
67
|
+
# --
|
54
68
|
def symlink?(entry)
|
55
69
|
site.safe && File.symlink?(entry) && symlink_outside_site_source?(entry)
|
56
70
|
end
|
57
71
|
|
72
|
+
# --
|
73
|
+
# NOTE: Pathutil#in_path? gets the realpath.
|
74
|
+
# @param [<Anything>] entry the entry you want to validate.
|
75
|
+
# Check if a path is outside of our given root.
|
76
|
+
# --
|
58
77
|
def symlink_outside_site_source?(entry)
|
59
|
-
!
|
60
|
-
|
61
|
-
|
62
|
-
def ensure_leading_slash(path)
|
63
|
-
path[0..0] == "/" ? path : "/#{path}"
|
78
|
+
!Pathutil.new(entry).in_path?(
|
79
|
+
site.in_source_dir
|
80
|
+
)
|
64
81
|
end
|
65
82
|
|
83
|
+
# --
|
84
|
+
# Check if an entry matches a specific pattern and return true,false.
|
66
85
|
# Returns true if path matches against any glob pattern.
|
67
|
-
#
|
86
|
+
# --
|
68
87
|
def glob_include?(enum, e)
|
69
|
-
entry =
|
88
|
+
entry = Pathutil.new(site.in_source_dir).join(e)
|
70
89
|
enum.any? do |exp|
|
71
|
-
|
72
|
-
|
90
|
+
# Users who send a Regexp knows what they want to
|
91
|
+
# exclude, so let them send a Regexp to exclude files,
|
92
|
+
# we will not bother caring if it works or not, it's
|
93
|
+
# on them at this point.
|
94
|
+
|
95
|
+
if exp.is_a?(Regexp)
|
96
|
+
entry =~ exp
|
97
|
+
|
98
|
+
else
|
99
|
+
item = Pathutil.new(site.in_source_dir).join(exp)
|
100
|
+
|
101
|
+
# If it's a directory they want to exclude, AKA
|
102
|
+
# ends with a "/" then we will go on to check and
|
103
|
+
# see if the entry falls within that path and
|
104
|
+
# exclude it if that's the case.
|
105
|
+
|
106
|
+
if e.end_with?("/")
|
107
|
+
entry.in_path?(
|
108
|
+
item
|
109
|
+
)
|
110
|
+
|
111
|
+
else
|
112
|
+
File.fnmatch?(item, entry) ||
|
113
|
+
entry.to_path.start_with?(
|
114
|
+
item
|
115
|
+
)
|
116
|
+
end
|
117
|
+
end
|
73
118
|
end
|
74
119
|
end
|
75
120
|
end
|
data/lib/bunto/errors.rb
CHANGED
@@ -2,13 +2,16 @@ module Bunto
|
|
2
2
|
module Errors
|
3
3
|
FatalException = Class.new(::RuntimeError)
|
4
4
|
|
5
|
+
InvalidThemeName = Class.new(FatalException)
|
6
|
+
|
5
7
|
DropMutationException = Class.new(FatalException)
|
6
8
|
InvalidPermalinkError = Class.new(FatalException)
|
7
9
|
InvalidYAMLFrontMatterError = Class.new(FatalException)
|
8
10
|
MissingDependencyException = Class.new(FatalException)
|
9
11
|
|
10
|
-
InvalidDateError
|
11
|
-
InvalidPostNameError
|
12
|
-
PostURLError
|
12
|
+
InvalidDateError = Class.new(FatalException)
|
13
|
+
InvalidPostNameError = Class.new(FatalException)
|
14
|
+
PostURLError = Class.new(FatalException)
|
15
|
+
InvalidURLError = Class.new(FatalException)
|
13
16
|
end
|
14
17
|
end
|
data/lib/bunto/excerpt.rb
CHANGED
@@ -7,7 +7,8 @@ module Bunto
|
|
7
7
|
attr_writer :output
|
8
8
|
|
9
9
|
def_delegators :@doc, :site, :name, :ext, :relative_path, :extname,
|
10
|
-
:render_with_liquid?, :collection, :related_posts
|
10
|
+
:render_with_liquid?, :collection, :related_posts,
|
11
|
+
:url, :next_doc, :previous_doc
|
11
12
|
|
12
13
|
# Initialize this Excerpt instance.
|
13
14
|
#
|
@@ -59,10 +60,7 @@ module Bunto
|
|
59
60
|
end
|
60
61
|
|
61
62
|
def to_liquid
|
62
|
-
|
63
|
-
@to_liquid ||= doc.to_liquid
|
64
|
-
doc.data['excerpt'] = self
|
65
|
-
@to_liquid
|
63
|
+
Bunto::Drops::ExcerptDrop.new(self)
|
66
64
|
end
|
67
65
|
|
68
66
|
# Returns the shorthand String identifier of this doc.
|
@@ -120,7 +118,7 @@ module Bunto
|
|
120
118
|
if tail.empty?
|
121
119
|
head
|
122
120
|
else
|
123
|
-
"" << head << "\n\n" << tail.scan(
|
121
|
+
"" << head << "\n\n" << tail.scan(%r!^\[[^\]]+\]:.+$!).join("\n")
|
124
122
|
end
|
125
123
|
end
|
126
124
|
end
|
data/lib/bunto/external.rb
CHANGED
@@ -17,13 +17,13 @@ module Bunto
|
|
17
17
|
#
|
18
18
|
# names - a string gem name or array of gem names
|
19
19
|
#
|
20
|
-
def require_if_present(names
|
20
|
+
def require_if_present(names)
|
21
21
|
Array(names).each do |name|
|
22
22
|
begin
|
23
23
|
require name
|
24
24
|
rescue LoadError
|
25
25
|
Bunto.logger.debug "Couldn't load #{name}. Skipping."
|
26
|
-
|
26
|
+
yield(name) if block_given?
|
27
27
|
false
|
28
28
|
end
|
29
29
|
end
|
@@ -39,7 +39,7 @@ module Bunto
|
|
39
39
|
def require_with_graceful_fail(names)
|
40
40
|
Array(names).each do |name|
|
41
41
|
begin
|
42
|
-
Bunto.logger.debug "Requiring:",
|
42
|
+
Bunto.logger.debug "Requiring:", name.to_s
|
43
43
|
require name
|
44
44
|
rescue LoadError => e
|
45
45
|
Bunto.logger.error "Dependency Error:", <<-MSG
|
@@ -50,7 +50,7 @@ The full error message from Ruby is: '#{e.message}'
|
|
50
50
|
|
51
51
|
If you run into trouble, you can find helpful resources at http://bunto.github.io/help/!
|
52
52
|
MSG
|
53
|
-
raise Bunto::Errors::MissingDependencyException
|
53
|
+
raise Bunto::Errors::MissingDependencyException, name
|
54
54
|
end
|
55
55
|
end
|
56
56
|
end
|
data/lib/bunto/filters.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
1
|
+
require "uri"
|
2
|
+
require "json"
|
3
|
+
require "date"
|
4
|
+
require "liquid"
|
5
5
|
|
6
6
|
module Bunto
|
7
7
|
module Filters
|
@@ -13,7 +13,7 @@ module Bunto
|
|
13
13
|
def markdownify(input)
|
14
14
|
site = @context.registers[:site]
|
15
15
|
converter = site.find_converter_instance(Bunto::Converters::Markdown)
|
16
|
-
converter.convert(input)
|
16
|
+
converter.convert(input.to_s)
|
17
17
|
end
|
18
18
|
|
19
19
|
# Convert quotes into smart quotes.
|
@@ -24,7 +24,7 @@ module Bunto
|
|
24
24
|
def smartify(input)
|
25
25
|
site = @context.registers[:site]
|
26
26
|
converter = site.find_converter_instance(Bunto::Converters::SmartyPants)
|
27
|
-
converter.convert(input)
|
27
|
+
converter.convert(input.to_s)
|
28
28
|
end
|
29
29
|
|
30
30
|
# Convert a Sass string into CSS output.
|
@@ -56,7 +56,7 @@ module Bunto
|
|
56
56
|
#
|
57
57
|
# Returns the given filename or title as a lowercase URL String.
|
58
58
|
# See Utils.slugify for more detail.
|
59
|
-
def slugify(input, mode=nil)
|
59
|
+
def slugify(input, mode = nil)
|
60
60
|
Utils.slugify(input, :mode => mode)
|
61
61
|
end
|
62
62
|
|
@@ -118,7 +118,7 @@ module Bunto
|
|
118
118
|
#
|
119
119
|
# Returns the escaped String.
|
120
120
|
def xml_escape(input)
|
121
|
-
input.to_s.encode(:xml => :attr).gsub(
|
121
|
+
input.to_s.encode(:xml => :attr).gsub(%r!\A"|"\Z!, "")
|
122
122
|
end
|
123
123
|
|
124
124
|
# CGI escape a string for use in a URL. Replaces any special characters
|
@@ -133,7 +133,7 @@ module Bunto
|
|
133
133
|
#
|
134
134
|
# Returns the escaped String.
|
135
135
|
def cgi_escape(input)
|
136
|
-
CGI
|
136
|
+
CGI.escape(input)
|
137
137
|
end
|
138
138
|
|
139
139
|
# URI escape a string.
|
@@ -150,6 +150,15 @@ module Bunto
|
|
150
150
|
URI.escape(input)
|
151
151
|
end
|
152
152
|
|
153
|
+
# Replace any whitespace in the input string with a single space
|
154
|
+
#
|
155
|
+
# input - The String on which to operate.
|
156
|
+
#
|
157
|
+
# Returns the formatted String
|
158
|
+
def normalize_whitespace(input)
|
159
|
+
input.to_s.gsub(%r!\s+!, " ").strip
|
160
|
+
end
|
161
|
+
|
153
162
|
# Count the number of words in the input string.
|
154
163
|
#
|
155
164
|
# input - The String on which to operate.
|
@@ -180,7 +189,7 @@ module Bunto
|
|
180
189
|
when 2
|
181
190
|
"#{array[0]} #{connector} #{array[1]}"
|
182
191
|
else
|
183
|
-
"#{array[0...-1].join(
|
192
|
+
"#{array[0...-1].join(", ")}, #{connector} #{array[-1]}"
|
184
193
|
end
|
185
194
|
end
|
186
195
|
|
@@ -203,11 +212,14 @@ module Bunto
|
|
203
212
|
# "items" => [...] } # all the items where `property` == "larry"
|
204
213
|
def group_by(input, property)
|
205
214
|
if groupable?(input)
|
206
|
-
input.group_by
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
215
|
+
input.group_by { |item| item_property(item, property).to_s }
|
216
|
+
.each_with_object([]) do |item, array|
|
217
|
+
array << {
|
218
|
+
"name" => item.first,
|
219
|
+
"items" => item.last,
|
220
|
+
"size" => item.last.size
|
221
|
+
}
|
222
|
+
end
|
211
223
|
else
|
212
224
|
input
|
213
225
|
end
|
@@ -221,9 +233,11 @@ module Bunto
|
|
221
233
|
#
|
222
234
|
# Returns the filtered array of objects
|
223
235
|
def where(input, property, value)
|
224
|
-
return input unless input.
|
236
|
+
return input unless input.respond_to?(:select)
|
225
237
|
input = input.values if input.is_a?(Hash)
|
226
|
-
input.select
|
238
|
+
input.select do |object|
|
239
|
+
Array(item_property(object, property)).map(&:to_s).include?(value.to_s)
|
240
|
+
end || []
|
227
241
|
end
|
228
242
|
|
229
243
|
# Filters an array of objects against an expression
|
@@ -234,7 +248,7 @@ module Bunto
|
|
234
248
|
#
|
235
249
|
# Returns the filtered array of objects
|
236
250
|
def where_exp(input, variable, expression)
|
237
|
-
return input unless input.
|
251
|
+
return input unless input.respond_to?(:select)
|
238
252
|
input = input.values if input.is_a?(Hash) # FIXME
|
239
253
|
|
240
254
|
condition = parse_condition(expression)
|
@@ -243,7 +257,18 @@ module Bunto
|
|
243
257
|
@context[variable] = object
|
244
258
|
condition.evaluate(@context)
|
245
259
|
end
|
246
|
-
end
|
260
|
+
end || []
|
261
|
+
end
|
262
|
+
|
263
|
+
# Convert the input into integer
|
264
|
+
#
|
265
|
+
# input - the object string
|
266
|
+
#
|
267
|
+
# Returns the integer value
|
268
|
+
def to_integer(input)
|
269
|
+
return 1 if input == true
|
270
|
+
return 0 if input == false
|
271
|
+
input.to_i
|
247
272
|
end
|
248
273
|
|
249
274
|
# Sort an array of objects
|
@@ -255,33 +280,21 @@ module Bunto
|
|
255
280
|
# Returns the filtered array of objects
|
256
281
|
def sort(input, property = nil, nils = "first")
|
257
282
|
if input.nil?
|
258
|
-
raise ArgumentError
|
283
|
+
raise ArgumentError, "Cannot sort a null object."
|
259
284
|
end
|
260
285
|
if property.nil?
|
261
286
|
input.sort
|
262
287
|
else
|
263
|
-
|
264
|
-
when nils == "first"
|
288
|
+
if nils == "first"
|
265
289
|
order = - 1
|
266
|
-
|
290
|
+
elsif nils == "last"
|
267
291
|
order = + 1
|
268
292
|
else
|
269
|
-
raise ArgumentError
|
270
|
-
"'#{nils}' is not a valid nils order. It must be 'first' or 'last'."
|
293
|
+
raise ArgumentError, "Invalid nils order: " \
|
294
|
+
"'#{nils}' is not a valid nils order. It must be 'first' or 'last'."
|
271
295
|
end
|
272
296
|
|
273
|
-
input
|
274
|
-
apple_property = item_property(apple, property)
|
275
|
-
orange_property = item_property(orange, property)
|
276
|
-
|
277
|
-
if !apple_property.nil? && orange_property.nil?
|
278
|
-
- order
|
279
|
-
elsif apple_property.nil? && !orange_property.nil?
|
280
|
-
+ order
|
281
|
-
else
|
282
|
-
apple_property <=> orange_property
|
283
|
-
end
|
284
|
-
end
|
297
|
+
sort_input(input, property, order)
|
285
298
|
end
|
286
299
|
end
|
287
300
|
|
@@ -332,6 +345,22 @@ module Bunto
|
|
332
345
|
xml_escape(input.inspect)
|
333
346
|
end
|
334
347
|
|
348
|
+
private
|
349
|
+
def sort_input(input, property, order)
|
350
|
+
input.sort do |apple, orange|
|
351
|
+
apple_property = item_property(apple, property)
|
352
|
+
orange_property = item_property(orange, property)
|
353
|
+
|
354
|
+
if !apple_property.nil? && orange_property.nil?
|
355
|
+
- order
|
356
|
+
elsif apple_property.nil? && !orange_property.nil?
|
357
|
+
+ order
|
358
|
+
else
|
359
|
+
apple_property <=> orange_property
|
360
|
+
end
|
361
|
+
end
|
362
|
+
end
|
363
|
+
|
335
364
|
private
|
336
365
|
def time(input)
|
337
366
|
case input
|
@@ -344,15 +373,17 @@ module Bunto
|
|
344
373
|
when Numeric
|
345
374
|
Time.at(input)
|
346
375
|
else
|
347
|
-
|
348
|
-
|
376
|
+
raise Errors::InvalidDateError,
|
377
|
+
"Invalid Date: '#{input.inspect}' is not a valid datetime."
|
349
378
|
end.localtime
|
350
379
|
end
|
351
380
|
|
381
|
+
private
|
352
382
|
def groupable?(element)
|
353
383
|
element.respond_to?(:group_by)
|
354
384
|
end
|
355
385
|
|
386
|
+
private
|
356
387
|
def item_property(item, property)
|
357
388
|
if item.respond_to?(:to_liquid)
|
358
389
|
item.to_liquid[property.to_s]
|
@@ -363,6 +394,7 @@ module Bunto
|
|
363
394
|
end
|
364
395
|
end
|
365
396
|
|
397
|
+
private
|
366
398
|
def as_liquid(item)
|
367
399
|
case item
|
368
400
|
when Hash
|
@@ -386,6 +418,7 @@ module Bunto
|
|
386
418
|
end
|
387
419
|
|
388
420
|
# Parse a string to a Liquid Condition
|
421
|
+
private
|
389
422
|
def parse_condition(exp)
|
390
423
|
parser = Liquid::Parser.new(exp)
|
391
424
|
left_expr = parser.expression
|