mume-with-litvis
Version:
Fork of mume with added http://litvis.org/
332 lines • 15.8 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.processGraphs = void 0;
const block_attributes_1 = require("block-attributes");
const cheerio = require("cheerio");
const path = require("path");
const code_chunk_1 = require("./code-chunk");
const compute_checksum_1 = require("./lib/compute-checksum");
const magick_1 = require("./magick");
const plantumlAPI = require("./puml");
const utility_1 = require("./utility");
const vegaAPI = require("./vega");
const vegaLiteAPI = require("./vega-lite");
const viz_1 = require("./viz");
const mermaidAPI = require("./mermaid");
const wavedromAPI = require("./wavedrom");
const ditaaAPI = require("./ditaa");
function processGraphs(text, { fileDirectoryPath, projectDirectoryPath, imageDirectoryPath, imageFilePrefix, useRelativeFilePath, codeChunksData, graphsCache, imageMagickPath, mermaidTheme, addOptionsStr, plantumlServer, }) {
return __awaiter(this, void 0, void 0, function* () {
const lines = text.split("\n");
const codes = [];
let i = 0;
while (i < lines.length) {
const line = lines[i];
const trimmedLine = line.trim();
if (trimmedLine.match(/^```(.+)\"?cmd\"?[:=]/) || // code chunk
trimmedLine.match(/^```(puml|plantuml|dot|viz|mermaid|vega|vega\-lite|ditaa|wavedrom)/)) {
// graphs
const numOfSpacesAhead = line.match(/^\s*/).length;
let j = i + 1;
let content = "";
while (j < lines.length) {
if (lines[j].trim() === "```" &&
lines[j].match(/^\s*/).length === numOfSpacesAhead) {
let options = {};
let optionsStr = "";
const optionsMatch = trimmedLine.match(/\{(.+)\}$/);
if (optionsMatch) {
try {
options = (0, block_attributes_1.parseBlockAttributes)(optionsMatch[0]);
optionsStr = optionsMatch[1];
}
catch (error) {
options = {};
}
}
codes.push({
start: i,
end: j,
content,
options,
optionsStr,
});
i = j;
break;
}
content += lines[j] + "\n";
j += 1;
}
}
else if (trimmedLine.match(/^```\S/)) {
// remove {...} after ```lang
const indexOfFirstSpace = line.indexOf(" ", line.indexOf("```"));
if (indexOfFirstSpace > 0) {
lines[i] = line.slice(0, indexOfFirstSpace);
}
}
else if (!trimmedLine) {
lines[i] = " ";
}
i += 1;
}
if (!imageFilePrefix) {
imageFilePrefix =
Math.random()
.toString(36)
.substr(2, 9) + "_";
}
imageFilePrefix = imageFilePrefix.replace(/[\/&]/g, "_ss_");
imageFilePrefix = encodeURIComponent(imageFilePrefix);
let imgCount = 0;
const asyncFunctions = [];
const imagePaths = [];
let currentCodeChunk = null;
for (const key in codeChunksData) {
// get the first code chunk.
if (!codeChunksData[key].prev) {
currentCodeChunk = codeChunksData[key];
break;
}
}
/* tslint:disable-next-line:no-shadowed-variable */
function clearCodeBlock(lines, start, end) {
let s = start;
while (s <= end) {
lines[s] = "";
s += 1;
}
}
function convertSVGToPNGFile(outFileName = "", svg,
/* tslint:disable-next-line:no-shadowed-variable */
lines, start, end, modifyCodeBlock, altName, optionsStr) {
return __awaiter(this, void 0, void 0, function* () {
if (!outFileName) {
outFileName = imageFilePrefix + imgCount + ".png";
}
const pngFilePath = path.resolve(imageDirectoryPath, outFileName);
yield (0, magick_1.svgElementToPNGFile)(svg, pngFilePath, imageMagickPath);
let displayPNGFilePath;
if (useRelativeFilePath) {
displayPNGFilePath =
path.relative(fileDirectoryPath, pngFilePath) + "?" + Math.random();
}
else {
displayPNGFilePath =
"/" +
path.relative(projectDirectoryPath, pngFilePath) +
"?" +
Math.random();
}
displayPNGFilePath = displayPNGFilePath.replace(/\\/g, "/"); // fix windows path error.
imgCount++;
if (modifyCodeBlock) {
clearCodeBlock(lines, start, end);
let altCaption = altName;
if (altCaption == null) {
altCaption = "";
}
let imageOptions = "";
if (addOptionsStr) {
imageOptions = `{${optionsStr}}`;
}
lines[end] +=
"\n" + `${imageOptions} `;
}
imagePaths.push(pngFilePath);
return displayPNGFilePath;
});
}
for (const codeData of codes) {
const { start, end, content, options, optionsStr } = codeData;
const def = lines[start]
.trim()
.slice(3)
.trim();
if (options["code_block"]) {
// Do Nothing
}
else if (def.match(/^(puml|plantuml)/)) {
try {
const checksum = (0, compute_checksum_1.default)(optionsStr + content);
let svg = graphsCache[checksum];
if (!svg) {
// check whether in cache
svg = yield plantumlAPI.render(content, fileDirectoryPath, plantumlServer);
}
yield convertSVGToPNGFile(options["filename"], svg, lines, start, end, true, options["alt"], optionsStr);
}
catch (error) {
clearCodeBlock(lines, start, end);
lines[end] += `\n` + `\`\`\`\n${error}\n\`\`\` \n`;
}
}
else if (def.match(/^(viz|dot)/)) {
try {
const checksum = (0, compute_checksum_1.default)(optionsStr + content);
let svg = graphsCache[checksum];
if (!svg) {
const engine = options["engine"] || "dot";
svg = yield (0, viz_1.Viz)(content, { engine });
}
yield convertSVGToPNGFile(options["filename"], svg, lines, start, end, true, options["alt"], optionsStr);
}
catch (error) {
clearCodeBlock(lines, start, end);
lines[end] += `\n` + `\`\`\`\n${error}\n\`\`\` \n`;
}
}
else if (def.match(/^vega\-lite/)) {
// vega-lite
try {
const checksum = (0, compute_checksum_1.default)(optionsStr + content);
let svg = graphsCache[checksum];
if (!svg) {
svg = yield vegaLiteAPI.toSVG(content, fileDirectoryPath);
}
yield convertSVGToPNGFile(options["filename"], svg, lines, start, end, true, options["alt"], optionsStr);
}
catch (error) {
clearCodeBlock(lines, start, end);
lines[end] += `\n` + `\`\`\`\n${error}\n\`\`\` \n`;
}
}
else if (def.match(/^vega/)) {
// vega
try {
const checksum = (0, compute_checksum_1.default)(optionsStr + content);
let svg = graphsCache[checksum];
if (!svg) {
svg = yield vegaAPI.toSVG(content, fileDirectoryPath);
}
yield convertSVGToPNGFile(options["filename"], svg, lines, start, end, true, options["alt"], optionsStr);
}
catch (error) {
clearCodeBlock(lines, start, end);
lines[end] += `\n` + `\`\`\`\n${error}\n\`\`\` \n`;
}
}
else if (def.match(/^mermaid/)) {
// mermaid-cli Ver.8.4.8 has a bug, render in png https://github.com/mermaid-js/mermaid/issues/664
try {
const pngFilePath = path.resolve(imageDirectoryPath, imageFilePrefix + imgCount + ".png");
imgCount++;
yield mermaidAPI.mermaidToPNG(content, pngFilePath, projectDirectoryPath, mermaidTheme);
let displayPNGFilePath;
if (useRelativeFilePath) {
displayPNGFilePath =
path.relative(fileDirectoryPath, pngFilePath) + "?" + Math.random();
}
else {
displayPNGFilePath =
"/" +
path.relative(projectDirectoryPath, pngFilePath) +
"?" +
Math.random();
}
clearCodeBlock(lines, start, end);
let altCaption = options["alt"];
if (altCaption == null) {
altCaption = "";
}
let imageOptions = "";
if (addOptionsStr) {
imageOptions = `{${optionsStr}}`;
}
lines[end] +=
"\n" + `${imageOptions} `;
imagePaths.push(pngFilePath);
}
catch (error) {
clearCodeBlock(lines, start, end);
lines[end] += `\n` + `\`\`\`\n${error}\n\`\`\` \n`;
}
}
else if (def.match(/^wavedrom/)) {
try {
const checksum = (0, compute_checksum_1.default)(optionsStr + content);
let svg = graphsCache[checksum];
if (!svg) {
// check whether in cache
svg = yield wavedromAPI.render(content, projectDirectoryPath);
}
yield convertSVGToPNGFile(options["filename"], svg, lines, start, end, true, options["alt"], optionsStr);
}
catch (error) {
clearCodeBlock(lines, start, end);
lines[end] += `\n` + `\`\`\`\n${error}\n\`\`\` \n`;
}
}
else if (def.match(/^ditaa/)) {
try {
const checksum = (0, compute_checksum_1.default)(optionsStr + content);
let svg = graphsCache[checksum];
if (!svg) {
// check whether in cache
svg = yield ditaaAPI.render(content, options["args"]);
}
yield convertSVGToPNGFile(options["filename"], svg, lines, start, end, true, options["alt"], optionsStr);
}
catch (error) {
clearCodeBlock(lines, start, end);
lines[end] += `\n` + `\`\`\`\n${error}\n\`\`\` \n`;
}
}
else if (currentCodeChunk) {
// code chunk
if (currentCodeChunk.normalizedInfo.attributes["hide"]) {
// remove code block
clearCodeBlock(lines, start, end);
}
else {
// remove {...} after ```lang
const line = lines[start];
const indexOfFirstSpace = line.indexOf(" ", line.indexOf("```"));
lines[start] = line.slice(0, indexOfFirstSpace);
}
if (currentCodeChunk.result) {
// append result
let result = currentCodeChunk.result;
const attributes = currentCodeChunk.normalizedInfo.attributes;
if (attributes["output"] === "html" || attributes["matplotlib"]) {
// check svg and convert it to png
const $ = cheerio.load(currentCodeChunk.result); // xmlMode here is necessary...
const svg = $("svg");
if (svg.length === 1) {
const pngFilePath = (yield convertSVGToPNGFile(attributes["filename"], $.html("svg"), lines, start, end, false, options["alt"], optionsStr)).replace(/\\/g, "/");
result = ` \n`;
}
}
else if (((0, utility_1.extractCommandFromBlockInfo)(currentCodeChunk.normalizedInfo) || "").match(/^(la)?tex$/)) {
// for latex, need to run it again to generate svg file in currect directory.
result = yield (0, code_chunk_1.compileLaTeX)(content, fileDirectoryPath, Object.assign({}, attributes, {
latex_svg_dir: imageDirectoryPath,
}));
}
else if (currentCodeChunk.normalizedInfo.attributes["output"] === "markdown") {
result = currentCodeChunk.plainResult;
}
else if (!attributes["output"] || attributes["output"] === "text") {
result = `\n\`\`\`\n${currentCodeChunk.plainResult}\`\`\`\n`;
}
lines[end] += "\n" + result;
}
currentCodeChunk = codeChunksData[currentCodeChunk.next];
}
}
yield Promise.all(asyncFunctions);
const outputString = lines.filter((line) => line).join("\n");
return { outputString, imagePaths };
});
}
exports.processGraphs = processGraphs;
//# sourceMappingURL=process-graphs.js.map