marked-ast-crel
Version:
Using the AST generated my marked-ast create appropriate HTML elements with crel
118 lines (88 loc) • 2.44 kB
JavaScript
const crel = require('crel');
const entities = require('entities');
const languageMappings = {
js: 'javascript',
};
// lookup mappings and functions
// NOTE: the functions mutate the attr and children argument values
const lookup = {
paragraph: 'p',
link: 'a',
codeblock: 'code',
codespan: 'code',
listitem: 'li',
image: (node, attr) => {
const { href } = node;
delete attr['href'];
attr.src = href;
return 'img';
},
blockquote: (node, attr, children) => {
node.quote.forEach(function (item) {
children.push(item);
});
},
list: (node, attr, children) => {
node.body.forEach(function (item) {
children.push(item);
});
return node.ordered ? 'ol' : 'ul';
},
heading: node => `h${node.level}`,
code: (node, attr, children) => {
const lang = node.lang || '';
children.push({
class: 'hljs' + (lang ? ' ' + (languageMappings[lang] || lang) : ''),
type: 'codeblock',
text: node.code,
});
return 'pre';
},
};
const IGNORE_KEYS = ['type', 'text', 'code', 'body', 'ordered'];
/**
# marked-ast-crel
Using the AST generated by [marked-ast](https://github.com/pdubroy/marked-ast)
create HTML elements using [crel](https://github.com/KoryNunn/crel). Saves
doing any nasty `innerHTML` like things...
## Example Usage
Simple example:
```
npm run simple
```
<<< examples/simple.js
A little more complex (uses `brfs`):
```
npm run complex
```
<<< examples/complex.js
**/
const createNode = input => {
let attr = {};
if (Array.isArray(input)) {
return input.map(createNode);
}
// if we have a string for the node, pass through
if (typeof input == 'string' || input instanceof String) {
return entities.decodeHTML(input);
}
// if we have string node text, then encapsulate as an array
if (typeof input.text == 'string' || input.text instanceof String) {
input.text = [entities.decodeHTML(input.text)];
}
Object.keys(input).forEach(key => {
if (IGNORE_KEYS.indexOf(key) >= 0) {
return;
}
if (input[key]) {
attr[key] = input[key];
}
});
const children = input.text || [];
let tagName = lookup[input.type] || input.type;
if (typeof tagName == 'function') {
tagName = tagName(input, attr, children) || input.type;
}
return crel.apply(null, [tagName, attr].concat(children.map(createNode)));
};
module.exports = createNode;