UNPKG

mume-with-litvis

Version:

Fork of mume with added http://litvis.org/

332 lines 15.8 kB
"use strict"; 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" + `![${altCaption}](${displayPNGFilePath})${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" + `![${altCaption}](${displayPNGFilePath})${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 = `![](${pngFilePath}) \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