Skip to content

Instantly share code, notes, and snippets.

@rheinardkorf
Last active September 22, 2020 06:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rheinardkorf/95588360a25b516b528348d7f761e99d to your computer and use it in GitHub Desktop.
Save rheinardkorf/95588360a25b516b528348d7f761e99d to your computer and use it in GitHub Desktop.
Alternate Remark-Mermaid Plugin
{
"sequence":{
"diagramMarginY" :10,
"diagramMarginX" :50,
"actorMargin" :50,
"width" :150,
"height" :65,
"boxMargin" :10,
"boxTextMargin" :5,
"noteMargin" :10,
"messageMargin" :35,
"messageAlign" :"center",
"mirrorActors" :false,
"bottomMarginAdj" :1,
"useMaxWidth" :true,
"rightAngles" :false,
"showSequenceNumbers" :false
}
}
{
"plugins": {
"./remark-mermaid-alt.js": {
"destination": "./docs/images",
"linkRoot": "./images/",
"mermaidArgs": {
"configFile": ".mermaidrc"
}
}
}
}
const crypto = require( 'crypto' );
const fs = require( 'fs-extra' );
const path = require( 'path' );
const visit = require( 'unist-util-visit' );
const { execSync } = require( 'child_process' );
const mmdc = require.resolve( '@mermaid-js/mermaid-cli/index.bundle.js' );
const PLUGIN_NAME = 'remark-mermaid-alt';
async function generateSVG( value, file, options ) {
const { destination = './images', mermaidArgs = {} } = options;
// Unique paths.
const unique = crypto
.createHmac( 'sha1', PLUGIN_NAME )
.update( value )
.digest( 'hex' );
const inputFile = `${ unique }.mmd`;
const mmdPath = path.join( destination, inputFile );
const outputFile = `${ unique }.svg`;
const svgPath = path.join( destination, outputFile );
// Args for CLI.
mermaidArgs.input = mmdPath;
mermaidArgs.output = svgPath;
const args = []
.concat(
...Object.keys( mermaidArgs ).map( ( k ) => [
`--${ k }`,
mermaidArgs[ k ],
] )
)
.join( ' ' );
// Write temp file.
fs.outputFileSync( mmdPath, value, { encoding: 'utf8' } );
// Execute mermaid.
execSync( `${ mmdc } ${ args }` );
// Clean up.
fs.removeSync( mmdPath );
return `${ outputFile }`;
}
async function transformMermaidNode( node, file, index, parent, options ) {
const { lang, value, position } = node;
try {
const { linkRoot = './' } = options;
const svgFile = await generateSVG( value, file, options );
const message = `${ lang } code block replaced with rendered mermaid SVG`;
file.info( message, position, PLUGIN_NAME );
const newNode = {
type: 'image',
title: '`mermaid` image',
url: `${ linkRoot }${ svgFile }`,
};
parent.children.splice( index, 1, newNode );
} catch ( error ) {
file.fail( error, position, PLUGIN_NAME );
}
return node;
}
/**
* Remark plugin that converts mermaid codeblocks into SVG files.
*
* @param {Object} options
*/
function mermaid( options = {} ) {
/**
* Look for all code nodes that have the language mermaid,
* generate SVGs and update the url.
*
* @param {Node} ast The Markdown Tree
* @param {Object} file The virtual file.
* @return {Promise<void>} The altered tree.
*/
return async function ( ast, file ) {
const promises = []; // keep track of promises since visit isn't async
visit( ast, 'code', ( node, index, parent ) => {
// If this codeblock is not mermaid, bail.
if ( node.lang !== 'mermaid' ) {
return node;
}
promises.push(
transformMermaidNode( node, file, index, parent, options )
);
} );
await Promise.all( promises );
};
}
module.exports = mermaid;
@rheinardkorf
Copy link
Author

Maybe turn into a package. Not a priority at this present time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment