bunto 3.0.0 → 3.2.1

Sign up to get free protection for your applications and to get access to all the features.
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