You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

121 lines
3.9 KiB

const marked = require('marked');
const fs = require('fs');
const path = require('path');
const Prism = require('prismjs');
const PrismLanguages = require('prism-languages');
const _ = require('underscore');
const generateSidebar = require('./generateSidebar.js');
const helpers = require('./helpers');
const insertToTemplate = helpers.insertToTemplate;
const getPostMeta = helpers.getPostMeta;
const createHTML = async function createHTML(markdownFile, htmlFile, author, postMeta, rootDir) {
const guidesDir = path.resolve(rootDir, 'guides');
const markdownDir = path.resolve(rootDir, 'guides-markdown');
const templatesDir = path.resolve(rootDir, 'page-templates');
/******
Prepare the marked renderer
******/
const renderer = new marked.Renderer();
let guideTitle, guideDescription;
// Custom renderer for top two level headers
renderer.heading = (text, level) => {
let textURL = text.replace(/\(.+\)/, '').trim(); // for url remove any parentheses and their contents
textURL = textURL.replace(/[$-/:-?{-~!"^_`\[\]]/, '').replace(/ /g, '-').toLowerCase(); // and replace spaces with dashes
if (level == '1' ) {
// remove icon tag for the url
const iconCloseTagIndex = textURL.indexOf('</i>');
if (iconCloseTagIndex > -1) {
textURL = textURL.slice(iconCloseTagIndex + 4, textURL.length);
}
let header = `<h2 class="post-title panel-title" id="${textURL}">${text}</h2>`;
if (author) {
postMeta = getPostMeta(author)
header += postMeta;
}
guideTitle = text;
return header;
} else {
return `<h${level} id="${textURL}">${text}</h${level}>`;
}
}
renderer.code = function (code, language) {
if (language === 'post-author') {
// only return code block if wasn't set by argument
author = code;
return postMeta ? '' : getPostMeta(code);
}
if (language === 'post-description') {
guideDescription = code;
return '';
}
addClass = '';
if (language === 'command-line') {
addClass = 'command-line';
language = 'bash';
}
7 years ago
if (!language || !PrismLanguages)
language = 'bash';
return `<pre class="snippet line-numbers language-${language} ` + addClass + `">`
+ `<code class="line-numbers language-${language}">`
+ Prism.highlight(code, PrismLanguages[language])
+ '</code>'
+ '<button class="copy-button">'
+ '<img src="../assets/images/clippy.svg" alt="Copy to clipboard"></button>'
+ '</pre>';
}
marked.setOptions({
renderer,
gfm: true,
});
const markdownString = fs.readFileSync(markdownFile, 'utf8');
// Assemble guide text container
let blogText = marked(markdownString);
let guideText = fs.readFileSync(path.resolve(templatesDir, 'guides-template.html'))
.toString();
// these constants are comment text that mark the start
// of their respective sections in the template files
const GUIDE_START = 'START OF GUIDE'; // NOTE: Make sure to change this if the comment text changes
const SIDEBAR_START = 'START SIDEBAR';
// generate sidebar and insert into our page template
const sidebarText = await generateSidebar('guides', rootDir);
guideText = insertToTemplate(guideText, SIDEBAR_START, sidebarText);
// insert the guide text into our template
guideText = insertToTemplate(guideText, GUIDE_START, blogText);
const guideTemplate = _.template(guideText);
const postInfo = {
title: guideTitle,
author,
description: guideDescription
}
// create the html file for final output
return new Promise((resolve, reject) => {
fs.writeFile(htmlFile, guideTemplate(postInfo), {flags: 'w+'}, (err) => {
if (err) reject(err);
resolve(htmlFile)
});
})
.then((htmlFile) => console.log(`Finished ${path.basename(htmlFile)}!`));
}
module.exports = createHTML;