diff options
Diffstat (limited to 'src/index.js')
| -rw-r--r-- | src/index.js | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..2a58ad5 --- /dev/null +++ b/src/index.js @@ -0,0 +1,153 @@ +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<void>} + * + * @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>} 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}`); + } +} |