# Contributing to Bonsai

## Development

### System Dependencies

This project requires [Node.js](https://nodejs.org), [npm](https://npmjs.com), and Git to be installed for development work.

### Getting started

First, clone the Bonsai repository and change to the repo as your current working directory:

```shell
$ git clone git@github.com:ithaka/bonsai.git
$ cd bonsai/
```

You can install all necessary dependencies for building the package using npm:

```shell
$ npm install
```

#### Building the package

Once you've installed all the dependencies, building the package can be accomplished with the `build` script:

```shell
$ npm run build
```

To watch for changes, use the `watch` script:

```shell
$ npm run watch
```

#### Testing

To run tests, use the `test` script:

```shell
$ npm run test
```

## Style guide

The Bonsai style guide is dynamically generated using the [Supercollider](http://www.github.com/zurb/supercollider) library. To contribute to the Bonsai documentation and style guide, you'll want to run it locally.

### Running locally

To start a server with hot module reloading, use the `start` script:

```shell
$ npm run start
```

This will launch the development server on `http://localhost:8080`. Navigate there and you'll be redirected to the index of the style guide. While the server is running, any time a file change is saved the documentation will recompile. Refresh the page to see your change.

### Making a new page in the style guide

The style guide documentation is written in Markdown. Here are some resources if you're not familiar:

* [Learn Markdown](https://daringfireball.net/projects/markdown/syntax)
* [Markdown Cheatsheet](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet)

Suppose you're going to create a new feature giving esteemed researchers a plethora of new tools for their study of cats on JSTOR. Suddenly the style guide needs a page about cats! Here's how you'd make it.

Create a Markdown file `documentation/pages/cats.md`. At the very minimum it needs a title, description, and content. The title and description are specified in _front matter_, or a section that precedes the visible content of the document. The front matter is separated from the content with three hyphens on the top and bottom:

```markdown
---
title: Cats Cats Cats!
description: Guidelines for the JSTOR Cats feature set
---

<!-- Here down is Markdown, which supports a subset of HTML, too -->

![A cute kitten](kitten.jpeg)

<div class="cat-container">
    <p class="cat">CAT</p>
</div>
```

If you want to dynamically include the SASS or JavaScript documentation for the cats component, you can specify the path to those files in the front matter. Both `sass` and `js` are optional:

```markdown
---
title: Cats Cats Cats!
description: Guidelines for the JSTOR Cats feature set
sass: ./scss/_cats.scss
js: ./js/bonsai.cats.js
---
```

Additionally, Supercollider allows you to create custom adapters if you need to generate documentation other than HTML, SASS, and JavaScript.

#### HTML examples

When documenting how to use a component, you may want to include example code. You can use a Markdown code block with the language `html_example` to insert the rendered HTML directly after the Markdown example. As an example, the following will both show the code snippet as well as the rendered button on the generated page:

`````markdown
```html_example
<button>I am button</button>
```
`````

#### Routing

Before spending too much time authoring your Markdown file, you should add it to the style guide routes so you can view the rendered page. Go to `documentation/routes.js` and add a line in the array that has the name of your Markdown file:

```diff
--- routes.js
+++ routes.js
 module.exports = [
   "button",
-  "modal"
+  "modal",
+  "cats"
 ]
```

By adding `"cats"` to this array, you'll be able to see the page in the style guide navigation, view it in your browser, and enable hot reloading for the `cats.md` file.

## The style guide build system

* webpack
  * webpack-shell-plugin
  * raw-loader
* Supercollider
  * foundation-docs custom markdown interpreter
* handlebars

### What happens when running `npm run start`?

<img src="https://i.imgflip.com/1tlvet.jpg" width="250" alt="SpongeBob says Webpack" />

1. Webpack processes all the files defined in the entry object in `webpack.config.js`.
1. Once all the files are processed, the `WebpackShellPlugin` runs `node generate-docs.js`.
1. `generate-docs.js` contains the Supercollider configuration and initialization.
1. Supercollider generates the HTML by taking all the Markdown templates, running them through the Markdown interpreter, getting the sassDoc and jsDoc strings associated with each Markdown file, and running them all through the primary handlebars template. This is all output as raw HTML to `documentation/styleguide/`. These settings are all in the `generate-docs.js` file.
1. A development server is launched at `http://localhost:8080`.
1. The development server watches the SASS, JavaScript, Markdown, and main template HTML for changes, reloading when it notices a change.

### Publishing to npm

Bonsai is published to the public npm registry. Publishing is tag-based, and the easiest way to create tags is through a GitHub release. Releases create a tag in the repository and allow you to enter a Markdown description of the release, which is a good place to put the changelog notes for the new version.

#### Creating a prerelease

A prerelease created from your feature branch is a good way to test your packaged changes before creating a final release. You can do the setup for a prerelease in a few steps:

1. Update `package.json` to the next semantic version for your changes, including any prerelease identifier. This will be something like `"5.15.3-beta.6"`.
1. [Draft a new GitHub release](https://github.com/ithaka/bonsai/releases/new).
  1. Find your branch in the **Target** dropdown, and specify your release version in the **Tag version** and **Release title** fields with a `v` in front. This will be something like `v5.15.3-beta.6`.
  1. Add a description of the changes contained in the prerelease
  1. Check the **This is a pre-release** checkbox.
1. Click **Publish release**.

This will create the tag and a GitHub release, but hasn't yet published the package to npm. You'll use a Jenkins job to find the tag you just created, package the code, and publish it to npm:

1. Go to [the Jenkins job](https://blue-jenkins.eks.test.cirrostratus.org/job/Bonsai%20Publish/) and make sure you're logged in.
1. Click the **Tags** tab.
1. Find the tag you just created, which will be something like `v5.15.3-beta.6`.
1. Click **Build Now** in the left menu.
1. Verify the new package version has been published [on Bonsai's npm page](https://www.npmjs.com/package/@ithaka/bonsai) under the **Versions** tab. The version should be associated with the `dev` tag.

Congratulations, you've published a Bonsai release! You can repeat this process as many times as you need on your branch, incrementing the prerelease version in `package.json` and making new tags and releases until your changes are ready for a final release.

#### Creating a final release

The process for creating a final release is very similar to a prerelease, with some key differences:

* Final releases should be made from the `develop` branch, so you'll need to open a pull request from your feature branch first.
* Final release versions look like `5.15.3` with no extra `beta` or other qualifiers. You'll need to update your `package.json` file accordingly.

Follow the same process of creating a GitHub release, this time targeting the `develop` branch and setting the tag version and release title accordingly.
Use the Jenkins job to publish the package from your tag, as before.

#### Testing a release

Once a release has been published, it will be associated with the `dev` tag by default regardless of being a prerelease or a final release. You can still install this version by specifying it directly:

```shell
$ npm install @ithaka/bonsai@5.15.3`
```

You can also install whatever the current `dev` tag points to at any time:

```shell
$ npm install @ithaka/bonsai@dev
```

Install your version in your project and see that it has the changes you expect. Depending on the outcome of your testing, you can keep working and issue another prerelease or open a pull request to start creating a final release.

#### Promoting a release

Once you've tested out a final release, you'll likely want to make it the one that users will get by default when they run `npm install @ithaka/bonsai`. You can do this by associating the `latest` tag with the release. You'll need to be a member of the ITHAKA organization on npmjs.com to do this. Create an npm account and ask to be added if you haven't already.

Once you've got permission to administer the Bonsai package, you can update the `latest` tag to point to your release:

```shell
$ npm login
Username:
Password:

$ npm dist-tag add @ithaka/bonsai@5.15.3 latest
```

Users will then receive `v5.15.3` when running `npm install @ithaka/bonsai` until the next release.

