git.fiddlerwoaroof.com
Raw Blame History
'use strict';

const nodesStupidFs = require('fs');
const path = require('path');
import frontMatter from 'front-matter';
import {markdown} from 'markdown';

const ALL_ACCESS = 0o777;

export function createPrepare(fs) {

  function storeJsonData(filePath, data) {
    return writeData(filePath, JSON.stringify(data));
  }

  function writeData(filePath, data) {
    return new Promise((resolve, reject) => {
      fs.writeFile(filePath, data, function (err) {
        if (err) reject(err);
        else resolve(data)
      })
    });
  }

  function ensureDirectoryExists(directory) {
    return new Promise(function (resolve, reject) {
      const maybeCreate = err => {
        if (err) {
          fs.mkdir(directory, ALL_ACCESS, function (err) {
            if (err) reject(err);
            else resolve()
          })
        } else {
          resolve()
        }
      };
      fs.access(directory, fs.constants.F_OK, maybeCreate);
    });
  }

  function getFiles(directory) {
    return new Promise((resolve, reject) => {
      const cb = (err, data) => {
        if (err) {
          reject(err);
        }
        else {
          const qualified = data.map((p => directory + '/' + p));
          resolve(qualified);
        }
      };
      fs.readdir(directory, cb);
    });
  }

  function readFiles(files) {

    const promises = files.map((file) => new Promise((resolve, reject) => {
      const cb = (err, data) => {
        if (err) {
          reject(err);
        } else {
          resolve(data);
        }
      };
      fs.readFile(file, 'UTF-8', cb);
    }));
    return Promise.all(promises);
  }

  function fileOutputName(id, directory) {
    const regularizedDir = directory.endsWith('/') ? directory : directory + '/';

    return regularizedDir + id + '.html';
  }

  async function writeHtmlFromParsed(items, outputHtmlDir) {

    const promises = items.map(async (item) => {
      const id = item.attributes.id;
      const filePath = fileOutputName(id, outputHtmlDir);

      let contents = markdown.toHTML(item.body);
      return await writeData(filePath, contents);
    });

    return Promise.all(promises);
  }

  return async function (dataDir, pagesDir, tableOfContentsFile, outputHtmlDir) {
    await ensureDirectoryExists(dataDir);
    await ensureDirectoryExists(outputHtmlDir);

    const files = await getFiles(pagesDir);
    const filesContents = await readFiles(files);
    const parsed = filesContents.map(frontMatter);

    const data = parsed.map(item => {
      const attr = item.attributes;
      return Object.assign({
        contentsUrl: fileOutputName(attr.id, outputHtmlDir.replace('public', ''))
      }, attr);
    });

    await writeHtmlFromParsed(parsed, outputHtmlDir);

    return await storeJsonData(dataDir + '/' + tableOfContentsFile, data);
  }
}


export default function runnerBuilder() {

  const Filesystem = nodesStupidFs,
        pagesDir = 'src/pages',
        outputHtmlDir = 'public/pages',
        dataDir = 'src/data',
        pagesDataFilename = 'pages.json';

  const runnable = createPrepare(Filesystem);
  return () => runnable(dataDir, pagesDir, pagesDataFilename, outputHtmlDir);
};