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.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.markdown +59 -0
- data/bin/bunto +51 -0
- data/lib/bunto.rb +179 -0
- data/lib/bunto/cleaner.rb +105 -0
- data/lib/bunto/collection.rb +205 -0
- data/lib/bunto/command.rb +65 -0
- data/lib/bunto/commands/build.rb +77 -0
- data/lib/bunto/commands/clean.rb +42 -0
- data/lib/bunto/commands/doctor.rb +114 -0
- data/lib/bunto/commands/help.rb +31 -0
- data/lib/bunto/commands/new.rb +82 -0
- data/lib/bunto/commands/serve.rb +204 -0
- data/lib/bunto/commands/serve/servlet.rb +61 -0
- data/lib/bunto/configuration.rb +323 -0
- data/lib/bunto/converter.rb +48 -0
- data/lib/bunto/converters/identity.rb +21 -0
- data/lib/bunto/converters/markdown.rb +92 -0
- data/lib/bunto/converters/markdown/kramdown_parser.rb +117 -0
- data/lib/bunto/converters/markdown/rdiscount_parser.rb +33 -0
- data/lib/bunto/converters/markdown/redcarpet_parser.rb +102 -0
- data/lib/bunto/converters/smartypants.rb +34 -0
- data/lib/bunto/convertible.rb +297 -0
- data/lib/bunto/deprecator.rb +46 -0
- data/lib/bunto/document.rb +444 -0
- data/lib/bunto/drops/bunto_drop.rb +21 -0
- data/lib/bunto/drops/collection_drop.rb +22 -0
- data/lib/bunto/drops/document_drop.rb +27 -0
- data/lib/bunto/drops/drop.rb +176 -0
- data/lib/bunto/drops/site_drop.rb +38 -0
- data/lib/bunto/drops/unified_payload_drop.rb +25 -0
- data/lib/bunto/drops/url_drop.rb +83 -0
- data/lib/bunto/entry_filter.rb +72 -0
- data/lib/bunto/errors.rb +10 -0
- data/lib/bunto/excerpt.rb +127 -0
- data/lib/bunto/external.rb +59 -0
- data/lib/bunto/filters.rb +367 -0
- data/lib/bunto/frontmatter_defaults.rb +188 -0
- data/lib/bunto/generator.rb +3 -0
- data/lib/bunto/hooks.rb +101 -0
- data/lib/bunto/layout.rb +49 -0
- data/lib/bunto/liquid_extensions.rb +22 -0
- data/lib/bunto/liquid_renderer.rb +39 -0
- data/lib/bunto/liquid_renderer/file.rb +50 -0
- data/lib/bunto/liquid_renderer/table.rb +94 -0
- data/lib/bunto/log_adapter.rb +115 -0
- data/lib/bunto/mime.types +800 -0
- data/lib/bunto/page.rb +180 -0
- data/lib/bunto/plugin.rb +96 -0
- data/lib/bunto/plugin_manager.rb +95 -0
- data/lib/bunto/post.rb +329 -0
- data/lib/bunto/publisher.rb +21 -0
- data/lib/bunto/reader.rb +126 -0
- data/lib/bunto/readers/collection_reader.rb +20 -0
- data/lib/bunto/readers/data_reader.rb +69 -0
- data/lib/bunto/readers/layout_reader.rb +53 -0
- data/lib/bunto/readers/page_reader.rb +21 -0
- data/lib/bunto/readers/post_reader.rb +62 -0
- data/lib/bunto/readers/static_file_reader.rb +21 -0
- data/lib/bunto/regenerator.rb +175 -0
- data/lib/bunto/related_posts.rb +56 -0
- data/lib/bunto/renderer.rb +191 -0
- data/lib/bunto/site.rb +391 -0
- data/lib/bunto/static_file.rb +141 -0
- data/lib/bunto/stevenson.rb +58 -0
- data/lib/bunto/tags/highlight.rb +122 -0
- data/lib/bunto/tags/include.rb +190 -0
- data/lib/bunto/tags/post_url.rb +88 -0
- data/lib/bunto/url.rb +136 -0
- data/lib/bunto/utils.rb +287 -0
- data/lib/bunto/utils/ansi.rb +59 -0
- data/lib/bunto/utils/platforms.rb +30 -0
- data/lib/bunto/version.rb +3 -0
- data/lib/site_template/.gitignore +3 -0
- data/lib/site_template/_config.yml +21 -0
- data/lib/site_template/_includes/footer.html +38 -0
- data/lib/site_template/_includes/head.html +12 -0
- data/lib/site_template/_includes/header.html +27 -0
- data/lib/site_template/_includes/icon-github.html +1 -0
- data/lib/site_template/_includes/icon-github.svg +1 -0
- data/lib/site_template/_includes/icon-twitter.html +1 -0
- data/lib/site_template/_includes/icon-twitter.svg +1 -0
- data/lib/site_template/_layouts/default.html +20 -0
- data/lib/site_template/_layouts/page.html +14 -0
- data/lib/site_template/_layouts/post.html +15 -0
- data/lib/site_template/_posts/0000-00-00-welcome-to-bunto.markdown.erb +25 -0
- data/lib/site_template/_sass/_base.scss +206 -0
- data/lib/site_template/_sass/_layout.scss +242 -0
- data/lib/site_template/_sass/_syntax-highlighting.scss +71 -0
- data/lib/site_template/about.md +15 -0
- data/lib/site_template/css/main.scss +53 -0
- data/lib/site_template/feed.xml +30 -0
- data/lib/site_template/index.html +23 -0
- metadata +252 -0
@@ -0,0 +1,21 @@
|
|
1
|
+
module Bunto
|
2
|
+
class Publisher
|
3
|
+
def initialize(site)
|
4
|
+
@site = site
|
5
|
+
end
|
6
|
+
|
7
|
+
def publish?(thing)
|
8
|
+
can_be_published?(thing) && !hidden_in_the_future?(thing)
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def can_be_published?(thing)
|
14
|
+
thing.data.fetch('published', true) || @site.unpublished
|
15
|
+
end
|
16
|
+
|
17
|
+
def hidden_in_the_future?(thing)
|
18
|
+
thing.respond_to?(:date) && !@site.future && thing.date.to_i > @site.time.to_i
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/bunto/reader.rb
ADDED
@@ -0,0 +1,126 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'csv'
|
3
|
+
|
4
|
+
module Bunto
|
5
|
+
class Reader
|
6
|
+
attr_reader :site
|
7
|
+
|
8
|
+
def initialize(site)
|
9
|
+
@site = site
|
10
|
+
end
|
11
|
+
|
12
|
+
# Read Site data from disk and load it into internal data structures.
|
13
|
+
#
|
14
|
+
# Returns nothing.
|
15
|
+
def read
|
16
|
+
@site.layouts = LayoutReader.new(site).read
|
17
|
+
read_directories
|
18
|
+
sort_files!
|
19
|
+
@site.data = DataReader.new(site).read(site.config['data_dir'])
|
20
|
+
CollectionReader.new(site).read
|
21
|
+
end
|
22
|
+
|
23
|
+
# Sorts posts, pages, and static files.
|
24
|
+
def sort_files!
|
25
|
+
site.collections.values.each { |c| c.docs.sort! }
|
26
|
+
site.pages.sort_by!(&:name)
|
27
|
+
site.static_files.sort_by!(&:relative_path)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Recursively traverse directories to find pages and static files
|
31
|
+
# that will become part of the site according to the rules in
|
32
|
+
# filter_entries.
|
33
|
+
#
|
34
|
+
# dir - The String relative path of the directory to read. Default: ''.
|
35
|
+
#
|
36
|
+
# Returns nothing.
|
37
|
+
def read_directories(dir = '')
|
38
|
+
base = site.in_source_dir(dir)
|
39
|
+
|
40
|
+
dot = Dir.chdir(base) { filter_entries(Dir.entries('.'), base) }
|
41
|
+
dot_dirs = dot.select { |file| File.directory?(@site.in_source_dir(base, file)) }
|
42
|
+
dot_files = (dot - dot_dirs)
|
43
|
+
dot_pages = dot_files.select { |file| Utils.has_yaml_header?(@site.in_source_dir(base, file)) }
|
44
|
+
dot_static_files = dot_files - dot_pages
|
45
|
+
|
46
|
+
retrieve_posts(dir)
|
47
|
+
retrieve_dirs(base, dir, dot_dirs)
|
48
|
+
retrieve_pages(dir, dot_pages)
|
49
|
+
retrieve_static_files(dir, dot_static_files)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Retrieves all the posts(posts/drafts) from the given directory
|
53
|
+
# and add them to the site and sort them.
|
54
|
+
#
|
55
|
+
# dir - The String representing the directory to retrieve the posts from.
|
56
|
+
#
|
57
|
+
# Returns nothing.
|
58
|
+
def retrieve_posts(dir)
|
59
|
+
site.posts.docs.concat(PostReader.new(site).read_posts(dir))
|
60
|
+
site.posts.docs.concat(PostReader.new(site).read_drafts(dir)) if site.show_drafts
|
61
|
+
end
|
62
|
+
|
63
|
+
# Recursively traverse directories with the read_directories function.
|
64
|
+
#
|
65
|
+
# base - The String representing the site's base directory.
|
66
|
+
# dir - The String representing the directory to traverse down.
|
67
|
+
# dot_dirs - The Array of subdirectories in the dir.
|
68
|
+
#
|
69
|
+
# Returns nothing.
|
70
|
+
def retrieve_dirs(_base, dir, dot_dirs)
|
71
|
+
dot_dirs.map do |file|
|
72
|
+
dir_path = site.in_source_dir(dir, file)
|
73
|
+
rel_path = File.join(dir, file)
|
74
|
+
@site.reader.read_directories(rel_path) unless @site.dest.sub(/\/$/, '') == dir_path
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# Retrieve all the pages from the current directory,
|
79
|
+
# add them to the site and sort them.
|
80
|
+
#
|
81
|
+
# dir - The String representing the directory retrieve the pages from.
|
82
|
+
# dot_pages - The Array of pages in the dir.
|
83
|
+
#
|
84
|
+
# Returns nothing.
|
85
|
+
def retrieve_pages(dir, dot_pages)
|
86
|
+
site.pages.concat(PageReader.new(site, dir).read(dot_pages))
|
87
|
+
end
|
88
|
+
|
89
|
+
# Retrieve all the static files from the current directory,
|
90
|
+
# add them to the site and sort them.
|
91
|
+
#
|
92
|
+
# dir - The directory retrieve the static files from.
|
93
|
+
# dot_static_files - The static files in the dir.
|
94
|
+
#
|
95
|
+
# Returns nothing.
|
96
|
+
def retrieve_static_files(dir, dot_static_files)
|
97
|
+
site.static_files.concat(StaticFileReader.new(site, dir).read(dot_static_files))
|
98
|
+
end
|
99
|
+
|
100
|
+
# Filter out any files/directories that are hidden or backup files (start
|
101
|
+
# with "." or "#" or end with "~"), or contain site content (start with "_"),
|
102
|
+
# or are excluded in the site configuration, unless they are web server
|
103
|
+
# files such as '.htaccess'.
|
104
|
+
#
|
105
|
+
# entries - The Array of String file/directory entries to filter.
|
106
|
+
# base_directory - The string representing the optional base directory.
|
107
|
+
#
|
108
|
+
# Returns the Array of filtered entries.
|
109
|
+
def filter_entries(entries, base_directory = nil)
|
110
|
+
EntryFilter.new(site, base_directory).filter(entries)
|
111
|
+
end
|
112
|
+
|
113
|
+
# Read the entries from a particular directory for processing
|
114
|
+
#
|
115
|
+
# dir - The String representing the relative path of the directory to read.
|
116
|
+
# subfolder - The String representing the directory to read.
|
117
|
+
#
|
118
|
+
# Returns the list of entries to process
|
119
|
+
def get_entries(dir, subfolder)
|
120
|
+
base = site.in_source_dir(dir, subfolder)
|
121
|
+
return [] unless File.exist?(base)
|
122
|
+
entries = Dir.chdir(base) { filter_entries(Dir['**/*'], base) }
|
123
|
+
entries.delete_if { |e| File.directory?(site.in_source_dir(base, e)) }
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Bunto
|
2
|
+
class CollectionReader
|
3
|
+
SPECIAL_COLLECTIONS = %w(posts data).freeze
|
4
|
+
|
5
|
+
attr_reader :site, :content
|
6
|
+
def initialize(site)
|
7
|
+
@site = site
|
8
|
+
@content = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
# Read in all collections specified in the configuration
|
12
|
+
#
|
13
|
+
# Returns nothing.
|
14
|
+
def read
|
15
|
+
site.collections.each do |_, collection|
|
16
|
+
collection.read unless SPECIAL_COLLECTIONS.include?(collection.label)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Bunto
|
2
|
+
class DataReader
|
3
|
+
attr_reader :site, :content
|
4
|
+
def initialize(site)
|
5
|
+
@site = site
|
6
|
+
@content = {}
|
7
|
+
end
|
8
|
+
|
9
|
+
# Read all the files in <source>/<dir>/_drafts and create a new Draft
|
10
|
+
# object with each one.
|
11
|
+
#
|
12
|
+
# dir - The String relative path of the directory to read.
|
13
|
+
#
|
14
|
+
# Returns nothing.
|
15
|
+
def read(dir)
|
16
|
+
base = site.in_source_dir(dir)
|
17
|
+
read_data_to(base, @content)
|
18
|
+
@content
|
19
|
+
end
|
20
|
+
|
21
|
+
# Read and parse all yaml files under <dir> and add them to the
|
22
|
+
# <data> variable.
|
23
|
+
#
|
24
|
+
# dir - The string absolute path of the directory to read.
|
25
|
+
# data - The variable to which data will be added.
|
26
|
+
#
|
27
|
+
# Returns nothing
|
28
|
+
def read_data_to(dir, data)
|
29
|
+
return unless File.directory?(dir) && (!site.safe || !File.symlink?(dir))
|
30
|
+
|
31
|
+
entries = Dir.chdir(dir) do
|
32
|
+
Dir['*.{yaml,yml,json,csv}'] + Dir['*'].select { |fn| File.directory?(fn) }
|
33
|
+
end
|
34
|
+
|
35
|
+
entries.each do |entry|
|
36
|
+
path = @site.in_source_dir(dir, entry)
|
37
|
+
next if File.symlink?(path) && site.safe
|
38
|
+
|
39
|
+
key = sanitize_filename(File.basename(entry, '.*'))
|
40
|
+
if File.directory?(path)
|
41
|
+
read_data_to(path, data[key] = {})
|
42
|
+
else
|
43
|
+
data[key] = read_data_file(path)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Determines how to read a data file.
|
49
|
+
#
|
50
|
+
# Returns the contents of the data file.
|
51
|
+
def read_data_file(path)
|
52
|
+
case File.extname(path).downcase
|
53
|
+
when '.csv'
|
54
|
+
CSV.read(path, {
|
55
|
+
:headers => true,
|
56
|
+
:encoding => site.config['encoding']
|
57
|
+
}).map(&:to_hash)
|
58
|
+
else
|
59
|
+
SafeYAML.load_file(path)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def sanitize_filename(name)
|
64
|
+
name.gsub!(/[^\w\s-]+/, '')
|
65
|
+
name.gsub!(/(^|\b\s)\s+($|\s?\b)/, '\\1\\2')
|
66
|
+
name.gsub(/\s+/, '_')
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Bunto
|
2
|
+
class LayoutReader
|
3
|
+
attr_reader :site
|
4
|
+
def initialize(site)
|
5
|
+
@site = site
|
6
|
+
@layouts = {}
|
7
|
+
end
|
8
|
+
|
9
|
+
def read
|
10
|
+
layout_entries.each do |f|
|
11
|
+
@layouts[layout_name(f)] = Layout.new(site, layout_directory, f)
|
12
|
+
end
|
13
|
+
|
14
|
+
@layouts
|
15
|
+
end
|
16
|
+
|
17
|
+
def layout_directory
|
18
|
+
@layout_directory ||= (layout_directory_in_cwd || layout_directory_inside_source)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def layout_entries
|
24
|
+
entries = []
|
25
|
+
within(layout_directory) do
|
26
|
+
entries = EntryFilter.new(site).filter(Dir['**/*.*'])
|
27
|
+
end
|
28
|
+
entries
|
29
|
+
end
|
30
|
+
|
31
|
+
def layout_name(file)
|
32
|
+
file.split(".")[0..-2].join(".")
|
33
|
+
end
|
34
|
+
|
35
|
+
def within(directory)
|
36
|
+
return unless File.exist?(directory)
|
37
|
+
Dir.chdir(directory) { yield }
|
38
|
+
end
|
39
|
+
|
40
|
+
def layout_directory_inside_source
|
41
|
+
site.in_source_dir(site.config['layouts_dir'])
|
42
|
+
end
|
43
|
+
|
44
|
+
def layout_directory_in_cwd
|
45
|
+
dir = Bunto.sanitized_path(Dir.pwd, site.config['layouts_dir'])
|
46
|
+
if File.directory?(dir) && !site.safe
|
47
|
+
dir
|
48
|
+
else
|
49
|
+
nil
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Bunto
|
2
|
+
class PageReader
|
3
|
+
attr_reader :site, :dir, :unfiltered_content
|
4
|
+
def initialize(site, dir)
|
5
|
+
@site = site
|
6
|
+
@dir = dir
|
7
|
+
@unfiltered_content = []
|
8
|
+
end
|
9
|
+
|
10
|
+
# Read all the files in <source>/<dir>/ for Yaml header and create a new Page
|
11
|
+
# object for each file.
|
12
|
+
#
|
13
|
+
# dir - The String relative path of the directory to read.
|
14
|
+
#
|
15
|
+
# Returns an array of static pages.
|
16
|
+
def read(files)
|
17
|
+
files.map { |page| @unfiltered_content << Page.new(@site, @site.source, @dir, page) }
|
18
|
+
@unfiltered_content.select { |page| site.publisher.publish?(page) }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Bunto
|
2
|
+
class PostReader
|
3
|
+
attr_reader :site, :unfiltered_content
|
4
|
+
def initialize(site)
|
5
|
+
@site = site
|
6
|
+
end
|
7
|
+
|
8
|
+
# Read all the files in <source>/<dir>/_drafts and create a new
|
9
|
+
# Document object with each one.
|
10
|
+
#
|
11
|
+
# dir - The String relative path of the directory to read.
|
12
|
+
#
|
13
|
+
# Returns nothing.
|
14
|
+
def read_drafts(dir)
|
15
|
+
read_publishable(dir, '_drafts', Document::DATELESS_FILENAME_MATCHER)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Read all the files in <source>/<dir>/_posts and create a new Document
|
19
|
+
# object with each one.
|
20
|
+
#
|
21
|
+
# dir - The String relative path of the directory to read.
|
22
|
+
#
|
23
|
+
# Returns nothing.
|
24
|
+
def read_posts(dir)
|
25
|
+
read_publishable(dir, '_posts', Document::DATE_FILENAME_MATCHER)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Read all the files in <source>/<dir>/<magic_dir> and create a new
|
29
|
+
# Document object with each one insofar as it matches the regexp matcher.
|
30
|
+
#
|
31
|
+
# dir - The String relative path of the directory to read.
|
32
|
+
#
|
33
|
+
# Returns nothing.
|
34
|
+
def read_publishable(dir, magic_dir, matcher)
|
35
|
+
read_content(dir, magic_dir, matcher).tap do |docs|
|
36
|
+
docs.each(&:read)
|
37
|
+
end.select do |doc|
|
38
|
+
site.publisher.publish?(doc)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Read all the content files from <source>/<dir>/magic_dir
|
43
|
+
# and return them with the type klass.
|
44
|
+
#
|
45
|
+
# dir - The String relative path of the directory to read.
|
46
|
+
# magic_dir - The String relative directory to <dir>,
|
47
|
+
# looks for content here.
|
48
|
+
# klass - The return type of the content.
|
49
|
+
#
|
50
|
+
# Returns klass type of content files
|
51
|
+
def read_content(dir, magic_dir, matcher)
|
52
|
+
@site.reader.get_entries(dir, magic_dir).map do |entry|
|
53
|
+
next unless entry =~ matcher
|
54
|
+
path = @site.in_source_dir(File.join(dir, magic_dir, entry))
|
55
|
+
Document.new(path, {
|
56
|
+
:site => @site,
|
57
|
+
:collection => @site.posts
|
58
|
+
})
|
59
|
+
end.reject(&:nil?)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Bunto
|
2
|
+
class StaticFileReader
|
3
|
+
attr_reader :site, :dir, :unfiltered_content
|
4
|
+
def initialize(site, dir)
|
5
|
+
@site = site
|
6
|
+
@dir = dir
|
7
|
+
@unfiltered_content = []
|
8
|
+
end
|
9
|
+
|
10
|
+
# Read all the files in <source>/<dir>/ for Yaml header and create a new Page
|
11
|
+
# object for each file.
|
12
|
+
#
|
13
|
+
# dir - The String relative path of the directory to read.
|
14
|
+
#
|
15
|
+
# Returns an array of static files.
|
16
|
+
def read(files)
|
17
|
+
files.map { |file| @unfiltered_content << StaticFile.new(@site, @site.source, @dir, file) }
|
18
|
+
@unfiltered_content
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,175 @@
|
|
1
|
+
module Bunto
|
2
|
+
class Regenerator
|
3
|
+
attr_reader :site, :metadata, :cache
|
4
|
+
|
5
|
+
def initialize(site)
|
6
|
+
@site = site
|
7
|
+
|
8
|
+
# Read metadata from file
|
9
|
+
read_metadata
|
10
|
+
|
11
|
+
# Initialize cache to an empty hash
|
12
|
+
clear_cache
|
13
|
+
end
|
14
|
+
|
15
|
+
# Checks if a renderable object needs to be regenerated
|
16
|
+
#
|
17
|
+
# Returns a boolean.
|
18
|
+
def regenerate?(document)
|
19
|
+
case document
|
20
|
+
when Page
|
21
|
+
document.asset_file? || document.data['regenerate'] ||
|
22
|
+
source_modified_or_dest_missing?(
|
23
|
+
site.in_source_dir(document.relative_path), document.destination(@site.dest)
|
24
|
+
)
|
25
|
+
when Document
|
26
|
+
!document.write? || document.data['regenerate'] ||
|
27
|
+
source_modified_or_dest_missing?(
|
28
|
+
document.path, document.destination(@site.dest)
|
29
|
+
)
|
30
|
+
else
|
31
|
+
source_path = document.respond_to?(:path) ? document.path : nil
|
32
|
+
dest_path = document.respond_to?(:destination) ? document.destination(@site.dest) : nil
|
33
|
+
source_modified_or_dest_missing?(source_path, dest_path)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Add a path to the metadata
|
38
|
+
#
|
39
|
+
# Returns true, also on failure.
|
40
|
+
def add(path)
|
41
|
+
return true unless File.exist?(path)
|
42
|
+
|
43
|
+
metadata[path] = {
|
44
|
+
"mtime" => File.mtime(path),
|
45
|
+
"deps" => []
|
46
|
+
}
|
47
|
+
cache[path] = true
|
48
|
+
end
|
49
|
+
|
50
|
+
# Force a path to regenerate
|
51
|
+
#
|
52
|
+
# Returns true.
|
53
|
+
def force(path)
|
54
|
+
cache[path] = true
|
55
|
+
end
|
56
|
+
|
57
|
+
# Clear the metadata and cache
|
58
|
+
#
|
59
|
+
# Returns nothing
|
60
|
+
def clear
|
61
|
+
@metadata = {}
|
62
|
+
clear_cache
|
63
|
+
end
|
64
|
+
|
65
|
+
# Clear just the cache
|
66
|
+
#
|
67
|
+
# Returns nothing
|
68
|
+
def clear_cache
|
69
|
+
@cache = {}
|
70
|
+
end
|
71
|
+
|
72
|
+
# Checks if the source has been modified or the
|
73
|
+
# destination is missing
|
74
|
+
#
|
75
|
+
# returns a boolean
|
76
|
+
def source_modified_or_dest_missing?(source_path, dest_path)
|
77
|
+
modified?(source_path) || (dest_path && !File.exist?(dest_path))
|
78
|
+
end
|
79
|
+
|
80
|
+
# Checks if a path's (or one of its dependencies)
|
81
|
+
# mtime has changed
|
82
|
+
#
|
83
|
+
# Returns a boolean.
|
84
|
+
def modified?(path)
|
85
|
+
return true if disabled?
|
86
|
+
|
87
|
+
# objects that don't have a path are always regenerated
|
88
|
+
return true if path.nil?
|
89
|
+
|
90
|
+
# Check for path in cache
|
91
|
+
if cache.key? path
|
92
|
+
return cache[path]
|
93
|
+
end
|
94
|
+
|
95
|
+
# Check path that exists in metadata
|
96
|
+
data = metadata[path]
|
97
|
+
if data
|
98
|
+
data["deps"].each do |dependency|
|
99
|
+
if modified?(dependency)
|
100
|
+
return cache[dependency] = cache[path] = true
|
101
|
+
end
|
102
|
+
end
|
103
|
+
if File.exist?(path) && data["mtime"].eql?(File.mtime(path))
|
104
|
+
return cache[path] = false
|
105
|
+
else
|
106
|
+
return add(path)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# Path does not exist in metadata, add it
|
111
|
+
return add(path)
|
112
|
+
end
|
113
|
+
|
114
|
+
# Add a dependency of a path
|
115
|
+
#
|
116
|
+
# Returns nothing.
|
117
|
+
def add_dependency(path, dependency)
|
118
|
+
return if metadata[path].nil? || @disabled
|
119
|
+
|
120
|
+
unless metadata[path]["deps"].include? dependency
|
121
|
+
metadata[path]["deps"] << dependency
|
122
|
+
add(dependency) unless metadata.include?(dependency)
|
123
|
+
end
|
124
|
+
regenerate? dependency
|
125
|
+
end
|
126
|
+
|
127
|
+
# Write the metadata to disk
|
128
|
+
#
|
129
|
+
# Returns nothing.
|
130
|
+
def write_metadata
|
131
|
+
unless disabled?
|
132
|
+
File.binwrite(metadata_file, Marshal.dump(metadata))
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
# Produce the absolute path of the metadata file
|
137
|
+
#
|
138
|
+
# Returns the String path of the file.
|
139
|
+
def metadata_file
|
140
|
+
site.in_source_dir('.bunto-metadata')
|
141
|
+
end
|
142
|
+
|
143
|
+
# Check if metadata has been disabled
|
144
|
+
#
|
145
|
+
# Returns a Boolean (true for disabled, false for enabled).
|
146
|
+
def disabled?
|
147
|
+
@disabled = !site.incremental? if @disabled.nil?
|
148
|
+
@disabled
|
149
|
+
end
|
150
|
+
|
151
|
+
private
|
152
|
+
|
153
|
+
# Read metadata from the metadata file, if no file is found,
|
154
|
+
# initialize with an empty hash
|
155
|
+
#
|
156
|
+
# Returns the read metadata.
|
157
|
+
def read_metadata
|
158
|
+
@metadata =
|
159
|
+
if !disabled? && File.file?(metadata_file)
|
160
|
+
content = File.binread(metadata_file)
|
161
|
+
|
162
|
+
begin
|
163
|
+
Marshal.load(content)
|
164
|
+
rescue TypeError
|
165
|
+
SafeYAML.load(content)
|
166
|
+
rescue ArgumentError => e
|
167
|
+
Bunto.logger.warn("Failed to load #{metadata_file}: #{e}")
|
168
|
+
{}
|
169
|
+
end
|
170
|
+
else
|
171
|
+
{}
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|