import { render } from "./renderer.js"; import { extendConfiguration } from "./configuration.js"; import { ImageType } from "./image_type.js"; import { StageType } from "./stage_type.js"; export { ImageType } from "./image_type.js"; export { StageType } from "./stage_type.js"; /** * @typedef {import('./configuration.js').tConfiguration} tConfiguration * @typedef {import('./image_type.js').ImageType} ImageType * @typedef {import('./stage_type.js').StageType} StageType * @typedef {import('wmap-parser').Map} ParsedMap * @typedef {import('canvas').Canvas} Canvas */ /** * Render a parsed Wardley map to a canvas element * Works in both browser and Node.js environments * * @param {ParsedMap} map - Parsed map object from wmap-parser * @param {HTMLCanvasElement|Canvas} canvas - Canvas element (browser) or Canvas instance (Node.js) * @param {StageType} [stageType=StageType.ACTIVITIES] - The labels to use for each stage in the map. * @param {tConfiguration} overrides - User configuration overrides * @returns {Promise} * * @example * // Browser * import { parse } from 'wmap-parser'; * import { renderToCanvas } from 'wmap-renderer-canvas'; * * const map = parse(wmapSource); * const canvas = document.getElementById('myCanvas'); * await renderToCanvas(map, canvas); * * @example * // Node.js * import { createCanvas } from 'canvas'; * import { parse } from 'wmap-parser'; * import { renderToCanvas } from 'wmap-renderer-canvas'; * * const map = parse(wmapSource); * const canvas = createCanvas(1384, 1084); * await renderToCanvas(map, canvas); */ export async function renderToCanvas( map, canvas, stageType = StageType.ACTIVITIES, overrides = {}, ) { if (!map) { throw new Error("Map object is required"); } if (!canvas) { throw new Error("Canvas is required"); } const configuration = extendConfiguration(overrides); const { mapWidth, mapHeight, padding } = configuration.theme.sizes; const totalWidth = mapWidth + padding * 2; const totalHeight = mapHeight + padding * 2; if (canvas.width !== totalWidth || canvas.height !== totalHeight) { canvas.width = totalWidth; canvas.height = totalHeight; } const context = canvas.getContext("2d"); await render(map, context, stageType, configuration); } /** * Render a parsed Wardley map to an image stream * Only available in Node.js environments * * @param {ParsedMap} map - Parsed map object from wmap-parser * @param {ImageType} imageType - Output image format ('png', 'jpeg', or 'pdf') * @param {StageType} [stageType=StageType.ACTIVITIES] - The labels to use for each stage in the map. * @param {tConfiguration} overrides - User configuration overrides * @returns {Promise} Stream of the rendered image * * @throws {Error} If not in Node.js environment * @throws {Error} If canvas module is not available * @throws {Error} If imageType is not supported * * @example * import { parse } from 'wmap-parser'; * import { renderToImage, ImageType } from 'wmap-renderer-canvas'; * import fs from 'fs'; * * const map = parse(wmapSource); * const stream = await renderToImage(map, ImageType.PNG); * const out = fs.createWriteStream('map.png'); * stream.pipe(out); */ export async function renderToImage( map, imageType = ImageType.PNG, stageType = StageType.ACTIVITIES, overrides = {}, ) { if (typeof window !== "undefined") { throw new Error( "renderToImage is only available in Node.js environments", ); } if (!map) { throw new Error("Map object is required"); } const validTypes = ["png", "jpeg", "pdf"]; if (!validTypes.includes(imageType)) { throw new Error( `Invalid image type. Must be one of: ${validTypes.join(", ")}`, ); } let createCanvas; try { const canvasModule = await import("canvas"); createCanvas = canvasModule.default?.createCanvas || canvasModule.createCanvas; } catch { throw new Error("canvas module is required for renderToImage."); } const configuration = extendConfiguration(overrides); const { mapWidth, mapHeight, padding } = configuration.theme.sizes; const totalWidth = mapWidth + padding * 2; const totalHeight = mapHeight + padding * 2; const canvas = imageType === "pdf" ? createCanvas(totalWidth, totalHeight, "pdf") : createCanvas(totalWidth, totalHeight); const ctx = canvas.getContext("2d"); await render(map, ctx, stageType, configuration); switch (imageType) { case "png": return canvas.createPNGStream(); case "jpeg": return canvas.createJPEGStream(); case "pdf": return canvas.createPDFStream(); default: throw new Error(`Unsupported image type: ${imageType}`); } }