Skip to content

Commit

Permalink
feat: use async/await and default grammar if not set on code section
Browse files Browse the repository at this point in the history
  • Loading branch information
Andreas Gerlach committed Apr 15, 2019
1 parent 86eae5c commit d01b00e
Showing 1 changed file with 32 additions and 28 deletions.
60 changes: 32 additions & 28 deletions lib/renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,23 @@ import { scopeForFenceName } from './utils';

const marked = require('marked');
const createDOMPurify = require('dompurify');

/**
* [domPurify description]
* safe DOM markup operations
* @type {DOMPurify}
*/
const domPurify = createDOMPurify();

/**
* [highlightCodeFragments description]
* @param {HTMLElement} domFragment [description]
* @returns {Promise}
* iterates over the content of the HTML fragment and replaces any code section
* found with an Atom TextEditor element that is used for syntax highlighting the code
*
* @param {HTMLElement} domFragment the HTML fragment to be analyzed and
* @param {String} grammar the default grammar to be used if the code section doesn't have a specific grammar set
* @return {Promise} a promise that is resolved when the fragment is ready
*/
function highlightCodeFragments(domFragment) {
const defaultLanguage = 'text';
async function highlightCodeFragments(domFragment, grammar) {
const defaultLanguage = grammar || 'text';
// set editor font family
const fontFamily = atom.config.get('editor.fontFamily');
const fontSize = atom.config.get('editor.fontSize');
Expand All @@ -28,8 +32,8 @@ function highlightCodeFragments(domFragment) {
});
}

let promises = new Array();
domFragment.querySelectorAll('pre').forEach((preElement) => {
const elements = [].slice.call(domFragment.querySelectorAll('pre'));
const promises = elements.map(async (preElement) => {
let codeBlock = preElement.firstElementChild != null ? preElement.firstElementChild : preElement;
let fenceName = codeBlock.getAttribute('class') ? codeBlock.getAttribute('class').replace(/^lang-/, '').replace(/^language-/, '') : defaultLanguage;
preElement.classList.add('editor-colors', `lang-${fenceName}`);
Expand All @@ -51,12 +55,18 @@ function highlightCodeFragments(domFragment) {

atom.grammars.assignLanguageMode(editor, scopeForFenceName(fenceName));
editor.setVisible(true);
promises.push(tokenizeEditor(editorElement, preElement));
return await tokenizeEditor(editorElement, preElement);
});

return Promise.all(promises);
return await Promise.all(promises);
}

/**
* takes an Atom TextEditor element, tokenize the content and move the resulting lines to the pre element given
* @param {HTMLElement} editorElement the HTML element containing the Atom TextEditor
* @param {HTMLPreElement} preElement the HTML pre element that should host the resulting lines
* @return {Promise} a promise that is triggered as soon as tokenization and moving the content is done
*/
function tokenizeEditor(editorElement, preElement) {
let p = new Promise((resolve, reject) => {
let done = () => {
Expand Down Expand Up @@ -84,10 +94,11 @@ function tokenizeEditor(editorElement, preElement) {
});
return p;
}

/**
* [render description]
* @param {String} markdownText [description]
* @returns {HTMLElement} node
* renders markdown to safe HTML
* @param {String} markdownText the markdown text to render
* @return {Node} the html template node containing the result
*/
function internalRender(markdownText) {
// Remove the <!doctype> since otherwise marked will escape it
Expand All @@ -102,26 +113,19 @@ function internalRender(markdownText) {

export default {
/**
* [render description]
* @param {String} requestToken
* @param {String} markdownText [description]
* @return {Promise} [description]
* renders the markdown text to html
* @param {String} markdownText the markdown text to render
* @param {String} grammar the default grammar used in code sections that have no specific grammar set
* @return {String} the inner HTML text of the rendered section
*/
render (markdownText) {
async render (markdownText, grammar) {
let node = internalRender(markdownText);
let div = document.createElement('div');
div.appendChild(node);
document.body.appendChild(div);

let result = new Promise((resolve, reject) => {
highlightCodeFragments(div).then(() => {
div.remove();
resolve(div.innerHTML);
}).catch((err) => {
console.error(err);
reject(err);
});
});
return result;
await highlightCodeFragments(div, grammar);
div.remove();
return div.innerHTML;
}
}

0 comments on commit d01b00e

Please sign in to comment.