Broadway

TODO: Tests. I’ve just extracted this out of a project and now I’ll write tests.

html2haml

This is the source for my blog. I develop the themes in Sinatra, and convert them into Jekyll for posts. I’m only doing this until someone gives Jekyll some HAML support so I can use it with Github… Or I find that it’s really not that good of an investment to use Github Pages.

The Goal

The goal of this project is to make it easy to manage 20 public software projects at once. This way, anyone developing their thing on github can easily post new examples and documentation as they develop their project, without anything out of their ordinary workflow.

Sinatra, HAML, JQuery, Textile

About this Blog

Jekyll and Sinatra

I use Jekyll for the static page generation (spits out all the pages, essentially pre-compiling everything into raw HTML). I don’t use Jekyll because it uses Liquid. Liquid might be nice for someone who doesn’t want to learn programming but would like to have fun with a few variables, and reuse some code. But for a programmer who takes pride in efficiency, clean code, and being DRY, HAML and full Ruby access is much better; it gives me freedom to do. I can:

  1. Format the HTML perfectly (using HAML with Textmate)
  2. Have Ruby hooks to conditionally link in elements throughout (getting rid of YAML headers)
  3. Use Ruby to dynamically process other URLs
  4. Extend the application to do other things like file uploading, all the while
  5. Keeping everything DRY and clean.

You can use _posts without any layout! And they can be raw HTML files!

Notes

  • Any folder starting with an underscore is private in terms of browser access

Directory Structure


.
|-- _config.yml
|-- _layouts
|-- _posts (generated output)
|-- _site (github's place)
|-- _source (sinatra application for development)
|   |-- files (blog files to-be published)
|   |-- posts (blog files)
|   |-- lib (sinatra helpers)
|   `-- public (sinatra public directory)
|-- shared (javascripts, css, media, etc.)
|-- index.html
|-- robots.txt (what google should ignore)
`-- sitemap.xml (google's sitemap from jekyll)

Configuration

Default Configuration


permalink: 
	if post's name is "entry": /path/to (index.haml)
	if post's name is "something-else": /path/to/something-else
	those are "directory" styled permalinks
title: Path - To - Index
keywords: nil
description: nil

Permalink Styles

directory: /path/to/index or /path/to/title date: /year/month/day/title category: /root/child/childer/title

If directories have underscores, they are subtracted from the path:

/path/to/_some_way_of_organizing_my_posts/my-post.textile => /path/to/my-post

Preference:

  1. If directory contains all of [index.haml, entry.textile], it will render index.haml
  2. If directory contains all of [entry.textile], it will render entry.textile

The Rendering Process

  1. Startup Sinatra
  2. Generate URLs from Post metadata, or, by default, directory to index.html or index.haml. Also collect all tags and categories in the application
  3. Now we have all: urls, tags, categories. But we haven’t read all of the files into memory which can be a problem
  4. Go to a URL via Sinatra, render HAML
  5. Read post for that URL into memory
  6. Save HAML to HTML file

Themes

When you make a request to a url, it renders out the template from the public/themes directory, but your content goes in public/posts. In public/posts, you can add HAML/HTML files to customize the base of the them (via ‘yield’), but you don’t need to. Instead, you just create your posts and they will be given a url. The default layout for anything in your public/posts directory is the root directory it’s in. That’s because you’re likely to initially structure your posts according to the theme’s RESTful page structure. But if you specify a layout in the header of your file, it will use that from the theme.

ln -s ~/viatropos/shared/themes ~/viatropos/_source/public/shared

Posts

There are 3 types of posts:

  1. Blog Posts
  2. Index Posts
  3. Regular Posts

Blog posts are dated, so they must be prefixed with a date (2010-03-11-my-blog-post.textile). Index posts describe the default page and metadata, and they must be named “index” (index.textile). Regular posts are posts that don’t care about date (such as wiki posts or just simple pages for a portfolio site), and they are named however (my-service-page.textile). Each post has metadata defined in a YAML header. The metadata can be wired explicitly to a themes implementation because, eventually, we’ll all come to some sort of consensus on what should and shouldn’t be included in the page metadata definition.

View Variables

Inside your view you have access to quite a lot of variables:

  1. metadata: Hash of all the config variables defined for your header metadata.
  2. config: Hash of global config values
  3. params: Hash of values passed in through the URL
  4. site: site object, which has these properties
    1. posts: array of posts
    2. categories: array of categories {:name => post}
    3. pages: array of pages (TBD)
  5. post: Post object, if applicable
    1. data: Hash of metadata specific to this post (symbolized keys)
    2. title: Post title
    3. url: Relative URL to Post
    4. date: Date post was created
    5. published: Whether or not it’s been officially published
    6. tags
    7. categories

ALL HASH KEYS ARE SYMBOLS, NOT STRINGS!

Layouts

There are quite a few layouts available in each project:

  1. Overview
  2. Blog
  3. Post w/ column
  4. Post w/o column
  5. Portfolio: two column grid
  6. Portfolio: three column grid
  7. Testimonials
  8. two column list
  9. Contact

TODO

  1. CycleHelper for easier haml repeaters

Theme Development

html2haml

Create a folder called shared/themes/my-theme-name. In there, create folders for html, touch, and flash. In the html folder, you need the following


.
|-- index.haml # home page (layout.haml is somewhere else entirely)
|-- about
|-- blog
|-- features
|-- demos
|-- download
|-- support
|-- community
|-- shared
|   |-- stylesheets
|   |-- javascripts
|   |-- images
|   `-- partials
|   	|-- _head.haml
|   	`-- _header.haml

There are two ways the posts/pages can be constructed:

  1. They have a date prefixing their name
  2. They are in an XML file

Dates specify an order, so do XML files. In the end, we have an xml file for each root directory that lists all of the posts in a tree. Whether they were from being in the “_posts” directory or because they were in an XML file, it doesn’t matter.

If the content of the post doesn’t need more than a few lines, you can specify it in XML (each item in XML is converted to a Post). Saves on space.

The end result is that we have 1 xml file for each category of posts, which can be imported into Flex.

Posts vs. Pages

Posts are pages that can be mass produced, such as wiki pages, blog entries, and forum posts. They may have these extra defined properties:

  1. date
  2. categories
  3. tags

However, Pages can also have categories and tags and dates, but they are not used the same way as posts.

A major difference between pages and posts however is that Posts cannot be nested; Pages can be nested.

So how do we define the difference between Pages and Posts in Broadway?

  1. Posts and Pages can be written with a date in their name: 2010-03-30-my-post.textile.
  2. Directories determine some of the categories of Posts and Pages (you can define additional ones)
  3. Posts are basically subclasses of Page, which we can define in two ways:
    1. Placing Posts into the __posts_ directory
    2. Adding a category to a Page called “post”
  4. Related Posts have the same layout, while related pages may have completely different layouts

So what we do is say, all Posts are leaf items. If a file is called index.textile, however, it is considered a Page for the corresponding directory. Thus, the following directory structure:

— overview | — index.textile | — screenshots.textile |
-- performance.textile

…corresponds to this XML structure:


<page url="/overview">
	<post url="/overview/screenshots"/>
	<post url="/overview/performance"/>
</page>

…which corresponds to these ruby objects


page = Page.new(:url => "/overview")
page.posts << Post.new(:url => "/overview/screenshots")
page.posts << Post.new(:url => "/overview/performance")

Posts can have dates, categories, and tags, while pages can only have categories and tags.

Post Properties

  1. title
  2. url
  3. has_one: image
  4. tooltip
  5. content
  6. description
  7. categories (directory)
  8. tags
  9. slug (identifier)
  10. published
  11. author
  12. comments
  13. attachments

Attachment Properties

id – Integer url – String slug – String title – String description – String caption – String parent – Integer mime_type – String images – Object

- Go through public directory - look for .xml and .textile/.markdown/.html - Can go arbitrary levels deep - Pages are for each directory - if no page, then it will render an error page - if index.haml, it will render that - Posts are organized by category, which map directly to their directory - Posts also have tags - Themes can sort posts based on categories - There is a global list of tags and categories - Posts unique id is the slug - posts can’t be nested - pages can’t be nested, but the urls can be - there are config files for random variables - posts are stored into xml files by page (root level) - posts can have 1 image, plus any random content in the post - snippets are config items, which can be textile/markdown/html

If there is an index.xml in a folder, it is appended to the child matching that url node in the root index.xml file - Content is either in XML, or in the index.textile file of a folder, or the name of the url dot textile. - overview/index.textile - overview.textile - The Post (textile file) or XML node can specify the layout: - - layout: guides If no layout is specified, it will check for these files: - path/to/post/index.haml - theme/path/index.haml - error

Defining Posts and Pages

Posts can be created in two ways: XML or text

Posts from Text (HTML, Textile, Markdown)

Post objects are built out of the path to the file

Posts from XML

Post objects are built out of everything in the XML. If the XML node is referencing a file outside of itself, then it falls into the first category.

Graphics

http://www.iconarchive.com/show/mac-icons-by-artua/Microphone-icon.html http://www.iconarchive.com/show/vista-multimedia-icons-by-icons-land/Microphone-Disabled-icon.html http://www.iconarchive.com/show/play-stop-pause-icons-by-icons-land/Microphone-Disabled-icon.html