Skip to content

Commit

Permalink
Merge pull request #64 from cloudfour/chore-cleanup-and-doc
Browse files Browse the repository at this point in the history
Chore: Clean up and Start Documenting more
  • Loading branch information
lyzadanger committed Apr 12, 2016
2 parents 8213377 + 6a4f301 commit 5b8ae43
Show file tree
Hide file tree
Showing 16 changed files with 312 additions and 95 deletions.
97 changes: 97 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,103 @@ drizzle(options).then(drizzleData => {
});
```

## Authoring with Drizzle

### Creating Resources

Drizzle builds static HTML output from source resource files.

* _Pages_ are compiled against a page layout template and output as HTML files.
* _Patterns_ are parsed into collections, which are compiled against a collection layout template and output as HTML files.
* _Data_ files can be used to provide data to patterns and pages.

#### Front Matter, YAML and JSON

Pages and patterns can use YAML front matter to override defaults, set particular attributes or provide arbitrary local data for the resource during template compilation. In general, data defined in front matter is made available at the top level of compilation (template) context for that resource.

##### Reserved Properties

Certain properties are reserved at the top level for Drizzle use. Each resource has its own reserved keys as well, but the following keys should not be used in front matter for any resource:

* `contents`: Used by Drizzle to store parsed and rendered contents for resources.
* `data`: Used for storing pattern- and page-specific data in global objects.
* `drizzle`: The `drizzle` property is reserved for global context during template compilation.
* `outputPath`: Used by Drizzle to record where the resource should be output to the file system.
* `path`: Used by Drizzle to retain the path to the original resource source file.

#### Formats and Parsing

#### Keys and Object Structure

#### Pages

Each file that matches the `pages` glob (`options.src.pages.glob`) will generate an HTML page.

##### Special Properties

* `layout`: Specify the layout template to use for this page resource (default layout templated is defined in `options.layouts.page`).

#### Patterns

##### Special Properties

* `name`: Override default naming for the pattern, which is based on filename.
* `hidden`: A truthy value will "hide" this pattern, making it available as data, but not rendered on its collection's page.
* `order`: Numeric value for where this pattern should appear in its collection's list of patterns. Defaults to alphabetical by filename.

##### Reserved Properties

* `collection`: Used by Drizzle to attach some metadata about this pattern's collection.

#### Collections

Collections are "meta" resources. Each directory within the glob match for `options.src.patterns.glob` that contains at least one matching pattern file is considered a "collection." By default, collections are named based on their directory name. One output HTML page is generated per collection.

##### Collection Metadata (Special Properties)

Creating a file named `collection.yaml`, `collection.yml` or `collection.json` in a pattern directory allows you to override data about that collection. Accepted properties are:

* `name` `{String}`: Override default directory-based naming
* `hidden` : An `Array` of `{String}` pattern ids to hide in the collection's output (base filename without extension)
* `order`: An `Array` of `{String}` pattern ids in the order you'd like them to display

`hidden` and `order` values can also be defined in individual patterns' front matter. Local pattern data will override data in `collection` metadata files.

Unlike other resources, properties in `collection` metadata files that are _not_ one the properties listed here will be ignored.

##### Reserved Properties

* `items`: Used by Drizzle to store _all_ of the patterns in this collection (even hidden ones)
* `patterns`: Used by Drizzle to store all of the _visible_, _ordered_ patterns in this collection.

#### Data

Files that match `options.src.data.globs` will be parsed and made available to templates. See documentation about global scope in the templates section.

### Templates

#### Context

The context available to resources during template compilation is a combination of a shared global context and a local context specific to the resource.

##### Global Context

Templates receive a `drizzle` data at the top level of their context. Top-level keys on this object are:

* `data`: Structured object of parsed data files
* `options`: Object of options that drizzle is using
* `pages`: Structured object of all page data
* `patterns`: Structured object of all patterns
* `templates`: Structured object of all templates (partials, layouts) and their contents

##### Local Context


#### handlebars-layouts

#### Default Templates


## API

### drizzle([options])
Expand Down
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
"version": "0.0.1",
"description": "The builder for Drizzle",
"main": "dist/index.js",
"files": ["dist"],
"files": [
"dist"
],
"engines": {
"node": ">=4.0.0"
},
Expand All @@ -21,7 +23,7 @@
"repository": "cloudfour/drizzle-builder",
"dependencies": {
"bluebird": "^3.3.1",
"deepmerge": "^0.2.10",
"deep-extend": "^0.4.1",
"front-matter": "^2.0.6",
"globby": "^4.0.0",
"handlebars": "^4.0.5",
Expand Down
7 changes: 4 additions & 3 deletions src/init.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import merge from 'deepmerge';
import deepExtend from 'deep-extend';
import defaults from './defaults';
import Promise from 'bluebird';

Expand All @@ -10,8 +10,9 @@ import Promise from 'bluebird';
* @return {Promise} resolving to merged options
*/
function init (options = {}, handlebars) {
options.handlebars = handlebars || require('handlebars');
return Promise.resolve(merge(defaults, options));
const opts = deepExtend({}, defaults, options);
opts.handlebars = handlebars || require('handlebars');
return Promise.resolve(opts);
}

export default init;
23 changes: 21 additions & 2 deletions src/parse/patterns.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,19 @@ const isPattern = obj => obj.hasOwnProperty('path');
const collectionPath = itms => path.dirname(itms[Object.keys(itms).pop()].path);
const collectionKey = itms => collectionPath(itms).split(path.sep).pop();

function checkNamespaceCollision (key, obj, id, options = {}) {
if (Array.isArray(key)) {
return key.map(oneKey =>
checkNamespaceCollision(oneKey, obj, id, options)
);
}
if (obj && obj.hasOwnProperty(key)) {
DrizzleError.error(new DrizzleError(`'${id}' has local '${key}'
property set. This is a Drizzle reserved property and will be
overwritten. See docs.`, DrizzleError.LEVELS.WARN), options.debug);
}
}

/**
* Should this pattern be hidden per collection or pattern metadata?
* @param {Object} collection Collection obj
Expand Down Expand Up @@ -65,8 +78,12 @@ const hasPatternOrdering = itms => {
*/
function buildPattern (patternObj, options) {
const patternFile = { path: patternObj.path };
const patternId = resourceId(patternFile,
options.src.patterns.basedir, 'patterns');
checkNamespaceCollision('id', patternObj.data,
`Pattern ${patternId}`, options);
return Object.assign(patternObj, {
id: resourceId(patternFile, options.src.patterns.basedir, 'patterns'),
id: patternId,
name: (patternObj.data && patternObj.data.name) ||
titleCase(resourceKey(patternFile))
});
Expand Down Expand Up @@ -148,9 +165,11 @@ function buildCollection (collectionObj, options) {
return readFiles(collectionGlob(items), options).then(collData => {
const collectionMeta = (collData.length) ? collData[0].contents : {};
collectionObj.collection = Object.assign ({
items: items,
name: titleCase(collectionKey(items))
}, collectionMeta);
checkNamespaceCollision(['items', 'patterns'], collectionObj.collection,
`Collection ${collectionObj.collection.name}`, options);
collectionObj.collection.items = items;
collectionObj.collection.patterns = buildOrderedPatterns(
collectionObj.collection);
return collectionObj;
Expand Down
19 changes: 15 additions & 4 deletions src/render/collections.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { resourceContext } from '../utils/context';
import { applyTemplate } from '../utils/render';
import { deepObj } from '../utils/object';
import DrizzleError from '../utils/error';

/**
* For any given `patterns` entry, render a pattern-collection page for
Expand All @@ -14,12 +16,21 @@ import { applyTemplate } from '../utils/render';
* @return {Object} patterns data at this level.
*/
function renderCollection (patterns, drizzleData, collectionKey) {
// TODO right now, layoutKey will only work if it is top-level in
// templates directory. Also, there is no override supported on a collection-
// by-collection level (i.e. in collection metadata files).
const layoutKey = drizzleData.options.layouts.collection;
let layoutObj;
try {
// deepObj will throw if it fails, which is good and fine...
layoutObj = deepObj(layoutKey.split('.'), drizzleData.templates, false);
} catch (e) {
// But Make this error more friendly and specific
DrizzleError.error(new DrizzleError(
`Could not find partial for default collection layout
'${layoutKey}'. Check 'options.layouts.collection' and/or
'options.src.templates' values to make sure they are OK`,
DrizzleError.LEVELS.ERROR), drizzleData.options.debug);
}
patterns.collection.contents = applyTemplate(
drizzleData.templates[layoutKey].contents,
layoutObj.contents,
resourceContext(patterns.collection, drizzleData),
drizzleData.options);
return patterns;
Expand Down
Empty file.
5 changes: 5 additions & 0 deletions test/fixtures/badPatterns/anotherBadCollection/collection.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
patterns:
- this
- is
- not
- OK
4 changes: 4 additions & 0 deletions test/fixtures/badPatterns/badCollection/collection.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
items:
- no
- no nope
- not here
Empty file.
6 changes: 6 additions & 0 deletions test/fixtures/badPatterns/localId.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
id: "This is a no-no"
name: "Overridden Name Is Fine"
---

This pattern tries to define a local ID.
9 changes: 6 additions & 3 deletions test/parse/data.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@ var expect = chai.expect;
var parseData = require('../../dist/parse/data');

describe ('parse/data', () => {
var opts = config.init(config.fixtureOpts);
var fileKeys = ['another-data', 'data-as-json', 'sample-data'];
var opts;
before (() => {
return config.init(config.fixtureOpts).then(options => opts = options);
});
it ('should parse data from files', () => {
return opts.then(parseData).then(allData => {
var fileKeys = ['another-data', 'data-as-json', 'sample-data'];
parseData(opts).then(allData => {
expect(allData).to.be.an('object').and.to.contain.keys(fileKeys);
});
});
Expand Down
Loading

0 comments on commit 5b8ae43

Please sign in to comment.