npm package: @seamly/doc-site
Description: This package allows you to easily build a documentation site with Webpack/Markdown/EJS. It provides:
Author: Seamly
Latest version: 4.1.1

# Seamly Doc Site builder

This package allows you to easily build a documentation site with Webpack/Markdown/EJS. It provides:

* A Webpack config transformer (`lib/config/site.js`) with:
  * Support for loading site data from `PROJECT_PATH/site.conf.js`
  * Support for pre-configured loaders
* A EJS Webpack loader (`loaders/ejs-layout-loader.js`) that supports:
  * Frontmatter (in combination with the `frontmatter-markdown-loader`)
  * Layouts
  * Loading of templates from this package
  * Table of content generation
* A HTML URL rewrite loader (`loaders/html-url-rewrite-loader.js`) that supports:
  * Rewriting links (it will resolve links so it will work with webpack publicPaths)
  * Requireable resources (`<img src="">` and `<link href="~...">` only)
* A small import loader (`loaders/import-loader.js`) that supports:
  * Writing raw css as assets, nees the CSS loader to be the last loader before this with `exportType` set to `string`.
* A set of EJS includes, layout and a default stylesheet to create Seamly documentation sites.

## Setting up your site

Some assumptions:
* You use Webpack 5.x
* You have directory from which you serve your public files. We use `public` in the examples below

In your `webpack.config.js`:

```javascript
const site = require('@seamly/doc-site/lib/config/site')

const SITE_ROOT = path.resolve(__dirname, 'public')

// Your usual webpack setup.
module.exports = function(env = {}, argv = {}) {
  const config = {}

  return site.addSiteConfig(config, {siteRoot: SITE_ROOT})
}
```

In your public folder add markdown (`.md`), HTML (`.html`) or EJS (`.ejs`) files. Add some front-matter to define what layout to use.

```markdown
---
layout: doc.ejs
toc: false
pageTitle: My page
---

# This is my page
```

Additionally you can setup a `site.conf.js` which should expose an object as in the example below. It will be used in the layout/templates.

```javascript
module.exports =  {
  // Title of the site (optional, default is name from package.json)
  title: "My Site",

  // Subtitle (optional, default is version from package.json)
  subTitle: "by me",

  // Extra items to render in the HEAD tag (optional)
  head: [
    "<script src='/lib/helpers.js'></script>"
  ],

  // The navigation tree. Can only be 2 levels deep (rest is ignored)
  // The URL in the toplevel is optional
  navigation: [
    {
      title: "Demos",
      children: [
        {
          title: "Demo 1",
          url: "/demos/demo1.html"
        },
        {
          title: "Demo 2",
          url: "/demos/demo2.html"
        },
      ],
      title: "Versions",
      url: "/versions"
    }
  ]
}
```

## The nitty gritty

### Config transformer

#### `addSiteConfig`
The `addSiteConfig` config transform will take your Webpack config as first parameter and will add the following:

* Get all `.md`, `.html` and `.ejs` files within the provided `siteRoot` matching `exclude` and `include` and add them as entries to the webpack config.
* Rules for:
  * Handling image/font files matching `exclude` and `include`
  * Handling `.scss` files within the @seamly/doc-site package (make sure you exclude them if you have another rule matching `.scss` files)
  * Handling `.html` and `.ejs` files matching `exclude` and `include`
  * Handling `.md` files matching `exclude` and `include`
* Read `package.json` and expose version, name and description to templates in the `data.pkg` key
* Read `site.conf.js` and expose it to templates in the `data.site` key

You can pass the following options:

* `siteRoot` _(String, required)_: the directory where your site resides
* `templateGlobals` _(Object)_: an object of extra properties to expose to the templates in the `data` key
* `outputName` _(String,Function)_: Function or string passed to `file-loader`
* `exclude` _(String,Array)_: Passed to webpack rules
* `include` _(String,Array)_: Passed to webpack rules

#### `htmlExtractLoaders`
Loader chain to use for processing HTML and emitting HTML to files.

#### `ejsLoaders`
Loader chain to use for processing EJS files with markdown support. Uses `htmlExtractLoaders` to emit files.

#### `markdownLoaders`
Loader chain to use for processing markdown files, will wrap with layout. Will not emit files.

#### `assetScssLoaders`
Loader chain to use for processing `.scss` Sass files to be written to file as Asset modules.

#### `styleScssLoaders`
Loader chain to use for processing `.scss` Sass files to be inlined with the style loader (the style loader is already part of this chain).

### `ejs-layout-loader.js`
This loader does 3 things:

* Optionally execute the source
* getFrontMatter and getContent to fetch the actual content and metadata
* Load a layout file if it exists (uses frontmatter.layout or options.defaultLayout if not defined)
* Generate a TOC of the content only (based on <hX> tags) if options.toc=true
* Wrap the content in the loaded layout by string replace
* Execute the content + layout as one .ejs template with:
  * data.frontMatter
  * data.toc (if generated)

Options for this loader are:

* `exec` _(boolean)_: Wether or not we should execute the module
* `contentPlaceholder` _(String)_: The replacement string to inject the content into the layout
* `layoutPath` _(Array)_: Path where to find layouts
* `globals` _(Object)_: Data to merge into top level data
* `toc` _(boolean)_: Should we generate TOC?
* `getFrontMatter` _(Function)_: What to use to extract the frontmatter
* `getContent` _(Function)_: What to use to get the content
* `defaultLayout` _(String, null)_: The defaul layout to us

### `html-url-rewrite-loader.js`
The `html-url-rewrite-loader` is a (limited) drop-in replacement for the HTML loader it will:

* require and potentially inline all img[src] attributes
* require link[rel=stylesheet][href^="~"]
* will rewrite local URL's in a[href], link[rel=stylesheet][href] and script[src]

## License
See LICENSE