Publican configuration options

2,210 words, 12-minute read

The following options can be set your publican.config.js configuration file to control how the static site is generated. The examples below presume you have defined a Publican object named publican at the top of the file:

publican.config.js excerpt

const publican = new Publican();

Directories #

The default Publican directories are:

You can change these as required:

publican.config.js excerpt

// change directories
publican.config.dir.content = './content/';
publican.config.dir.template = './templates/';
publican.config.dir.build = './mysite/';

Avoid setting the content directory as a sub-directory of template or vice versa.

Ignored content files #

config.ignoreContentFile can be set to regular expression so Publican ignores files with specific names. The default (/^_.*$/) omits any content file where the file name starts with an underscore _. You can remove this restriction:

publican.config.js excerpt

// do not ignore any file
publican.config.ignoreContentFile = null;

or add your own, e.g.

publican.config.js excerpt

// ignore files starting with a .
publican.config.ignoreContentFile = `/^\..*$/`;

Slug string replacement #

You can define any number of slug search and replace values in the publican.config.slugReplace Map object. Search values can be strings or regular expressions.

The following example removes two or more digits followed by an underscore and changes .html extensions to .htm:

publican.config.js excerpt

// slug replacement - removes NN_
publican.config.slugReplace.set(/\d{2,}_/g, '');

// slug replacement - rename .html to .htm
publican.config.slugReplace.set('.html', '.htm');

Front matter delimiter #

By default, Publican identifies front matter between --- delimiters, but you can change it to any other value, e.g.

publican.config.js excerpt

// locate front matter using this delimiter
publican.config.frontmatterDelimit = '~~~';

Root server path #

By default, Publican assumes the build directory is the root path of your website. The page rendered to build/index.html is therefore the home page of the site.

publican.config.js excerpt

// root path
publican.config.root = '/';

However, you may want to build files to a sub-directory of your site, e.g. /blog/. Each post’s data.link would then be incorrect.

The site’s root path can be set by changing the config.root value:

publican.config.js excerpt

// root path
publican.config.root = '/blog/';

Links to the root page would then become /blog/ rather than /.

You could set this option for the live production site but retain / in development:

const isDev = (process.env.NODE_ENV === 'development');
publican.config.root = isDev ? '/' : '/blog/';

All links, navigation, and pagination properties use the root as appropriate. If you want to link to a page in your content, you can use:

<p><a href="${ tacs.root }post/article-one/">link to Article one</a></p>

The ${ tacs.root } value cannot be used in markdown because it confuses the parser:

<!-- this will fail in markdown -->
[link to Article one](${ tacs.root }post/article-one/)

You can solve this using a root link search and replace.

Indexing frequency #

An index value can be set in front matter to a value used by search engine sitemaps: always, hourly, daily, weekly, monthly (the default), yearly, and never. You can also set false to omit the page from sitemaps.

Set publican.config.indexFrequency to a default value which applies to every page where index is not explicitly set.

Default template #

The default HTML template is default.html in the template directory. You can set publican.config.defaultHTMLTemplate to any other filename.

Markdown to HTML #

Publican converts markdown to HTML using markdown-it with the markdown-it-prism plugin to syntax-highlight code blocks.

By default, publican.config.markdownOptions defines an object with the child objects:

You can change the defaults from:

publican.config.js excerpt

 // markdown options
publican.config.markdownOptions = {
  core: {
    html: true,                 // permit HTML tags
    breaks: false,              // do not convert line breaks to <br>
    linkify: true,              // convert URLs to links
    typographer: true           // enable smart quotes
  },
  prism: {
    defaultLanguage: 'js',      // default syntax
    highlightInlineCode: true   // highlight inline code
  }
};

Content sub-headings (<h2> to <h6>) are automatically given id attributes so they are available as link targets and can be shown in an in-page menu. The publican.config.headingAnchor object controls how headings are rendered. You can set it to false (or any falsy value) to disable heading links or define your own values. The defaults are:

publican.config.js excerpt

// omit link from heading
publican.config.headingAnchor.nolink = 'nolink';

// text in heading link
publican.config.headingAnchor.linkContent = '#';

// heading link class for CSS
publican.config.headingAnchor.linkClass = 'headlink';

Example 1. A basic heading such as:

<h2>My heading</h2>

is transformed to (carriage returns added for clarity):

<h2 id="my-heading" tabindex="-1">
  My heading
  <a href="#my-heading" class="headlink">#</a>
</h2>

Example 2. Headings retain their IDs when transformed so:

<h2 id="myh2">My heading</h2>

is transformed to:

<h2 id="myh2" tabindex="-1">
  My heading
  <a href="#myh2" class="headlink">#</a>
</h2>

Example 3. Headings with nolink somewhere in the tag do not have a # link added. This is useful when a heading is inside a link:

<h2 class="nolink">My heading</h2>
<!-- OR -->
<h2 data-nolink>My heading</h2>

is transformed to:

<h2 id="my-heading" tabindex="-1" class="nolink">My heading</h2>

In-page navigation #

The code <nav-heading></nav-heading> can be placed in any content or template file. The page’s nested headings links (<h2> to <h6>) are rendered into the block, e.g.

<nav-heading>
  <nav class="contents">
    <ol>
      <li>
        <a href="#heading-2a" class="head-h2">Heading 2a</a>
        <ol>
          <li><a href="#heading-3a" class="head-h3">Heading 3a</a></li>
          <li><a href="#heading-3b" class="head-h3">Heading 3b</a></li>
        </ol>
      </li>
      <li><a href="#heading-2b" class="head-h2">Heading 2b</a><li>
    </ol>
  </nav>
</nav-heading>

Additional publican.config.headingAnchor properties control the options:

publican.config.js excerpt

// omit heading from menu
publican.config.headingAnchor.nomenu = 'nomenu';

// the tag name: <nav-heading></nav-heading>
publican.config.headingAnchor.tag = 'nav-heading';

// the class assigned to the parent <nav>
publican.config.headingAnchor.navClass = 'contents';

Headings with nomenu somewhere in the tag are omitted from the menu. For example, the following headings:

<h2 class="nomenu">Heading 1</h2>
<h2 class="nolink">Heading 2</h2>
<h2 data-nolink-nomenu>Heading 3</h2>

are transformed to:

<h2 id="heading1" tabindex="-1" class="nomenu">Heading 1 <a href="#heading1" class="headlink">#</a></h2>
<h2 id="heading2" tabindex="-1" class="nolink">Heading 2</h2>
<h2 data-nolink-nomenu>Heading 3</h2>

and the <nav-heading> block only shows Heading 2:

<nav-heading>
  <nav class="contents">
    <ol>
      <li><a href="#heading2" class="head-h2">Heading 2</a><li>
    </ol>
  </nav>
</nav-heading>

String replacement #

You can search and replace strings in the final built files using the publican.config.replace Map in your publican.config.js configuration file. (Note that pass-through files are ignored.)

publican.config.replace.set(<search>, <replace>);

where:

You can set as many search and replace options as you like, e.g.

publican.config.js excerpt

// replace YYYY-MM-DD dates with DD-MM-YYYY
publican.config.replace.set(
  /(\d{4})-(\d{2})-(\d{2})/g,
  '$3-$2-$1'
);

// replace −−COPYRIGHT−− with ©YYYY
publican.config.replace.set(
  '−−COPYRIGHT−−',
  `&copy;${ (new Date()).getUTCFullYear() }`
);

Refer to the string replacement page for more examples and alternative options.

Directory index pages #

Publican presumes directories in the root ./src/content/ directory contains specific types of content and generates paginated index pages. The publican.config.dirPages controls how these are generated using the following defaults you can override:

publican.config.js excerpt

// directory index pages
publican.config.dirPages = {
  size: 24,                   // number of items per paginated page
  sortBy: 'priority',         // sort by priority order
  sortOrder: -1,              // from highest to lowest
  template: 'default.html',   // using this template
  dir: {}                     // with no exceptions
};

You could order directories (and menus) by filename (each starts with digits NN_) from lowest to highest and only show six items per paginated page:

publican.config.js excerpt

publican.config.dirPages.size = 6;
publican.config.dirPages.sortBy = 'filename';
publican.config.dirPages.sortOrder = 1;

However, you still want content in the posts directory is ordered chronologically with the most recent first, so an exception is specified:

publican.config.js excerpt

publican.config.dirPages.dir.post = {
  sortBy: 'date',
  sortOrder: -1
};

Pages inside directories have the following properties:

Any template used by a directory index can access a data.pagination object to generate lists of pages.

Setting publican.config.dirPages to false (or any falsy value) disables directory index pages.

Tag index pages #

Content front matter can specify tags to identify specific topics. Publican generates paginated index pages for all tags. The publican.config.tagPages controls how these are generated using the following defaults you can override:

publican.config.js excerpt

// tag index pages
publican.config.tagPages = {
  root: 'tag',                // root tag directory
  size: 24,                   // number of items per paginated page
  sortBy: 'date',             // sort by date order
  sortOrder: -1,              // from most to least recent
  template: 'default.html',   // using this template
  menu: false,                // do not show tag on the menu
  index: 'monthly'            // index tag pages monthly
};

Any template used by a tag index can access a data.pagination object to generate lists of pages.

Setting publican.config.tagPages to false (or any falsy value) disables tag index pages.

Note that a root tag/index.html page is not automatically created. You can create a tag index page to output all tags using the tacs.tagList object.

HTML minification #

Publican minifies HTML using html-minifier. By default, publican.config.minify defines an object with the following html-minifier options which you can change or add further options:

publican.config.js excerpt

// tag index pages
publican.config.minify = {
  enabled: false,                     // minification not enabled
  collapseBooleanAttributes: true,    // remove boolean attribute values
  collapseWhitespace: true,           // collapse white space
  decodeEntities: false,              // use Unicode characters when available
  minifyCSS: true,                    // minify inline CSS
  minifyJS: true,                     // minify inline JS
  preventAttributesEscaping: false,   // prevent attribute escaping
  removeAttributeQuotes: true,        // remove attribute quotes
  removeComments: true,               // remove comments
  removeEmptyAttributes: true,        // remove empty attributes
  removeRedundantAttributes: true,    // remove redundant attributes
  removeScriptTypeAttributes: true,   // remove type="text/javascript"
  removeStyleLinkTypeAttributes: true,// remove type="text/css"
  useShortDoctype: true               // use the short HTML5 doctype
};

You can set your configuration to only minify production builds, e.g.

publican.config.js excerpt

// minify in production mode only
const isDev = (process.env.NODE_ENV === 'development');
publican.config.minify.enabled = !isDev;

Pass through files #

It’s sometimes necessary to copy files to the build directory that require no further processing by Publican, e.g. CSS, JavaScript, fonts, images, videos, etc. This can be implemented in your publican.config.js configuration file by adding an object to the .config.passThrough Set with .from and .to properties:

publican.config.passThrough.add({ from: <src>, to: <dest> });

where:

Publican recursively copies all files and sub-directories of the source to the destination.

publican.config.js excerpt

// copy ./src/media/favicons/**/* to ./build/
publican.config.passThrough.add({ from: './src/media/favicons', to: './' });

// copy ./src/media/images/**/* to ./build/images/
publican.config.passThrough.add({ from: './src/media/images', to: './images/' });

// copy ./src/css/**/* to ./build/css/
publican.config.passThrough.add({ from: './src/css', to: './css/' });

// copy ./src/js/**/* to ./build/js/
publican.config.passThrough.add({ from: './src/js', to: './js/' });

Event functions #

Functions can be defined in your configuration file that are called when specific events occur at build time. The functions can inspect, add, alter, or remove data.

Refer to event functions for details.

Watch mode #

Setting publican.config.watch to true (or any truthy value) watches for file changes and rebuilds the site. This is normally done in development mode only:

publican.config.js excerpt

// watch in development mode only
const isDev = (process.env.NODE_ENV === 'development');
publican.config.watch = isDev;

By default, Publican waits at least 300 milliseconds to ensure no further files are saved. This can be changed:

publican.config.js excerpt

// debounce watch for 1 second
publican.config.watchDebounce = 1000;

A shorter watchDebounce can negatively affect performance because multiple rebuilds are triggered for multiple file changes.

Press Ctrl | Cmd + C to stop Publican running.

Logging verbosity #

Set publican.config.logLevel to an integer: