Easier Documentation, Simpler Websites & Faster Collaboration

Every minute an editor spends managing presentational tweaks is one they can’t spend on critical stories.


Jeff Eaton

Build your site

Automate! Everything you type in a terminal is eventually a task you don’t have to do

Next
Install Awestruct

Check Your Ruby version

$ ruby --version
# ruby 1.9.3p429 (2013-05-15 revision 40747) [x86_64-linux]

Install RVM

Linux
$ curl -L https://get.rvm.io | bash -s stable --ruby=1.9.3
OSX
$ curl -L https://get.rvm.io | bash -s stable --ruby=1.9.3
On Mac, you’ll first need to install XCode from the MacApp store or the OSX system CD.
Windows (pik)
> gem install pik
> pik_install C:\bin
> pik add C:\ruby\IronRuby-091\bin
> pik install ruby
If you want to use Ruby 2.0, replace 1.9.3 with 2.0.0.

Create and use a new Ruby gemset

$ rvm use 1.9.3@writeadapt --create
If you want to use Ruby 2.0, replace 1.9.3 with 2.0.0.

Install Awestruct

$ gem install awestruct
Console output
Fetching: tilt-1.4.1.gem (100%)
Successfully installed tilt-1.4.1
Fetching: haml-4.0.3.gem (100%)

HEADS UP! Haml 4.0 has many improvements, but also has changes that may break
your application:

* Support for Ruby 1.8.6 dropped
* Support for Rails 2 dropped
* Sass filter now always outputs <style> tags
* Data attributes are now hyphenated, not underscored
* html2haml utility moved to the html2haml gem
* Textile and Maruku filters moved to the haml-contrib gem

For more info see:

http://rubydoc.info/github/haml/haml/file/CHANGELOG.md

Successfully installed haml-4.0.3
Fetching: mini_portile-0.5.1.gem (100%)
Successfully installed mini_portile-0.5.1
Fetching: nokogiri-1.6.0.gem (100%)
Building native extensions.  This could take a while...
Successfully installed nokogiri-1.6.0
Fetching: sass-3.2.9.gem (100%)
Successfully installed sass-3.2.9
Fetching: chunky_png-1.2.8.gem (100%)
Successfully installed chunky_png-1.2.8
Fetching: fssm-0.2.10.gem (100%)
Successfully installed fssm-0.2.10
Fetching: compass-0.12.2.gem (100%)
Successfully installed compass-0.12.2
Fetching: compass-960-plugin-0.10.4.gem (100%)
Successfully installed compass-960-plugin-0.10.4
Fetching: bootstrap-sass-2.3.2.0.gem (100%)
Successfully installed bootstrap-sass-2.3.2.0
Fetching: zurb-foundation-4.2.3.gem (100%)
Successfully installed zurb-foundation-4.2.3
Fetching: mime-types-1.23.gem (100%)
Successfully installed mime-types-1.23
Fetching: rest-client-1.6.7.gem (100%)
Successfully installed rest-client-1.6.7
Fetching: git-1.2.5.gem (100%)
Successfully installed git-1.2.5
Fetching: ruby-s3cmd-0.1.5.gem (100%)
Successfully installed ruby-s3cmd-0.1.5
Fetching: rb-fsevent-0.9.3.gem (100%)
Successfully installed rb-fsevent-0.9.3
Fetching: ffi-1.9.0.gem (100%)
Building native extensions.  This could take a while...
Successfully installed ffi-1.9.0
Fetching: rb-inotify-0.9.0.gem (100%)
Successfully installed rb-inotify-0.9.0
Fetching: rb-kqueue-0.2.0.gem (100%)
Successfully installed rb-kqueue-0.2.0
Fetching: listen-1.2.2.gem (100%)
Successfully installed listen-1.2.2
Fetching: rack-1.5.2.gem (100%)
Successfully installed rack-1.5.2
Fetching: awestruct-0.5.2.gem (100%)
Successfully installed awestruct-0.5.2
22 gems installed

Check version of Awestruct

$ awestruct --version
Console output
WARNING: Missing required dependency to activate optional built-in extension minify.rb
  cannot load such file -- htmlcompressor
WARNING: Missing required dependency to activate optional built-in extension coffeescripttransform.rb
  cannot load such file -- coffee-script
Awestruct: 0.5.2
http://awestruct.org/

Next
Setup a new Awestruct project

Create a project folder and switch to it

Make empty project directory
$ mkdir writeadapt
Switch to new directory
$ cd writeadapt
Don’t forget to switch to the new directory or else the website will be generated in the wrong location.

Generate website structure

$ awestruct -i -f foundation
Console output
WARNING: Missing required dependency to activate optional built-in extension minify.rb
  cannot load such file -- htmlcompressor
WARNING: Missing required dependency to activate optional built-in extension coffeescripttransform.rb
  cannot load such file -- coffee-script
Create directory: /path/to/writeadapt/_config
Create directory: /path/to/writeadapt/_layouts
Create directory: /path/to/writeadapt/_ext
Create file: /path/to/writeadapt/_ext/pipeline.rb
Create file: /path/to/writeadapt/.awestruct_ignore
Create file: /path/to/writeadapt/Rakefile
Create file: /path/to/writeadapt/Gemfile
Create directory: /path/to/writeadapt/stylesheets
directory _site/stylesheets/
directory javascripts/foundation/
directory javascripts/vendor/
   create stylesheets/_normalize.scss
   create stylesheets/_settings.scss
   create stylesheets/app.scss
   create humans.txt
   create robots.txt
   create MIT-LICENSE.txt
   create javascripts/foundation/foundation.orbit.js
   create javascripts/foundation/...
   create javascripts/foundation/foundation.reveal.js
   create javascripts/vendor/custom.modernizr.js
   create javascripts/vendor/jquery.js
   create javascripts/vendor/zepto.js
   create javascripts/foundation/foundation.js
   create index.html
   create _site/stylesheets/app.css

Now you're awestruct!

To generate and run your site in development mode, execute:

  awestruct -d

or, simply:

  rake

then visit your site at: http://localhost:4242

Create file: /path/to/writeadapt/_config/site.yml
Create file: /path/to/writeadapt/_layouts/base.html.haml
Create file: /path/to/writeadapt/index.html.haml

Awestruct project file tree

 .awestruct/
 `-- debug.log
 .awestruct_ignore
 _config/
 `-- site.yml
 _ext/
 `-- pipeline.rb
 Gemfile
 humans.txt
 index.html.haml
 javascripts/
 |-- foundation/
 |   |-- foundation.alerts.js
 |   |-- ...
 |   |-- foundation.js
 |   |-- ...
 |   `-- foundation.topbar.js
 `-- vendor/
     |-- custom.modernizr.js
     |-- jquery.js
     `-- zepto.js
 _layouts/
 `-- base.html.haml
 Rakefile
 robots.txt
 _site/
 stylesheets/
 |-- app.scss
 |-- _normalize.scss
 `-- _settings.scss

Next
Install Rake and Bundler

Install Rake and Bundler Gems

$ gem install rake bundler
Console output
Fetching: rake-10.1.0.gem (100%)
Successfully installed rake-10.1.0
Fetching: bundler-1.3.5.gem (100%)
Successfully installed bundler-1.3.5
2 gems installed

Ensure environment is setup correctly

$ rake setup

Generate and preview website

$ rake
The rake command with no arguments is a shortcut for rake preview.
Console output
WARNING: Missing required dependency to activate optional built-in extension minify.rb
  cannot load such file -- htmlcompressor
WARNING: Missing required dependency to activate optional built-in extension coffeescripttransform.rb
  cannot load such file -- coffee-script
Using profile: development
Generating site: http://localhost:4242
[Listen warning]:
The blocking parameter of Listen::Listener#start is deprecated.
Please use Listen::Adapter#start for a non-blocking listener and Listen::Listener#start! for a blocking one.
[2013-01-01 00:00:00] INFO  WEBrick 1.3.1
[2013-01-01 00:00:00] INFO  ruby 2.0.0 (2013-05-14) [x86_64-linux]
[2013-01-01 00:00:00] INFO  WEBrick::HTTPServer#start: pid=10485 port=4242
new awestruct foundation site desktop
Desktop view
new awestruct foundation site phone
Phone view

Halt the preview server

Press key combo

Ctrl+C

Console output
...
[2013-01-01 00:00:00] INFO  going to shutdown ...
[2013-01-01 00:00:00] INFO  WEBrick::HTTPServer#start done.

Structure of generated site

_site/
|-- humans.txt
|-- index.html
|-- javascripts/
|   |-- foundation/
|   |   |-- foundation.alerts.js
|   |   |-- ...
|   |   |-- foundation.js
|   |   |-- ...
|   |   `-- foundation.topbar.js
|   `-- vendor/
|       |-- custom.modernizr.js
|       |-- jquery.js
|       `-- zepto.js
|-- robots.txt
`-- stylesheets/
    `-- app.css

Next
Setup Git repository for project

Initialize new git repository

$ git init .
Console output
Initialized empty Git repository in ...

Instruct git to ignore generated files

$ cat > .gitignore << LINES
/.awestruct/
/.ruby-*
/.sass-cache/
/_site/
/_tmp/
/Gemfile.lock
LINES
Contents of .gitignore
/.awestruct/
/.ruby-*/
/.sass-cache/
/_site/
/_tmp/
/Gemfile.lock

Disable Jekyll

$ touch .nojekyll

Add all non-ignored files to the git repository

$ git add .

Commit the changes to make the snapshot

$ git commit -m 'Initial import of website sources'
Console output
 30 files changed, 18757 insertions(+)
 create mode 100644 .awestruct_ignore
 create mode 100644 .gitignore
 create mode 100644 .nojekyll
 create mode 100644 Gemfile
 create mode 100644 Rakefile
 create mode 100644 _config/site.yml
 create mode 100644 _ext/pipeline.rb
 create mode 100644 _layouts/base.html.haml
 create mode 100644 humans.txt
 create mode 100644 index.html.haml
 create mode 100644 javascripts/foundation/foundation.alerts.js
 create mode 100644 javascripts/foundation/...
 create mode 100644 javascripts/vendor/custom.modernizr.js
 create mode 100644 javascripts/vendor/jquery.js
 create mode 100644 javascripts/vendor/zepto.js
 create mode 100644 robots.txt
 create mode 100644 stylesheets/_normalize.scss
 create mode 100644 stylesheets/_settings.scss
 create mode 100644 stylesheets/app.scss
Changes are now tracked by git. You can rollback at any time.

Create repository on GitHub

Owner
{username}
Repository name
writeadapt-{username}
Description (optional)
An Awestruct demo site
More info
See Make a new repository on GitHub

Connect git repository to GitHub remote

$ git remote add origin https://github.com/{username}/writeadapt-{username}
$ git push origin master
Replace {username} with your GitHub username.

Next
Configure website metadata

Configure site identity

_config/site.yml
name: Write__Adapt__
title: WriteAdapt - For People Who Love Content
org: Strategy Media
author: The Octocat
author_url: https://github.com/octocat
base_url: ''
ctx_path: ''

Additional configuration to customize processor

_config/site.yml
# append
interpolate: false 1
haml:
  :ugly: true 2
1Disables interpolation of Ruby variable expressions in content (e.g., #{name})
2Disables pretty printing (indentation) of HTML output

Clean and preview site to see changes

$ rake clean
$ rake
The clean step is required since a change to the configuration file, _config/site.yml, does not force pages to be regenerated automatically.

Write in plain text

I do not believe that on-page, in-context editing should be the primary edit mode of a CMS.


Deane Barker

Next
Activate AsciiDoc content

Enable Asciidoctor gem, set version

Gemfile
gem 'asciidoctor', '>= 0.1.4.pre'

Update gems

$ bundle install
Console output
Fetching gem metadata from https://rubygems.org/...
Resolving dependencies...
Using rake (10.1.0)
Installing asciidoctor (0.1.4.preview.2)
Using sass (3.2.9)
Using bootstrap-sass (2.3.2.0)
Using chunky_png (1.2.8)
Using fssm (0.2.10)
Using compass (0.12.2)
Using compass-960-plugin (0.10.4)
Using git (1.2.5)
Using tilt (1.4.1)
Using haml (4.0.3)
Installing json (1.8.0)
Using rb-fsevent (0.9.3)
Using ffi (1.9.0)
Using rb-inotify (0.9.0)
Using rb-kqueue (0.2.0)
Using listen (1.2.2)
Using mini_portile (0.5.1)
Using nokogiri (1.6.0)
Using rack (1.5.2)
Using mime-types (1.23)
Using rest-client (1.6.7)
Using ruby-s3cmd (0.1.5)
Using zurb-foundation (4.2.3)
Using awestruct (0.5.2)
Using bundler (1.3.5)
Your bundle is updated!

Configure Asciidoctor

_config/site.yml
# append
asciidoctor:
  :safe: safe
  :attributes:
    sitename: WriteAdapt
    base_url: ''
    ctx_path: ''
    idprefix: ''
    idseparator: '-'
    sectanchors: ''
    icons: font

Create a page in AsciiDoc format

about.adoc
= About {sitename} 1
Your Name
:awestruct-layout: base 2

{sitename} was founded by {author} during a conference workshop.
It's quickly becoming much bigger than this humble beginning.

This page is written in http://asciidoc.org[AsciiDoc].
It's transformed by http://awestruct.org[Awestruct] and http://asciidoctor.org[Asciidoctor] into a webpage for this static website.
1Becomes main heading on the page
2Specifies the layout to use to frame this content

Add About link to navbar

_layouts/base.html.haml
        %li.divider
          %li
            %a(href="#{site.ctx_path}/about.html") About

Clean and preview site to see changes

$ rake clean preview

Next
Configure theme for website and AsciiDoc content

Clone Asciidoctor stylesheet factory as a submodule

$ git submodule add -b embedded-stylesheets \
https://github.com/asciidoctor/asciidoctor-stylesheet-factory.git \
stylesheets/_themes

Import theme into main stylesheet

  1. Delete all content in stylesheets/app.scss
  2. Populate the file with the content in the listing below
stylesheets/app.scss
$row-width: 72em;
@import "_themes/sass/foundation-embedded.scss";
Alternative themes for the first line include asciidoctor-embedded and rocket-panda-embedded.

Add extra styles needed for website layout

stylesheets/app.scss
@import "foundation/components/buttons";
@import "foundation/components/button-groups";
@import "foundation/components/top-bar";
@import "foundation/components/inline-lists";
$pagination-link-unavailable-font-color: #e9e9e9;
@import "foundation/components/pagination";

$footer-bg: $body-font-color !default;
$footer-font-color: invert($body-font-color) !default;
.top-bar a {
  text-decoration: none;
}
h1 em {
  letter-spacing: 1px;
}
body > footer {
  background: $footer-bg;
  padding: $panel-padding;
  color: $footer-font-color;
}

Load SASS functions for themes

Add line to top of _ext/pipeline.rb
require './stylesheets/_themes/lib/functions.rb'

Remove unnecessary files

$ rm stylesheets/{_normalize.scss,_settings.scss}
Also remove the normalize.css link from _layouts/base.html.haml.

Assign id to main content

Edit _layouts/base.html.haml
  #content.row
    .large-12.columns
      =content

Revise main heading on home page

Edit index.html.haml
.row
  .large-12.columns
    %h1 Welcome to #{Asciidoctor.render site.name, :doctype => :inline}!
Make sure to remove the %hr under the %h1.

Format site name in nav bar

Edit _layouts/base.html.haml
      %li.name
        %h1
          %a(href="#{site.ctx_path}/")
            =Asciidoctor.render(site.name, :doctype => :inline)

Clean and preview site to see changes

$ rake clean preview

Next
Convert a Markdown page to AsciiDoc

Sample files

Download
https://raw.github.com/mojombo/jekyll/master/site/docs/pages.md
Save As
docs/_creating-pages.md
Download
https://raw.github.com/mojombo/jekyll/master/site/docs/posts.md
Save As
docs/_writing-posts.md

Formatting

Markdown
**bold**

*italic*

`literal`

`_posts`
AsciiDoc
*bold*

_italic_

+literal+ (or `literal`)

[path]+_posts+

Document header

Markdown
---
layout: docs
title: Writing posts
prev_section: defining-frontmatter
next_section: creating-pages
permalink: /docs/writing-posts/
---
AsciiDoc
= Writing posts
:awestruct-layout: base
:showtitle:
:prev_section: defining-frontmatter
:next_section: creating-pages

Section titles (optional)

Markdown
## The Posts Folder
AsciiDoc
== The Posts Folder

Common article elements such as call-out warnings…were too complex for the WYSIWYG editor.


Jeff Eaton

[E]ditors tried to duplicate the precise markup. [O]thers tried to duplicate the appearance with the WYSIWYG editor’s tools.


Jeff Eaton

Admonitions

HTML embedded in Markdown
<div class="note">
  <h5>ProTip™: Show line numbers</h5>
  <p>
    You can make code snippets include line-numbers by adding the word
    <code>linenos</code> to the end of the opening highlight tag like
    this: <code>{% raw %}{% highlight ruby linenos %}{% endraw %}</code>
  </p>
</div>
AsciiDoc
[TIP, caption='ProTip(TM)']
.Show line numbers
You can make code snippets include line-numbers by adding the word
`linenos` to the end of the opening highlight tag like this:
`{% raw %}{% highlight ruby linenos %}{% endraw %}`

Relative links

Markdown
[directory structure](../structure)
AsciiDoc
link:../structure[directory structure]

External links

Markdown
[Markdown](http://daringfireball.net/projects/markdown/)
AsciiDoc
http://daringfireball.net/projects/markdown[Markdown]

File links

Markdown
[get the PDF]({% raw %}{{ site.url }}{% endraw %}/assets/mydoc.pdf)
AsciiDoc
link:{ctx_path}/assets/mydoc.pdf[get the PDF]
The location of ctx_path must be set in the Awestruct configuration.

Full example with links

Markdown
As explained on the [directory structure](../structure) page, the `_posts`
folder is where your blog posts will live. These files can be either
[Markdown](http://daringfireball.net/projects/markdown/) or
[Textile](http://textile.sitemonks.com/) formatted text files, and as long as
they have [YAML front-matter](../frontmatter), they will be converted from their
source format into an HTML page that is part of your static site.
AsciiDoc
As explained on the link:../structure[directory structure] page, the `_posts`
folder is where your blog posts will live. These files can be either
http://daringfireball.net/projects/markdown/[Markdown] or
http://textile.sitemonks.com/[Textile] formatted text files, and as long as
they have link:../frontmatter[YAML front-matter], they will be converted from
their source format into an HTML page that is part of your static site.

Images

Markdown
![Helpful screenshot]({% raw %}{{ site.url }}{% endraw %}/assets/screenshot.jpg)
AsciiDoc
image::screenshots.jpg[Helpful screenshot]
The location of imagesdir must be set in the Awestruct configuration.

Smart quotes

Markdown
One of Jekyll’s best aspects is that it is “blog aware”.
AsciiDoc
One of Jekyll's best aspects is that it is ``blog aware''.

Source code

Markdown
{% highlight bash %}
YEAR-MONTH-DAY-title.MARKUP
{% endhighlight %}
AsciiDoc
[source,bash]
YEAR-MONTH-DAY-title.MARKUP

Source code with callouts

Markdown
{% highlight ruby %}
def show
  @widget = Widget(params[:id])
  respond_to {|format| format.html # show.html.erb
  }
end
{% endhighlight %}
AsciiDoc
[source,ruby]
def show
  @widget = Widget(params[:id])
  respond_to {|format| format.html #<1>
  }
end

<1> show.html.erb

Next
Activate posts extension

Create the posts directory in the project root

$ mkdir posts

Enable the Posts extensions and Partial helper

_ext/pipeline.rb (partial)
Awestruct::Extensions::Pipeline.new do

  helper Awestruct::Extensions::Partial

  extension Awestruct::Extensions::Posts.new '/posts'

  extension Awestruct::Extensions::Paginator.new :posts, '/index',
      :page_name => 'posts/page/', :per_page => 5

  extension Awestruct::Extensions::Atomizer.new :posts, '/feed.xml',
      :num_entries => 10

end

Create a directory for partials in the project root

$ mkdir _partials

Create a partial to layout a post

_partials/post.html.haml
- author_url = page.post.author_url || site.author_url
- post_url = "#{site.ctx_path}#{page.post.url}"
%article.post
  %header.post-head
    %h1.title
      %a{:href=>post_url}=page.post.title
    %h4
      %em by
      %a.author{:href=>author_url}
        %img(src="#{author_url}.png" width=24 height=24)
        =page.post.author || site.author
      on
      %time.pubdate{:datetime=>page.post.date.strftime('%FT%T%:z')}
        =page.post.date.strftime '%B %e, %Y'
  .post-body
    =page.post.content

Create the base layout for a post

_layout/post.html.haml
---
layout: base
---
=partial 'post.html.haml', :post => page

Create the layout for pagination

_partials/pagination.html.haml
- paginator = page.paginator
.pagination-centered
  %ul.pagination
    - if paginator.previous_page
      %li.arrow
        %a(href="#{site.ctx_path}#{paginator.previous_page.url}")
          %i.icon-step-backward
    - else
      %li.arrow.unavailable
        %a(href='#')
          %i.icon-step-backward
    %li #{paginator.current_page_index + 1} of #{paginator.pages.size}
    - if paginator.next_page
      %li.arrow
        %a(href="#{site.ctx_path}#{paginator.next_page.url}")
          %i.icon-step-forward
    - else
      %li.arrow.unavailable
        %a(href='#')
          %i.icon-step-forward

Show all posts on front page

Edit index.html.haml
---
layout: base
---
.row
  .large-12.columns
    %h1 Welcome to #{Asciidoctor.render site.name, :doctype => :inline}!

.row
  .large-12.columns.posts
    - page.posts.each do |post|
      =partial 'post.html.haml', :post => post, :listing => true
    =partial 'pagination.html.haml', :paginator => page.posts

Create a new post

posts/docs-workshop-oscon-2013.adoc
= Docs Workshop at OSCON 2013
Author Name
2013-07-22
:awestruct-tags: [conference, oscon]

Content of first post, reporting from OSCON!
The default layout for a post is post, so you don’t have to specify it in the AsciiDoc header.

Add Atom feed site

Edit _layouts/base.html.haml
%link(rel='alternate'
      type='application/atom+xml'
      href="#{site.ctx_path}/feed.xml")

Clean and preview site to see changes

$ rake clean preview

Enable Tagger extension

Add declaration below Paginator in _ext/pipeline.rb
extension Awestruct::Extensions::Tagger.new :posts, '/index',
    'posts/tag', :per_page => 5

Add tag links below post

Append to _partials/post.html.haml
  %footer.post-footer
    - if page.post.tags
      .tags<
        %i.label.icon-tags
        -#=page.post.tag_links
        - page.post.tags.each_with_index do |tag, idx|
          - unless idx.zero?
            =', '
          %a{:href=>"#{site.ctx_path}#{tag.primary_page.url}"}=tag

Clean and preview site to see changes

$ rake clean preview

Publish your site

Next
Deploy to GitHub Pages

Commit and push any outstanding changes

$ git commit . -m 'Enhancements'
$ git push origin master

Create the publish branch, gh-pages

$ git checkout --orphan gh-pages
$ rm -rf *
$ rm -rf .awestruct* .sass-* .gitignore .gitmodules
$ git rm --cached *
$ echo "GitHub Pages placeholder" > index.html
$ git add index.html
$ git commit -m "Seed publish branch for GitHub Pages"

Push the publish branch

$ git push origin gh-pages
By pushing the gh-pages branch, you also activated GitHub Pages to publish your website.

View your website at: http://{username}.github.io/writeadapt-{username}/

Setup the Awestruct GitHub Pages deployer

Switch to the master branch
$ git checkout master
$ git submodule update
Append to _config/site.yml
profiles:
  development:
    deploy:
      dummy:
  production:
    base_url: http://{username}.github.io/writeadapt-{username}
    ctx_path: /writeadapt-{username}
    asciidoctor:
      :attributes:
        base_url: http://{username}.github.io/writeadapt-{username}
        ctx_path: /writeadapt-{username}
        # imagesdir must be absolute to work around Atom feed bug
        imagesdir: http://{username}.github.io/writeadapt-{username}/images
    deploy:
      host: github_pages
      branch: gh-pages

Commit deployer configuration

$ git commit _config/site.yml -m "Add profile for GitHub Pages deployment"
$ git push origin master

Deploy to GitHub Pages

$ rake clean deploy

View your website again at:
http://{username}.github.io/writeadapt-{username}

Your Awestruct-based website is now live, and available worldwide!

Content Write, Read and Chunk

Write once, use anywhere and everywhere

Read in the raw

Write the chunk