npm package: @namgoe/gcmstatic
Description: Statically generated GCMS lookalike
Latest version: 0.0.2

# gcmstatic

A GCMS lookalike based on the [Metalsmith](http://metalsmith.io) static site
generator.

## Quick start

1. Fork this project by clicking the `Fork` button on the
   project's [GitLab page](https://gitlab.gwdg.de/nam/gcmstatic).

2. Clone your fork, and add this project as a remote (makes it easier to track
   updates):

   ```
   $ git clone https://gitlab.gwdg.de/<USER>/gcmstatic.git
   $ git remote add upstream https://gitlab.gwdg.de/nam/gcmstatic.git
   ```

3. Install [Node.js](https://nodejs.org) version at least `7.10`, either via the
   linked website, or via your distribution's package manager. You can also
   install it locally into your home directory
   using [NVM](https://github.com/creationix/nvm).

   **Note**: While Node.js does run on Windows, `gcmstatic` has not been tested
   there yet. In particular, differences in the path separator (`/` and `\`) may
   lead to problems when processing the source directory hierarchy.

4. Run `npm install` from the project's root directory to fetch all
   dependencies.

5. Add some content to the `src` directory:

   - `src/index.de.md`

      ```
      ---
      title: Willkommen
      ---

      Sehr informativer Inhalt hier.
      ```

   - `src/index.en.md`

      ```
      ---
      title: Welcome
      ---

      Very informative content here.
      ```

   **Note**: As a general rule, you should likely not modify any files *outside
   the `src` directory*. If we make changes the `lib`, merging the updates can
   otherwise become arbitrarily complex over time. On the other hand, we will
   try and take care not to break existing site setups in `src`. If you need
   functionality that is not available via means described below, please tell
   us.

6. From the project's root directory, run

   ```
   ./generate
   ```

   The generated website will be written to the `build` directory. `gcmstatic`
   is a *static* site generator; it will generate a set of static HTML files
   which can be directly opened in a browser or pushed to the document root of a
   web server.

   For development, you can also run

   ```
   ./generate --serve
   ```

   This will start a local web server on [http://localhost:8080](). It will also
   monitor files for changes, rebuild the website if needed, and tell the
   browser to reload.

   **Note**: The HTML generated by `generate --serve` contains additional
   javascript for the livereload functionality. Make sure to always run
   `generate` without `--serve` once before pushing to a web server to get rid
   of the script. It may also be useful to completely remove the `build`
   directory before the final `generate`, just to be sure.

   **Another note**: You will still not be able to view the generated website
   without a network connection, as some resources (jQuery, Bootstrap, ...) are
   fetched from external servers. We will (probably) add an option for
   completely offline webpages later.

## Directory structure

The structure of `src` is mostly mirrored in `build`. Markdown files (`.md`)
will be processed to `.html`, dotfiles removed, and some other file types will
be processed and removed as well (see below for details).

The biggest difference is that all language-specific files will be moved to
separate directory hierarchies. Given these an `src` directory like

```
index.de.md
index.en.md
foobar.de.md
subpage/
  index.de.md
  index.en.md
img/
  logo.png
```

the `build` directory will contain

```
de/
  index.html
  foobar.html
  subpage/
    index.html
en/
  index.html
  subpage/
    index.html
img/
  logo.png
static/
index.html
```

The `static` subdirectory contains stylesheets and scripts mosyly copied from
GCMS. The top-level `index.html` is (almost) identical to `de/index.html` and
serves as the default landing page.

### Navigation sidebar

All pages by default have a navigation sidebar on the right hand side consisting
of up to three boxes containing

- links to all pages in the same directory,
- links to the `index.html` files of all subdirectories, and
- optional supplementary links that can be configured in metadata (see below).

The subdirectories of the current language's top-level directory (i.e. the
`subpage` directories in the example above) are listed in the page header
instead of the sidebar.

### Links

In-site links in Markdown or HTML should usually be written relative to the
current directory so as not to break when moving files to the language-specific
subdirectories. If you use absolute links, make sure to take the target's final
location into account.

As a final processing step, after the directory structures are fixed, all
absolute links are automatically rewritten to relative links. This makes it
possible to serve the generated site from a subdirectory of the web server or
your local drive.

## Metadata

Files can be preceded by a *front matter*, which is a block of YAML data
delimited by lines containing only `---`. YAML is a simple language for
structured data, consisting essentially of lists, key-value-maps and some
elementary data types like strings and numbers. To quickly learn about the
basics, [Learn YAML in Y minutes](https://learnxinyminutes.com/docs/yaml/) is a
good resource.

The front matter can contain arbitrary data. Some keys have special meaning, but
all keys defined here will are available when processing the input files via the
template engine (see *Templates* below).

### `defaults.yaml`

In addition to specifying metadata in the front matter, the source will be
searched for files named `defaults.yaml`. These should contain YAML maps, the
keys of which are taken as shell-style glob patterns, and the values are again
maps which are applied to all files matching the pattern relative to the
subdirectory the `defaults.yaml` is located in, e.g.

```
"*.md":
  key1: val1

"**/*.txt":
  key2: val2
```

will set `key1` to `val1` in all `.md` files, and `key2` to `val2` in all `.txt`
files in all subdirectories (`**/` matches arbitrarily many subdirectories).

If both a key is specified both in the front matter and a `defaults.yaml`, the
former takes precedence. On conflicts between multiple `defaults.yaml` files,
the one further down the directory hierarchy wins.

### Special properties

The following file properties have special meaning. Some of them can be set to
control how the file contents will be processed, others are automatically
generated to be used by templates if needed.

- **`layout`**

  The content generated from each file can optionally be wrapped in a *layout*.
  Currently, the only available layout is `default`, which is enabled for all
  Markdown and HTML files. If unset, the generated content will be used as-is.

  The `default` layout uses some additional properties.

  - **`title`**

    Sets the page title.

  - **`navtitle`**

    An alternative title to be used in the navigation sidebar. If unset, `title`
    will be used.

  - **`sidebar`**

    Whether to show the sidebar at all. Defaults to `true`.

  - **`links`**

    A list of supplementary list of links to be displayed in the sidebar. This
    should be a YAML list of strings. These strings will be inserted into the
    sidebar verbatim, so they should be valid HTML.

  - **`stylesheets`**

    A YAML list of additional CSS stylesheets to be loaded in the generated page
    header.

  - **`mathjax`**

    Add a `<script>` header to fetch [MathJax](https://www.mathjax.org/) from
    external servers. In combination with the already-installed
    MathJax [Markdown plugin](https://github.com/classeur/markdown-it-mathjax),
    this allows you to write LaTeX math in `.md` files (or `.html` files, if you
    really want to).

    The MathJax scripts are somewhat heavy, so they should only be activated on
    pages that actually need this.

  - **`livereload`**

    Add a script supporting automatic page reloading when using `generate
    --serve`. Defaults to `true`, and only has an effect if the `--serve` option
    is actually given. There should be little reason to set this to `false`.

- **`template`**

  Setting this to `false` causes the template engine (see below) to ignore this
  file. Defaults to `true` for Markdown and HTML, `false` otherwise.

- **`partial`**

  Declares the file to be a *partial template* (see below). The value should be
  the intended partial name, or `true`, in which case the name is derived from
  the filename up to the first dot. The file itself will not appear in the
  generated output. All other properties of the file are ignored. Defaults to
  `false`.

- **`bibname`**

  Declares the file to be a BibTeX collection. The value is processed just as
  the `partial` parameter above. See below for more details on the BibTeX
  plugin.

  The plugin will remove the file from the generated output. If you want to also
  make a BibTeX file available for download, you will have to include it a
  second time.

- **`data`**

  Used by the [data loader plugin](https://github.com/tests-always-included/metalsmith-data-loader).
  Can be set to the (relative) path of a supplementary YAML or JSON file, a list
  of such paths, or a map with such paths as values. The files will be loaded
  and inserted in place of the respective paths.

  This does have some conceptual overlap with the `defaults.yaml` mechanism. Its
  main usecase is to have an external script generate some additional data which
  can be processed by the template.

- **`contents`**, **`stats`**

  Auto-generated, mostly for internal use; these properties should not be
  assigned otherwise.

### Multiple languages

There are some additional properties that govern the multiple language support.
Their behaviour is slightly more complex. For the most part, using files ending
in `.de.md` and `.en.md` (or `...html`) should *just work*.

- **`lang`**

  This is the language of the file and determines where in the directory
  hierarchy the genreated file ends up. It defaults to `en` for all `.en.md` and
  `.en.html` files, and to `de` for all other `.md` and `.html` files (its
  probably a good idea to use `.de.md` nevertheless). All other files do not
  have `lang` set by default and will not be moved to the language-specific
  directories.

  `lang` can also be set to a list of languages. In this case, multiple copies
  of the file will be generated, one for each entry. When processing the
  individual templates, `lang` will be set to the respective language.

  Finally, `lang` can be map from languages to addtional language-specific
  metadata. Processing will be performed as for the list case above, but with
  the respective language-specific metadata available. Example:

  ```
  ---
  lang:
    de:
      title: Deutscher Seitentitel
    en:
      title: English page title
  ---

  ...
  ```

- **`basename`**

  The file name of the generated file in the language-specific directory.
  Defaults to the file name itself with `.${lang}.` removed if `lang` is set,
  and to the plain file name otherwise. Files are regarded as different versions
  of the same page if they have the same path (inside the language-specific
  directory) and `basename`, and corresponding links below the header will be
  generated.

- **`langinfo`**

  Auto-generated property that contains supplementary language information from
  the site's `meta.yaml` (see below).

- **`lang_versions`**

  Auto-generated map from languages to versions of the same page in a different
  language. This is mainly used to generate the "other language" links below the
  page header and probably not really useful otherwise.

### Standard settings

The default properties, except for the ones auto-generated during processing,
are set from `lib/defaults.yaml`. Here are its contents (at the time of writing
this README):

```
'**/*.de.{md,htm,html}':
  lang: de

'**/*.en.{md,htm,html}':
  lang: en

---

'**':
  livereload: true
  sidebar: true

'**/*.{md,htm,html}':
  layout: default
  template: true
  lang: de
```

The `---` ensures that the lower part is applied *after* the upper part, so the
upper part takes precedence. Otherwise, the order of applying the `lang`
properties would be undefined.

### `meta.yaml`

Finally, some configuration options are site-wide rather than page-specific. The
defaults of these are set in `lib/meta.yaml`, which can be overridden in
`src/meta.yaml`. Here they are:

```
langs:
  de:
    name: Deutsch
    sitename: Institut für Numerische und Angewandte Mathematik
  en:
    name: English
    sitename: Institute for Numerical and Applied Mathematics

indexlang: de
```

All of these are available in templates as well, but get overriden by
site-specific settings. The applicable branch of the the `langs` property is
availabe as `langinfo` in templates. `indexlang` determines the language of the
top-level `index.html`.

If you want to support a third language, adding it is only a matter of extending
`langs` and various glob patterns in `defaults.yaml`. `de` and `en` are not
hard-coded otherwise.

Finally, some plugins may be configured in `meta.yaml`. Currently, this only
applies to BibTeX.

## Markdown

`gcmstatic` used the [markdown-it](https://github.com/markdown-it/markdown-it)
Markdown parser, which is [CommonMark](http://commonmark.org/) compliant and
extensible by plugins. If you never used Markdown, the plain text of this README
or markdown-it's [homepage](https://markdown-it.github.io/) should give you an
idea.

markdown-it is extensible via plugins, of which we are currently using the
following ones.

### [MathJax](https://github.com/classeur/markdown-it-mathjax)

This was already mentioned for the `mathjax` file property above. It allows you
to use a subset LaTeX math via [MathJax](https://www.mathjax.org/).

### [Decorate](https://github.com/rstacruz/markdown-it-decorate)

This allows you to add HTML classes, id's and attributes to Markdown elements,
which can be useful in combination with custom CSS (see the `stylesheets`
property above) or Bootstrap (see below).

Note that you can also include most HTML constructs directly in Markdown, in
case this plugin does not suffice.

## [BibTeX](https://github.com/JulesFrancoise/metalsmith-bibtex)

`gcmstatic` includes a BibTeX plugin, which adds some template helpers (see the
*Templates* section below) to include bibliography listings in a customizable
format on a page, and to cite references inline. Configuration is done via the
`bibtex` key in `meta.yaml`. Collections (i.e. bibtex source files) can either
be configured there, or via the `bibname` file property desctibed above.

## Bootstrap

GCMS' responsive page layout is based on
the [Bootstrap framework](http://getbootstrap.com/), and `gcmstatic` inherits
this dependency. For documentation, refer to the linked page.

Presence of the framework should be mostly transparent, as it is handled in the
`default` layout, but you may use it for your own purposes, for example to
create a responsive multi-column layout. The layout wraps the page content in a
`.container-fluid`, so all you need to do is to add a row and two columns:

```
---
title: Column example
---

<div class="row">
<div class="col-sm-6">

## First column

</div>
<div class="col-sm-6">

## Second column

</div>
</div>
```

**Note**: The `default` layout adds the page title as an `<h1>`, so in-page
headings should mostly be `<h2>` (i.e. `##` in Markdown) or higher.

## Templates

`gcmstatic` uses the [Handlebars](http://handlebarsjs.com/) template engine on
all files having a `template` property. The basics are rather simple. Variable
expansion happens between `{{` and `}}`, so `{{title}}` expands to the page
title set in the front matter. Conditionals are written like

```
{{#if someproperty}}It's set.{{else}}It's unset.{{/if}}
{{#unless someproperty}}It's set.{{else}}It's unset.{{/unless}}
```

where in both cases the `{{else}}` branch is optional. Iteration over lists and
maps can be done by

```
{{#each somelist}}{{somefield}}{{/each}}
```

which expands to the the `somefield` properties of all list elements in turn.

For debugging, there is a `log` helper:

```
{{log something}}
```

outputs the value of `something` to the console on expansion.

For full documentation, refer to the website linked above.

### Partials

A *partial* is a "non-evaluated" template that can be included in other
templates and is expanded in the context of the containing template (by
default). Partials in `gcmstatic` are registered using the `partial` property
(see above for details), and are included by

```
{{> somepartial}}
```

Parials can also receive other contexts, additional variables or entire template
blocks as parameters, which allows for
some [pretty flexible trickery](http://handlebarsjs.com/partials.html).

### Helpers

Handlebars by itself is very minimal and delegates most tasks to *helpers*,
which can be arbitrary Javascript functions. Registering helpers is (somewhat
intentionally) not possible without modifying the `lib` directory. If you need
some helper functions, please tell us.

Currently, our custom helpers only include elementary logic operations:

- **`or`**

  Takes an arbitraty number of arguments and evaluates to first non-"false" one,
  otherwise to `undefined` (which expands to nothing in templates). "false" has
  a somewhat broad definition; it's the same one
  [Handlebars' own `if` helper](http://handlebarsjs.com/builtin_helpers.html)
  uses.

  ```
  {{or false someproperty}}
  ```

  expands to whatever `someproperty` would expand to. `or` can also be used in
  conditionals:

  ```
  {{if (or a b)}} ... {{/if}}
  ```

  and as a block helper, i.e.

  ```
  {{#or a b}} ... {{/or}}
  ```

  In the latter case, it evaluates the block in the context of the first
  non-"false" argument.

- **`and`**

  Evaluates to the last argument if all arguments are non-"false", and
  `undefined` otherwise. The rest of the behaviour is the same as for `or`.

- **`eq`** and **`eqw`**

  These correspond to Javascripts' `===` and `==`, respectively. If unsure about
  the difference, `eq` is the one you want.

  ```
  {{if (eq key1 key2)}} ... {{/if}}
  ```

  does the obvious thing.

- **`not`**

  Does what you think it does.

## Updating

TODO

If you do change files outside `src`, it would be great if you would
[tell us about it](mailto:admin@math.uni-goettingen.de) or even
[create a merge request](https://docs.gitlab.com/ce/gitlab-basics/add-merge-request.html),
so that your changes are made available to others, and so we can make sure not
to break them on updates.

## Bugs

Found a bug? Need some additional functionality, template helpers, markdown
plugins or custom javascript? [Tell us](mailto:admin@math.uni-goettingen.de)
or [create an issue](https://gitlab.gwdg.de/nam/gcmstatic/issues/new) on GitLab.