bunto 3.2.1 → 3.4.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +21 -4
  3. data/LICENSE +1 -1
  4. data/README.markdown +20 -25
  5. data/exe/bunto +1 -1
  6. data/lib/bunto.rb +10 -4
  7. data/lib/bunto/collection.rb +11 -4
  8. data/lib/bunto/commands/build.rb +17 -2
  9. data/lib/bunto/commands/doctor.rb +1 -1
  10. data/lib/bunto/commands/new.rb +35 -5
  11. data/lib/bunto/commands/new_theme.rb +4 -2
  12. data/lib/bunto/commands/serve.rb +45 -15
  13. data/lib/bunto/commands/serve/servlet.rb +1 -1
  14. data/lib/bunto/configuration.rb +9 -7
  15. data/lib/bunto/converters/markdown/kramdown_parser.rb +2 -2
  16. data/lib/bunto/converters/markdown/redcarpet_parser.rb +1 -1
  17. data/lib/bunto/convertible.rb +21 -82
  18. data/lib/bunto/desktop.ini +1 -1
  19. data/lib/bunto/document.rb +118 -81
  20. data/lib/bunto/drops/bunto_drop.rb +1 -1
  21. data/lib/bunto/drops/static_file_drop.rb +11 -0
  22. data/lib/bunto/drops/url_drop.rb +5 -0
  23. data/lib/bunto/entry_filter.rb +9 -10
  24. data/lib/bunto/excerpt.rb +2 -3
  25. data/lib/bunto/external.rb +1 -1
  26. data/lib/bunto/filters.rb +10 -32
  27. data/lib/bunto/filters/grouping_filters.rb +63 -0
  28. data/lib/bunto/filters/url_filters.rb +40 -0
  29. data/lib/bunto/frontmatter_defaults.rb +1 -1
  30. data/lib/bunto/hooks.rb +9 -9
  31. data/lib/bunto/log_adapter.rb +1 -1
  32. data/lib/bunto/page.rb +8 -4
  33. data/lib/bunto/plugin.rb +1 -1
  34. data/lib/bunto/reader.rb +2 -1
  35. data/lib/bunto/readers/data_reader.rb +9 -10
  36. data/lib/bunto/readers/post_reader.rb +1 -1
  37. data/lib/bunto/readers/theme_assets_reader.rb +47 -0
  38. data/lib/bunto/regenerator.rb +1 -1
  39. data/lib/bunto/related_posts.rb +3 -9
  40. data/lib/bunto/renderer.rb +26 -6
  41. data/lib/bunto/site.rb +12 -7
  42. data/lib/bunto/static_file.rb +20 -9
  43. data/lib/bunto/tags/highlight.rb +3 -3
  44. data/lib/bunto/tags/include.rb +9 -5
  45. data/lib/bunto/tags/link.rb +4 -2
  46. data/lib/bunto/tags/post_url.rb +4 -2
  47. data/lib/bunto/theme.rb +8 -4
  48. data/lib/bunto/theme_builder.rb +2 -2
  49. data/lib/bunto/url.rb +31 -8
  50. data/lib/bunto/utils.rb +16 -2
  51. data/lib/bunto/utils/ansi.rb +1 -1
  52. data/lib/bunto/utils/exec.rb +25 -0
  53. data/lib/bunto/utils/platforms.rb +52 -2
  54. data/lib/bunto/utils/win_tz.rb +73 -0
  55. data/lib/bunto/version.rb +1 -1
  56. data/lib/site_template/_config.yml +8 -3
  57. data/lib/site_template/_posts/0000-00-00-welcome-to-bunto.markdown.erb +4 -4
  58. data/lib/site_template/about.md +1 -1
  59. data/lib/site_template/index.md +6 -0
  60. data/lib/theme_template/LICENSE.txt.erb +1 -1
  61. data/lib/theme_template/README.md.erb +4 -4
  62. data/lib/theme_template/gitignore.erb +1 -0
  63. data/lib/theme_template/theme.gemspec.erb +3 -2
  64. metadata +55 -40
  65. data/lib/site_template/css/main.scss +0 -39
  66. data/lib/site_template/feed.xml +0 -30
  67. data/lib/site_template/index.html +0 -23
@@ -20,7 +20,7 @@ module Bunto
20
20
  def to_h
21
21
  @to_h ||= {
22
22
  "version" => version,
23
- "environment" => environment
23
+ "environment" => environment,
24
24
  }
25
25
  end
26
26
 
@@ -0,0 +1,11 @@
1
+ module Bunto
2
+ module Drops
3
+ class StaticFileDrop < Drop
4
+ extend Forwardable
5
+ def_delegators :@obj, :name, :extname, :modified_time, :basename
6
+ def_delegator :@obj, :relative_path, :path
7
+ def_delegator :@obj, :data, :fallback_data
8
+ def_delegator :@obj, :type, :collection
9
+ end
10
+ end
11
+ end
@@ -78,6 +78,11 @@ module Bunto
78
78
  def y_day
79
79
  @obj.date.strftime("%j")
80
80
  end
81
+
82
+ private
83
+ def fallback_data
84
+ {}
85
+ end
81
86
  end
82
87
  end
83
88
  end
@@ -2,7 +2,7 @@ module Bunto
2
2
  class EntryFilter
3
3
  attr_reader :site
4
4
  SPECIAL_LEADING_CHARACTERS = [
5
- ".", "_", "#", "~"
5
+ ".", "_", "#", "~",
6
6
  ].freeze
7
7
 
8
8
  def initialize(site, base_directory = nil)
@@ -36,8 +36,7 @@ module Bunto
36
36
  end
37
37
 
38
38
  def included?(entry)
39
- glob_include?(site.include,
40
- entry)
39
+ glob_include?(site.include, entry)
41
40
  end
42
41
 
43
42
  def special?(entry)
@@ -50,14 +49,14 @@ module Bunto
50
49
  end
51
50
 
52
51
  def excluded?(entry)
53
- excluded = glob_include?(site.exclude, relative_to_source(entry))
54
- if excluded
55
- Bunto.logger.debug(
56
- "EntryFilter:",
57
- "excluded #{relative_to_source(entry)}"
58
- )
52
+ glob_include?(site.exclude, relative_to_source(entry)).tap do |excluded|
53
+ if excluded
54
+ Bunto.logger.debug(
55
+ "EntryFilter:",
56
+ "excluded #{relative_to_source(entry)}"
57
+ )
58
+ end
59
59
  end
60
- excluded
61
60
  end
62
61
 
63
62
  # --
@@ -30,8 +30,7 @@ module Bunto
30
30
  @data
31
31
  end
32
32
 
33
- def trigger_hooks(*)
34
- end
33
+ def trigger_hooks(*); end
35
34
 
36
35
  # 'Path' of the excerpt.
37
36
  #
@@ -118,7 +117,7 @@ module Bunto
118
117
  if tail.empty?
119
118
  head
120
119
  else
121
- "" << head << "\n\n" << tail.scan(%r!^\[[^\]]+\]:.+$!).join("\n")
120
+ "" << head << "\n\n" << tail.scan(%r!^ {0,3}\[[^\]]+\]:.+$!).join("\n")
122
121
  end
123
122
  end
124
123
  end
@@ -48,7 +48,7 @@ In order to use Bunto as currently configured, you'll need to install this gem.
48
48
 
49
49
  The full error message from Ruby is: '#{e.message}'
50
50
 
51
- If you run into trouble, you can find helpful resources at http://bunto.github.io/help/!
51
+ If you run into trouble, you can find helpful resources at https://buntorb.com/help/!
52
52
  MSG
53
53
  raise Bunto::Errors::MissingDependencyException, name
54
54
  end
@@ -1,10 +1,15 @@
1
- require "uri"
1
+ require "addressable/uri"
2
2
  require "json"
3
3
  require "date"
4
4
  require "liquid"
5
5
 
6
+ require_all "bunto/filters"
7
+
6
8
  module Bunto
7
9
  module Filters
10
+ include URLFilters
11
+ include GroupingFilters
12
+
8
13
  # Convert a Markdown string into HTML output.
9
14
  #
10
15
  # input - The Markdown String to convert.
@@ -147,7 +152,7 @@ module Bunto
147
152
  #
148
153
  # Returns the escaped String.
149
154
  def uri_escape(input)
150
- URI.escape(input)
155
+ Addressable::URI.normalize_component(input)
151
156
  end
152
157
 
153
158
  # Replace any whitespace in the input string with a single space
@@ -172,6 +177,7 @@ module Bunto
172
177
  # word "and" for the last one.
173
178
  #
174
179
  # array - The Array of Strings to join.
180
+ # connector - Word used to connect the last 2 items in the array
175
181
  #
176
182
  # Examples
177
183
  #
@@ -179,8 +185,7 @@ module Bunto
179
185
  # # => "apples, oranges, and grapes"
180
186
  #
181
187
  # Returns the formatted String.
182
- def array_to_sentence_string(array)
183
- connector = "and"
188
+ def array_to_sentence_string(array, connector = "and")
184
189
  case array.length
185
190
  when 0
186
191
  ""
@@ -202,29 +207,6 @@ module Bunto
202
207
  as_liquid(input).to_json
203
208
  end
204
209
 
205
- # Group an array of items by a property
206
- #
207
- # input - the inputted Enumerable
208
- # property - the property
209
- #
210
- # Returns an array of Hashes, each looking something like this:
211
- # {"name" => "larry"
212
- # "items" => [...] } # all the items where `property` == "larry"
213
- def group_by(input, property)
214
- if groupable?(input)
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
223
- else
224
- input
225
- end
226
- end
227
-
228
210
  # Filter an array of objects
229
211
  #
230
212
  # input - the object array
@@ -378,11 +360,6 @@ module Bunto
378
360
  end.localtime
379
361
  end
380
362
 
381
- private
382
- def groupable?(element)
383
- element.respond_to?(:group_by)
384
- end
385
-
386
363
  private
387
364
  def item_property(item, property)
388
365
  if item.respond_to?(:to_liquid)
@@ -433,6 +410,7 @@ module Bunto
433
410
 
434
411
  condition
435
412
  end
413
+
436
414
  end
437
415
  end
438
416
 
@@ -0,0 +1,63 @@
1
+ module Bunto
2
+ module Filters
3
+ module GroupingFilters
4
+ # Group an array of items by a property
5
+ #
6
+ # input - the inputted Enumerable
7
+ # property - the property
8
+ #
9
+ # Returns an array of Hashes, each looking something like this:
10
+ # {"name" => "larry"
11
+ # "items" => [...] } # all the items where `property` == "larry"
12
+ def group_by(input, property)
13
+ if groupable?(input)
14
+ groups = input.group_by { |item| item_property(item, property).to_s }
15
+ grouped_array(groups)
16
+ else
17
+ input
18
+ end
19
+ end
20
+
21
+ # Group an array of items by an expression
22
+ #
23
+ # input - the object array
24
+ # variable - the variable to assign each item to in the expression
25
+ # expression -a Liquid comparison expression passed in as a string
26
+ #
27
+ # Returns the filtered array of objects
28
+ def group_by_exp(input, variable, expression)
29
+ return input unless groupable?(input)
30
+
31
+ parsed_expr = parse_expression(expression)
32
+ @context.stack do
33
+ groups = input.group_by do |item|
34
+ @context[variable] = item
35
+ parsed_expr.render(@context)
36
+ end
37
+ grouped_array(groups)
38
+ end
39
+ end
40
+
41
+ private
42
+ def parse_expression(str)
43
+ Liquid::Variable.new(str, {})
44
+ end
45
+
46
+ private
47
+ def groupable?(element)
48
+ element.respond_to?(:group_by)
49
+ end
50
+
51
+ private
52
+ def grouped_array(groups)
53
+ groups.each_with_object([]) do |item, array|
54
+ array << {
55
+ "name" => item.first,
56
+ "items" => item.last,
57
+ "size" => item.last.size,
58
+ }
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,40 @@
1
+ require "addressable/uri"
2
+
3
+ module Bunto
4
+ module Filters
5
+ module URLFilters
6
+ # Produces an absolute URL based on site.url and site.baseurl.
7
+ #
8
+ # input - the URL to make absolute.
9
+ #
10
+ # Returns the absolute URL as a String.
11
+ def absolute_url(input)
12
+ return if input.nil?
13
+ site = @context.registers[:site]
14
+ return relative_url(input).to_s if site.config["url"].nil?
15
+ Addressable::URI.parse(site.config["url"] + relative_url(input)).normalize.to_s
16
+ end
17
+
18
+ # Produces a URL relative to the domain root based on site.baseurl.
19
+ #
20
+ # input - the URL to make relative to the domain root
21
+ #
22
+ # Returns a URL relative to the domain root as a String.
23
+ def relative_url(input)
24
+ return if input.nil?
25
+ site = @context.registers[:site]
26
+ parts = [site.config["baseurl"], input]
27
+ Addressable::URI.parse(
28
+ parts.compact.map { |part| ensure_leading_slash(part.to_s) }.join
29
+ ).normalize.to_s
30
+ end
31
+
32
+ private
33
+ def ensure_leading_slash(input)
34
+ return input if input.nil? || input.empty? || input.start_with?("/")
35
+ "/#{input}"
36
+ end
37
+
38
+ end
39
+ end
40
+ end
@@ -188,7 +188,7 @@ module Bunto
188
188
  if path.nil? || path.empty?
189
189
  ""
190
190
  else
191
- path.gsub(%r!\A/!, "").gsub(%r!([^/])\z!, '\1')
191
+ path.gsub(%r!\A/|(?<=[^/])\z!, "".freeze)
192
192
  end
193
193
  end
194
194
  end
@@ -6,7 +6,7 @@ module Bunto
6
6
  PRIORITY_MAP = {
7
7
  :low => 10,
8
8
  :normal => 20,
9
- :high => 30
9
+ :high => 30,
10
10
  }.freeze
11
11
 
12
12
  # initial empty hooks
@@ -17,26 +17,26 @@ module Bunto
17
17
  :post_read => [],
18
18
  :pre_render => [],
19
19
  :post_render => [],
20
- :post_write => []
20
+ :post_write => [],
21
21
  },
22
22
  :pages => {
23
23
  :post_init => [],
24
24
  :pre_render => [],
25
25
  :post_render => [],
26
- :post_write => []
26
+ :post_write => [],
27
27
  },
28
28
  :posts => {
29
29
  :post_init => [],
30
30
  :pre_render => [],
31
31
  :post_render => [],
32
- :post_write => []
32
+ :post_write => [],
33
33
  },
34
34
  :documents => {
35
35
  :post_init => [],
36
36
  :pre_render => [],
37
37
  :post_render => [],
38
- :post_write => []
39
- }
38
+ :post_write => [],
39
+ },
40
40
  }
41
41
 
42
42
  # map of all hooks and their priorities
@@ -54,7 +54,7 @@ module Bunto
54
54
 
55
55
  # Ensure the priority is a Fixnum
56
56
  def self.priority_value(priority)
57
- return priority if priority.is_a?(Fixnum)
57
+ return priority if priority.is_a?(Integer)
58
58
  PRIORITY_MAP[priority] || DEFAULT_PRIORITY
59
59
  end
60
60
 
@@ -64,7 +64,7 @@ module Bunto
64
64
  :post_init => [],
65
65
  :pre_render => [],
66
66
  :post_render => [],
67
- :post_write => []
67
+ :post_write => [],
68
68
  }
69
69
 
70
70
  unless @registry[owner][event]
@@ -80,7 +80,7 @@ module Bunto
80
80
  end
81
81
 
82
82
  def self.insert_hook(owner, event, priority, &block)
83
- @hook_priority[block] = "#{priority}.#{@hook_priority.size}".to_f
83
+ @hook_priority[block] = [-priority, @hook_priority.size]
84
84
  @registry[owner][event] << block
85
85
  end
86
86
 
@@ -6,7 +6,7 @@ module Bunto
6
6
  :debug => ::Logger::DEBUG,
7
7
  :info => ::Logger::INFO,
8
8
  :warn => ::Logger::WARN,
9
- :error => ::Logger::ERROR
9
+ :error => ::Logger::ERROR,
10
10
  }.freeze
11
11
 
12
12
  # Public: Create a new instance of a log writer
@@ -40,7 +40,11 @@ module Bunto
40
40
  @base = base
41
41
  @dir = dir
42
42
  @name = name
43
- @path = site.in_source_dir(base, dir, name)
43
+ @path = if site.in_theme_dir(base) == base # we're in a theme
44
+ site.in_theme_dir(base, dir, name)
45
+ else
46
+ site.in_source_dir(base, dir, name)
47
+ end
44
48
 
45
49
  process(name)
46
50
  read_yaml(File.join(base, dir), name)
@@ -54,7 +58,7 @@ module Bunto
54
58
 
55
59
  # The generated directory into which the page will be placed
56
60
  # upon generation. This is derived from the permalink or, if
57
- # permalink is absent, we be '/'
61
+ # permalink is absent, will be '/'
58
62
  #
59
63
  # Returns the String destination directory.
60
64
  def dir
@@ -94,7 +98,7 @@ module Bunto
94
98
  @url ||= URL.new({
95
99
  :template => template,
96
100
  :placeholders => url_placeholders,
97
- :permalink => permalink
101
+ :permalink => permalink,
98
102
  }).to_s
99
103
  end
100
104
 
@@ -104,7 +108,7 @@ module Bunto
104
108
  {
105
109
  :path => @dir,
106
110
  :basename => basename,
107
- :output_ext => output_ext
111
+ :output_ext => output_ext,
108
112
  }
109
113
  end
110
114
 
@@ -5,7 +5,7 @@ module Bunto
5
5
  :highest => 100,
6
6
  :lowest => -100,
7
7
  :normal => 0,
8
- :high => 10
8
+ :high => 10,
9
9
  }.freeze
10
10
 
11
11
  #
@@ -18,6 +18,7 @@ module Bunto
18
18
  sort_files!
19
19
  @site.data = DataReader.new(site).read(site.config["data_dir"])
20
20
  CollectionReader.new(site).read
21
+ ThemeAssetsReader.new(site).read
21
22
  end
22
23
 
23
24
  # Sorts posts, pages, and static files.
@@ -70,7 +71,7 @@ module Bunto
70
71
  #
71
72
  # Returns nothing.
72
73
  def retrieve_dirs(_base, dir, dot_dirs)
73
- dot_dirs.map do |file|
74
+ dot_dirs.each do |file|
74
75
  dir_path = site.in_source_dir(dir, file)
75
76
  rel_path = File.join(dir, file)
76
77
  unless @site.dest.sub(%r!/$!, "") == dir_path