yuzu 0.2.1.pre

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