yuzu 0.2.1.pre
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.
- data/.document +5 -0
- data/.yardopts +7 -0
- data/ChangeLog.md +8 -0
- data/Gemfile +26 -0
- data/Gemfile.lock +30 -0
- data/LICENSE.txt +20 -0
- data/README.md +52 -0
- data/Rakefile +62 -0
- data/bin/yuzu +17 -0
- data/docs/About.md +19 -0
- data/docs/GettingStarted.md +48 -0
- data/docs/Reference.md +97 -0
- data/lib/helpers/object.rb +19 -0
- data/lib/helpers/path.rb +296 -0
- data/lib/helpers/string.rb +35 -0
- data/lib/helpers/system_checks.rb +10 -0
- data/lib/helpers/url.rb +64 -0
- data/lib/html/base.rb +187 -0
- data/lib/uploader/base.rb +59 -0
- data/lib/uploader/config.rb +19 -0
- data/lib/uploader/filesystem_service.rb +72 -0
- data/lib/uploader/ftp_service.rb +90 -0
- data/lib/uploader/s3_service.rb +135 -0
- data/lib/uploader/service.rb +57 -0
- data/lib/uploader/suppressor.rb +25 -0
- data/lib/yuzu.rb +6 -0
- data/lib/yuzu/argparse.rb +60 -0
- data/lib/yuzu/command.rb +104 -0
- data/lib/yuzu/commands/base.rb +150 -0
- data/lib/yuzu/commands/create.rb +68 -0
- data/lib/yuzu/commands/generate.rb +95 -0
- data/lib/yuzu/commands/help.rb +20 -0
- data/lib/yuzu/commands/preview.rb +58 -0
- data/lib/yuzu/commands/publish.rb +43 -0
- data/lib/yuzu/commands/stage.rb +62 -0
- data/lib/yuzu/commands/watch.rb +70 -0
- data/lib/yuzu/content/blog_post.rb +45 -0
- data/lib/yuzu/content/sample_project.rb +130 -0
- data/lib/yuzu/core/config.rb +154 -0
- data/lib/yuzu/core/layout.rb +85 -0
- data/lib/yuzu/core/paginated_file.rb +69 -0
- data/lib/yuzu/core/registrar.rb +32 -0
- data/lib/yuzu/core/siteroot.rb +57 -0
- data/lib/yuzu/core/template.rb +158 -0
- data/lib/yuzu/core/updater.rb +123 -0
- data/lib/yuzu/core/visitor.rb +44 -0
- data/lib/yuzu/core/website_base.rb +150 -0
- data/lib/yuzu/core/website_file.rb +270 -0
- data/lib/yuzu/core/website_folder.rb +176 -0
- data/lib/yuzu/filters/base.rb +86 -0
- data/lib/yuzu/filters/catalog.rb +248 -0
- data/lib/yuzu/filters/categories.rb +58 -0
- data/lib/yuzu/filters/currentpath.rb +35 -0
- data/lib/yuzu/filters/description.rb +16 -0
- data/lib/yuzu/filters/extension.rb +16 -0
- data/lib/yuzu/filters/images.rb +32 -0
- data/lib/yuzu/filters/linkroot.rb +35 -0
- data/lib/yuzu/filters/post_date.rb +45 -0
- data/lib/yuzu/filters/post_title.rb +66 -0
- data/lib/yuzu/filters/post_title_removed.rb +28 -0
- data/lib/yuzu/filters/sidebar.rb +26 -0
- data/lib/yuzu/filters/template.rb +16 -0
- data/lib/yuzu/generators/base.rb +44 -0
- data/lib/yuzu/generators/category_folders.rb +91 -0
- data/lib/yuzu/generators/index.rb +108 -0
- data/lib/yuzu/generators/paginate.rb +136 -0
- data/lib/yuzu/postprocessors/all_categories.rb +48 -0
- data/lib/yuzu/postprocessors/base.rb +34 -0
- data/lib/yuzu/postprocessors/contents_without_first_paragraph.rb +20 -0
- data/lib/yuzu/postprocessors/excerpt.rb +23 -0
- data/lib/yuzu/postprocessors/first_paragraph.rb +16 -0
- data/lib/yuzu/postprocessors/pagination.rb +35 -0
- data/lib/yuzu/postprocessors/recent_posts.rb +27 -0
- data/lib/yuzu/postprocessors/thumbnails.rb +48 -0
- data/lib/yuzu/preprocessors/base.rb +71 -0
- data/lib/yuzu/preprocessors/insert_contents.rb +57 -0
- data/lib/yuzu/renderers/base.rb +23 -0
- data/lib/yuzu/renderers/breadcrumb.rb +163 -0
- data/lib/yuzu/renderers/gallery.rb +24 -0
- data/lib/yuzu/renderers/title.rb +21 -0
- data/lib/yuzu/translators/base.rb +57 -0
- data/lib/yuzu/translators/markdown.rb +21 -0
- data/lib/yuzu/translators/plaintext.rb +17 -0
- data/lib/yuzu/version.rb +12 -0
- data/resources/config/compass.rb +6 -0
- data/resources/config/yuzu.yml +166 -0
- data/resources/git/post-commit +42 -0
- data/resources/sample_content/introduction/_snippets/about_insert_contents.md +3 -0
- data/resources/sample_content/introduction/about.md +6 -0
- data/resources/sample_content/introduction/advanced-posts.md +18 -0
- data/resources/sample_content/introduction/blog/blog-folder-is-special.md +8 -0
- data/resources/sample_content/introduction/getting-started.md +14 -0
- data/resources/sample_content/introduction/index.md +6 -0
- data/resources/sample_content/introduction/sample-post.md +13 -0
- data/resources/sample_projects.yml +7 -0
- data/resources/themes/minimal/_sass/print.sass +0 -0
- data/resources/themes/minimal/_sass/screen.sass +81 -0
- data/resources/themes/minimal/_templates/_block.haml +4 -0
- data/resources/themes/minimal/_templates/_blog.haml +3 -0
- data/resources/themes/minimal/_templates/_footer.haml +2 -0
- data/resources/themes/minimal/_templates/_gallery.haml +25 -0
- data/resources/themes/minimal/_templates/_head.haml +12 -0
- data/resources/themes/minimal/_templates/_header.haml +1 -0
- data/resources/themes/minimal/_templates/_menu.haml +6 -0
- data/resources/themes/minimal/_templates/blog.haml +21 -0
- data/resources/themes/minimal/_templates/generic.haml +26 -0
- data/resources/themes/minimal/_templates/home.haml +15 -0
- data/resources/themes/minimal/_templates/index.haml +21 -0
- data/resources/themes/minimal/css/print.css +0 -0
- data/resources/themes/minimal/css/screen.css +133 -0
- data/resources/themes/minimal/img/favicon.png +0 -0
- data/resources/yard/default/fulldoc/html/css/common.css +16 -0
- data/test/helper.rb +18 -0
- data/test/test_yuzu.rb +8 -0
- data/yuzu.gemspec +182 -0
- metadata +302 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
require 'core/website_file'
|
|
2
|
+
|
|
3
|
+
module Yuzu::Core
|
|
4
|
+
class PaginatedWebsiteFile < WebsiteFile
|
|
5
|
+
attr_reader :original_file
|
|
6
|
+
|
|
7
|
+
# Initialize a new generated file from an existing WebsiteFile
|
|
8
|
+
#
|
|
9
|
+
# @param [WebsiteFile] original_file The root file representing page 1.
|
|
10
|
+
# @param [String] new_raw_contents The new contents with the INSERTCATALOG directives updated to
|
|
11
|
+
# include the page:N argument.
|
|
12
|
+
# @param [Fixnum] page The page that this generated file represents.
|
|
13
|
+
def initialize(original_file, new_raw_contents, page)
|
|
14
|
+
@raw_contents = new_raw_contents
|
|
15
|
+
@page = page
|
|
16
|
+
|
|
17
|
+
@path = Yuzu::Core.get_paginated_path(original_file.path, page)
|
|
18
|
+
raise "@path is nil in #{self}" if @path.nil?
|
|
19
|
+
|
|
20
|
+
@original_file = original_file
|
|
21
|
+
@parent = original_file.parent
|
|
22
|
+
@kind = :file
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def to_s
|
|
26
|
+
"PaginatedWebsiteFile(#{@path.relative})"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def get_raw_contents
|
|
30
|
+
@raw_contents
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def modified_at
|
|
34
|
+
@original_file.modified_at
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def created_at
|
|
38
|
+
@original_file.created_at
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def load_file_info!
|
|
42
|
+
# No need to do anything here. All dependent methods are overridden.
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def generated?
|
|
46
|
+
true
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def paginated?
|
|
50
|
+
true
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Calculate the page of this file, assuming it's a file produced from pagination.
|
|
55
|
+
#
|
|
56
|
+
# @param [Path] original_path The path of the original seed file being paginated.
|
|
57
|
+
# @param [Fixnum] page The page of the new file.
|
|
58
|
+
# @return [Path] The new path in the format path/to/file_N.ext where N is the page number.
|
|
59
|
+
def get_paginated_path(original_path, page)
|
|
60
|
+
new_path = original_path.dup
|
|
61
|
+
new_path.make_file!
|
|
62
|
+
tr = new_path.add_suffix(page)
|
|
63
|
+
raise "New path is nil!" if tr.nil?
|
|
64
|
+
tr.make_file!
|
|
65
|
+
tr
|
|
66
|
+
end
|
|
67
|
+
module_function :get_paginated_path
|
|
68
|
+
|
|
69
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
|
|
2
|
+
module Yuzu::Registrar
|
|
3
|
+
|
|
4
|
+
# Class Register includes routines for storing singletons of objects with a common base class that
|
|
5
|
+
# can be executed as a set.
|
|
6
|
+
class Register
|
|
7
|
+
# Subclasses should redefine `registry` with a unique identifier equal to the name of the class
|
|
8
|
+
# variable that will contain the singletons.
|
|
9
|
+
@@registered = {}
|
|
10
|
+
def self.registry
|
|
11
|
+
:registered
|
|
12
|
+
end
|
|
13
|
+
def self.registered
|
|
14
|
+
@@registered
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Subclasses of the Register should call this method after their definitions to register them
|
|
18
|
+
# into the registry.
|
|
19
|
+
def self.register(name_to_class={})
|
|
20
|
+
class_var = "@@#{self.registry}".to_sym
|
|
21
|
+
register = class_variable_get(class_var)
|
|
22
|
+
if register.nil?
|
|
23
|
+
class_variable_set(class_var, {})
|
|
24
|
+
register = {}
|
|
25
|
+
end
|
|
26
|
+
name_to_instance = Hash[name_to_class.collect {|name, klass| [name, klass.new]}]
|
|
27
|
+
class_variable_set(class_var, register.merge(name_to_instance))
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
end
|
|
32
|
+
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
require 'core/website_folder'
|
|
2
|
+
|
|
3
|
+
Dir["#{File.dirname(__FILE__)}/../generators/*"].each { |c| require c }
|
|
4
|
+
|
|
5
|
+
module Yuzu::Core
|
|
6
|
+
class SiteRoot < WebsiteFolder
|
|
7
|
+
include Yuzu::Generators
|
|
8
|
+
|
|
9
|
+
attr_reader :config
|
|
10
|
+
def initialize(yuzu_config)
|
|
11
|
+
@config = yuzu_config
|
|
12
|
+
@path = @config.pwd
|
|
13
|
+
@parent = nil
|
|
14
|
+
@kind = :folder
|
|
15
|
+
|
|
16
|
+
generate!
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def name
|
|
20
|
+
@config.site_name
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Given a Path, return the WebsiteFile or WebsiteFolder corresponding to the Path.
|
|
24
|
+
def find_file_by_path(path)
|
|
25
|
+
path_elements = path.relative.split(File::SEPARATOR)
|
|
26
|
+
|
|
27
|
+
parent = self
|
|
28
|
+
path_elements.each do |element|
|
|
29
|
+
child = parent.get_child_by_rootname(element)
|
|
30
|
+
return nil if child.nil?
|
|
31
|
+
parent = child
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
return parent
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def generators
|
|
38
|
+
Generator.generators
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Process all the generators to make all the new files required from things like pagination of
|
|
42
|
+
# catalogs and new index files.
|
|
43
|
+
def generate!
|
|
44
|
+
generators.each_pair do |name, generator|
|
|
45
|
+
v = Visitor.new(generator.visitor_filter)
|
|
46
|
+
|
|
47
|
+
v.traverse(self) do |node|
|
|
48
|
+
if generator.should_generate?(node)
|
|
49
|
+
generator.generate!(node)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
end
|
|
57
|
+
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
require 'haml'
|
|
2
|
+
require 'helpers/path'
|
|
3
|
+
|
|
4
|
+
module Yuzu::Core
|
|
5
|
+
class Template
|
|
6
|
+
include Helpers
|
|
7
|
+
|
|
8
|
+
# TODO Make this part of a module-level config.
|
|
9
|
+
@@template_dir = Path.new("_templates")
|
|
10
|
+
|
|
11
|
+
# template_name -- String. The filename of the template, e.g. _gallery.haml
|
|
12
|
+
def initialize(template_name)
|
|
13
|
+
@template_name = template_name
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def path
|
|
17
|
+
@@template_dir + @template_name
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def exists?
|
|
21
|
+
path.exists?
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def fallback_path
|
|
25
|
+
# TODO Configure fallbacks in a more general way.
|
|
26
|
+
if @template_name[0].chr == "_"
|
|
27
|
+
@@template_dir + "_block.haml"
|
|
28
|
+
else
|
|
29
|
+
@@template_dir + "generic.haml"
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def fallback_exists?
|
|
34
|
+
fallback_path.exists?
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def contents
|
|
38
|
+
@contents ||= get_contents
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def get_contents
|
|
42
|
+
tr = get_template_contents(path)
|
|
43
|
+
tr.nil? ? get_template_contents(fallback_path) : tr
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def get_template_contents(file_path)
|
|
47
|
+
if file_path.exists?
|
|
48
|
+
f = File.open(file_path.absolute, 'r')
|
|
49
|
+
contents = f.read
|
|
50
|
+
f.close
|
|
51
|
+
contents
|
|
52
|
+
else
|
|
53
|
+
$stderr.puts "WARNING: Couldn't find template #{file_path}"
|
|
54
|
+
nil
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def render(website_file, data={})
|
|
59
|
+
""
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class HamlTemplate < Template
|
|
65
|
+
def options
|
|
66
|
+
{:format => :html5}
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def engine
|
|
70
|
+
@engine ||= Haml::Engine.new(contents, options)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def locals(website_file)
|
|
74
|
+
{
|
|
75
|
+
:post => website_file.properties,
|
|
76
|
+
:config => website_file.config
|
|
77
|
+
}
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def render(website_file, data={})
|
|
81
|
+
engine.render(
|
|
82
|
+
TemplateMethods.new(website_file.root),
|
|
83
|
+
locals(website_file).merge(data)
|
|
84
|
+
)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
# The root object that contains functions that can be called from inside the Haml template.
|
|
90
|
+
class TemplateMethods
|
|
91
|
+
def initialize(siteroot)
|
|
92
|
+
@siteroot = siteroot
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def insert_raw_file(filename)
|
|
96
|
+
insert_contents(filename, :raw_contents)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def insert_rendered_contents(filename)
|
|
100
|
+
insert_contents(filename, :rendered_contents)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def insert_contents(filename, method=:raw_contents)
|
|
104
|
+
path = Helpers::Path.new(filename)
|
|
105
|
+
return (Html::Comment.new << "File #{filename} not found.") if not path.exists?
|
|
106
|
+
|
|
107
|
+
website_file = @siteroot.find_file_by_path(path)
|
|
108
|
+
|
|
109
|
+
if not website_file.nil?
|
|
110
|
+
website_file.send(method)
|
|
111
|
+
|
|
112
|
+
else
|
|
113
|
+
|
|
114
|
+
f = File.open(filename, "r")
|
|
115
|
+
contents = f.read
|
|
116
|
+
f.close
|
|
117
|
+
|
|
118
|
+
return contents if method == :raw_contents
|
|
119
|
+
Yuzu::Translators::Translator.translate(contents, path.extension)
|
|
120
|
+
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def format_date(raw_date)
|
|
125
|
+
if not raw_date.is_a?(String) and not raw_date.is_a?(Time)
|
|
126
|
+
return raw_date
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
if raw_date.is_a?(String)
|
|
130
|
+
raw_date = Time.parse(raw_date)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
date = raw_date.strftime("%Y-%m-%d")
|
|
134
|
+
|
|
135
|
+
months = {
|
|
136
|
+
"01" => "January",
|
|
137
|
+
"02" => "February",
|
|
138
|
+
"03" => "March",
|
|
139
|
+
"04" => "April",
|
|
140
|
+
"05" => "May",
|
|
141
|
+
"06" => "June",
|
|
142
|
+
"07" => "July",
|
|
143
|
+
"08" => "August",
|
|
144
|
+
"09" => "September",
|
|
145
|
+
"10" => "October",
|
|
146
|
+
"11" => "November",
|
|
147
|
+
"12" => "December"
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
year, month, day = date.split("-")[0..2]
|
|
151
|
+
month = months[month]
|
|
152
|
+
|
|
153
|
+
"#{year} #{month} #{day}"
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
require 'core/visitor'
|
|
2
|
+
require 'helpers/path'
|
|
3
|
+
require 'core/siteroot'
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
module Yuzu::Core
|
|
8
|
+
BOLD = "\033[1m"
|
|
9
|
+
WHITE = "\033[37m"
|
|
10
|
+
ENDC = "\033[0m"
|
|
11
|
+
|
|
12
|
+
# Updater is the primary mechanism to update a website and filter for the files that need
|
|
13
|
+
# updating.
|
|
14
|
+
class Updater
|
|
15
|
+
|
|
16
|
+
def initialize(uploader, config)
|
|
17
|
+
@uploader = uploader
|
|
18
|
+
@config = config
|
|
19
|
+
|
|
20
|
+
@siteroot = SiteRoot.new(@config)
|
|
21
|
+
|
|
22
|
+
$stderr.puts "Updater initialized..." if @config.verbose?
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def update_all
|
|
26
|
+
$stderr.puts "Updating all..." if @config.verbose?
|
|
27
|
+
|
|
28
|
+
filter = proc {|c| (c.processable? or c.resource? or c.image? or c.asset?) and not c.hidden?}
|
|
29
|
+
update_by_filter(filter)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def update_text
|
|
33
|
+
$stderr.puts "Updating text files..." if @config.verbose?
|
|
34
|
+
|
|
35
|
+
filter = proc {|c| c.processable? and not c.hidden?}
|
|
36
|
+
update_by_filter(filter)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def upload_new_images(known_images=[])
|
|
40
|
+
filter = proc {|c| c.image? and not c.hidden? and not known_images.include?(c)}
|
|
41
|
+
update_by_filter(filter)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def upload_all_images
|
|
45
|
+
filter = proc {|c| c.image? and not c.hidden?}
|
|
46
|
+
update_by_filter(filter)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def upload_all_assets
|
|
50
|
+
filter = proc {|c| c.asset? and not c.hidden?}
|
|
51
|
+
update_by_filter(filter)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def upload_all_resources
|
|
55
|
+
filter = proc {|c| c.resource? and not c.hidden?}
|
|
56
|
+
update_by_filter(filter)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def upload_all_css
|
|
60
|
+
filter = proc {|c| c.path.extension == ".css" and not c.hidden?}
|
|
61
|
+
update_by_filter(filter)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def update_by_filter(proc_filter)
|
|
65
|
+
updated = []
|
|
66
|
+
visit = Visitor.new(proc_filter)
|
|
67
|
+
|
|
68
|
+
visit.traverse(@siteroot) do |file|
|
|
69
|
+
update_file(file)
|
|
70
|
+
updated.push(file)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
updated
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Update a single WebsiteFile. This effectively initiates the uploader to publish the file to
|
|
77
|
+
# the destination specified by the currently selected service.
|
|
78
|
+
def update_file(website_file)
|
|
79
|
+
$stderr.puts "#{BOLD}#{WHITE}Updating #{website_file}#{ENDC}#{ENDC}" if @config.verbose?
|
|
80
|
+
|
|
81
|
+
if website_file.processable?
|
|
82
|
+
@uploader.upload(website_file.remote_path, website_file.html_contents)
|
|
83
|
+
|
|
84
|
+
elsif website_file.resource? or website_file.image? or website_file.asset?
|
|
85
|
+
f = File.open(website_file.path.absolute, "r")
|
|
86
|
+
@uploader.upload(website_file.remote_path, f)
|
|
87
|
+
f.close
|
|
88
|
+
|
|
89
|
+
else
|
|
90
|
+
$stderr.puts "Can't update #{website_file}." if @config.verbose?
|
|
91
|
+
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Update a particular list of files. This is relatively expensive as it requires searching
|
|
96
|
+
# through the file tree, but it should work well for a few files.
|
|
97
|
+
#
|
|
98
|
+
# @param [Array] files_to_update An Array of Strings holding absolute file paths or paths
|
|
99
|
+
# relative to the project folder.
|
|
100
|
+
def update_these(files_to_update=[])
|
|
101
|
+
if files_to_update.empty?
|
|
102
|
+
update_all
|
|
103
|
+
return
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
$stderr.puts "Updating files..." if @config.verbose?
|
|
107
|
+
|
|
108
|
+
files_to_update.each do |relative_path|
|
|
109
|
+
p = Helpers::Path.new(relative_path)
|
|
110
|
+
website_file = @siteroot.find_file_by_path(p)
|
|
111
|
+
if not website_file.nil?
|
|
112
|
+
update_file(website_file)
|
|
113
|
+
else
|
|
114
|
+
$stderr.puts "Couldn't find a WebsiteFile for #{p}" if @config.verbose?
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def done
|
|
120
|
+
@uploader.close! unless @uploader.nil?
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
|
|
2
|
+
module Yuzu::Core
|
|
3
|
+
|
|
4
|
+
# Visitor is a convenience mechanism for traversing a tree structure. To be traversable, objects
|
|
5
|
+
# in the data structure must have the following interface defined:
|
|
6
|
+
#
|
|
7
|
+
# def children
|
|
8
|
+
# return an array of nodes or nil
|
|
9
|
+
# end
|
|
10
|
+
#
|
|
11
|
+
# WebsiteBase and Path have this interface, so are traversable. Given a Proc that returns a
|
|
12
|
+
# boolean, we can limit the operation performed by the visitor to a subset of available nodes.
|
|
13
|
+
#
|
|
14
|
+
# Usage:
|
|
15
|
+
#
|
|
16
|
+
# filter_for_files_only = proc {|c| c.file?}
|
|
17
|
+
# v = Visitor.new(filter_for_files_only)
|
|
18
|
+
# v.traverse(root) do |child|
|
|
19
|
+
# # Do something with child.
|
|
20
|
+
# end
|
|
21
|
+
#
|
|
22
|
+
# Each node passing the `filter_for_files_only` filter will be executed in the given block.
|
|
23
|
+
class Visitor
|
|
24
|
+
|
|
25
|
+
# Create a visitor
|
|
26
|
+
#
|
|
27
|
+
# @param [Proc] filter A proc that returns true/false given the child object in question
|
|
28
|
+
def initialize(filter=nil)
|
|
29
|
+
#raise "Visitor must be given a Proc." if not filter.is_a?(Proc)
|
|
30
|
+
@filter = filter.nil? ? proc {|c| true} : filter
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def traverse(container, &block)
|
|
34
|
+
return if container.children.nil?
|
|
35
|
+
|
|
36
|
+
container.children.each do |child|
|
|
37
|
+
block.call(child) if @filter.call(child)
|
|
38
|
+
self.traverse(child, &block) if not child.children.nil?
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
end
|
|
44
|
+
|