bunto 1.0.0

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 (95) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.markdown +59 -0
  4. data/bin/bunto +51 -0
  5. data/lib/bunto.rb +179 -0
  6. data/lib/bunto/cleaner.rb +105 -0
  7. data/lib/bunto/collection.rb +205 -0
  8. data/lib/bunto/command.rb +65 -0
  9. data/lib/bunto/commands/build.rb +77 -0
  10. data/lib/bunto/commands/clean.rb +42 -0
  11. data/lib/bunto/commands/doctor.rb +114 -0
  12. data/lib/bunto/commands/help.rb +31 -0
  13. data/lib/bunto/commands/new.rb +82 -0
  14. data/lib/bunto/commands/serve.rb +204 -0
  15. data/lib/bunto/commands/serve/servlet.rb +61 -0
  16. data/lib/bunto/configuration.rb +323 -0
  17. data/lib/bunto/converter.rb +48 -0
  18. data/lib/bunto/converters/identity.rb +21 -0
  19. data/lib/bunto/converters/markdown.rb +92 -0
  20. data/lib/bunto/converters/markdown/kramdown_parser.rb +117 -0
  21. data/lib/bunto/converters/markdown/rdiscount_parser.rb +33 -0
  22. data/lib/bunto/converters/markdown/redcarpet_parser.rb +102 -0
  23. data/lib/bunto/converters/smartypants.rb +34 -0
  24. data/lib/bunto/convertible.rb +297 -0
  25. data/lib/bunto/deprecator.rb +46 -0
  26. data/lib/bunto/document.rb +444 -0
  27. data/lib/bunto/drops/bunto_drop.rb +21 -0
  28. data/lib/bunto/drops/collection_drop.rb +22 -0
  29. data/lib/bunto/drops/document_drop.rb +27 -0
  30. data/lib/bunto/drops/drop.rb +176 -0
  31. data/lib/bunto/drops/site_drop.rb +38 -0
  32. data/lib/bunto/drops/unified_payload_drop.rb +25 -0
  33. data/lib/bunto/drops/url_drop.rb +83 -0
  34. data/lib/bunto/entry_filter.rb +72 -0
  35. data/lib/bunto/errors.rb +10 -0
  36. data/lib/bunto/excerpt.rb +127 -0
  37. data/lib/bunto/external.rb +59 -0
  38. data/lib/bunto/filters.rb +367 -0
  39. data/lib/bunto/frontmatter_defaults.rb +188 -0
  40. data/lib/bunto/generator.rb +3 -0
  41. data/lib/bunto/hooks.rb +101 -0
  42. data/lib/bunto/layout.rb +49 -0
  43. data/lib/bunto/liquid_extensions.rb +22 -0
  44. data/lib/bunto/liquid_renderer.rb +39 -0
  45. data/lib/bunto/liquid_renderer/file.rb +50 -0
  46. data/lib/bunto/liquid_renderer/table.rb +94 -0
  47. data/lib/bunto/log_adapter.rb +115 -0
  48. data/lib/bunto/mime.types +800 -0
  49. data/lib/bunto/page.rb +180 -0
  50. data/lib/bunto/plugin.rb +96 -0
  51. data/lib/bunto/plugin_manager.rb +95 -0
  52. data/lib/bunto/post.rb +329 -0
  53. data/lib/bunto/publisher.rb +21 -0
  54. data/lib/bunto/reader.rb +126 -0
  55. data/lib/bunto/readers/collection_reader.rb +20 -0
  56. data/lib/bunto/readers/data_reader.rb +69 -0
  57. data/lib/bunto/readers/layout_reader.rb +53 -0
  58. data/lib/bunto/readers/page_reader.rb +21 -0
  59. data/lib/bunto/readers/post_reader.rb +62 -0
  60. data/lib/bunto/readers/static_file_reader.rb +21 -0
  61. data/lib/bunto/regenerator.rb +175 -0
  62. data/lib/bunto/related_posts.rb +56 -0
  63. data/lib/bunto/renderer.rb +191 -0
  64. data/lib/bunto/site.rb +391 -0
  65. data/lib/bunto/static_file.rb +141 -0
  66. data/lib/bunto/stevenson.rb +58 -0
  67. data/lib/bunto/tags/highlight.rb +122 -0
  68. data/lib/bunto/tags/include.rb +190 -0
  69. data/lib/bunto/tags/post_url.rb +88 -0
  70. data/lib/bunto/url.rb +136 -0
  71. data/lib/bunto/utils.rb +287 -0
  72. data/lib/bunto/utils/ansi.rb +59 -0
  73. data/lib/bunto/utils/platforms.rb +30 -0
  74. data/lib/bunto/version.rb +3 -0
  75. data/lib/site_template/.gitignore +3 -0
  76. data/lib/site_template/_config.yml +21 -0
  77. data/lib/site_template/_includes/footer.html +38 -0
  78. data/lib/site_template/_includes/head.html +12 -0
  79. data/lib/site_template/_includes/header.html +27 -0
  80. data/lib/site_template/_includes/icon-github.html +1 -0
  81. data/lib/site_template/_includes/icon-github.svg +1 -0
  82. data/lib/site_template/_includes/icon-twitter.html +1 -0
  83. data/lib/site_template/_includes/icon-twitter.svg +1 -0
  84. data/lib/site_template/_layouts/default.html +20 -0
  85. data/lib/site_template/_layouts/page.html +14 -0
  86. data/lib/site_template/_layouts/post.html +15 -0
  87. data/lib/site_template/_posts/0000-00-00-welcome-to-bunto.markdown.erb +25 -0
  88. data/lib/site_template/_sass/_base.scss +206 -0
  89. data/lib/site_template/_sass/_layout.scss +242 -0
  90. data/lib/site_template/_sass/_syntax-highlighting.scss +71 -0
  91. data/lib/site_template/about.md +15 -0
  92. data/lib/site_template/css/main.scss +53 -0
  93. data/lib/site_template/feed.xml +30 -0
  94. data/lib/site_template/index.html +23 -0
  95. metadata +252 -0
@@ -0,0 +1,61 @@
1
+ require "webrick"
2
+
3
+ module Bunto
4
+ module Commands
5
+ class Serve
6
+ class Servlet < WEBrick::HTTPServlet::FileHandler
7
+ DEFAULTS = {
8
+ "Cache-Control" => "private, max-age=0, proxy-revalidate, " \
9
+ "no-store, no-cache, must-revalidate"
10
+ }
11
+
12
+ def initialize(server, root, callbacks)
13
+ # So we can access them easily.
14
+ @bunto_opts = server.config[:BuntoOptions]
15
+ set_defaults
16
+ super
17
+ end
18
+
19
+ # Add the ability to tap file.html the same way that Nginx does on our
20
+ # Docker images (or on GitHub Pages.) The difference is that we might end
21
+ # up with a different preference on which comes first.
22
+
23
+ def search_file(req, res, basename)
24
+ # /file.* > /file/index.html > /file.html
25
+ super || super(req, res, "#{basename}.html")
26
+ end
27
+
28
+ #
29
+
30
+ def do_GET(req, res)
31
+ rtn = super
32
+ validate_and_ensure_charset(req, res)
33
+ res.header.merge!(@headers)
34
+ rtn
35
+ end
36
+
37
+ #
38
+
39
+ private
40
+ def validate_and_ensure_charset(_req, res)
41
+ key = res.header.keys.grep(/content-type/i).first
42
+ typ = res.header[key]
43
+
44
+ unless typ =~ /;\s*charset=/
45
+ res.header[key] = "#{typ}; charset=#{@bunto_opts["encoding"]}"
46
+ end
47
+ end
48
+
49
+ #
50
+
51
+ private
52
+ def set_defaults
53
+ hash_ = @bunto_opts.fetch("webrick", {}).fetch("headers", {})
54
+ DEFAULTS.each_with_object(@headers = hash_) do |(key, val), hash|
55
+ hash[key] = val unless hash.key?(key)
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,323 @@
1
+ # encoding: UTF-8
2
+
3
+ module Bunto
4
+ class Configuration < Hash
5
+ # Default options. Overridden by values in _config.yml.
6
+ # Strings rather than symbols are used for compatibility with YAML.
7
+ DEFAULTS = Configuration[{
8
+ # Where things are
9
+ 'source' => Dir.pwd,
10
+ 'destination' => File.join(Dir.pwd, '_site'),
11
+ 'plugins_dir' => '_plugins',
12
+ 'layouts_dir' => '_layouts',
13
+ 'data_dir' => '_data',
14
+ 'includes_dir' => '_includes',
15
+ 'collections' => {},
16
+
17
+ # Handling Reading
18
+ 'safe' => false,
19
+ 'include' => ['.htaccess'],
20
+ 'exclude' => [],
21
+ 'keep_files' => ['.git', '.svn'],
22
+ 'encoding' => 'utf-8',
23
+ 'markdown_ext' => 'markdown,mkdown,mkdn,mkd,md',
24
+
25
+ # Filtering Content
26
+ 'show_drafts' => nil,
27
+ 'limit_posts' => 0,
28
+ 'future' => false,
29
+ 'unpublished' => false,
30
+
31
+ # Plugins
32
+ 'whitelist' => [],
33
+ 'gems' => [],
34
+
35
+ # Conversion
36
+ 'markdown' => 'kramdown',
37
+ 'highlighter' => 'rouge',
38
+ 'lsi' => false,
39
+ 'excerpt_separator' => "\n\n",
40
+ 'incremental' => false,
41
+
42
+ # Serving
43
+ 'detach' => false, # default to not detaching the server
44
+ 'port' => '4000',
45
+ 'host' => '127.0.0.1',
46
+ 'baseurl' => '',
47
+
48
+ # Output Configuration
49
+ 'permalink' => 'date',
50
+ 'paginate_path' => '/page:num',
51
+ 'timezone' => nil, # use the local timezone
52
+
53
+ 'quiet' => false,
54
+ 'verbose' => false,
55
+ 'defaults' => [],
56
+
57
+ 'rdiscount' => {
58
+ 'extensions' => []
59
+ },
60
+
61
+ 'redcarpet' => {
62
+ 'extensions' => []
63
+ },
64
+
65
+ 'kramdown' => {
66
+ 'auto_ids' => true,
67
+ 'toc_levels' => '1..6',
68
+ 'entity_output' => 'as_char',
69
+ 'smart_quotes' => 'lsquo,rsquo,ldquo,rdquo',
70
+ 'input' => "GFM",
71
+ 'hard_wrap' => false,
72
+ 'footnote_nr' => 1
73
+ }
74
+ }]
75
+
76
+ # Public: Turn all keys into string
77
+ #
78
+ # Return a copy of the hash where all its keys are strings
79
+ def stringify_keys
80
+ reduce({}) { |hsh, (k, v)| hsh.merge(k.to_s => v) }
81
+ end
82
+
83
+ def get_config_value_with_override(config_key, override)
84
+ override[config_key] || self[config_key] || DEFAULTS[config_key]
85
+ end
86
+
87
+ # Public: Directory of the Bunto source folder
88
+ #
89
+ # override - the command-line options hash
90
+ #
91
+ # Returns the path to the Bunto source directory
92
+ def source(override)
93
+ get_config_value_with_override('source', override)
94
+ end
95
+
96
+ def quiet(override = {})
97
+ get_config_value_with_override('quiet', override)
98
+ end
99
+ alias_method :quiet?, :quiet
100
+
101
+ def verbose(override = {})
102
+ get_config_value_with_override('verbose', override)
103
+ end
104
+ alias_method :verbose?, :verbose
105
+
106
+ def safe_load_file(filename)
107
+ case File.extname(filename)
108
+ when /\.toml/i
109
+ Bunto::External.require_with_graceful_fail('toml') unless defined?(TOML)
110
+ TOML.load_file(filename)
111
+ when /\.ya?ml/i
112
+ SafeYAML.load_file(filename) || {}
113
+ else
114
+ raise ArgumentError, "No parser for '#{filename}' is available. Use a .toml or .y(a)ml file instead."
115
+ end
116
+ end
117
+
118
+ # Public: Generate list of configuration files from the override
119
+ #
120
+ # override - the command-line options hash
121
+ #
122
+ # Returns an Array of config files
123
+ def config_files(override)
124
+ # Adjust verbosity quickly
125
+ Bunto.logger.adjust_verbosity(:quiet => quiet?(override), :verbose => verbose?(override))
126
+
127
+ # Get configuration from <source>/_config.yml or <source>/<config_file>
128
+ config_files = override.delete('config')
129
+ if config_files.to_s.empty?
130
+ default = %w(yml yaml).find(-> { 'yml' }) do |ext|
131
+ File.exist?(Bunto.sanitized_path(source(override), "_config.#{ext}"))
132
+ end
133
+ config_files = Bunto.sanitized_path(source(override), "_config.#{default}")
134
+ @default_config_file = true
135
+ end
136
+ config_files = [config_files] unless config_files.is_a? Array
137
+ config_files
138
+ end
139
+
140
+ # Public: Read configuration and return merged Hash
141
+ #
142
+ # file - the path to the YAML file to be read in
143
+ #
144
+ # Returns this configuration, overridden by the values in the file
145
+ def read_config_file(file)
146
+ next_config = safe_load_file(file)
147
+ check_config_is_hash!(next_config, file)
148
+ Bunto.logger.info "Configuration file:", file
149
+ next_config
150
+ rescue SystemCallError
151
+ if @default_config_file
152
+ Bunto.logger.warn "Configuration file:", "none"
153
+ {}
154
+ else
155
+ Bunto.logger.error "Fatal:", "The configuration file '#{file}' could not be found."
156
+ raise LoadError, "The Configuration file '#{file}' could not be found."
157
+ end
158
+ end
159
+
160
+ # Public: Read in a list of configuration files and merge with this hash
161
+ #
162
+ # files - the list of configuration file paths
163
+ #
164
+ # Returns the full configuration, with the defaults overridden by the values in the
165
+ # configuration files
166
+ def read_config_files(files)
167
+ configuration = clone
168
+
169
+ begin
170
+ files.each do |config_file|
171
+ new_config = read_config_file(config_file)
172
+ configuration = Utils.deep_merge_hashes(configuration, new_config)
173
+ end
174
+ rescue ArgumentError => err
175
+ Bunto.logger.warn "WARNING:", "Error reading configuration. " \
176
+ "Using defaults (and options)."
177
+ $stderr.puts "#{err}"
178
+ end
179
+
180
+ configuration.fix_common_issues.backwards_compatibilize.add_default_collections
181
+ end
182
+
183
+ # Public: Split a CSV string into an array containing its values
184
+ #
185
+ # csv - the string of comma-separated values
186
+ #
187
+ # Returns an array of the values contained in the CSV
188
+ def csv_to_array(csv)
189
+ csv.split(",").map(&:strip)
190
+ end
191
+
192
+ # Public: Ensure the proper options are set in the configuration to allow for
193
+ # backwards-compatibility with Bunto pre-1.0
194
+ #
195
+ # Returns the backwards-compatible configuration
196
+ def backwards_compatibilize
197
+ config = clone
198
+ # Provide backwards-compatibility
199
+ if config.key?('auto') || config.key?('watch')
200
+ Bunto::Deprecator.deprecation_message "Auto-regeneration can no longer" \
201
+ " be set from your configuration file(s). Use the"\
202
+ " --[no-]watch/-w command-line option instead."
203
+ config.delete('auto')
204
+ config.delete('watch')
205
+ end
206
+
207
+ if config.key? 'server'
208
+ Bunto::Deprecator.deprecation_message "The 'server' configuration option" \
209
+ " is no longer accepted. Use the 'bunto serve'" \
210
+ " subcommand to serve your site with WEBrick."
211
+ config.delete('server')
212
+ end
213
+
214
+ renamed_key 'server_port', 'port', config
215
+ renamed_key 'plugins', 'plugins_dir', config
216
+ renamed_key 'layouts', 'layouts_dir', config
217
+ renamed_key 'data_source', 'data_dir', config
218
+
219
+ if config.key? 'pygments'
220
+ Bunto::Deprecator.deprecation_message "The 'pygments' configuration option" \
221
+ " has been renamed to 'highlighter'. Please update your" \
222
+ " config file accordingly. The allowed values are 'rouge', " \
223
+ "'pygments' or null."
224
+
225
+ config['highlighter'] = 'pygments' if config['pygments']
226
+ config.delete('pygments')
227
+ end
228
+
229
+ %w(include exclude).each do |option|
230
+ config[option] ||= []
231
+ if config[option].is_a?(String)
232
+ Bunto::Deprecator.deprecation_message "The '#{option}' configuration option" \
233
+ " must now be specified as an array, but you specified" \
234
+ " a string. For now, we've treated the string you provided" \
235
+ " as a list of comma-separated values."
236
+ config[option] = csv_to_array(config[option])
237
+ end
238
+ config[option].map!(&:to_s)
239
+ end
240
+
241
+ if (config['kramdown'] || {}).key?('use_coderay')
242
+ Bunto::Deprecator.deprecation_message "Please change 'use_coderay'" \
243
+ " to 'enable_coderay' in your configuration file."
244
+ config['kramdown']['use_coderay'] = config['kramdown'].delete('enable_coderay')
245
+ end
246
+
247
+ if config.fetch('markdown', 'kramdown').to_s.downcase.eql?("maruku")
248
+ Bunto.logger.abort_with "Error:", "You're using the 'maruku' " \
249
+ "Markdown processor, which has been removed as of 3.0.0. " \
250
+ "We recommend you switch to Kramdown. To do this, replace " \
251
+ "`markdown: maruku` with `markdown: kramdown` in your " \
252
+ "`_config.yml` file."
253
+ end
254
+
255
+ config
256
+ end
257
+
258
+ def fix_common_issues
259
+ config = clone
260
+
261
+ if config.key?('paginate') && (!config['paginate'].is_a?(Integer) || config['paginate'] < 1)
262
+ Bunto.logger.warn "Config Warning:", "The `paginate` key must be a" \
263
+ " positive integer or nil. It's currently set to '#{config['paginate'].inspect}'."
264
+ config['paginate'] = nil
265
+ end
266
+
267
+ config
268
+ end
269
+
270
+ def add_default_collections
271
+ config = clone
272
+
273
+ return config if config['collections'].nil?
274
+
275
+ if config['collections'].is_a?(Array)
276
+ config['collections'] = Hash[config['collections'].map { |c| [c, {}] }]
277
+ end
278
+ config['collections']['posts'] ||= {}
279
+ config['collections']['posts']['output'] = true
280
+ config['collections']['posts']['permalink'] = style_to_permalink(config['permalink'])
281
+
282
+ config
283
+ end
284
+
285
+ def renamed_key(old, new, config, _ = nil)
286
+ if config.key?(old)
287
+ Bunto::Deprecator.deprecation_message "The '#{old}' configuration" \
288
+ "option has been renamed to '#{new}'. Please update your config " \
289
+ "file accordingly."
290
+ config[new] = config.delete(old)
291
+ end
292
+ end
293
+
294
+ private
295
+
296
+ def style_to_permalink(permalink_style)
297
+ case permalink_style.to_sym
298
+ when :pretty
299
+ "/:categories/:year/:month/:day/:title/"
300
+ when :none
301
+ "/:categories/:title:output_ext"
302
+ when :date
303
+ "/:categories/:year/:month/:day/:title:output_ext"
304
+ when :ordinal
305
+ "/:categories/:year/:y_day/:title:output_ext"
306
+ else
307
+ permalink_style.to_s
308
+ end
309
+ end
310
+
311
+ # Private: Checks if a given config is a hash
312
+ #
313
+ # extracted_config - the value to check
314
+ # file - the file from which the config was extracted
315
+ #
316
+ # Raises an ArgumentError if given config is not a hash
317
+ def check_config_is_hash!(extracted_config, file)
318
+ unless extracted_config.is_a?(Hash)
319
+ raise ArgumentError.new("Configuration file: (INVALID) #{file}".yellow)
320
+ end
321
+ end
322
+ end
323
+ end
@@ -0,0 +1,48 @@
1
+ module Bunto
2
+ class Converter < Plugin
3
+ # Public: Get or set the highlighter prefix. When an argument is specified,
4
+ # the prefix will be set. If no argument is specified, the current prefix
5
+ # will be returned.
6
+ #
7
+ # highlighter_prefix - The String prefix (default: nil).
8
+ #
9
+ # Returns the String prefix.
10
+ def self.highlighter_prefix(highlighter_prefix = nil)
11
+ @highlighter_prefix = highlighter_prefix if highlighter_prefix
12
+ @highlighter_prefix
13
+ end
14
+
15
+ # Public: Get or set the highlighter suffix. When an argument is specified,
16
+ # the suffix will be set. If no argument is specified, the current suffix
17
+ # will be returned.
18
+ #
19
+ # highlighter_suffix - The String suffix (default: nil).
20
+ #
21
+ # Returns the String suffix.
22
+ def self.highlighter_suffix(highlighter_suffix = nil)
23
+ @highlighter_suffix = highlighter_suffix if highlighter_suffix
24
+ @highlighter_suffix
25
+ end
26
+
27
+ # Initialize the converter.
28
+ #
29
+ # Returns an initialized Converter.
30
+ def initialize(config = {})
31
+ @config = config
32
+ end
33
+
34
+ # Get the highlighter prefix.
35
+ #
36
+ # Returns the String prefix.
37
+ def highlighter_prefix
38
+ self.class.highlighter_prefix
39
+ end
40
+
41
+ # Get the highlighter suffix.
42
+ #
43
+ # Returns the String suffix.
44
+ def highlighter_suffix
45
+ self.class.highlighter_suffix
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,21 @@
1
+ module Bunto
2
+ module Converters
3
+ class Identity < Converter
4
+ safe true
5
+
6
+ priority :lowest
7
+
8
+ def matches(_ext)
9
+ true
10
+ end
11
+
12
+ def output_ext(ext)
13
+ ext
14
+ end
15
+
16
+ def convert(content)
17
+ content
18
+ end
19
+ end
20
+ end
21
+ end