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.
Files changed (116) hide show
  1. data/.document +5 -0
  2. data/.yardopts +7 -0
  3. data/ChangeLog.md +8 -0
  4. data/Gemfile +26 -0
  5. data/Gemfile.lock +30 -0
  6. data/LICENSE.txt +20 -0
  7. data/README.md +52 -0
  8. data/Rakefile +62 -0
  9. data/bin/yuzu +17 -0
  10. data/docs/About.md +19 -0
  11. data/docs/GettingStarted.md +48 -0
  12. data/docs/Reference.md +97 -0
  13. data/lib/helpers/object.rb +19 -0
  14. data/lib/helpers/path.rb +296 -0
  15. data/lib/helpers/string.rb +35 -0
  16. data/lib/helpers/system_checks.rb +10 -0
  17. data/lib/helpers/url.rb +64 -0
  18. data/lib/html/base.rb +187 -0
  19. data/lib/uploader/base.rb +59 -0
  20. data/lib/uploader/config.rb +19 -0
  21. data/lib/uploader/filesystem_service.rb +72 -0
  22. data/lib/uploader/ftp_service.rb +90 -0
  23. data/lib/uploader/s3_service.rb +135 -0
  24. data/lib/uploader/service.rb +57 -0
  25. data/lib/uploader/suppressor.rb +25 -0
  26. data/lib/yuzu.rb +6 -0
  27. data/lib/yuzu/argparse.rb +60 -0
  28. data/lib/yuzu/command.rb +104 -0
  29. data/lib/yuzu/commands/base.rb +150 -0
  30. data/lib/yuzu/commands/create.rb +68 -0
  31. data/lib/yuzu/commands/generate.rb +95 -0
  32. data/lib/yuzu/commands/help.rb +20 -0
  33. data/lib/yuzu/commands/preview.rb +58 -0
  34. data/lib/yuzu/commands/publish.rb +43 -0
  35. data/lib/yuzu/commands/stage.rb +62 -0
  36. data/lib/yuzu/commands/watch.rb +70 -0
  37. data/lib/yuzu/content/blog_post.rb +45 -0
  38. data/lib/yuzu/content/sample_project.rb +130 -0
  39. data/lib/yuzu/core/config.rb +154 -0
  40. data/lib/yuzu/core/layout.rb +85 -0
  41. data/lib/yuzu/core/paginated_file.rb +69 -0
  42. data/lib/yuzu/core/registrar.rb +32 -0
  43. data/lib/yuzu/core/siteroot.rb +57 -0
  44. data/lib/yuzu/core/template.rb +158 -0
  45. data/lib/yuzu/core/updater.rb +123 -0
  46. data/lib/yuzu/core/visitor.rb +44 -0
  47. data/lib/yuzu/core/website_base.rb +150 -0
  48. data/lib/yuzu/core/website_file.rb +270 -0
  49. data/lib/yuzu/core/website_folder.rb +176 -0
  50. data/lib/yuzu/filters/base.rb +86 -0
  51. data/lib/yuzu/filters/catalog.rb +248 -0
  52. data/lib/yuzu/filters/categories.rb +58 -0
  53. data/lib/yuzu/filters/currentpath.rb +35 -0
  54. data/lib/yuzu/filters/description.rb +16 -0
  55. data/lib/yuzu/filters/extension.rb +16 -0
  56. data/lib/yuzu/filters/images.rb +32 -0
  57. data/lib/yuzu/filters/linkroot.rb +35 -0
  58. data/lib/yuzu/filters/post_date.rb +45 -0
  59. data/lib/yuzu/filters/post_title.rb +66 -0
  60. data/lib/yuzu/filters/post_title_removed.rb +28 -0
  61. data/lib/yuzu/filters/sidebar.rb +26 -0
  62. data/lib/yuzu/filters/template.rb +16 -0
  63. data/lib/yuzu/generators/base.rb +44 -0
  64. data/lib/yuzu/generators/category_folders.rb +91 -0
  65. data/lib/yuzu/generators/index.rb +108 -0
  66. data/lib/yuzu/generators/paginate.rb +136 -0
  67. data/lib/yuzu/postprocessors/all_categories.rb +48 -0
  68. data/lib/yuzu/postprocessors/base.rb +34 -0
  69. data/lib/yuzu/postprocessors/contents_without_first_paragraph.rb +20 -0
  70. data/lib/yuzu/postprocessors/excerpt.rb +23 -0
  71. data/lib/yuzu/postprocessors/first_paragraph.rb +16 -0
  72. data/lib/yuzu/postprocessors/pagination.rb +35 -0
  73. data/lib/yuzu/postprocessors/recent_posts.rb +27 -0
  74. data/lib/yuzu/postprocessors/thumbnails.rb +48 -0
  75. data/lib/yuzu/preprocessors/base.rb +71 -0
  76. data/lib/yuzu/preprocessors/insert_contents.rb +57 -0
  77. data/lib/yuzu/renderers/base.rb +23 -0
  78. data/lib/yuzu/renderers/breadcrumb.rb +163 -0
  79. data/lib/yuzu/renderers/gallery.rb +24 -0
  80. data/lib/yuzu/renderers/title.rb +21 -0
  81. data/lib/yuzu/translators/base.rb +57 -0
  82. data/lib/yuzu/translators/markdown.rb +21 -0
  83. data/lib/yuzu/translators/plaintext.rb +17 -0
  84. data/lib/yuzu/version.rb +12 -0
  85. data/resources/config/compass.rb +6 -0
  86. data/resources/config/yuzu.yml +166 -0
  87. data/resources/git/post-commit +42 -0
  88. data/resources/sample_content/introduction/_snippets/about_insert_contents.md +3 -0
  89. data/resources/sample_content/introduction/about.md +6 -0
  90. data/resources/sample_content/introduction/advanced-posts.md +18 -0
  91. data/resources/sample_content/introduction/blog/blog-folder-is-special.md +8 -0
  92. data/resources/sample_content/introduction/getting-started.md +14 -0
  93. data/resources/sample_content/introduction/index.md +6 -0
  94. data/resources/sample_content/introduction/sample-post.md +13 -0
  95. data/resources/sample_projects.yml +7 -0
  96. data/resources/themes/minimal/_sass/print.sass +0 -0
  97. data/resources/themes/minimal/_sass/screen.sass +81 -0
  98. data/resources/themes/minimal/_templates/_block.haml +4 -0
  99. data/resources/themes/minimal/_templates/_blog.haml +3 -0
  100. data/resources/themes/minimal/_templates/_footer.haml +2 -0
  101. data/resources/themes/minimal/_templates/_gallery.haml +25 -0
  102. data/resources/themes/minimal/_templates/_head.haml +12 -0
  103. data/resources/themes/minimal/_templates/_header.haml +1 -0
  104. data/resources/themes/minimal/_templates/_menu.haml +6 -0
  105. data/resources/themes/minimal/_templates/blog.haml +21 -0
  106. data/resources/themes/minimal/_templates/generic.haml +26 -0
  107. data/resources/themes/minimal/_templates/home.haml +15 -0
  108. data/resources/themes/minimal/_templates/index.haml +21 -0
  109. data/resources/themes/minimal/css/print.css +0 -0
  110. data/resources/themes/minimal/css/screen.css +133 -0
  111. data/resources/themes/minimal/img/favicon.png +0 -0
  112. data/resources/yard/default/fulldoc/html/css/common.css +16 -0
  113. data/test/helper.rb +18 -0
  114. data/test/test_yuzu.rb +8 -0
  115. data/yuzu.gemspec +182 -0
  116. metadata +302 -0
@@ -0,0 +1,35 @@
1
+
2
+ unless String.method_defined?(:titlecase)
3
+
4
+ class String
5
+ def titlecase
6
+ self.downcase.spacify.split(" ").collect {|str| str.capitalize}.join(" ")
7
+ end
8
+
9
+ def titleize
10
+ titlecase
11
+ end
12
+
13
+ def spacify
14
+ self.gsub("-", " ").gsub("_", " ")
15
+ end
16
+
17
+ def dasherize
18
+ self.gsub(" ", "-").gsub("_", "-")
19
+ end
20
+
21
+ def underline
22
+ self.gsub(/\W/, "_")
23
+ end
24
+
25
+ def includes_one_of?(arr)
26
+ tr = false
27
+ arr.each do |el|
28
+ tr ||= self.include?(el)
29
+ end
30
+ tr
31
+ end
32
+ end
33
+
34
+ end
35
+
@@ -0,0 +1,10 @@
1
+ module SystemChecks
2
+ module_function
3
+ def gem_available?(name)
4
+ Gem::Specification.find_by_name(name)
5
+ rescue Gem::LoadError
6
+ false
7
+ rescue
8
+ Gem.available?(name)
9
+ end
10
+ end
@@ -0,0 +1,64 @@
1
+ # Url holds an abstraction for web URLs, closely tied to the Path objects. This aids in translating
2
+ # on-disk paths to URLs for links.
3
+ module Helpers
4
+
5
+ class Url
6
+ # Create a new Url object.
7
+ #
8
+ # @param [String, Path] url_path The root path of the Url, from the file system, with the
9
+ # appropriate extension in place ideally.
10
+ # @param [String] prefix A prefix to add to the front of the url. This usually consists of the
11
+ # root common path on the server like http://domain.com/blah
12
+ def initialize(url_path, prefix=nil)
13
+ if url_path.is_a?(Path)
14
+ @path = url_path
15
+
16
+ elsif url_path.is_a?(String)
17
+ @path = Path.new(url_path)
18
+
19
+ elsif url_path.is_a?(Url)
20
+ @path = url_path.path
21
+
22
+ else
23
+ raise "Url must be initialized with a String, Url, or Path instance."
24
+
25
+ end
26
+
27
+ @prefix = prefix
28
+ end
29
+
30
+ attr_accessor :path
31
+
32
+ def + (other)
33
+ if other.is_a?(String)
34
+ Url.new(@path + other, prefix=@prefix)
35
+
36
+ elsif other.is_a?(Url)
37
+ Url.new(@path + other.path.relative, prefix=@prefix)
38
+
39
+ elsif other.is_a?(Path)
40
+ Url.new(@path + other.relative_path, prefix=@prefix)
41
+
42
+ else
43
+ raise "Url + accepts String, Path, and Url instances."
44
+
45
+ end
46
+ end
47
+
48
+ def to_s
49
+ full
50
+ end
51
+
52
+ def full(new_extension=nil)
53
+ new_extension.nil? ? join(@prefix, @path) : join(@prefix, @path.with_extension(new_extension))
54
+ end
55
+
56
+ # Join a set of paths together
57
+ def join(prefix, path, suffix=nil)
58
+ root = prefix.nil? ? path.relative : prefix + "/" + path.relative
59
+ suffix.nil? ? root : root + "/" + suffix
60
+ end
61
+ end
62
+
63
+ end
64
+
data/lib/html/base.rb ADDED
@@ -0,0 +1,187 @@
1
+ # Html provides a concise way of programmatically expressing HTML tags and structure.
2
+ #
3
+ # This enables one to express a list like this:
4
+ #
5
+ # Html::UnorderedList.new << (Html::ListItem.new << "first") + (Html::ListItem.new << "second")
6
+ #
7
+ # which results in:
8
+ #
9
+ # <ul><li>first</li><li>second</li></ul>
10
+ #
11
+ # The << operator means "contains", and reduces an Html object and a string to another string. So
12
+ # after the << operation, the tags just obey String semantics.
13
+ #
14
+ # Commonly used nested tags can be composited and deployed as templates multiple times.
15
+ #
16
+ # title_link = Html::H1.new << Html::Link(:href => "http://mysite.com")
17
+ # title_link << "My Site"
18
+ #
19
+ # which results in:
20
+ #
21
+ # <h1><a href="http://mysite.com">My Site</a></h1>
22
+ #
23
+ # This is seemingly more verbose that writing it directly, but it enables you to write HTML without
24
+ # having to do string interpolation and concatenation, and it doesn't imbue Ruby code with a lot of
25
+ # HTML-related strings.
26
+ #
27
+ # words = %w(hello doctor name continue yesterday tomorrow)
28
+ # Html::UnorderedList.new << words.collect {|w| Html::ListItem.new(:class => "class-#{w}") << w}.join
29
+ #
30
+ # which will yield:
31
+ #
32
+ # <ul>
33
+ # <li class="class-hello">hello</li>
34
+ # <li class="class-doctor">doctor</li>
35
+ # <li class="class-name">name</li>
36
+ # <li class="class-continue">continue</li>
37
+ # <li class="class-yesterday">yesterday</li>
38
+ # <li class="class-tomorrow">tomorrow</li>
39
+ # </ul>
40
+
41
+ module Html
42
+ # The base Html class provides functionality for wrapping HTML tags, e.g. <div>...</div>
43
+ class Base
44
+ def initialize(attr={})
45
+ @attr = attr
46
+ end
47
+
48
+ @tag = "div"
49
+ def self.tag
50
+ @tag
51
+ end
52
+
53
+ def tag
54
+ self.class.tag
55
+ end
56
+
57
+ def attributes
58
+ @attr.length == 0 ? "" : @attr.collect {|key, value| " #{key.to_s}='#{value}'"}.join
59
+ end
60
+
61
+ def processed_output(contents)
62
+ "<#{tag}#{attributes}>#{contents}</#{tag}>"
63
+ end
64
+
65
+ def << (other)
66
+ if other.is_a?(String)
67
+ processed_output(other)
68
+ else
69
+ Composite.new(self, other)
70
+ end
71
+ end
72
+ end
73
+
74
+ # Class that sets off the tag by newlines to aid in readability for raw output.
75
+ class Container < Base
76
+ def processed_output(contents)
77
+ "\n<#{tag}#{attributes}>\n#{contents}\n</#{tag}>\n"
78
+ end
79
+ end
80
+
81
+ class Item < Base
82
+ def processed_output(contents)
83
+ "<#{tag}#{attributes}>#{contents}</#{tag}>\n"
84
+ end
85
+ end
86
+
87
+ # Class for compositing nested tags togther and using them multiple times in different contexts.
88
+ class Composite
89
+ def initialize(first, second)
90
+ @first = first
91
+ @second = second
92
+ end
93
+
94
+ def << (other)
95
+ if other.is_a?(String)
96
+ @first << (@second << other)
97
+ else
98
+ Composite.new(self, other)
99
+ end
100
+ end
101
+ end
102
+
103
+ # HTML flags are those that don't have a closing tag, e.g. <img href="">
104
+ class Flag < Base
105
+ def to_s
106
+ "<#{tag}#{attributes}>"
107
+ end
108
+
109
+ def << (other)
110
+ self.to_s + other
111
+ end
112
+ end
113
+
114
+ # Handler for adding HTML comments inline.
115
+ class Comment < Base
116
+ def << (other)
117
+ "\n<!-- #{other} -->\n"
118
+ end
119
+ end
120
+
121
+ # Class handler for <div> tags.
122
+ class Div < Container
123
+ instance_variable_set(:@tag, "div")
124
+ end
125
+
126
+ # Class handler for <a> links.
127
+ class Link < Base
128
+ instance_variable_set(:@tag, "a")
129
+ end
130
+
131
+ # Class handler for <li> list item tags.
132
+ class ListItem < Item
133
+ instance_variable_set(:@tag, "li")
134
+ end
135
+
136
+ # Class handler for <ul> unordered lists.
137
+ class UnorderedList < Container
138
+ instance_variable_set(:@tag, "ul")
139
+ end
140
+
141
+ # Handler for <ol> ordered lists.
142
+ class OrderedList < Container
143
+ instance_variable_set(:@tag, "ol")
144
+ end
145
+
146
+ # Handler for <h1> headers.
147
+ class H1 < Item
148
+ instance_variable_set(:@tag, "h1")
149
+ end
150
+
151
+ # Handler for <h2> headers.
152
+ class H2 < Item
153
+ instance_variable_set(:@tag, "h2")
154
+ end
155
+
156
+ # Handler for <h3> headers.
157
+ class H3 < Item
158
+ instance_variable_set(:@tag, "h3")
159
+ end
160
+
161
+ # Handler for <h4> headers.
162
+ class H4 < Item
163
+ instance_variable_set(:@tag, "h4")
164
+ end
165
+
166
+ # Handler for <span> tags.
167
+ class Span < Base
168
+ instance_variable_set(:@tag, "span")
169
+ end
170
+
171
+ # Handler for <p> paragraph tags.
172
+ class Paragraph < Container
173
+ instance_variable_set(:@tag, "p")
174
+ end
175
+
176
+ # Handler for <img> images.
177
+ class Image < Flag
178
+ instance_variable_set(:@tag, "img")
179
+ end
180
+
181
+ # Handler for <br> line breaks.
182
+ class Break < Flag
183
+ instance_variable_set(:@tag, "br")
184
+ end
185
+
186
+ end
187
+
@@ -0,0 +1,59 @@
1
+ # Require service.rb first.
2
+ require 'uploader/service'
3
+ require 'uploader/suppressor'
4
+ require 'uploader/config'
5
+
6
+ Dir["#{File.dirname(__FILE__)}/*"].each do |service|
7
+ require service if service.include?("_service")
8
+ end
9
+
10
+
11
+ module Uploader
12
+ class UnrecognizedService < Exception; end
13
+
14
+ class UploadManager
15
+
16
+ def initialize(config, service_override=nil)
17
+ @config = config # UploaderConfig
18
+ @service_override = service_override
19
+ @suppressor = Suppressor.new
20
+
21
+ set_service!
22
+ connect!
23
+ end
24
+
25
+ def set_service!
26
+ service_name, service_class = get_service
27
+ service_config_hash = @config.send(service_name).merge({:verbose? => @config.verbose?})
28
+
29
+ @service = service_class.new(UploaderConfig.new(service_config_hash))
30
+ end
31
+
32
+ def get_service
33
+ service_key = (@service_override || @config.connection).to_sym
34
+
35
+ if Service.is_registered?(service_key)
36
+ $stderr.puts "Using service #{service_key}" if @config.verbose?
37
+
38
+ return service_key, Service.services[service_key]
39
+ else
40
+ raise UnrecognizedService
41
+ end
42
+ end
43
+
44
+ def connect!
45
+ @service.connect!
46
+ end
47
+
48
+ def upload(remote_path, contents)
49
+ @service.upload(remote_path, contents)
50
+ end
51
+
52
+ def close!
53
+ @service.close!
54
+ @suppressor.close!
55
+ end
56
+ end
57
+
58
+ end
59
+
@@ -0,0 +1,19 @@
1
+
2
+ module Uploader
3
+
4
+ class UploaderConfig
5
+ def initialize(config_hash)
6
+ @config_hash = config_hash
7
+
8
+ (class << self; self; end).class_eval do
9
+ config_hash.each_pair do |key, value|
10
+ define_method(key) do
11
+ value
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+
18
+ end
19
+
@@ -0,0 +1,72 @@
1
+ require 'uploader/base'
2
+ require 'uploader/service'
3
+ require 'fileutils'
4
+
5
+
6
+ module Uploader
7
+ GREEN = "\033[32m"
8
+ ENDC = "\033[0m"
9
+
10
+ class FileSystemService < Service
11
+ def connect!
12
+ end
13
+
14
+ def upload(remote_path, contents)
15
+ raise UploadArgumentError if not remote_path.is_a?(Path)
16
+
17
+ contents_to_upload, binmode = get_upload_contents(contents)
18
+
19
+ copy_contents_to_file_system(remote_path, contents_to_upload, binmode)
20
+ end
21
+
22
+ def get_upload_contents(contents)
23
+ binmode = false
24
+ if contents.is_a?(File)
25
+ contents_to_upload = contents.read
26
+ binmode = true
27
+
28
+ elsif contents.is_a?(String)
29
+ contents_to_upload = contents
30
+
31
+ else
32
+ raise UnrecognizedContentType
33
+ end
34
+
35
+ return contents_to_upload, binmode
36
+ end
37
+
38
+ def copy_contents_to_file_system(remote_path, contents, binary=true)
39
+ destination = Path.new(@config.destination) + remote_path.relative
40
+ if @config.verbose?
41
+ $stderr.puts %Q{Copying #{GREEN}#{remote_path}#{ENDC} to the file system
42
+ --> #{destination}}
43
+ else
44
+ $stderr.print "."
45
+ end
46
+
47
+ begin
48
+ f = File.open(destination.absolute, "w+")
49
+
50
+ rescue => detail
51
+ $stderr.puts detail.message
52
+ $stderr.puts "Attempting to create the path."
53
+
54
+ # Assume the directories leading to the file don't exist. Create them.
55
+ FileUtils::mkdir_p(destination.dirname)
56
+
57
+ f = File.open(destination.absolute, "w+")
58
+ end
59
+
60
+ unless f.nil?
61
+ f.syswrite(contents)
62
+ f.close
63
+ $stderr.puts "Done with #{destination.relative}." if @config.verbose?
64
+ end
65
+ end
66
+ end
67
+
68
+ Service.register(:filesystem => FileSystemService)
69
+ Service.register(:stage => FileSystemService)
70
+ Service.register(:preview => FileSystemService)
71
+ end
72
+