Permalink
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
606 lines (407 sloc) 23.1 KB
---
title: FAQ
area: docs
section: getting started
---
{{#todo}}
* pretty links
* list categories, by page
* list categories for a given/specific page
* list categories for "this" page
* list pages for each category
* generate links to/from each page in each category
{{/todo}}
## Source files for the Docs
On each page of Assemble's live documentation you will find a "See the templates for this page" link, so you can take a look behind the curtains and get a peek at how we build our own docs. Of course, you can also fork or download the entire project if you want to go deeper with it (or make a pull request, you thoughtful and charitable community member you!).
## Generating a list from a collection
The simplest way to generate a list from a collection is to create a block expression using the name of the collection, and the collection items inside.
### Collection items from "all pages"
To generate a list of [categories][options-collections] for all [pages][pages] in a [target][targets], add the following block expression to a page or a [layout][layouts] (depending on whether or not you want the list to render to a _specified page/pages_ or _all_ pages):
```html
<h2>All Categories</h2>
<ul>
\{{#categories}}
<li>\{{category}}</li>
\{{/categories}}
</ul>
```
Now, if two of the pages in your target have categories defined as such:
```html
---
title: Page One
categories:
- apples
- oranges
---
```
and
```html
---
title: Page Two
categories:
- grapes
- bananas
- coconuts
---
```
The generated output will be a basic list containing the merged values from the `categories` collection of each page:
```html
<h2>All Categories</h2>
<ul>
<li>apples</li>
<li>bananas</li>
<li>coconuts</li>
<li>grapes</li>
<li>oranges</li>
</ul>
```
### Collection items on a given page
To generate a list of [categories][options-collections] for a page, you would add the following to the page on which you want to generate the list:
```html
\{{#page.categories}}
\{{.}}
\{{/page.categories}}
```
Or you can use the `\{{#each page.categories}}...\{{/each}}` block expression with the name of the collection as a variable to get the list of pages in the current [target][targets].
## Dynamically building navigation
Following the previous example, you can use the `\{{#each}}...\{{/each}}` block expression with the [pages][pages] variable to get the list of pages in the current [target][targets].
Then, using the `\{{#is}}...\{{/is}}` comparison helper from the [handlebars-helpers][handlebars-helpers] library, you can dynamically build navigation items by comparing a property (or properties) from the YAML front matter for each page in the list with the given values.
In other words, the `is` helper will ask: "does this page have a 'getting started' section? If 'true', then add the page as a list item, otherwise skip it". For example, this example shows two different sections being generated:
```handlebars
<h2>Getting Started</h2>
\{{#each pages}}
\{{#is data.section "getting started"}}
<li> <a href="#">\{{data.title}}</a> </li>
\{{/is}}
\{{/each}}
<h2>Configuration</h2>
\{{#each pages}}
\{{#is data.section "configuration"}}
<li> <a href="#">\{{data.title}}</a> </li>
\{{/is}}
\{{/each}}
```
Any pages with `section: getting-started` in the YAML front matter will render in the first list, and pages with `section: configuration` will render in the second list.
\{{#todo}} update the docs once [Pages Arrays][pages-array] can achieve this as well.\{{/todo}}
## Adding "active" links to navigation items
If you want to add `class="active"` to a navigation item for the "current page", you can achieve this using the `\{{#is}}...\{{/is}}` [comparison helper](https://github.com/assemble/handlebars-helpers#comparisons-equal-helpers) from the [handlebars-helpers][handlebars-helpers] library.
### Using YFM properties
You can achieve this using many different variables, but a relatively easy one is to compare the _[basename][built-in-variables] of the current page_ to the _given value_:
```html
<ul class="nav navbar-nav">
<li\{{#is basename "getting-started"}} class="active"\{{/is}}>
<a href="getting-started.html">Getting started</a>
</li>
<li\{{#is basename "css"}} class="active"\{{/is}}>
<a href="css.html">CSS</a>
</li>
<li\{{#is basename "components"}} class="active"\{{/is}}>
<a href="components.html">Components</a>
</li>
<li\{{#is basename "js"}} class="active"\{{/is}}>
<a href="javascript.html">JavaScript</a>
</li>
<li\{{#is basename "customize"}} class="active"\{{/is}}>
<a href="customize.html">Customize</a>
</li>
</ul>
```
_The above example is from the navbar in [assemble-bootstrap](https://github.com/assemble/assemble-bootstrap)._
### Without YFM
However, if you don't use YFM (or don't want to use properties from YFM to create active links), you can compare the _destination of the current page_ to the _destination of the linked page_ to get a truthy or falsy value.
```html
\{{#is page.dest this.dest}} class="active"\{{/is}}
```
**The trick** with using this method is that the context must be correct for it to work. So if you are dynamically generating nav items, as in the [Dynamically build navigation][#dynamically-build-navigation] example, you will need to use `../../` to access the context of `pages` being generated:
```html
<h2>Getting Started</h2>
\{{#each pages}}
\{{#is data.section "getting started"}}
<li\{{#is ../../page.dest this.dest}} class="active"\{{/is}}>
<a href="#">\{{data.title}}</a>
</li>
\{{/is}}
\{{/each}}
```
## Generating relative paths for links
To get the relative path from the _destination of the current page_ to the _destination of the linked page_, the [\{{relative}}](https://github.com/assemble/handlebars-helpers#relative) helper works quite well:
```html
\{{relative page.dest this.dest}}
```
As with the previous example, if you nest templates the context must be adjusted for this to work:
```html
<h2>Getting Started</h2>
\{{#each pages}}
\{{#is data.section "getting started"}}
<li\{{#is ../../page.dest this.dest}} class="active"\{{/is}}>
<a href="\{{relative ../../page.dest this.dest}}">\{{data.title}}</a>
</li>
\{{/is}}
\{{/each}}
```
{{#draft}}
#### "Titleizing" strings
We can even go a step further and make the rendered titles propercase:
```html
<ul>
\{{#each pages}}
<li><a href="#">\{{titleize title}}</a></li>
\{{/each}}
</ul>
```
which renders to:
```html
<ul>
<li><a \{{#is basename "index"}} class="active"\{{/is}} href="index.html">Home</a></li>
<li><a \{{#is basename "our-vision"}} class="active"\{{/is}} href="our-vision.html">Our Vision</a></li>
<li><a \{{#is basename "our-mission"}} class="active"\{{/is}} href="our-mission.html">Our Mission</a></li>
<li><a \{{#is basename "our-values"}} class="active"\{{/is}} href="our-values.html">Our Values</a></li>
</ul>
```
```handlebars
<ul class="nav nav-pills nav-stacked">
\{{#each pages}}
\{{#is data.section "toc"}}
<li\{{#is ../../page.dest this.dest}} class="active"\{{/is}}>
<a href="\{{relative ../../page.dest this.dest}}">\{{data.title}}</a>
</li>
\{{/is}}
\{{/each}}
</ul>
```
## Grunt conventions
If you're not familiar with Grunt, here are some very high level FAQs to get you oriented:
* Grunt itself is a "task runner", which means that Grunt will run whatever tasks you need for your project.
* Grunt tasks are configured in the `Gruntfile.js` of your project
* Each task in the Gruntfile is powered by a Grunt "plugin"
* Plugins are typically external to the Gruntfile, but not always. If you develop a very small plugin for a specific project and you want to store it in the Gruntfile, go for it.
* You can either `npm install` plugins or add your own locally.
* When adding a plugin via `npm install`, you must register the task using `grunt.loadNpmTasks('assemble');` outside of the `grunt.initConfig({...}):` object.
* If you develop a Grunt plugin or otherwise add one locally, the convention is to store the plugin in the `./tasks` directory of your project.
* Local plugins are registered with `grunt.loadTasks('tasks');` outside of the `grunt.initConfig({...}):` object.
* Each task can have one or more [targets][targets]
* Each target can have a different configuration for dynamically building `src` and `dest` files lists.
* Options can be defined at both the task-level and the target-level.
* Options defined at the target level will typically override options defined at the task level. This can be modified with custom programming.
### [Target][targets]
Please read [Task Configuration and Targets][tasks-targets] on the Grunt website for more information.
Grunt offers a ton of flexibility regarding how task and targets are configured, and Assemble takes full advantage of this. Each target in a task can have a completely different configuration. Options and files can be defined specifically for each target, while also inheriting options defined at the task level.
Throughout the Assemble docs, anytime we refere to a target(s), we are refering specifically to the targets you have configured in the Assemble task in your Gruntfile. For example, the following task is configured with three targets, "docs", "blog", and "site":
In the following example, the `assemble` task is configured with three targets:
```js
assemble: {
docs: {
'docs/': 'src/docs/*.hbs'
},
blog: {
'articles/': 'src/posts/*.hbs'
},
site: {
'site/': 'src/pages/*.hbs'
}
}
```
This is just one aspect of Grunt's conventions that we have found to be extremely useful and powerful. Oftentimes we see developers looking for overly complicated workarounds to difficult issues that could very easily be solved by just adding another target to the assemble task (or even by adding another supplemental task).
<a class="anchor" name="current-target" id="current-target"></a>
### "Current Target"
Throughout Assemble's docs, when you see the term "current target", this refers to the _context of the target currently being run_.
If we use the targets from the previous section as an example, if you run `grunt assemble:docs`, then the `docs` target would be the "current target". If you run `grunt assemble` and each target is executed successively (`docs`, `blog` and `site`), then "current target" would refer to the output that you should expect to see from files specified in a given target.
For example, [collections][collections] will only render with _collection items from files defined in the current target_. So when `\{{#each pages}}...\{{/each}}` is used to render a list of pages, only the pages that are specified in the currently running target will be included in the collection. If we again use the targets from the previous section as an example, if we assume that the layout used by the `site` target contains `\{{#each pages}}...\{{/each}}`, then after running `grunt assemble` we will find that files in the `site/` directory will include the list of pages defined in the `site` target (and only in the `site` target).
This is what is meant by "current target".
<a name="files-configuration" id="files-configuration"></a>
### Files Configuration
Please read [Building the Files Object Dynamically][files-object] on the Grunt website for more information.
Grunt offers a few different options for dynamically building files lists. Throughout this documentation you will see the following concepts referred to repeatedly, so this is good information to have:
#### "src-dest" format
```js
assemble: {
options: {},
blog: {
options: {},
src: 'src/templates/posts/*.hbs',
dest: 'dest/posts/'
}
}
```
#### "files-object" format
```js
assemble: {
options: {},
docs: {
options: {},
files: {
'dest/posts/': ['src/templates/posts/*.hbs'],
'dest/archives/': ['src/templates/archives/*.hbs']
}
}
}
```
#### "files-array" format
This format allows multiple src-dest files mappings for a target, and each mapping may have additional options defined for it allowing a higher level of granularity.
```js
assemble: {
options: {},
blog: {
options: {},
// additional options/properties may be defined in each mapping
files: [
{
expand: true,
flatten: true,
cwd: 'src/templates/posts',
src: ['*.hbs'],
dest: 'dest/posts/',
ext: '.html'
},
{
expand: true,
flatten: true,
cwd: 'src/templates/archives',
src: ['*.hbs'],
dest: 'dest/archives/',
ext: '.html'
}
]
}
}
```
[tasks-targets]: http://gruntjs.com/configuring-tasks#task-configuration-and-targets
[files-object]: http://gruntjs.com/configuring-tasks#building-the-files-object-dynamically
## Introduction to Assemble
> Beginner's guide to using Assemble for building web projects, sites or components.
Dead simple site and component generator, built from the ground up as a [Grunt.js](http://gruntjs.com/) plugin.
> Assemble makes it dead simple to build modular sites and components from **templates** and **data**.
> Assemble is an "opinion aware" site generator that makes it dead simple to build sites and components
With Assemble, you can use any directory structure and any naming conventions you want.
Just add templates and data and Assemble will produce a fully-grown
Assemble is an easy-bake oven for web projects.
Just water it with templates and data and Assemble will produce a fully-grown
## What differentiates Assemble from other site builders?
Assemble was designed from the ground up as a plugin to [Grunt.js](http://gruntjs.com/), the fantastic JavaScript "task runner". So Assemble follows the same conventions as hundreds of other Grunt plugins, providing you with the flexibility to configure your build process however you want, _with or without Assemble_.
Assemble also offers strong conventions for working with templates and data. For example, your project might include a few of the following concepts in some form:
Raw templates and data
Processes templates and data
YAML, YAML Front-Matter, JSON
Markdown, external (dedicated files) or inline (embedded in HTML).
raw templates, Handlebars, HTML, plain text, markdown
generated content
can be any extension
(representing the raw form of a website)
runs it through Textile or Markdown and Liquid converters, and spits out a complete, static website suitable for serving with Apache or your favorite web server. This is also the engine behind "GitHub Pages":http://pages.github.com, which you can use to host your project's page or blog right here from GitHub.
See examples for plain HTML and CSS, scaffolds, client-side templates, mock-data, CSS pre-processors, markdown, YAML, JSON, sensible configuration defaults and a Grunt.js build system to make it work.
Assemble is great for gh-pages, documentation, static sites, mocking etc.
Get the rocks out of your socks. Assemble helps you quickly launch static web projects by emphasizing a strong separation of concerns between structure, style, content and configuration.
## Separation of Concerns
Assemble brings order to web projects by showing you how to separate structure, styling, content, data and behavior.
### Everything is a Component
Strictly keep structure (markup), presentation (styling), and behavior (scripting) apart, and try to keep the interaction between the three to an absolute minimum.
That is, make sure documents and templates contain only HTML and HTML that is solely serving structural purposes. Move everything presentational into style sheets, and everything behavioral into scripts.
In addition, keep the contact area as small as possible by linking as few style sheets and scripts as possible from documents and templates.
Separating structure from presentation from behavior is important for maintenance reasons. It is always more expensive to change HTML documents and templates than it is to update style sheets and scripts.
HTML, CSS and JavaScript. The language of the web"
Most web projects involve
a lot of JavaScript, one of the first things you learn is to stop tying your data to the DOM. It's all too easy to create JavaScript applications that end up as tangled piles of jQuery selectors and callbacks, all trying frantically to keep data in sync between the HTML UI, your JavaScript logic, and the database on your server. For rich client-side applications, a more structured approach is often helpful.
With Backbone, you represent your data as Models, which can be created, validated, destroyed, and saved to the server. Whenever a UI action causes an attribute of a model to change, the model triggers a "change" event; all the Views that display the model's state can be notified of the change, so that they are able to respond accordingly, re-rendering themselves with the new information. In a finished Backbone app, you don't have to write the glue code that looks into the DOM to find an element with a specific id, and update the HTML manually — when the model changes, the views simply update themselves.
If you're new here, and aren't yet quite sure what Backbone is for, start by browsing the list of Backbone-based projects.
Many of the examples that follow are runnable. Click the play button to execute them.
## Overview
In a nutshell, assemble was designed to simplify
## Conventions
Assemble allows you to use your own conventions for just about everything, including folder structure and file names. Bearing this in mind, it's easiest to explain how to get the most out of assemble if we establish a common dialog using the following conventions:
* The "assets" folder contains CSS, JavaScripts, images, fonts, icons and so on. We'll talk about this more later, but in general assets can be found in the `dest/assets` folder.
* Projects have one or more locations for `src` and `dest` files.
* "Templates" refers to structural code, which includes HTML, Mustache, Handlebars or any other templating library.
assume the following structure
use a generic example, following these assumptions:
Everyone likes to organize their projects differently. Sure, there is a ton of value in standardizing folder structures, documentation methodologies, an so on. But there is also a ton of value in creativity and change. The bottom line is that you should be able to decide how to organize your own project.
So bearing in mind that assemble honors this and allows you to use your own conventions,
# Assemble
Assemble a [Node.js]() application and [Grunt.js]() plugin used to generate web components, pages, themes, sites, or documentation. By default, the output of Assemble is formatted as HTML pages, but templates can be used to build files with just about any extension. `sitemap.xml` is a common example, and this README was generated from templates.
Assemble provides:
* Speed: Assemble builds pages quickly.
* Live previews. Assemble includes a standalone doc server, making it trivial to preview your docs as you write.
* Modern markup. Assemble's generated documentation is an attractive, functional web application with real URLs and graceful fallbacks for spiders and other agents that can't run JavaScript.
* Flexible template engine support. Assemble was originally designed to use Handlebars by default, but it is not tied to any particular engine or preprocessor. You can use it with any engine that supports.................. [TODO].
## Configurable Conventions
As a philosophy, Assemble does not force opinions on you, freeing you to use your own conventions for most things, including:
* How and where configuration data is stored
* Terminology for variables ("global" variables, page variables or component variables, and so on)
* Folder structure and file naming conventions.
* Template engine: by default, Assemble
* Content format: Assemble reads in data as text and parses it using your template engine of choice. So however you want to write your content is up to you. However, out of the box you can easily store content in any of the following formats and Assemble will build it: `.md|.markdown`, YAML front matter, `.yaml`, `.json`, `.txt`, `.html`, `.mustache|.hbs|.handlebars` (any arbitrary handlebars/mustache extension).
it can be used easily and productively on non-YUI code
## Summary
To get the most out of Assemble it's important to first understand the role that Assemble plays within the context of a broader web development process. Depending on the team or environment you work in, you might use some or all of the following elements:
* Design process
* A development process
To establish context,
In a nutshell, here are the major
and where Assemble fits into that picture.
Assemble is really just the here are the basic building blocks that Assemble works with to :
* Templates basically are blocks of code (HTML, text, markdown, etc.) which, like pieces of a puzzle, will eventually be put together by Assemble.
* Variables are used inside templates as placeholders that will eventually be replaced with real data
## Templates and Variables
Let's start by creating a template, which can be any kind of markdown, text, xml or markup (such as HTML) we want it to be. For this example our template is going to be HTML, and since we're feeling creative, let's call it `my-template.tmpl`, and focusing only on the `head` of our HTML document let's add template variables for `title` and `author` so that we can later replace them with real data:
```handlebars
<!DOCTYPE html>
<html lang="en">
<head>
<title>\{{title}}</title>
<meta name="author" content="\{{author}}">
</head>
<body>
</body>
</html>
```
Handlebars.js is the default template engine in Assemble, so our variables are wrapped in "Handlebars expressions": `\{{` and `}}`. Given that our template is in Handlebars format, let's also change the file extension to `.hbs`, so our template is now named: `my-template.hbs`.
## Data
Now that it's time to add data, things get more interesting. Assembles allows you to work with several data formats inside your templates:
* [JSON]() files, such as `my-data.json`
* [YAML]() files, such as `my-data.yml`
* [YAML Front-Matter](), embedded directly inside the template itself
The best part is that you can mix and match these formats however you want.
### JSON
When working with "external" data files, if we:
a. name our file the same as our template, and
b. add the path to the data file to the `options.data` object in the `assemble` task
then Assemble will pick it up and use it automatically.
Here is an example of what we might put inside of `my-template.json` to populate our template with data.
```json
{
"title": "Assemble",
"author": "Brian Woodward"
}
```
Here is the same in YAML format: `my-template.yml`
```yaml
title: Assemble
author: Brian Woodward
```
And this template:
`my-template.hbs`
```handlebars
<h1>\{{ title }}</h1>
```
Or, in cases where we only require simple metadata we can use YAML Front-matter to eliminate the need for an external data file:
```yaml
---
title: Assemble
author: Brian Woodward
---
<h1>\{{ title }}</h1>
```
Furthermore, we can optionally use underscore templates in the YAML front-matter to translate external variables into data inside the content:
```handlebars
---
title: <%= some.title.variable %>
author: Brian Woodward
---
<h1>\{{ title }}</h1>
<p>\{{ author }}</p>
```
Outputs:
```html
<h1>Assemble</h1>
<p>Brian Woodward</p>
```
{{/draft}}