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