bunto 3.0.0 → 3.2.1

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.
Files changed (101) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +124 -76
  3. data/README.markdown +49 -12
  4. data/{bin → exe}/bunto +18 -14
  5. data/lib/bunto.rb +83 -78
  6. data/lib/bunto/cleaner.rb +10 -8
  7. data/lib/bunto/collection.rb +33 -17
  8. data/lib/bunto/command.rb +19 -13
  9. data/lib/bunto/commands/build.rb +22 -14
  10. data/lib/bunto/commands/clean.rb +9 -8
  11. data/lib/bunto/commands/doctor.rb +10 -8
  12. data/lib/bunto/commands/help.rb +4 -3
  13. data/lib/bunto/commands/new.rb +30 -21
  14. data/lib/bunto/commands/new_theme.rb +36 -0
  15. data/lib/bunto/commands/serve.rb +26 -20
  16. data/lib/bunto/commands/serve/servlet.rb +4 -5
  17. data/lib/bunto/configuration.rb +187 -125
  18. data/lib/bunto/converters/markdown.rb +19 -9
  19. data/lib/bunto/converters/markdown/kramdown_parser.rb +12 -5
  20. data/lib/bunto/converters/markdown/rdiscount_parser.rb +4 -4
  21. data/lib/bunto/converters/markdown/redcarpet_parser.rb +90 -84
  22. data/lib/bunto/convertible.rb +38 -25
  23. data/lib/bunto/deprecator.rb +11 -6
  24. data/lib/bunto/desktop.ini +2 -0
  25. data/lib/bunto/document.rb +53 -51
  26. data/lib/bunto/drops/bunto_drop.rb +12 -0
  27. data/lib/bunto/drops/document_drop.rb +40 -5
  28. data/lib/bunto/drops/drop.rb +49 -10
  29. data/lib/bunto/drops/excerpt_drop.rb +15 -0
  30. data/lib/bunto/drops/site_drop.rb +4 -2
  31. data/lib/bunto/drops/url_drop.rb +4 -4
  32. data/lib/bunto/entry_filter.rb +64 -19
  33. data/lib/bunto/errors.rb +6 -3
  34. data/lib/bunto/excerpt.rb +4 -6
  35. data/lib/bunto/external.rb +4 -4
  36. data/lib/bunto/filters.rb +72 -39
  37. data/lib/bunto/frontmatter_defaults.rb +45 -38
  38. data/lib/bunto/hooks.rb +21 -21
  39. data/lib/bunto/layout.rb +4 -8
  40. data/lib/bunto/liquid_renderer.rb +14 -3
  41. data/lib/bunto/liquid_renderer/file.rb +5 -1
  42. data/lib/bunto/liquid_renderer/table.rb +11 -11
  43. data/lib/bunto/log_adapter.rb +2 -2
  44. data/lib/bunto/page.rb +10 -10
  45. data/lib/bunto/plugin.rb +5 -5
  46. data/lib/bunto/plugin_manager.rb +12 -8
  47. data/lib/bunto/publisher.rb +1 -1
  48. data/lib/bunto/reader.rb +11 -7
  49. data/lib/bunto/readers/data_reader.rb +9 -9
  50. data/lib/bunto/readers/layout_reader.rb +7 -7
  51. data/lib/bunto/readers/page_reader.rb +3 -1
  52. data/lib/bunto/readers/post_reader.rb +9 -10
  53. data/lib/bunto/readers/static_file_reader.rb +3 -1
  54. data/lib/bunto/regenerator.rb +50 -28
  55. data/lib/bunto/related_posts.rb +1 -1
  56. data/lib/bunto/renderer.rb +33 -23
  57. data/lib/bunto/site.rb +94 -51
  58. data/lib/bunto/static_file.rb +33 -26
  59. data/lib/bunto/stevenson.rb +6 -5
  60. data/lib/bunto/tags/highlight.rb +50 -35
  61. data/lib/bunto/tags/include.rb +42 -31
  62. data/lib/bunto/tags/link.rb +11 -4
  63. data/lib/bunto/tags/post_url.rb +8 -7
  64. data/lib/bunto/theme.rb +10 -8
  65. data/lib/bunto/theme_builder.rb +117 -0
  66. data/lib/bunto/url.rb +21 -14
  67. data/lib/bunto/utils.rb +57 -28
  68. data/lib/bunto/utils/ansi.rb +9 -9
  69. data/lib/bunto/utils/platforms.rb +2 -2
  70. data/lib/bunto/version.rb +1 -1
  71. data/lib/site_template/_config.yml +3 -1
  72. data/lib/site_template/_posts/0000-00-00-welcome-to-bunto.markdown.erb +3 -3
  73. data/lib/site_template/about.md +3 -3
  74. data/lib/site_template/css/main.scss +3 -17
  75. data/lib/theme_template/CODE_OF_CONDUCT.md.erb +74 -0
  76. data/lib/theme_template/Gemfile +2 -0
  77. data/lib/theme_template/LICENSE.txt.erb +21 -0
  78. data/lib/theme_template/README.md.erb +48 -0
  79. data/lib/theme_template/_layouts/default.html +1 -0
  80. data/lib/theme_template/_layouts/page.html +5 -0
  81. data/lib/theme_template/_layouts/post.html +5 -0
  82. data/lib/theme_template/example/_config.yml.erb +1 -0
  83. data/lib/theme_template/example/_post.md +12 -0
  84. data/lib/theme_template/example/index.html +14 -0
  85. data/lib/theme_template/example/style.scss +7 -0
  86. data/lib/theme_template/gitignore.erb +4 -0
  87. data/lib/theme_template/theme.gemspec.erb +18 -0
  88. metadata +40 -19
  89. data/lib/site_template/_includes/footer.html +0 -38
  90. data/lib/site_template/_includes/head.html +0 -12
  91. data/lib/site_template/_includes/header.html +0 -27
  92. data/lib/site_template/_includes/icon-github.html +0 -1
  93. data/lib/site_template/_includes/icon-github.svg +0 -1
  94. data/lib/site_template/_includes/icon-twitter.html +0 -1
  95. data/lib/site_template/_includes/icon-twitter.svg +0 -1
  96. data/lib/site_template/_layouts/default.html +0 -20
  97. data/lib/site_template/_layouts/page.html +0 -14
  98. data/lib/site_template/_layouts/post.html +0 -15
  99. data/lib/site_template/_sass/_base.scss +0 -200
  100. data/lib/site_template/_sass/_layout.scss +0 -242
  101. data/lib/site_template/_sass/_syntax-highlighting.scss +0 -71
@@ -1,5 +1,5 @@
1
1
  # encoding: UTF-8
2
- require 'csv'
2
+ require "csv"
3
3
 
4
4
  module Bunto
5
5
  class Site
@@ -18,8 +18,8 @@ module Bunto
18
18
  # config - A Hash containing site configuration details.
19
19
  def initialize(config)
20
20
  # Source and destination may not be changed after the site has been created.
21
- @source = File.expand_path(config['source']).freeze
22
- @dest = File.expand_path(config['destination']).freeze
21
+ @source = File.expand_path(config["source"]).freeze
22
+ @dest = File.expand_path(config["destination"]).freeze
23
23
 
24
24
  self.config = config
25
25
 
@@ -29,10 +29,10 @@ module Bunto
29
29
 
30
30
  Bunto.sites << self
31
31
 
32
- Bunto::Hooks.trigger :site, :after_init, self
33
-
34
32
  reset
35
33
  setup
34
+
35
+ Bunto::Hooks.trigger :site, :after_init, self
36
36
  end
37
37
 
38
38
  # Public: Set the site's configuration. This handles side-effects caused by
@@ -49,19 +49,12 @@ module Bunto
49
49
  self.send("#{opt}=", config[opt])
50
50
  end
51
51
 
52
- self.plugin_manager = Bunto::PluginManager.new(self)
53
- self.plugins = plugin_manager.plugins_path
52
+ configure_plugins
53
+ configure_theme
54
+ configure_include_paths
55
+ configure_file_read_opts
54
56
 
55
- self.theme = nil
56
- self.theme = Bunto::Theme.new(config["theme"]) if config["theme"]
57
-
58
- @includes_load_paths = Array(in_source_dir(config["includes_dir"].to_s))
59
- @includes_load_paths << theme.includes_path if self.theme
60
-
61
- self.file_read_opts = {}
62
- self.file_read_opts[:encoding] = config['encoding'] if config['encoding']
63
-
64
- self.permalink_style = config['permalink'].to_sym
57
+ self.permalink_style = config["permalink"].to_sym
65
58
 
66
59
  @config
67
60
  end
@@ -80,7 +73,7 @@ module Bunto
80
73
  end
81
74
 
82
75
  def print_stats
83
- if @config['profile']
76
+ if @config["profile"]
84
77
  puts @liquid_renderer.stats_table
85
78
  end
86
79
  end
@@ -89,7 +82,11 @@ module Bunto
89
82
  #
90
83
  # Returns nothing
91
84
  def reset
92
- self.time = (config['time'] ? Utils.parse_date(config['time'].to_s, "Invalid time in _config.yml.") : Time.now)
85
+ if config["time"]
86
+ self.time = Utils.parse_date(config["time"].to_s, "Invalid time in _config.yml.")
87
+ else
88
+ self.time = Time.now
89
+ end
93
90
  self.layouts = {}
94
91
  self.pages = []
95
92
  self.static_files = []
@@ -123,18 +120,23 @@ module Bunto
123
120
  dest_pathname = Pathname.new(dest)
124
121
  Pathname.new(source).ascend do |path|
125
122
  if path == dest_pathname
126
- raise Errors::FatalException.new "Destination directory cannot be or contain the Source directory."
123
+ raise(
124
+ Errors::FatalException,
125
+ "Destination directory cannot be or contain the Source directory."
126
+ )
127
127
  end
128
128
  end
129
129
  end
130
130
 
131
131
  # The list of collections and their corresponding Bunto::Collection instances.
132
- # If config['collections'] is set, a new instance is created for each item in the collection.
133
- # If config['collections'] is not set, a new hash is returned.
132
+ # If config['collections'] is set, a new instance is created
133
+ # for each item in the collection, a new hash is returned otherwise.
134
134
  #
135
135
  # Returns a Hash containing collection name-to-instance pairs.
136
136
  def collections
137
- @collections ||= Hash[collection_names.map { |coll| [coll, Bunto::Collection.new(self, coll)] } ]
137
+ @collections ||= Hash[collection_names.map do |coll|
138
+ [coll, Bunto::Collection.new(self, coll)]
139
+ end]
138
140
  end
139
141
 
140
142
  # The list of collection names.
@@ -142,11 +144,11 @@ module Bunto
142
144
  # Returns an array of collection names from the configuration,
143
145
  # or an empty array if the `collections` key is not set.
144
146
  def collection_names
145
- case config['collections']
147
+ case config["collections"]
146
148
  when Hash
147
- config['collections'].keys
149
+ config["collections"].keys
148
150
  when Array
149
- config['collections']
151
+ config["collections"]
150
152
  when nil
151
153
  []
152
154
  else
@@ -168,7 +170,10 @@ module Bunto
168
170
  # Returns nothing.
169
171
  def generate
170
172
  generators.each do |generator|
173
+ start = Time.now
171
174
  generator.generate(self)
175
+ Bunto.logger.debug "Generating:",
176
+ "#{generator.class} finished in #{Time.now - start} seconds."
172
177
  end
173
178
  end
174
179
 
@@ -182,26 +187,15 @@ module Bunto
182
187
 
183
188
  Bunto::Hooks.trigger :site, :pre_render, self, payload
184
189
 
185
- collections.each do |_, collection|
186
- collection.docs.each do |document|
187
- if regenerator.regenerate?(document)
188
- document.output = Bunto::Renderer.new(self, document, payload).run
189
- document.trigger_hooks(:post_render)
190
- end
191
- end
192
- end
193
-
194
- pages.flatten.each do |page|
195
- if regenerator.regenerate?(page)
196
- page.output = Bunto::Renderer.new(self, page, payload).run
197
- page.trigger_hooks(:post_render)
198
- end
199
- end
190
+ render_docs(payload)
191
+ render_pages(payload)
200
192
 
201
193
  Bunto::Hooks.trigger :site, :post_render, self, payload
194
+ # rubocop: disable HandleExceptions
202
195
  rescue Errno::ENOENT
203
196
  # ignore missing layout dir
204
197
  end
198
+ # rubocop: enable HandleExceptions
205
199
 
206
200
  # Remove orphaned files and empty directories in destination.
207
201
  #
@@ -222,7 +216,7 @@ module Bunto
222
216
  end
223
217
 
224
218
  def posts
225
- collections['posts'] ||= Collection.new(self, 'posts')
219
+ collections["posts"] ||= Collection.new(self, "posts")
226
220
  end
227
221
 
228
222
  # Construct a Hash of Posts indexed by the specified Post attribute.
@@ -242,17 +236,19 @@ module Bunto
242
236
  # Build a hash map based on the specified post attribute ( post attr =>
243
237
  # array of posts ) then sort each array in reverse order.
244
238
  hash = Hash.new { |h, key| h[key] = [] }
245
- posts.docs.each { |p| p.data[post_attr].each { |t| hash[t] << p } if p.data[post_attr] }
239
+ posts.docs.each do |p|
240
+ p.data[post_attr].each { |t| hash[t] << p } if p.data[post_attr]
241
+ end
246
242
  hash.values.each { |posts| posts.sort!.reverse! }
247
243
  hash
248
244
  end
249
245
 
250
246
  def tags
251
- post_attr_hash('tags')
247
+ post_attr_hash("tags")
252
248
  end
253
249
 
254
250
  def categories
255
- post_attr_hash('categories')
251
+ post_attr_hash("categories")
256
252
  end
257
253
 
258
254
  # Prepare site data for site payload. The method maintains backward compatibility
@@ -260,7 +256,7 @@ module Bunto
260
256
  #
261
257
  # Returns the Hash to be hooked to site.data.
262
258
  def site_data
263
- config['data'] || data
259
+ config["data"] || data
264
260
  end
265
261
 
266
262
  # The Hash payload containing site-wide data.
@@ -279,6 +275,7 @@ module Bunto
279
275
  def site_payload
280
276
  Drops::UnifiedPayloadDrop.new self
281
277
  end
278
+ alias_method :to_liquid, :site_payload
282
279
 
283
280
  # Get the implementation class for the given Converter.
284
281
  # Returns the Converter instance implementing the given Converter.
@@ -305,11 +302,11 @@ module Bunto
305
302
  #
306
303
  # Returns
307
304
  def relative_permalinks_are_deprecated
308
- if config['relative_permalinks']
305
+ if config["relative_permalinks"]
309
306
  Bunto.logger.abort_with "Since v3.0, permalinks for pages" \
310
307
  " in subfolders must be relative to the" \
311
308
  " site source directory, not the parent" \
312
- " directory. Check http://bunto.github.io/docs/upgrading/"\
309
+ " directory. Check http://bunto.github.io/docs/upgrading"\
313
310
  " for more info."
314
311
  end
315
312
  end
@@ -350,7 +347,7 @@ module Bunto
350
347
  #
351
348
  # Returns a Boolean: true for a full rebuild, false for normal build
352
349
  def incremental?(override = {})
353
- override['incremental'] || config['incremental']
350
+ override["incremental"] || config["incremental"]
354
351
  end
355
352
 
356
353
  # Returns the publisher or creates a new publisher if it doesn't
@@ -398,11 +395,10 @@ module Bunto
398
395
  end
399
396
  end
400
397
 
401
- private
402
-
403
398
  # Limits the current posts; removes the posts which exceed the limit_posts
404
399
  #
405
400
  # Returns nothing
401
+ private
406
402
  def limit_posts!
407
403
  if limit_posts > 0
408
404
  limit = posts.docs.length < limit_posts ? posts.docs.length : limit_posts
@@ -414,8 +410,55 @@ module Bunto
414
410
  # already exist.
415
411
  #
416
412
  # Returns The Cleaner
413
+ private
417
414
  def site_cleaner
418
415
  @site_cleaner ||= Cleaner.new(self)
419
416
  end
417
+
418
+ private
419
+ def configure_plugins
420
+ self.plugin_manager = Bunto::PluginManager.new(self)
421
+ self.plugins = plugin_manager.plugins_path
422
+ end
423
+
424
+ private
425
+ def configure_theme
426
+ self.theme = nil
427
+ self.theme = Bunto::Theme.new(config["theme"]) if config["theme"]
428
+ end
429
+
430
+ private
431
+ def configure_include_paths
432
+ @includes_load_paths = Array(in_source_dir(config["includes_dir"].to_s))
433
+ @includes_load_paths << theme.includes_path if self.theme
434
+ end
435
+
436
+ private
437
+ def configure_file_read_opts
438
+ self.file_read_opts = {}
439
+ self.file_read_opts[:encoding] = config["encoding"] if config["encoding"]
440
+ end
441
+
442
+ private
443
+ def render_docs(payload)
444
+ collections.each do |_, collection|
445
+ collection.docs.each do |document|
446
+ if regenerator.regenerate?(document)
447
+ document.output = Bunto::Renderer.new(self, document, payload).run
448
+ document.trigger_hooks(:post_render)
449
+ end
450
+ end
451
+ end
452
+ end
453
+
454
+ private
455
+ def render_pages(payload)
456
+ pages.flatten.each do |page|
457
+ if regenerator.regenerate?(page)
458
+ page.output = Bunto::Renderer.new(self, page, payload).run
459
+ page.trigger_hooks(:post_render)
460
+ end
461
+ end
462
+ end
420
463
  end
421
464
  end
@@ -1,16 +1,25 @@
1
1
  module Bunto
2
2
  class StaticFile
3
- # The cache of last modification times [path] -> mtime.
4
- @@mtimes = {}
5
-
6
3
  attr_reader :relative_path, :extname
7
4
 
5
+ class << self
6
+ # The cache of last modification times [path] -> mtime.
7
+ def mtimes
8
+ @mtimes ||= {}
9
+ end
10
+
11
+ def reset_cache
12
+ @mtimes = nil
13
+ end
14
+ end
15
+
8
16
  # Initialize a new StaticFile.
9
17
  #
10
18
  # site - The Site.
11
19
  # base - The String path to the <source>.
12
20
  # dir - The String path between <source> and the file.
13
21
  # name - The String filename of the file.
22
+ # rubocop: disable ParameterLists
14
23
  def initialize(site, base, dir, name, collection = nil)
15
24
  @site = site
16
25
  @base = base
@@ -20,6 +29,7 @@ module Bunto
20
29
  @relative_path = File.join(*[@dir, @name].compact)
21
30
  @extname = File.extname(@name)
22
31
  end
32
+ # rubocop: enable ParameterLists
23
33
 
24
34
  # Returns source file path.
25
35
  def path
@@ -56,7 +66,7 @@ module Bunto
56
66
  #
57
67
  # Returns true if modified since last write.
58
68
  def modified?
59
- @@mtimes[path] != mtime
69
+ self.class.mtimes[path] != mtime
60
70
  end
61
71
 
62
72
  # Whether to write the file to the filesystem
@@ -64,7 +74,7 @@ module Bunto
64
74
  # Returns true unless the defaults for the destination path from
65
75
  # _config.yml contain `published: false`.
66
76
  def write?
67
- defaults.fetch('published', true)
77
+ defaults.fetch("published", true)
68
78
  end
69
79
 
70
80
  # Write the static file to the destination directory (if modified).
@@ -76,28 +86,15 @@ module Bunto
76
86
  dest_path = destination(dest)
77
87
 
78
88
  return false if File.exist?(dest_path) && !modified?
79
- @@mtimes[path] = mtime
89
+ self.class.mtimes[path] = mtime
80
90
 
81
91
  FileUtils.mkdir_p(File.dirname(dest_path))
82
92
  FileUtils.rm(dest_path) if File.exist?(dest_path)
83
- if @site.safe || Bunto.env == "production"
84
- FileUtils.cp(path, dest_path)
85
- else
86
- FileUtils.copy_entry(path, dest_path)
87
- end
88
- File.utime(@@mtimes[path], @@mtimes[path], dest_path)
93
+ copy_file(dest_path)
89
94
 
90
95
  true
91
96
  end
92
97
 
93
- # Reset the mtimes cache (for testing purposes).
94
- #
95
- # Returns nothing.
96
- def self.reset_cache
97
- @@mtimes = {}
98
- nil
99
- end
100
-
101
98
  def to_liquid
102
99
  {
103
100
  "extname" => extname,
@@ -109,11 +106,11 @@ module Bunto
109
106
  def placeholders
110
107
  {
111
108
  :collection => @collection.label,
112
- :path => relative_path[
109
+ :path => relative_path[
113
110
  @collection.relative_directory.size..relative_path.size],
114
- :output_ext => '',
115
- :name => '',
116
- :title => ''
111
+ :output_ext => "",
112
+ :name => "",
113
+ :title => ""
117
114
  }
118
115
  end
119
116
 
@@ -125,10 +122,10 @@ module Bunto
125
122
  relative_path
126
123
  else
127
124
  ::Bunto::URL.new({
128
- :template => @collection.url_template,
125
+ :template => @collection.url_template,
129
126
  :placeholders => placeholders
130
127
  })
131
- end.to_s.gsub(/\/$/, '')
128
+ end.to_s.gsub(%r!/$!, "")
132
129
  end
133
130
 
134
131
  # Returns the type of the collection if present, nil otherwise.
@@ -141,5 +138,15 @@ module Bunto
141
138
  def defaults
142
139
  @defaults ||= @site.frontmatter_defaults.all url, type
143
140
  end
141
+
142
+ private
143
+ def copy_file(dest_path)
144
+ if @site.safe || Bunto.env == "production"
145
+ FileUtils.cp(path, dest_path)
146
+ else
147
+ FileUtils.copy_entry(path, dest_path)
148
+ end
149
+ File.utime(self.class.mtimes[path], self.class.mtimes[path], dest_path)
150
+ end
144
151
  end
145
152
  end
@@ -6,13 +6,13 @@ module Bunto
6
6
  @default_formatter = Formatter.new
7
7
  @logdev = $stdout
8
8
  @formatter = proc do |_, _, _, msg|
9
- "#{msg}"
9
+ msg.to_s
10
10
  end
11
11
  end
12
12
 
13
- def add(severity, message = nil, progname = nil, &block)
13
+ def add(severity, message = nil, progname = nil)
14
14
  severity ||= UNKNOWN
15
- @logdev = set_logdevice(severity)
15
+ @logdev = logdevice(severity)
16
16
 
17
17
  if @logdev.nil? || severity < @level
18
18
  return true
@@ -27,7 +27,8 @@ module Bunto
27
27
  end
28
28
  end
29
29
  @logdev.puts(
30
- format_message(format_severity(severity), Time.now, progname, message))
30
+ format_message(format_severity(severity), Time.now, progname, message)
31
+ )
31
32
  true
32
33
  end
33
34
 
@@ -47,7 +48,7 @@ module Bunto
47
48
 
48
49
  private
49
50
 
50
- def set_logdevice(severity)
51
+ def logdevice(severity)
51
52
  if severity > INFO
52
53
  $stderr
53
54
  else