const fs = require("./fs_promises.js"), path = require("path"), wboPencilPoint = require("../client-data/tools/pencil/wbo_pencil_point.js").wboPencilPoint; function htmlspecialchars(str) { if (typeof str !== "string") return ""; return str.replace(/[<>&"']/g, function (c) { switch (c) { case '<': return '<'; case '>': return '>'; case '&': return '&'; case '"': return '"'; case "'": return '''; }}); } function renderPath(el, pathstring) { return ''; } const Tools = { /** * @return {string} */ "Text": function (el) { return '' + htmlspecialchars(el.txt || "") + ''; }, /** * @return {string} */ "Pencil": function (el) { if (!el._children) return ""; let pts = el._children.reduce(function (pts, point) { return wboPencilPoint(pts, point.x, point.y); }, []); const pathstring = pts.map(function (op) { return op.type + ' ' + op.values.join(' ') }).join(' '); return renderPath(el, pathstring); }, /** * @return {string} */ "Rectangle": function (el) { return ''; }, /** * @return {string} */ "Ellipse": function (el) { const cx = Math.round((el.x2 + el.x) / 2); const cy = Math.round((el.y2 + el.y) / 2); const rx = Math.abs(el.x2 - el.x) / 2; const ry = Math.abs(el.y2 - el.y) / 2; const pathstring = "M" + (cx - rx) + " " + cy + "a" + rx + "," + ry + " 0 1,0 " + (rx * 2) + ",0" + "a" + rx + "," + ry + " 0 1,0 " + (rx * -2) + ",0"; return renderPath(el, pathstring); }, /** * @return {string} */ "Straight line": function (el) { const pathstring = "M" + el.x + " " + el.y + "L" + el.x2 + " " + el.y2; return renderPath(el, pathstring); } }; /** * Writes the given board as an svg to the given writeable stream * @param {Object[string, BoardElem]} obj * @param {WritableStream} writeable */ async function toSVG(obj, writeable) { const margin = 400; const elems = Object.values(obj); const dim = elems.reduce(function (dim, elem) { return [ Math.max(elem.x + margin | 0, dim[0]), Math.max(elem.y + margin | 0, dim[1]), ] }, [margin, margin]); writeable.write( '' + '' ); await Promise.all(elems.map(async function (elem) { await Promise.resolve(); // Do not block the event loop const renderFun = Tools[elem.tool]; if (renderFun) writeable.write(renderFun(elem)); else console.warn("Missing render function for tool", elem.tool); })); writeable.write(''); } async function renderBoard(file, stream) { const data = await fs.promises.readFile(file); var board = JSON.parse(data); return toSVG(board, stream); } if (require.main === module) { const config = require("./configuration.js"); const HISTORY_FILE = process.argv[2] || path.join(config.HISTORY_DIR, "board-anonymous.json"); renderBoard(HISTORY_FILE, process.stdout) .catch(console.error.bind(console)); } else { module.exports = { 'renderBoard': renderBoard }; }