const pandoc = require('node-pandoc'); const utils = require('../utils/utils.js'); const sql = require('../utils/sql'); const argsFull = '--from markdown-markdown_in_html_blocks+raw_html --toc --toc-depth=3 -N --mathjax -t html5 --no-highlight'; const argsPreview = '--mathjax -t html5'; module.exports= { /** * Renders the entire blog post based on the sql data pulled * from the database. * * @param post sql data which has title, date, and header img location * @param blocks number of blocks to display for a preview or -1 for * all the blocks * @returns {Promise} async call which renders the entire blog post. */ generateBlogPost: function(post, blocks) { return new Promise(function(resolve, reject) { Promise.all([module.exports.generateBlogPostHeader(post), module.exports.generateBlogPostBody(post, blocks)]) .then(function() { resolve(post); }).catch(function(error) { reject(error); }) }); }, /** * Renders the header of the blog post which contains the header image, and date * published. * * @param post sql data * @returns {string} */ generateBlogPostHeader: function(post) { if(post.picture_url !== "n/a") post.hasPicture = true; post.published = post.published.toDateString(); return; }, /** * Method which renders the body of the blog post. This is responsible for getting * the contents of the markdown/latex file and rendering it into beautiful html. * * @param post stuff from the SQL table * @param blocks * @returns {Promise} */ generateBlogPostBody: function(post, blocks) { return new Promise(function(resolve, reject) { sql.getCategory(post.category_id).then(function(category) { module.exports.generateBlogPostComponent(category[0].url, post.url, blocks).then(function(html) { post.categoryURL = category[0].url; post.blogBody = html; resolve(); }); }); }) }, /** * Decomposition from Generate Blog Post used for the * blog previewer. * * @param categoryURL * @param postURL * @param blocks * @returns {Promise} */ generateBlogPostComponent: function(categoryURL, postURL, blocks) { return new Promise(function(resolve, reject) { const pathName = "content/posts/" + categoryURL + "/" + postURL + ".md"; var markDown = utils.getFileContents(pathName).toString(); markDown = markDown.split("(media/").join("(" + "../content/posts/" + categoryURL + "/media/"); module.exports.convertToHTML(markDown, blocks).then(function(result) { // hackey stuff to fix this open issue on pandoc https://github.com/jgm/pandoc/issues/3858 //search for pattern
 and replace with 
                    var re = /\
/;
                    while (result.search(re) != -1)
                    {
                        var preTag = result.match(/\
/g)[0];
                        var finishIndex = preTag.split('"', 2).join('"').length;
                        lang = preTag.substring(12, finishIndex);
                        var newHTML = `
`
                        var original = `
`;
                        result = result.split(original).join(newHTML);
                    }

                    result = result.split("
").join("
"); //this line prevents older versions of pandoc from including invalid cdm scripts result = result.split("").join(""); result = result.split("").join(""); //stuff for youtube videos var re = /\/; // while (result.search(re) != -1) { var ytid = result.substring(result.search(re) + 14, result.search(re)+ 11 + 14); var youtubeHTML = `
`; var original = ``; result = result.split(original).join(youtubeHTML); } var regExp = /\/; while (result.search(regExp) != -1) { const pathName = "content/posts/" + categoryURL + "/html/" + postURL + ".html"; var htmlContent = utils.getFileContents(pathName).toString(); result = result.split("").join(htmlContent); } if(blocks == -1) resolve(result); const htmlBlocks = result.split("

"); var html = ""; for(var i = 0; i < blocks; i++) { html += "

" + htmlBlocks[i]; } resolve(html); }).catch(function(error) { reject(error); }) }) }, /** * Converts markdown into html. * * @param markdownContents * @param type * @returns {Promise} */ convertToHTML: function(markdownContents, type) { if(type == -1) { return module.exports.pandocWrapper(markdownContents, argsFull); } else { return module.exports.pandocWrapper(markdownContents, argsFull); } }, pandocWrapper: function(markdownContents, pandocArgs) { return new Promise((resolve, reject)=> { // Set your callback function callback = function (err, html) { if (err) { reject(err); } if(html === undefined) { resolve(""); } else { html = html.split("").join(""); resolve(html); } }; pandoc(markdownContents, pandocArgs, callback); }); }, /** * Renders a bunch of blog post previews to the user * * @param baseURL-- url of the page * @param posts -- sql data about the blog to render * @param currentPage -- the current page to render * @param numOfPosts -- number of blog to render * @returns {Promise} renders the html of the blog */ renderBatchOfPosts: function(baseURL, posts, currentPage, numOfPosts, templateContext) { if(typeof currentPage == "undefined") { currentPage = 1; } else { currentPage = Number(currentPage); } return new Promise(function(resolve, reject) { const promises = []; for(var i = (currentPage-1) * numOfPosts; i < (currentPage-1) * numOfPosts + numOfPosts; i++) { if(i < posts.length) { promises.push(new Promise(function(res, rej) { module.exports.generateBlogPost(posts[i], posts.length === 1 ? -1: 3).then(function(tempContext) { if(posts.length != 1) { templateContext.preview = true } res(tempContext); }).catch(function(error) { rej(); }) })); } } Promise.all(promises).then(function(posts) { templateContext.posts = posts; if(posts.length == 1) templateContext.title = posts[0].name; else if(currentPage != 1 && baseURL === "/") templateContext.title = "page " + currentPage; resolve(); }).catch(function(error) { reject(error); }); }); } };