Skip to content

AsciiWriter/asciiwriter

Repository files navigation

AsciiWriter static site generator

AsciiWriter is a fork of "Dev-Mind website" Gulp scaffold (version 1.0), it uses Node.js, Asciidoctor.js and Handlebars templating engine. You can write pages with plain text using Asciidoc markup language, specifically Asciidoctor implementation. It is very similar to Markdown in spirit although it is not written in the same manner, the difference is that you don’t have to implement special helping functions to get important features. That makes Asciidoc text much more usable.

Main pages are generated with Articles slug and with minimal editing you should be able to adapt it to for your own purpose. To get familiar with Asciidoc, check out Asciidoc syntax

Target audience

AsciiWriter is for everyone who likes to write in plain text. If you appreciate Asciidoc markup, but feel that Antora is too overwhelming to use or too overkill for your project. Another goal is to be accessible even to novice Node.js users and keep the possibilities for easy modifications. Because of this AsciiWriter tries to minimize the amount of dependencies and self documenting source files. Currently the is no incremental build or preview process in AsciiWriter static site generator.

Clone using git:

git clone https://github.com/asciiwriter/asciiwriter

To create HTML files, simply run npm scripts:

npm install && npm run build

Sass styless can be generated with:

npm run default:sass

Once your pages are generated navigate to the build/docs directory and initialize git:

git init

Add and commit your changes

git add .
git commit -m  "Some changes description"

and set your upstream branch

git push --set-upstream https://github.com/<your-usename>/<your-repository> master

The aim is to use Handlebars templates and Asciidoctor.js to write dynamic pages such as articles. Several others extensions help to generate a rss file and a sitemap file.

Settings

Most of the settings are stored within gulpfile.js. If you expand the site beyond simple article writing, then you might need to change some other files as well.

Keeping the documentation up to date

To keep the documentation current AsciiWriter mirrors the source files into src/articles/code. In the root of the file system there are 2 scripts awailable to keep it synchronized, on Windows code.bat uses Robocopy to mirror files. On Linux and Unix-like systems you need install rsync to keep the files mirrored.

TODO

Create AsciiWriter styleguide included files need to have their path partially specified e.g :sass: src/sass/

Provide good templates

apply-template

apply-template extension specified in index.js (extApplyTemplate) sets the handlebar templates on a file stream. Templates are applied after read-html and read-asciidoctor extensions create the templateModel which is then sent to Handlebars where the template is used.

Example of template usage

const HANDLEBARS_PARTIALS = [
  {key: '_html_header', path: 'src/templates/_html_header.hbs'},
  {key: '_html_footer', path: 'src/templates/_html_footer.hbs'}
];

gulp.task('html-template', () =>
  gulp.src(`src/html/**/*.html`)
      .pipe(website.readHtml())
      .pipe(website.applyTemplate(`src/templates/articles.hbs`, HANDLEBARS_PARTIALS))
      .pipe(gulp.dest('build/docs')));

The templateModel has several attributes. For more details read the section about read-html or read-asciidoctor extension.

convert-to-html

Used to change Asciidoc file extension to html

Example of usage

gulp.task('articles-indexing', () =>
  gulp.src('src/articles/**/*.adoc')
      .pipe(website.readAsciidoc())
      .pipe(website.convertToHtml())
      .pipe(gulp.dest('build/.tmp'))
);

convert-to-json

Used to generate a JSON file with data read in HTML or Asciidoc file

Example of usage

gulp.task('articles-indexing', () =>
  gulp.src('src/articles/**/*.adoc')
      .pipe(website.readAsciidoc())
      .pipe(website.convertToHtml())
      .pipe(website.convertToJson('articlesindex.json'))
      .pipe(gulp.dest('build/.tmp'))
);

The example JSON file:

[
  {
      "strdate": "28/09/2018",
      "revdate": "28/09/2018",
      "doctitle": "Expérience de Guillaume EHRET",
      "description": "CV numérique de Guillaume EHRET fondateur de Dev-Mind",
      "keywords": [
        "Dev-mind",
        "Java",
        "JavaScript",
        "HTML",
        "CSS"
      ],
      "filename": "extra",
      "priority": 0.6,
      "dir": "/"
    }
    ...
]

read-index and convert-to-rss

read-index extension parses files and generates a JSON list, then convert-to-rss extension transforms this JSON list with metadata into RSS file called articles.xml:

Example in gulpfile

gulp.task('articles-rss', () =>
  gulp.src('build/.tmp/articlesindex.json')
      .pipe(website.readIndex())
      .pipe(website.convertToRss('articles.xml'))
      .pipe(gulp.dest('build/docs/rss'))
);

convert-to-sitemap

Search engines will index your static website using sitemap.xml which maps the pages of your site. convert-to-sitemap extension is used to generate sitemap.xml.

Example

gulp.task('sitemap', () =>
  gulp.src(['build/.tmp/articlesindex.json', 'build/.tmp/pageindex.json'])
      .pipe(website.readIndex())
      .pipe(website.convertToSitemap())
      .pipe(gulp.dest('build/docs'))
);

In this example Gulp takes 2 index written in Json (articlesindex and pageindex). Extension read-index helps to read them, and send them to the extension convert-to-sitemap which is able to generate the file sitemap.xml

Here’s the example for build/.tmp/articlesindex.json file:

[
  {
      "strdate": "28/09/2018",
      "revdate": "28/09/2018",
      "doctitle": "Expérience de Guillaume EHRET",
      "description": "CV numérique de Guillaume EHRET fondateur de Dev-Mind",
      "keywords": [
        "Dev-mind",
        "Java",
        "JavaScript",
        "HTML",
        "CSS"
      ],
      "filename": "extra",
      "priority": 0.6,
      "
  }
]

verify-files

verify-files extension is used to verify that the necessary files are present in your project. If some file is not available an exception is thrown that warns you about it.

verify-files extension will return true if the file exists

Example of usage

const page = path.resolve(__dirname, options.path, file.path);
if(!fileExist(page)){
  throw new PluginError('verify-files', `File ${file.path} does not exist!`);
}

Example of usage

gulp.task('check', () =>
  gulp.src([ 'build/.tmp/articlesindex.json',
             'build/.tmp/pageindex.json',
             'build/docs/rss/articles.xml',
             'build/docs/sitemap.xml'])
      .pipe(website.extVerifyFiles())
      .pipe(gulp.dest('build/check'))
);

highlight-code

highlight-code extension is used to highlight the source code defined in yours HTML pages.

Example of usage If your code is defined between these markups

<pre class="highlight">
    <code class="language-html" data-lang="java">
        // My code
    </code>
</pre>

You can use this extension like this

gulp.task('articles-page', (cb) => {
  gulp.src('src/articles/**/*.adoc')
      .pipe(website.readHtml())
      .pipe(website.highlightCode({selector: 'pre.highlight code'}))
      .pipe(gulp.dest('build/docs/articles'))
      .on('end', () => cb())
});

read-asciidoctor

read-asciidoctor extension reads a stream of asciidoc files and builds HTML pages. When there are code examples in asciidoc files, prism.js is used to highlight the language keywords.

  • a templateModel, a structure JSON used after with handlebar and

  • an indexData object is used to build an index file that is then processed by other extensions

Example of usage

gulp.task('adoc-template', () =>
  gulp.src(`src/html/**/*.html`)
      .pipe(website.readAsciidoc())
      .pipe(website.convertToHtml())
      .pipe(website.applyTemplate(`src/templates/articles.hbs`))
      .pipe(gulp.dest('build/docs')));

The JSON templateModel has these values.

  • keywords : to provided in a metadata JSON

  • title : to provided in a metadata JSON

  • description : to provided in a metadata JSON

  • contents : read from the file in the stream

  • gendate : current instant

  • filename : name of the future page

  • dir : for asciidoc you can define your page in a subdirectory (usefull for articles with a subdirectory per year, or by topic)

  • category : to regroup elements

  • teaser: little teaser to introduce the page

  • imgteaser: image to use with this teaser (used to display page articles with all articles)

  • canonicalUrl : computed from the current file path

  • modedev : read in environment variables

Pages created in AsciiWriter need to be in Asciidoc format and has to specify some metadata in their header:

:doctitle: Do your Articles yourself
:description: Comment construire le articles parfait
:keywords: Web, Articles, Asciidoc, Asciidoctor, CMS, Clever Cloud
:author: Guillaume EHRET - Dev-Mind
:revdate: 2018-01-02
:category: Web
:teaser: Début 2017, j'ai choisi de migrer mon articles de Articlesspot vers une solution personnalisée à base de Asciidoc. J'ai continué à faire évoluer mon site web pour enfin arriver à une solution qui me satisfait.
:imgteaser: ../../img/articles/2018/siteweb_00.jpg

Start of your article

In your handlebar template you can use the templateModel property values. For example

<html>
    <head>
        <title>{{ title }}</title>
    </head>
    <body>
        <h1>{{ title }}</h1>
        <p><small>{{category}}</small></p>
        {{content}}
    </body>
</html>

read-html

read-html extension reads a stream of HTML files and builds pages

  • a templateModel, a structure JSON used after with handlebar and

  • an indexData object used to build an index file used by other extensions

Example of usage

gulp.task('html-template', () =>
  gulp.src(`src/html/**/*.html`)
      .pipe(website.readHtml())
      .pipe(website.applyTemplate(`src/templates/articles.hbs`))
      .pipe(gulp.dest('build/docs')));

The JSON templateModel has these values.

  • keywords : to provided in a metadata JSON

  • title : to provided in a metadata JSON

  • description : to provided in a metadata JSON

  • contents : read from the file in the stream

  • gendate : current instant

  • canonicalUrl : computed from the current file path

  • modedev : read in environment variables

Some elements cannot be deduced. You have to provide these informations in JSON structure. By default this module read src/metadata/html.json. You can override this property in the config sent to this module

const WEBSITE_PARAMS = {
  metadata : {
    html: 'src/metadata/html.json'
  }
};
const website = require('./index')(WEBSITE_PARAMS);

This file has for example this content

{
  "404.html" : {
    "keywords": "Asciidoctor.js, Asciidoc, Node.js, Gulp, Static Site Generator",
    "title": "404 there is no page here!",
    "description" : "Page not found",
    "priority": -1
  },
  "index.html" : {
    "keywords": "Asciidoctor.js, Asciidoc, Node.js, Gulp, Static Site Generator",
    "title": "AsciiWriter - a simple static site generator that uses asciidoc file format",
    "description" : "AsciiWriter is a simple static site generator based on Asciidoctor.js, Gulp and Handlebars",
    "priority": 0.8
  }
}

In your handlebar template you can use the templateModel property values. For example:

<html>
    <head>
        <title>{{ title }}</title>
    </head>
    <body>
        <h1>{{ title }}</h1>
        {{content}}
    </body>
</html>

read-index

read-index extension is used to parse a JSON file with metadata and send the content to another extension in file stream in gulp

Example of usage

gulp.task('articles-rss', () =>
  gulp.src('build/.tmp/articlesindex.json')
      .pipe(website.readIndex())
      .pipe(website.convertToRss('articles.xml'))
      .pipe(gulp.dest('build/docs/rss'))
);

In this example Gulp takes an index written in Json and read-index helps to read the content and send it to another extension like convert-to-rss for example

convert-to-articles-list

TODO

convert-to-articles-page

TODO

Dev & prod

In production you have to activate the mode prod in environment variable. For more detail you can read http://expressjs.com/en/advanced/best-practice-performance.html#set-node_env-to-production

With systemd, use the Environment directive in your unit file. For example:

# /etc/systemd/system/myservice.service
Environment=NODE_ENV=production

If we are not in production the templateModel used in handlebar templates contains a property modeDev to true (see section about read-html or read-asciidoctor extension)

Compatibility

You have to use a

  • node version >= 10.0

  • gulp >= 4.0.0

License

AsciiWriter is released under the MIT license.