bunto 3.2.1 → 3.4.5
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +21 -4
- data/LICENSE +1 -1
- data/README.markdown +20 -25
- data/exe/bunto +1 -1
- data/lib/bunto.rb +10 -4
- data/lib/bunto/collection.rb +11 -4
- data/lib/bunto/commands/build.rb +17 -2
- data/lib/bunto/commands/doctor.rb +1 -1
- data/lib/bunto/commands/new.rb +35 -5
- data/lib/bunto/commands/new_theme.rb +4 -2
- data/lib/bunto/commands/serve.rb +45 -15
- data/lib/bunto/commands/serve/servlet.rb +1 -1
- data/lib/bunto/configuration.rb +9 -7
- data/lib/bunto/converters/markdown/kramdown_parser.rb +2 -2
- data/lib/bunto/converters/markdown/redcarpet_parser.rb +1 -1
- data/lib/bunto/convertible.rb +21 -82
- data/lib/bunto/desktop.ini +1 -1
- data/lib/bunto/document.rb +118 -81
- data/lib/bunto/drops/bunto_drop.rb +1 -1
- data/lib/bunto/drops/static_file_drop.rb +11 -0
- data/lib/bunto/drops/url_drop.rb +5 -0
- data/lib/bunto/entry_filter.rb +9 -10
- data/lib/bunto/excerpt.rb +2 -3
- data/lib/bunto/external.rb +1 -1
- data/lib/bunto/filters.rb +10 -32
- data/lib/bunto/filters/grouping_filters.rb +63 -0
- data/lib/bunto/filters/url_filters.rb +40 -0
- data/lib/bunto/frontmatter_defaults.rb +1 -1
- data/lib/bunto/hooks.rb +9 -9
- data/lib/bunto/log_adapter.rb +1 -1
- data/lib/bunto/page.rb +8 -4
- data/lib/bunto/plugin.rb +1 -1
- data/lib/bunto/reader.rb +2 -1
- data/lib/bunto/readers/data_reader.rb +9 -10
- data/lib/bunto/readers/post_reader.rb +1 -1
- data/lib/bunto/readers/theme_assets_reader.rb +47 -0
- data/lib/bunto/regenerator.rb +1 -1
- data/lib/bunto/related_posts.rb +3 -9
- data/lib/bunto/renderer.rb +26 -6
- data/lib/bunto/site.rb +12 -7
- data/lib/bunto/static_file.rb +20 -9
- data/lib/bunto/tags/highlight.rb +3 -3
- data/lib/bunto/tags/include.rb +9 -5
- data/lib/bunto/tags/link.rb +4 -2
- data/lib/bunto/tags/post_url.rb +4 -2
- data/lib/bunto/theme.rb +8 -4
- data/lib/bunto/theme_builder.rb +2 -2
- data/lib/bunto/url.rb +31 -8
- data/lib/bunto/utils.rb +16 -2
- data/lib/bunto/utils/ansi.rb +1 -1
- data/lib/bunto/utils/exec.rb +25 -0
- data/lib/bunto/utils/platforms.rb +52 -2
- data/lib/bunto/utils/win_tz.rb +73 -0
- data/lib/bunto/version.rb +1 -1
- data/lib/site_template/_config.yml +8 -3
- data/lib/site_template/_posts/0000-00-00-welcome-to-bunto.markdown.erb +4 -4
- data/lib/site_template/about.md +1 -1
- data/lib/site_template/index.md +6 -0
- data/lib/theme_template/LICENSE.txt.erb +1 -1
- data/lib/theme_template/README.md.erb +4 -4
- data/lib/theme_template/gitignore.erb +1 -0
- data/lib/theme_template/theme.gemspec.erb +3 -2
- metadata +55 -40
- data/lib/site_template/css/main.scss +0 -39
- data/lib/site_template/feed.xml +0 -30
- data/lib/site_template/index.html +0 -23
@@ -7,20 +7,20 @@ module Bunto
|
|
7
7
|
@entry_filter = EntryFilter.new(site)
|
8
8
|
end
|
9
9
|
|
10
|
-
# Read all the files in <
|
11
|
-
# object with each one.
|
10
|
+
# Read all the files in <dir> and adds them to @content
|
12
11
|
#
|
13
12
|
# dir - The String relative path of the directory to read.
|
14
13
|
#
|
15
|
-
# Returns
|
14
|
+
# Returns @content, a Hash of the .yaml, .yml,
|
15
|
+
# .json, and .csv files in the base directory
|
16
16
|
def read(dir)
|
17
17
|
base = site.in_source_dir(dir)
|
18
18
|
read_data_to(base, @content)
|
19
19
|
@content
|
20
20
|
end
|
21
21
|
|
22
|
-
# Read and parse all yaml
|
23
|
-
# <data> variable.
|
22
|
+
# Read and parse all .yaml, .yml, .json, and .csv
|
23
|
+
# files under <dir> and add them to the <data> variable.
|
24
24
|
#
|
25
25
|
# dir - The string absolute path of the directory to read.
|
26
26
|
# data - The variable to which data will be added.
|
@@ -37,10 +37,10 @@ module Bunto
|
|
37
37
|
path = @site.in_source_dir(dir, entry)
|
38
38
|
next if @entry_filter.symlink?(path)
|
39
39
|
|
40
|
-
key = sanitize_filename(File.basename(entry, ".*"))
|
41
40
|
if File.directory?(path)
|
42
|
-
read_data_to(path, data[
|
41
|
+
read_data_to(path, data[sanitize_filename(entry)] = {})
|
43
42
|
else
|
43
|
+
key = sanitize_filename(File.basename(entry, ".*"))
|
44
44
|
data[key] = read_data_file(path)
|
45
45
|
end
|
46
46
|
end
|
@@ -54,7 +54,7 @@ module Bunto
|
|
54
54
|
when ".csv"
|
55
55
|
CSV.read(path, {
|
56
56
|
:headers => true,
|
57
|
-
:encoding => site.config["encoding"]
|
57
|
+
:encoding => site.config["encoding"],
|
58
58
|
}).map(&:to_hash)
|
59
59
|
else
|
60
60
|
SafeYAML.load_file(path)
|
@@ -62,8 +62,7 @@ module Bunto
|
|
62
62
|
end
|
63
63
|
|
64
64
|
def sanitize_filename(name)
|
65
|
-
name.gsub!(%r![^\w\s-]
|
66
|
-
name.gsub!(%r!(^|\b\s)\s+($|\s?\b)!, '\\1\\2')
|
65
|
+
name.gsub!(%r![^\w\s-]+|(?<=^|\b\s)\s+(?=$|\s?\b)!, "".freeze)
|
67
66
|
name.gsub(%r!\s+!, "_")
|
68
67
|
end
|
69
68
|
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Bunto
|
2
|
+
class ThemeAssetsReader
|
3
|
+
attr_reader :site
|
4
|
+
def initialize(site)
|
5
|
+
@site = site
|
6
|
+
end
|
7
|
+
|
8
|
+
def read
|
9
|
+
return unless site.theme && site.theme.assets_path
|
10
|
+
|
11
|
+
Find.find(site.theme.assets_path) do |path|
|
12
|
+
next if File.directory?(path)
|
13
|
+
if File.symlink?(path)
|
14
|
+
Bunto.logger.warn "Theme reader:", "Ignored symlinked asset: #{path}"
|
15
|
+
else
|
16
|
+
read_theme_asset(path)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
def read_theme_asset(path)
|
23
|
+
base = site.theme.root
|
24
|
+
dir = File.dirname(path.sub("#{site.theme.root}/", ""))
|
25
|
+
name = File.basename(path)
|
26
|
+
|
27
|
+
if Utils.has_yaml_header?(path)
|
28
|
+
append_unless_exists site.pages,
|
29
|
+
Bunto::Page.new(site, base, dir, name)
|
30
|
+
else
|
31
|
+
append_unless_exists site.static_files,
|
32
|
+
Bunto::StaticFile.new(site, base, dir, name)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def append_unless_exists(haystack, new_item)
|
37
|
+
if haystack.any? { |file| file.relative_path == new_item.relative_path }
|
38
|
+
Bunto.logger.debug "Theme:",
|
39
|
+
"Ignoring #{new_item.relative_path} in theme due to existing file " \
|
40
|
+
"with that path in site."
|
41
|
+
return
|
42
|
+
end
|
43
|
+
|
44
|
+
haystack << new_item
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/lib/bunto/regenerator.rb
CHANGED
data/lib/bunto/related_posts.rb
CHANGED
@@ -26,15 +26,15 @@ module Bunto
|
|
26
26
|
def build_index
|
27
27
|
self.class.lsi ||= begin
|
28
28
|
lsi = ClassifierReborn::LSI.new(:auto_rebuild => false)
|
29
|
-
|
29
|
+
Bunto.logger.info("Populating LSI...")
|
30
30
|
|
31
31
|
site.posts.docs.each do |x|
|
32
32
|
lsi.add_item(x)
|
33
33
|
end
|
34
34
|
|
35
|
-
|
35
|
+
Bunto.logger.info("Rebuilding index...")
|
36
36
|
lsi.build_index
|
37
|
-
|
37
|
+
Bunto.logger.info("")
|
38
38
|
lsi
|
39
39
|
end
|
40
40
|
end
|
@@ -46,11 +46,5 @@ module Bunto
|
|
46
46
|
def most_recent_posts
|
47
47
|
@most_recent_posts ||= (site.posts.docs.reverse - [post]).first(10)
|
48
48
|
end
|
49
|
-
|
50
|
-
def display(output)
|
51
|
-
$stdout.print("\n")
|
52
|
-
$stdout.print(Bunto.logger.formatted_topic(output))
|
53
|
-
$stdout.flush
|
54
|
-
end
|
55
49
|
end
|
56
50
|
end
|
data/lib/bunto/renderer.rb
CHANGED
@@ -2,12 +2,32 @@
|
|
2
2
|
|
3
3
|
module Bunto
|
4
4
|
class Renderer
|
5
|
-
attr_reader :document, :site
|
5
|
+
attr_reader :document, :site
|
6
|
+
attr_writer :layouts, :payload
|
6
7
|
|
7
8
|
def initialize(site, document, site_payload = nil)
|
8
9
|
@site = site
|
9
10
|
@document = document
|
10
|
-
@payload = site_payload
|
11
|
+
@payload = site_payload
|
12
|
+
end
|
13
|
+
|
14
|
+
# Fetches the payload used in Liquid rendering.
|
15
|
+
# It can be written with #payload=(new_payload)
|
16
|
+
# Falls back to site.site_payload if no payload is set.
|
17
|
+
#
|
18
|
+
# Returns a Bunto::Drops::UnifiedPayloadDrop
|
19
|
+
def payload
|
20
|
+
@payload ||= site.site_payload
|
21
|
+
end
|
22
|
+
|
23
|
+
# The list of layouts registered for this Renderer.
|
24
|
+
# It can be written with #layouts=(new_layouts)
|
25
|
+
# Falls back to site.layouts if no layouts are registered.
|
26
|
+
#
|
27
|
+
# Returns a Hash of String => Bunto::Layout identified
|
28
|
+
# as basename without the extension name.
|
29
|
+
def layouts
|
30
|
+
@layouts || site.layouts
|
11
31
|
end
|
12
32
|
|
13
33
|
# Determine which converters to use based on this document's
|
@@ -15,7 +35,7 @@ module Bunto
|
|
15
35
|
#
|
16
36
|
# Returns an array of Converter instances.
|
17
37
|
def converters
|
18
|
-
@converters ||= site.converters.select { |c| c.matches(document.extname) }
|
38
|
+
@converters ||= site.converters.select { |c| c.matches(document.extname) }.sort
|
19
39
|
end
|
20
40
|
|
21
41
|
# Determine the extname the outputted file should have
|
@@ -126,7 +146,7 @@ module Bunto
|
|
126
146
|
#
|
127
147
|
# Returns true if the layout is invalid, false if otherwise
|
128
148
|
def invalid_layout?(layout)
|
129
|
-
!document.data["layout"].nil? && layout.nil?
|
149
|
+
!document.data["layout"].nil? && layout.nil? && !(document.is_a? Bunto::Excerpt)
|
130
150
|
end
|
131
151
|
|
132
152
|
# Render layouts and place given content inside.
|
@@ -137,7 +157,7 @@ module Bunto
|
|
137
157
|
# Returns the content placed in the Liquid-rendered layouts
|
138
158
|
def place_in_layouts(content, payload, info)
|
139
159
|
output = content.dup
|
140
|
-
layout =
|
160
|
+
layout = layouts[document.data["layout"]]
|
141
161
|
|
142
162
|
Bunto.logger.warn(
|
143
163
|
"Build Warning:",
|
@@ -167,7 +187,7 @@ module Bunto
|
|
167
187
|
site.in_source_dir(layout.path)
|
168
188
|
) if document.write?
|
169
189
|
|
170
|
-
if (layout =
|
190
|
+
if (layout = layouts[layout.data["layout"]])
|
171
191
|
break if used.include?(layout)
|
172
192
|
used << layout
|
173
193
|
end
|
data/lib/bunto/site.rb
CHANGED
@@ -191,11 +191,7 @@ module Bunto
|
|
191
191
|
render_pages(payload)
|
192
192
|
|
193
193
|
Bunto::Hooks.trigger :site, :post_render, self, payload
|
194
|
-
# rubocop: disable HandleExceptions
|
195
|
-
rescue Errno::ENOENT
|
196
|
-
# ignore missing layout dir
|
197
194
|
end
|
198
|
-
# rubocop: enable HandleExceptions
|
199
195
|
|
200
196
|
# Remove orphaned files and empty directories in destination.
|
201
197
|
#
|
@@ -306,7 +302,7 @@ module Bunto
|
|
306
302
|
Bunto.logger.abort_with "Since v3.0, permalinks for pages" \
|
307
303
|
" in subfolders must be relative to the" \
|
308
304
|
" site source directory, not the parent" \
|
309
|
-
" directory. Check
|
305
|
+
" directory. Check https://buntorb.com/docs/upgrading/"\
|
310
306
|
" for more info."
|
311
307
|
end
|
312
308
|
end
|
@@ -424,13 +420,22 @@ module Bunto
|
|
424
420
|
private
|
425
421
|
def configure_theme
|
426
422
|
self.theme = nil
|
427
|
-
|
423
|
+
return if config["theme"].nil?
|
424
|
+
|
425
|
+
self.theme =
|
426
|
+
if config["theme"].is_a?(String)
|
427
|
+
Bunto::Theme.new(config["theme"])
|
428
|
+
else
|
429
|
+
Bunto.logger.warn "Theme:", "value of 'theme' in config should be " \
|
430
|
+
"String to use gem-based themes, but got #{config["theme"].class}"
|
431
|
+
nil
|
432
|
+
end
|
428
433
|
end
|
429
434
|
|
430
435
|
private
|
431
436
|
def configure_include_paths
|
432
437
|
@includes_load_paths = Array(in_source_dir(config["includes_dir"].to_s))
|
433
|
-
@includes_load_paths << theme.includes_path if
|
438
|
+
@includes_load_paths << theme.includes_path if theme && theme.includes_path
|
434
439
|
end
|
435
440
|
|
436
441
|
private
|
data/lib/bunto/static_file.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module Bunto
|
2
2
|
class StaticFile
|
3
|
-
attr_reader :relative_path, :extname
|
3
|
+
attr_reader :relative_path, :extname, :name
|
4
4
|
|
5
5
|
class << self
|
6
6
|
# The cache of last modification times [path] -> mtime.
|
@@ -28,6 +28,10 @@ module Bunto
|
|
28
28
|
@collection = collection
|
29
29
|
@relative_path = File.join(*[@dir, @name].compact)
|
30
30
|
@extname = File.extname(@name)
|
31
|
+
|
32
|
+
data.default_proc = proc do |_, key|
|
33
|
+
site.frontmatter_defaults.find(relative_path, type, key)
|
34
|
+
end
|
31
35
|
end
|
32
36
|
# rubocop: enable ParameterLists
|
33
37
|
|
@@ -96,11 +100,15 @@ module Bunto
|
|
96
100
|
end
|
97
101
|
|
98
102
|
def to_liquid
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
}
|
103
|
+
@to_liquid ||= Drops::StaticFileDrop.new(self)
|
104
|
+
end
|
105
|
+
|
106
|
+
def data
|
107
|
+
@data ||= {}
|
108
|
+
end
|
109
|
+
|
110
|
+
def basename
|
111
|
+
File.basename(name, extname)
|
104
112
|
end
|
105
113
|
|
106
114
|
def placeholders
|
@@ -110,7 +118,7 @@ module Bunto
|
|
110
118
|
@collection.relative_directory.size..relative_path.size],
|
111
119
|
:output_ext => "",
|
112
120
|
:name => "",
|
113
|
-
:title => ""
|
121
|
+
:title => "",
|
114
122
|
}
|
115
123
|
end
|
116
124
|
|
@@ -123,7 +131,7 @@ module Bunto
|
|
123
131
|
else
|
124
132
|
::Bunto::URL.new({
|
125
133
|
:template => @collection.url_template,
|
126
|
-
:placeholders => placeholders
|
134
|
+
:placeholders => placeholders,
|
127
135
|
})
|
128
136
|
end.to_s.gsub(%r!/$!, "")
|
129
137
|
end
|
@@ -146,7 +154,10 @@ module Bunto
|
|
146
154
|
else
|
147
155
|
FileUtils.copy_entry(path, dest_path)
|
148
156
|
end
|
149
|
-
|
157
|
+
|
158
|
+
unless File.symlink?(dest_path)
|
159
|
+
File.utime(self.class.mtimes[path], self.class.mtimes[path], dest_path)
|
160
|
+
end
|
150
161
|
end
|
151
162
|
end
|
152
163
|
end
|
data/lib/bunto/tags/highlight.rb
CHANGED
@@ -8,7 +8,7 @@ module Bunto
|
|
8
8
|
# forms: name, name=value, or name="<quoted list>"
|
9
9
|
#
|
10
10
|
# <quoted list> is a space-separated list of numbers
|
11
|
-
SYNTAX = %r!^([a-zA-Z0-9
|
11
|
+
SYNTAX = %r!^([a-zA-Z0-9.+#_-]+)((\s+\w+(=(\w+|"([0-9]+\s)*[0-9]+"))?)*)$!
|
12
12
|
|
13
13
|
def initialize(tag_name, markup, tokens)
|
14
14
|
super
|
@@ -54,7 +54,7 @@ eos
|
|
54
54
|
[:hl_lines, opts.fetch(:hl_lines, nil)],
|
55
55
|
[:linenos, opts.fetch(:linenos, nil)],
|
56
56
|
[:encoding, opts.fetch(:encoding, "utf-8")],
|
57
|
-
[:cssclass, opts.fetch(:cssclass, nil)]
|
57
|
+
[:cssclass, opts.fetch(:cssclass, nil)],
|
58
58
|
].reject { |f| f.last.nil? }]
|
59
59
|
else
|
60
60
|
opts
|
@@ -125,7 +125,7 @@ eos
|
|
125
125
|
def add_code_tag(code)
|
126
126
|
code_attributes = [
|
127
127
|
"class=\"language-#{@lang.to_s.tr("+", "-")}\"",
|
128
|
-
"data-lang=\"#{@lang}\""
|
128
|
+
"data-lang=\"#{@lang}\"",
|
129
129
|
].join(" ")
|
130
130
|
"<figure class=\"highlight\"><pre><code #{code_attributes}>"\
|
131
131
|
"#{code.chomp}</code></pre></figure>"
|
data/lib/bunto/tags/include.rb
CHANGED
@@ -112,8 +112,8 @@ eos
|
|
112
112
|
def locate_include_file(context, file, safe)
|
113
113
|
includes_dirs = tag_includes_dirs(context)
|
114
114
|
includes_dirs.each do |dir|
|
115
|
-
path = File.join(dir, file)
|
116
|
-
return path if valid_include_file?(path, dir, safe)
|
115
|
+
path = File.join(dir.to_s, file.to_s)
|
116
|
+
return path if valid_include_file?(path, dir.to_s, safe)
|
117
117
|
end
|
118
118
|
raise IOError, "Could not locate the included file '#{file}' in any of "\
|
119
119
|
"#{includes_dirs}. Ensure it exists in one of those directories and, "\
|
@@ -155,15 +155,19 @@ eos
|
|
155
155
|
if cached_partial.key?(path)
|
156
156
|
cached_partial[path]
|
157
157
|
else
|
158
|
-
|
158
|
+
unparsed_file = context.registers[:site]
|
159
159
|
.liquid_renderer
|
160
160
|
.file(path)
|
161
|
-
|
161
|
+
begin
|
162
|
+
cached_partial[path] = unparsed_file.parse(read_file(path, context))
|
163
|
+
rescue Liquid::SyntaxError => ex
|
164
|
+
raise IncludeTagError.new(ex.message, path)
|
165
|
+
end
|
162
166
|
end
|
163
167
|
end
|
164
168
|
|
165
169
|
def valid_include_file?(path, dir, safe)
|
166
|
-
!
|
170
|
+
!outside_site_source?(path, dir, safe) && File.file?(path)
|
167
171
|
end
|
168
172
|
|
169
173
|
def outside_site_source?(path, dir, safe)
|
data/lib/bunto/tags/link.rb
CHANGED
@@ -16,8 +16,10 @@ module Bunto
|
|
16
16
|
def render(context)
|
17
17
|
site = context.registers[:site]
|
18
18
|
|
19
|
-
site.
|
20
|
-
return
|
19
|
+
site.each_site_file do |item|
|
20
|
+
return item.url if item.relative_path == @relative_path
|
21
|
+
# This takes care of the case for static files that have a leading /
|
22
|
+
return item.url if item.relative_path == "/#{@relative_path}"
|
21
23
|
end
|
22
24
|
|
23
25
|
raise ArgumentError, <<eos
|
data/lib/bunto/tags/post_url.rb
CHANGED
@@ -14,7 +14,9 @@ module Bunto
|
|
14
14
|
"'#{name}' does not contain valid date and/or title."
|
15
15
|
end
|
16
16
|
|
17
|
-
|
17
|
+
escaped_slug = Regexp.escape(slug)
|
18
|
+
@name_regex = %r!^_posts/#{path}#{date}-#{escaped_slug}\.[^.]+|
|
19
|
+
^#{path}_posts/?#{date}-#{escaped_slug}\.[^.]+!x
|
18
20
|
end
|
19
21
|
|
20
22
|
def post_date
|
@@ -23,7 +25,7 @@ module Bunto
|
|
23
25
|
end
|
24
26
|
|
25
27
|
def ==(other)
|
26
|
-
other.
|
28
|
+
other.relative_path.match(@name_regex)
|
27
29
|
end
|
28
30
|
|
29
31
|
def deprecated_equality(other)
|
data/lib/bunto/theme.rb
CHANGED
@@ -18,15 +18,19 @@ module Bunto
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def includes_path
|
21
|
-
path_for
|
21
|
+
path_for "_includes".freeze
|
22
22
|
end
|
23
23
|
|
24
24
|
def layouts_path
|
25
|
-
path_for
|
25
|
+
path_for "_layouts".freeze
|
26
26
|
end
|
27
27
|
|
28
28
|
def sass_path
|
29
|
-
path_for
|
29
|
+
path_for "_sass".freeze
|
30
|
+
end
|
31
|
+
|
32
|
+
def assets_path
|
33
|
+
path_for "assets".freeze
|
30
34
|
end
|
31
35
|
|
32
36
|
def configure_sass
|
@@ -43,7 +47,7 @@ module Bunto
|
|
43
47
|
end
|
44
48
|
|
45
49
|
def realpath_for(folder)
|
46
|
-
File.realpath(Bunto.sanitized_path(root,
|
50
|
+
File.realpath(Bunto.sanitized_path(root, folder.to_s))
|
47
51
|
rescue Errno::ENOENT, Errno::EACCES, Errno::ELOOP
|
48
52
|
nil
|
49
53
|
end
|