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
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/.yardopts ADDED
@@ -0,0 +1,7 @@
1
+ -
2
+ docs/About.md
3
+ docs/GettingStarted.md
4
+ docs/Reference.md
5
+ ChangeLog.md
6
+ README.md
7
+ LICENSE.txt
data/ChangeLog.md ADDED
@@ -0,0 +1,8 @@
1
+ # ChangeLog
2
+
3
+ 2013-02-09 William Martin <william.martin@anomalus.com>
4
+
5
+ Major refactoring work to update the project. It's a shame that I didn't keep this change under more fine-grained source control, but it was such a drastic re-architecting that it seemed ok to get the infrastructure in place then add features and bugfixes later.
6
+
7
+ * Version bump to 0.2.0.
8
+ * Renamed project to 'yuzu'
data/Gemfile ADDED
@@ -0,0 +1,26 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem 'haml', ">= 3.1.7"
4
+ gem 'kramdown', ">= 0.13.7"
5
+
6
+ # AWS S3 gem not included by default.
7
+ #gem 'aws-s3', ">= 0.6.2"
8
+
9
+ # fssm is deprecated. Keep until picking an alternate event handler.
10
+ #gem 'fssm', ">= 0.2.5"
11
+
12
+ # PDF generation soon to come...
13
+ #gem 'hpricot', ">= 0.8.3"
14
+ #gem 'prawn', ">= 0.8.4"
15
+
16
+ # Textile rendering not available yet.
17
+ #gem 'RedCloth', ">= 4.2.3"
18
+
19
+ group :development do
20
+ gem "shoulda", ">= 0"
21
+ gem "bundler", "~> 1.2.3"
22
+ gem "jeweler", "~> 1.8.4"
23
+ gem "rcov", ">= 0"
24
+ gem "yard", ">= 0.8.3"
25
+ end
26
+
data/Gemfile.lock ADDED
@@ -0,0 +1,30 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ git (1.2.5)
5
+ haml (3.1.7)
6
+ jeweler (1.8.4)
7
+ bundler (~> 1.0)
8
+ git (>= 1.2.5)
9
+ rake
10
+ rdoc
11
+ json (1.5.1)
12
+ kramdown (0.13.7)
13
+ rake (0.8.7)
14
+ rcov (0.9.9)
15
+ rdoc (3.12)
16
+ json (~> 1.4)
17
+ shoulda (2.11.3)
18
+ yard (0.8.3)
19
+
20
+ PLATFORMS
21
+ ruby
22
+
23
+ DEPENDENCIES
24
+ bundler (~> 1.2.3)
25
+ haml (>= 3.1.7)
26
+ jeweler (~> 1.8.4)
27
+ kramdown (>= 0.13.7)
28
+ rcov
29
+ shoulda
30
+ yard (>= 0.8.3)
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011-13 William Martin
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,52 @@
1
+ Yuzu is a blog-aware, static-website generator and publisher that builds an HTML5 website from a folder of text files and images.
2
+
3
+ For an example of a site rendered with Yuzu, see [Spatial Pixel](http://spatialpixel.com).
4
+
5
+ ## Current Features
6
+
7
+ * Website generation from a folder of text files (Markdown, plain text, HAML, and more) with minimal additional configuration.
8
+ * Embedded support for multiple publication destinations: FTP, S3, local filesystem (can be used for Dropbox's public folder or a local webserver installation).
9
+ * Content mixing: Any file can be inserted and rendered into other files (barring circular references).
10
+ * Templating: Use HAML to make resuable templates, partials, and layout.
11
+ * Catalogs: A list of files can be gathered, rendered, and paginated on any page.
12
+ * Widget-like components like photo galleries and breadcrumbs.
13
+ * Uses Compass and Less for SASS (or SCSS) to CSS.
14
+ * A blog folder for more blog-like content, supporting categories, recent posts, RSS feeds.
15
+ * Automatic index.html file generation for folders.
16
+ * On Mac: image thumbnail generation.
17
+
18
+
19
+ ## Features Coming Soon
20
+
21
+ * Extensibility: The current implementation supports registering new functionality relatively easily. Soon to be refined.
22
+ * Multiple publication formats (HTML, jQuery slideshow, PDF, etc.)
23
+ * Integration with website tools like Bootstrap and HTML5 Boilerplate
24
+ * git hooks for version control and publication management
25
+ * Site themes for quick website creation
26
+ * Watcher script for efficient workflow.
27
+
28
+ Yuzu supports many features of CMS systems but without having to install resource-intensive publishing software like Wordpress, Drupal, Mephisto, Typo, or Expression Engine, but yuzu is best for small sites that need fast deployment.
29
+
30
+ Yuzu first came about from the need to publish lecture material for online course material in multiple formats, specifically a single webpage, javascript-enabled slideshow, and PDF. The content-mixing functionality was critical. It is intended to support these multiple rendering points easily so the content only has to be written once. Then the need expanded into building small project-specific websites quickly.
31
+
32
+
33
+ ## Sample Workflow (Mac)
34
+
35
+ 1. Edit your Markdown content files
36
+ 2. Open a terminal
37
+ 3. `cd ~/Documents/yuzu-projects/project-folder`
38
+ 4. `yuzu preview`
39
+ 5. View in a web browser: `http://localhost/~username/project-folder`
40
+ 6. Publish to the web: `yuzu publish`
41
+
42
+
43
+ ## Contributing to yuzu
44
+
45
+ * Check out the latest master branch to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
46
+ * Fork the repo.
47
+ * Run the tests to make sure all is well.
48
+ * Create a new branch.
49
+ * Commit and push.
50
+ * Make sure to add tests for your change.
51
+ * Send me a pull request.
52
+
data/Rakefile ADDED
@@ -0,0 +1,62 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'rake'
11
+
12
+ require 'jeweler'
13
+ require './lib/yuzu/version.rb'
14
+ Jeweler::Tasks.new do |gem|
15
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
16
+ gem.name = "yuzu"
17
+ gem.homepage = "http://github.com/awmartin/yuzu"
18
+ gem.license = "MIT"
19
+ gem.summary = %Q{A blog-aware, static-website generator that converts a folder of text files and images into an HTML5 website.}
20
+ gem.description = %Q{Yuzu is a blog-aware, static-website (and PDF) generator that converts a folder of text files and images into multiple forms and publishes them to an FTP server, file system, or Amazon Simple Storage Service (S3). It is extensible and designed to function with minimal setup.}
21
+ gem.email = "william.martin@anomalus.com"
22
+ gem.authors = ["William Martin"]
23
+ gem.executables = ['yuzu']
24
+ gem.version = Yuzu::Version::STRING
25
+
26
+ gem.add_dependency 'kramdown', '>= 0.13.7'
27
+ gem.add_dependency 'haml', '>= 3.1.1'
28
+ # gem.add_development_dependency 'rspec', '> 1.2.3'
29
+ end
30
+ Jeweler::RubygemsDotOrgTasks.new
31
+
32
+ require 'yard'
33
+ YARD::Rake::YardocTask.new do |t|
34
+ #t.files = ['lib/**/*.rb', OTHER_PATHS]
35
+ t.options = ['t', 'default', '-p', 'resources/yard', "--markup", "markdown"]
36
+ end
37
+
38
+ # require 'rake/testtask'
39
+ # Rake::TestTask.new(:test) do |test|
40
+ # test.libs << 'lib' << 'test'
41
+ # test.pattern = 'test/**/test_*.rb'
42
+ # test.verbose = true
43
+ # end
44
+ #
45
+ # require 'rcov/rcovtask'
46
+ # Rcov::RcovTask.new do |test|
47
+ # test.libs << 'test'
48
+ # test.pattern = 'test/**/test_*.rb'
49
+ # test.verbose = true
50
+ # end
51
+ #
52
+ # task :default => :test
53
+ #
54
+ # require 'rake/rdoctask'
55
+ # Rake::RDocTask.new do |rdoc|
56
+ # version = File.exist?('VERSION') ? File.read('VERSION') : ""
57
+ #
58
+ # rdoc.rdoc_dir = 'rdoc'
59
+ # rdoc.title = "yuzu #{version}"
60
+ # rdoc.rdoc_files.include('README*')
61
+ # rdoc.rdoc_files.include('lib/**/*.rb')
62
+ # end
data/bin/yuzu ADDED
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+
5
+ $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../lib')
6
+
7
+ require 'yuzu'
8
+ require 'yuzu/command'
9
+
10
+ args = ARGV.dup
11
+ ARGV.clear
12
+
13
+ command_str = args[0].strip rescue 'help'
14
+ command_str = command_str.start_with?("-") ? nil : command_str
15
+
16
+ Yuzu::Command.run(command_str, args)
17
+
data/docs/About.md ADDED
@@ -0,0 +1,19 @@
1
+ # About
2
+
3
+ The primary design objective for Yuzu was to build a publication tool that supports:
4
+
5
+ 1. multiple media endpoints (website, javascript slideshow, PDF),
6
+ 2. content mixing, to support separate organizations for content in its raw form versus its published form (depending on the endpoint medium), and
7
+ 3. embedded publication capabilities (FTP, S3, filesystem).
8
+
9
+ A major design goal was to require users to get started with as little setup and metadata overhead as possible. Other website generators require you to specify metadata for every page, such a YAML header. Yuzu derives some properties without having to explicitly specify them. For example, page and post titles are extracted from the file name, unless explicitly declared with a tag. This enables you to make a complete website without typing any metadata at all if you need to work quickly. Just author the content and publish.
10
+
11
+ For example, if you have a folder structure of text files before using Yuzu, you can generate a website from them without creating any new files yourself. Yuzu generates index.html files for every folder and inserts a "catalog" of those files' contents. You can customize this of course, but this is designed to enable the easiest route from a set of text files to a website.
12
+
13
+ Yuzu distinguishes between local preview and remote publication. Previews allow you to use a local Apache instance (like Web Sharing on a Mac) or Dropbox Public folder to view the polished, rendered website before publishing it on the web.
14
+
15
+ For local previews, instead of stashing the rendered website into a "site" folder inside the project, you can specify any folder on your harddrive. For example, on a Mac, you can specify your Sites folder (~/Sites/my-site) and on a Mac, view it with Web Sharing (http://localhost/~username/my-site) or another Apache instance.
16
+
17
+ For remote publication, Yuzu provides interfaces for Amazon Simple Storage Service (S3) and FTP for regular web servers. Specifying a local shared folder, like Dropbox's Public folder, can also be a way to publish the site.
18
+
19
+ Also, with content mixing, a user can structure raw content irrespective of the website structure. If you're writing about a topic organized in a deep, hierarchical content tree, you can remix and publish the same content in the website structure without having to copy files or copy/paste text. Just use INSERTCONTENTS to insert the contents of another file into this one. In this way, you can author with one folder structure and publish with another, or support two means of browsing and navigating the same content.
@@ -0,0 +1,48 @@
1
+ # Getting Started with Yuzu
2
+
3
+ Using yuzu requires some familiarity with using a terminal application. On a Mac, this is Terminal.app or iTerm2.app.
4
+
5
+
6
+ ## Creating a New Project
7
+
8
+ 1. Create a folder for your project.
9
+ 2. Open your terminal.
10
+ 3. Change the directory into your project folder, e.g.
11
+
12
+ cd ~/Documents/Projects/my-yuzu-project
13
+
14
+ 4. Create the yuzu project. This command will copy a series of files into the directory, including setting up a Compass project for SASS/SCSS.
15
+
16
+ yuzu create
17
+
18
+
19
+ ## Edit yuzu.yml
20
+
21
+ This is a YAML file that contains all the necessary configuration to make Yuzu run properly, such as the public name of the site, configuration settings for the preview, remote FTP server, and so on.
22
+
23
+ Read through the comments in this file to get a more complete sense of what the options mean. For now, to get started, all we need is to set the site's name and to put in the preview settings.
24
+
25
+ site_name: My First Yuzu Project
26
+
27
+ connections:
28
+ preview:
29
+ domain: localhost/~username/my-yuzu-project
30
+ destination: /Users/username/Sites/my-yuzu-project
31
+ link_root: /~username/my-yuzu-project
32
+
33
+ The trickiest setting is `link_root`. This is prepended to every URL to get the relative links right. This is a convenience setting, so you can enter LINKROOT/images/grid.png to get /~username/my-yuzu-project/images/grid.png.
34
+
35
+ This is useful because our site doesn't live at the root server folder, and yuzu uses relative links by default. You can make all links absolute by changing `link_root` to a fully qualified domain name. You can also forget this entirely and specify the complete URLs yourself.
36
+
37
+
38
+ ## Preview the Sample Site
39
+
40
+ In Terminal, type `yuzu preview:all`
41
+
42
+ This will generate your website and produce the rendered version in the folder you specified under `destination` above. Yuzu will automatically create this folder for you.
43
+
44
+ In a web browser, go to http://localhost/~username/my-yuzu-project.
45
+
46
+
47
+
48
+
data/docs/Reference.md ADDED
@@ -0,0 +1,97 @@
1
+ # Yuzu Tag Reference
2
+
3
+ ## Post Titles
4
+
5
+ Specify the title of a post, available with `post.post_title`, with the following placed in your file:
6
+
7
+ TITLE(Post Title)
8
+
9
+ If the `TITLE(...)` tag is not present, yuzu will attempt to use rules from the translators. For Markdown, it grabs "# ...". If not present, yuzu will extrapolate the title from the filename. Files should be named in one of two ways:
10
+
11
+ a-post-title.md
12
+ 2011-10-10-a-post-title.md
13
+
14
+ ## Catalogs
15
+
16
+ A catalog is a listing of posts and pages rendered in a partial form. An example would be an index page of blog posts. This allows you to insert several sets of posts from different parts of a website.
17
+
18
+ INSERTCATALOG(path:folder-name)
19
+ INSERTCATALOG(path:folder-name, per_page:10, per_col:1, template:_block.haml)
20
+
21
+ * `path`
22
+ The folder containing the posts to be placed into the catalog.
23
+ * `total`
24
+ The number of posts to be shown in this catalog.
25
+ * `per_col`
26
+ Catalogs are grids of posts rendered with the _template_ specified. This field specifies how many columns there are in the grid. Use 1 (default) for a straight run of typical blog posts.
27
+ * `template`
28
+ The name of the template file in the `_templates` folder to apply to each item in the catalog (e.g. _block.haml)
29
+ * `category`
30
+ A category filter, showing pages that only have this category.
31
+ * `page`
32
+ To control which page to render, such as only the first page, use this field. If not present, yuzu will attempt to paginate the _first_ catalog found in a page without this flag.
33
+
34
+ ## Images
35
+
36
+ Adding an images tag provides a mechanism for galleries and other renderers to reference those images in a structured way.
37
+
38
+ IMAGES(
39
+ LINKROOT/img/image01.png,
40
+ LINKROOT/img/image02.png
41
+ )
42
+
43
+ ## Categories
44
+
45
+ Categories for blog posts (files only showing up in the `blog_dir` folder) can be specified by setting them explicitly in the content of a post:
46
+
47
+ CATEGORIES(Architecture, Design)
48
+
49
+ The list of categories is available in the `post.categories` variable in all HAML templates. For all the categories in a site, use `post.all_categories`.
50
+
51
+ ## Sidebar Content
52
+
53
+ Contents of sidebars can be separated by using the tag below. This supports the ability to lay out the sidebar in the templates, instead of putting layout and HTML structure the posts themselves.
54
+
55
+ SIDEBAR{
56
+ This will show up in the "post.sidebar" variable inside templates.
57
+ }
58
+
59
+ The format of all contents between the braces must match the contents of the file itself (e.g. Markdown).
60
+
61
+ ## Templates
62
+
63
+ All HAML files in the template_dir folder, specified in yuzu.yml, are considered templates, where several default variables are available to access and insert content.
64
+
65
+ Specifying which template to use for a particular file can be achieved with the TEMPLATE tag:
66
+
67
+ TEMPLATE(_default.haml)
68
+
69
+ yuzu automatically looks in the `_templates` folder for the HAML files to use. The default templates required by yuzu are:
70
+
71
+ * `index.haml`
72
+ The template for index.html pages.
73
+ * `generic.haml`
74
+ The overall template for all other generic pages and posts (default).
75
+
76
+ ## Templates and Partials
77
+
78
+ "Partials" are templates that are rendered as part of other templates. They typically contain repeated contents and information that are context-dependent, but cannot be rendered on their own.
79
+
80
+ The default templates and partials that must be specified are as follows:
81
+
82
+ * `_header.haml`
83
+ A partial that contains any header content for a typical page.
84
+ * `_footer.haml`
85
+ Partial that contains any footer for a typical page.
86
+ * `_menu.haml`
87
+ Partial with the global navigation menu.
88
+ * `_head.haml`
89
+ Partial containing the HTML `<head></head>` tag for all typical pages.
90
+ * `_gallery.haml`
91
+ Partial that renders a gallery of images. Optional.
92
+
93
+ These are automatically generated with the `create` command when creating a new yuzu project from scratch. Partials and auto-generated templates have a leading underscore as part of their name. Your custom templates don't have to have this.
94
+
95
+
96
+
97
+
@@ -0,0 +1,19 @@
1
+ unless Object.method_defined?(:blank?)
2
+
3
+ class Object
4
+ def blank?
5
+ case
6
+ when self.nil?
7
+ true
8
+ when is_a?(String)
9
+ self.empty?
10
+ when is_a?(Array)
11
+ self.empty?
12
+ else
13
+ false
14
+ end
15
+ end
16
+ end
17
+
18
+ end
19
+
@@ -0,0 +1,296 @@
1
+ require 'pathname'
2
+
3
+ module Helpers
4
+
5
+ # Path enables more intelligent handling of disk paths. Using Pathname as a foundation, Path
6
+ # instances can detect parent/child relationships, handle extension and name manipulations natively,
7
+ # and automate absolute/relative path distinctions.
8
+ class Path
9
+ attr_reader :pathname
10
+
11
+ def self.join(path1, path2)
12
+ # TODO This is rather expensive. Make the join more efficient.
13
+ Path.new(path1).join(Path.new(path2))
14
+ #Pathname.new(path1).join(Pathname.new(path2)).to_s
15
+ end
16
+
17
+ def initialize(*args)
18
+ if args.length > 1
19
+ path = File.join(*args)
20
+ else
21
+ path = args[0]
22
+ end
23
+
24
+ if path.nil?
25
+ @pathname = pwd
26
+
27
+ elsif path.is_a?(Pathname)
28
+ @pathname = path
29
+
30
+ elsif path.is_a?(String)
31
+ @pathname = Pathname.new(path)
32
+
33
+ elsif path.is_a?(Path)
34
+ @pathname = path.pathname
35
+
36
+ else
37
+ raise "Path#initialize didn't get a recognizable argument. Must be String, Pathname, or another Path."
38
+
39
+ end
40
+ raise "@pathname was nil" if @pathname.nil?
41
+
42
+ if not @pathname.absolute?
43
+ @pathname = @pathname.expand_path.relative_path_from(pwd)
44
+ end
45
+ @force_is_file = false
46
+ @force_is_folder = false
47
+ end
48
+
49
+ def dup
50
+ Path.new(@pathname.dup)
51
+ end
52
+
53
+ def make_file!
54
+ @force_is_file = true
55
+ @force_is_folder = false
56
+ end
57
+
58
+ def make_folder!
59
+ @force_is_file = false
60
+ @force_is_folder = true
61
+ end
62
+
63
+ def parent
64
+ Path.new(@pathname.parent)
65
+ end
66
+
67
+ def markdown?
68
+ [".md", ".mdown", ".mkd", ".markdown", ".markd"].include?(extension)
69
+ end
70
+
71
+ def plaintext?
72
+ [".txt", ".text"].include?(extension)
73
+ end
74
+
75
+ def == (other)
76
+ return false if not other.is_a?(Path)
77
+ @pathname.expand_path == other.pathname.expand_path
78
+ end
79
+
80
+ def stringify
81
+ "Path(#{absolute})"
82
+ end
83
+
84
+ def + (other)
85
+ join(other)
86
+ end
87
+
88
+ def join(other)
89
+ if other.is_a?(Path)
90
+ Path.new(@pathname + other.pathname)
91
+ else
92
+ Path.new(@pathname + other)
93
+ end
94
+ end
95
+
96
+ def get_child_by_pathname(pathname)
97
+ return nil if children.nil?
98
+ children.each do |c|
99
+ return c if c.pathname == pathname
100
+ end
101
+ nil
102
+ end
103
+
104
+ def get_child_by_rootname(rootname)
105
+ return nil if children.nil?
106
+ children.each do |c|
107
+ return c if c.rootname == rootname
108
+ end
109
+ nil
110
+ end
111
+
112
+ def get_child_by_basename(basename)
113
+ return nil if children.nil?
114
+ children.each do |c|
115
+ return c if c.basename == basename
116
+ end
117
+ nil
118
+ end
119
+
120
+ def get_child_by_filename(filename)
121
+ return nil if children.nil?
122
+ children.each do |c|
123
+ return c if c.filename == filename
124
+ end
125
+ nil
126
+ end
127
+
128
+ # Returns the name of the path
129
+ #
130
+ # /path/to/file.md -- file.md
131
+ # /path/to/folder -- folder
132
+ #
133
+ # @return [String]
134
+ def name
135
+ folder? ? @pathname.basename.to_s : filename.to_s
136
+ end
137
+
138
+ # Returns the base of the filename
139
+ #
140
+ # /path/to/file.md -- file
141
+ # /path/to/folder -- nil
142
+ #
143
+ # @return [String, nil]
144
+ def basename
145
+ folder? ? nil : @pathname.basename(extension).to_s
146
+ end
147
+
148
+ # Returns the actual filename
149
+ #
150
+ # /path/to/file.md -- file.md
151
+ # /path/to/folder -- nil
152
+ #
153
+ # @return [String, nil]
154
+ def filename
155
+ folder? ? nil : @pathname.basename.to_s
156
+ end
157
+
158
+ # Returns the directory of this Path
159
+ #
160
+ # /path/to/file.md -- /path/to
161
+ # /path/to/folder -- /path/to/folder
162
+ #
163
+ # @return [String]
164
+ def dirname
165
+ tr = folder? ? @pathname.to_s : @pathname.dirname.to_s
166
+ tr == "." ? "" : tr
167
+ end
168
+
169
+ # Return the name of the last element of the Path
170
+ #
171
+ # /path/to/file.md -- file.md
172
+ # /path/to/folder -- folder
173
+ #
174
+ # @return [String]
175
+ def rootname
176
+ @pathname.basename.to_s
177
+ end
178
+
179
+ def extension
180
+ @pathname.extname
181
+ end
182
+
183
+ # Return another Path but with the file's extension changed to the one passed in.
184
+ def with_extension(new_extension)
185
+ # This method should not return the same value, ever.
186
+ if exists?
187
+ file? ? Path.new(relative_path.dirname + (basename + new_extension)) : nil
188
+ else
189
+ Path.new(relative_path.dirname + (basename + new_extension))
190
+ end
191
+ end
192
+
193
+ def add_suffix(suffix)
194
+ file? ? Path.new(@pathname.parent + (basename + "_#{suffix}" + extension)) : nil
195
+ end
196
+
197
+ # Return whether this Path contains the given Path, Pathname, or String representing a file
198
+ # path.
199
+ #
200
+ # @param [Path, Pathname, String] other The file or folder to be checked.
201
+ # @return [TrueClass, FalseClass] Whether the given file or folder is contained in this Path.
202
+ def contains?(other)
203
+ if other.is_a?(String)
204
+ path = Path.new(Pathname.new(other))
205
+
206
+ elsif other.is_a?(Pathname)
207
+ path = Path.new(other)
208
+
209
+ elsif other.is_a?(Path)
210
+ path = other
211
+
212
+ else
213
+ raise "Pathname#contains got an argument it didn't recognize."
214
+ end
215
+
216
+ other.absolute.start_with?(absolute)
217
+ end
218
+
219
+ def pwd
220
+ Pathname.pwd
221
+ end
222
+
223
+ def to_s
224
+ @pathname.to_s
225
+ end
226
+
227
+ # Return the absolute path of this Path object as a String.
228
+ def absolute
229
+ absolute_path.to_s
230
+ end
231
+
232
+ def absolute_path
233
+ @pathname.expand_path
234
+ end
235
+
236
+ # Return the relative path of this Path object as a String.
237
+ def relative
238
+ tr = relative_path.to_s
239
+ return "" if tr == "."
240
+ tr
241
+ end
242
+
243
+ def relative_path
244
+ @pathname.expand_path.relative_path_from(pwd.expand_path)
245
+ end
246
+
247
+ def descend(&block)
248
+ @pathname.descend(&block)
249
+ end
250
+
251
+ def ascend(&block)
252
+ @pathname.descend(&block)
253
+ end
254
+
255
+ def exists?
256
+ @pathname.exist?
257
+ end
258
+
259
+ def folder?
260
+ @force_is_folder ? true : @pathname.directory?
261
+ end
262
+
263
+ def file?
264
+ @force_is_file ? true : @pathname.file?
265
+ end
266
+
267
+ # Return the contained children of this Path as an array of Path objects.
268
+ #
269
+ # @return [Array] An array of Path objects.
270
+ def children
271
+ @children ||= get_children
272
+ end
273
+
274
+ def get_children
275
+ # Run these checks first. If the pathname doesn't exist, we can't check for its children. If
276
+ # the folder has no children, it's nil.
277
+ return nil if not exists?
278
+ return nil if @pathname.children.nil?
279
+ folder? ? @pathname.children.collect {|c| Path.new(c)} : nil
280
+ end
281
+
282
+ def files
283
+ children.select {|path| path.file?}
284
+ end
285
+
286
+ def folders
287
+ children.select {|path| path.folder?}
288
+ end
289
+
290
+ def url_for(prefix=nil)
291
+ Url.new(self, prefix=prefix)
292
+ end
293
+ end
294
+
295
+ end
296
+