@swiftlysingh/excalidraw-cli 1.0.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/README.md +77 -2
  2. package/dist/cli.d.ts +1 -1
  3. package/dist/cli.js +104 -15
  4. package/dist/cli.js.map +1 -1
  5. package/dist/exporter/dom-polyfill.d.ts +25 -0
  6. package/dist/exporter/dom-polyfill.d.ts.map +1 -0
  7. package/dist/exporter/dom-polyfill.js +220 -0
  8. package/dist/exporter/dom-polyfill.js.map +1 -0
  9. package/dist/exporter/image-exporter.d.ts +87 -0
  10. package/dist/exporter/image-exporter.d.ts.map +1 -0
  11. package/dist/exporter/image-exporter.js +188 -0
  12. package/dist/exporter/image-exporter.js.map +1 -0
  13. package/dist/exporter/index.d.ts +6 -0
  14. package/dist/exporter/index.d.ts.map +1 -0
  15. package/dist/exporter/index.js +5 -0
  16. package/dist/exporter/index.js.map +1 -0
  17. package/dist/factory/connection-factory.js +12 -8
  18. package/dist/factory/connection-factory.js.map +1 -1
  19. package/dist/factory/image-factory.d.ts +38 -0
  20. package/dist/factory/image-factory.d.ts.map +1 -0
  21. package/dist/factory/image-factory.js +172 -0
  22. package/dist/factory/image-factory.js.map +1 -0
  23. package/dist/factory/index.d.ts +1 -0
  24. package/dist/factory/index.d.ts.map +1 -1
  25. package/dist/factory/index.js +1 -0
  26. package/dist/factory/index.js.map +1 -1
  27. package/dist/factory/node-factory.js +16 -9
  28. package/dist/factory/node-factory.js.map +1 -1
  29. package/dist/factory/text-factory.d.ts +1 -0
  30. package/dist/factory/text-factory.d.ts.map +1 -1
  31. package/dist/factory/text-factory.js +1 -0
  32. package/dist/factory/text-factory.js.map +1 -1
  33. package/dist/generator/excalidraw-generator.d.ts.map +1 -1
  34. package/dist/generator/excalidraw-generator.js +100 -29
  35. package/dist/generator/excalidraw-generator.js.map +1 -1
  36. package/dist/index.d.ts +4 -1
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js +14 -8
  39. package/dist/index.js.map +1 -1
  40. package/dist/layout/elk-layout.d.ts +8 -1
  41. package/dist/layout/elk-layout.d.ts.map +1 -1
  42. package/dist/layout/elk-layout.js +99 -3
  43. package/dist/layout/elk-layout.js.map +1 -1
  44. package/dist/layout/index.d.ts +1 -1
  45. package/dist/layout/index.d.ts.map +1 -1
  46. package/dist/layout/index.js +1 -1
  47. package/dist/layout/index.js.map +1 -1
  48. package/dist/parser/dot-parser.d.ts +23 -0
  49. package/dist/parser/dot-parser.d.ts.map +1 -0
  50. package/dist/parser/dot-parser.js +277 -0
  51. package/dist/parser/dot-parser.js.map +1 -0
  52. package/dist/parser/dsl-parser.d.ts +10 -0
  53. package/dist/parser/dsl-parser.d.ts.map +1 -1
  54. package/dist/parser/dsl-parser.js +214 -8
  55. package/dist/parser/dsl-parser.js.map +1 -1
  56. package/dist/parser/index.d.ts +1 -0
  57. package/dist/parser/index.d.ts.map +1 -1
  58. package/dist/parser/index.js +1 -0
  59. package/dist/parser/index.js.map +1 -1
  60. package/dist/parser/json-parser.js +1 -1
  61. package/dist/parser/json-parser.js.map +1 -1
  62. package/dist/types/dsl.d.ts +68 -1
  63. package/dist/types/dsl.d.ts.map +1 -1
  64. package/dist/types/dsl.js.map +1 -1
  65. package/dist/types/excalidraw.d.ts +22 -3
  66. package/dist/types/excalidraw.d.ts.map +1 -1
  67. package/dist/types/excalidraw.js.map +1 -1
  68. package/man/excalidraw-cli.1 +399 -0
  69. package/package.json +13 -4
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Image Exporter
3
+ *
4
+ * Exports Excalidraw files to SVG and PNG image formats.
5
+ * Keeps `@excalidraw/utils` because it is still required for:
6
+ * - `exportToSvg()` during SVG generation
7
+ * - bundled font assets used by server-side SVG/PNG text rendering
8
+ *
9
+ * PNG export rasterizes the generated SVG with `@resvg/resvg-js`.
10
+ */
11
+ import type { ExcalidrawFile } from '../types/excalidraw.js';
12
+ /**
13
+ * Export options matching Excalidraw website capabilities
14
+ */
15
+ export interface ExportOptions {
16
+ /** Output format: 'svg' or 'png' */
17
+ format: 'svg' | 'png';
18
+ /** Whether to include the background in the export (default: true) */
19
+ exportBackground?: boolean;
20
+ /** Background color (default: from appState or '#ffffff') */
21
+ viewBackgroundColor?: string;
22
+ /** Export with dark mode (default: false) */
23
+ dark?: boolean;
24
+ /** Embed scene data into the exported image (default: false) */
25
+ exportEmbedScene?: boolean;
26
+ /** Padding around the exported content in pixels (default: 10) */
27
+ padding?: number;
28
+ /** Scale factor for PNG export (default: 1). Higher values = higher resolution */
29
+ scale?: number;
30
+ }
31
+ /**
32
+ * Default export options
33
+ */
34
+ export declare const DEFAULT_EXPORT_OPTIONS: Required<ExportOptions>;
35
+ /**
36
+ * Convert an Excalidraw file to an SVG string.
37
+ *
38
+ * Internally initialises the DOM polyfill (if not already done) and
39
+ * delegates to `@excalidraw/utils.exportToSvg` for the actual rendering.
40
+ * Console noise from font / Path2D warnings is suppressed during the call.
41
+ *
42
+ * @param file - The Excalidraw file to convert.
43
+ * @param options - Optional overrides for background, dark-mode, padding, etc.
44
+ * @returns The rendered SVG markup as a string.
45
+ */
46
+ export declare function convertToSVG(file: ExcalidrawFile, options?: Partial<ExportOptions>): Promise<string>;
47
+ /**
48
+ * Convert an Excalidraw file to a PNG image buffer.
49
+ *
50
+ * Pipeline: Excalidraw → SVG (via {@link convertToSVG}) → PNG (via resvg-js).
51
+ * The `scale` option controls the output resolution.
52
+ *
53
+ * Font rendering note: `@resvg/resvg-js` ignores `@font-face` CSS inside the
54
+ * SVG, so bundled TTF font files are provided through the `fontDirs` option.
55
+ *
56
+ * @param file - The Excalidraw file to convert.
57
+ * @param options - Optional overrides for scale, background, dark-mode, etc.
58
+ * @returns A Buffer containing the PNG image data.
59
+ */
60
+ export declare function convertToPNG(file: ExcalidrawFile, options?: Partial<ExportOptions>): Promise<Buffer>;
61
+ /**
62
+ * Convert an Excalidraw file to the specified image format.
63
+ *
64
+ * This is the main entry-point that routes to {@link convertToSVG} or
65
+ * {@link convertToPNG} based on `options.format`.
66
+ *
67
+ * @param file - The Excalidraw file to convert.
68
+ * @param options - Export options; `format` is required (`'svg'` | `'png'`).
69
+ * @returns An SVG string when `format` is `'svg'`, or a PNG `Buffer` when `'png'`.
70
+ */
71
+ export declare function convertImage(file: ExcalidrawFile, options: ExportOptions): Promise<string | Buffer>;
72
+ /**
73
+ * Replace a file path's extension with a new one.
74
+ *
75
+ * If the path has no extension (no dot, or dot at position 0 like `.gitignore`),
76
+ * the new extension is appended instead.
77
+ *
78
+ * @param filePath - The original file path (may include directories).
79
+ * @param newExt - The new extension **without** the leading dot (e.g. `'svg'`).
80
+ * @returns The file path with its extension swapped.
81
+ *
82
+ * @example
83
+ * swapExtension('diagram.excalidraw', 'png') // → 'diagram.png'
84
+ * swapExtension('/tmp/out.json', 'svg') // → '/tmp/out.svg'
85
+ */
86
+ export declare function swapExtension(filePath: string, newExt: string): string;
87
+ //# sourceMappingURL=image-exporter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image-exporter.d.ts","sourceRoot":"","sources":["../../src/exporter/image-exporter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAE7D;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,oCAAoC;IACpC,MAAM,EAAE,KAAK,GAAG,KAAK,CAAC;IAEtB,sEAAsE;IACtE,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAE3B,6DAA6D;IAC7D,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAE7B,6CAA6C;IAC7C,IAAI,CAAC,EAAE,OAAO,CAAC;IAEf,gEAAgE;IAChE,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAE3B,kEAAkE;IAClE,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,kFAAkF;IAClF,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,eAAO,MAAM,sBAAsB,EAAE,QAAQ,CAAC,aAAa,CAQ1D,CAAC;AA6BF;;;;;;;;;;GAUG;AACH,wBAAsB,YAAY,CAChC,IAAI,EAAE,cAAc,EACpB,OAAO,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,GAC/B,OAAO,CAAC,MAAM,CAAC,CAGjB;AAeD;;;;;;;;;;;;GAYG;AACH,wBAAsB,YAAY,CAChC,IAAI,EAAE,cAAc,EACpB,OAAO,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,GAC/B,OAAO,CAAC,MAAM,CAAC,CAqCjB;AAED;;;;;;;;;GASG;AACH,wBAAsB,YAAY,CAChC,IAAI,EAAE,cAAc,EACpB,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC,CAK1B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAGtE"}
@@ -0,0 +1,188 @@
1
+ /**
2
+ * Image Exporter
3
+ *
4
+ * Exports Excalidraw files to SVG and PNG image formats.
5
+ * Keeps `@excalidraw/utils` because it is still required for:
6
+ * - `exportToSvg()` during SVG generation
7
+ * - bundled font assets used by server-side SVG/PNG text rendering
8
+ *
9
+ * PNG export rasterizes the generated SVG with `@resvg/resvg-js`.
10
+ */
11
+ import { parse, format } from 'node:path';
12
+ import { withDOMPolyfill, getExcalidrawAssetDir } from './dom-polyfill.js';
13
+ /**
14
+ * Default export options
15
+ */
16
+ export const DEFAULT_EXPORT_OPTIONS = {
17
+ format: 'svg',
18
+ exportBackground: true,
19
+ viewBackgroundColor: '#ffffff',
20
+ dark: false,
21
+ exportEmbedScene: false,
22
+ padding: 10,
23
+ scale: 1,
24
+ };
25
+ /**
26
+ * Merge user options with defaults, applying appState values where appropriate.
27
+ *
28
+ * Priority order (highest → lowest):
29
+ * 1. Explicitly provided options
30
+ * 2. Values from the file's `appState` (e.g. `viewBackgroundColor`)
31
+ * 3. `DEFAULT_EXPORT_OPTIONS`
32
+ *
33
+ * @param file - The Excalidraw file whose `appState` supplies fallback values.
34
+ * @param options - Partial options supplied by the caller.
35
+ * @returns Fully-resolved options with every field populated.
36
+ */
37
+ function resolveOptions(file, options) {
38
+ return {
39
+ ...DEFAULT_EXPORT_OPTIONS,
40
+ ...options,
41
+ // Use appState background color if available
42
+ viewBackgroundColor: options.viewBackgroundColor ??
43
+ file.appState?.viewBackgroundColor ??
44
+ DEFAULT_EXPORT_OPTIONS.viewBackgroundColor,
45
+ };
46
+ }
47
+ /**
48
+ * Convert an Excalidraw file to an SVG string.
49
+ *
50
+ * Internally initialises the DOM polyfill (if not already done) and
51
+ * delegates to `@excalidraw/utils.exportToSvg` for the actual rendering.
52
+ * Console noise from font / Path2D warnings is suppressed during the call.
53
+ *
54
+ * @param file - The Excalidraw file to convert.
55
+ * @param options - Optional overrides for background, dark-mode, padding, etc.
56
+ * @returns The rendered SVG markup as a string.
57
+ */
58
+ export async function convertToSVG(file, options) {
59
+ const opts = resolveOptions(file, { format: 'svg', ...options });
60
+ return withExporterRuntime(() => renderSvg(file, opts));
61
+ }
62
+ /**
63
+ * Get the directory containing @excalidraw/utils bundled font assets (TTF files).
64
+ *
65
+ * These are needed by resvg-js for text rendering since it doesn't
66
+ * parse `@font-face` CSS from SVG — fonts must be provided via `fontDirs`.
67
+ * The result is cached after the first call.
68
+ *
69
+ * @returns Absolute path to the assets directory.
70
+ */
71
+ function getExcalidrawFontDir() {
72
+ return getExcalidrawAssetDir();
73
+ }
74
+ /**
75
+ * Convert an Excalidraw file to a PNG image buffer.
76
+ *
77
+ * Pipeline: Excalidraw → SVG (via {@link convertToSVG}) → PNG (via resvg-js).
78
+ * The `scale` option controls the output resolution.
79
+ *
80
+ * Font rendering note: `@resvg/resvg-js` ignores `@font-face` CSS inside the
81
+ * SVG, so bundled TTF font files are provided through the `fontDirs` option.
82
+ *
83
+ * @param file - The Excalidraw file to convert.
84
+ * @param options - Optional overrides for scale, background, dark-mode, etc.
85
+ * @returns A Buffer containing the PNG image data.
86
+ */
87
+ export async function convertToPNG(file, options) {
88
+ const opts = resolveOptions(file, { format: 'png', ...options });
89
+ return withExporterRuntime(async () => {
90
+ const svgString = await renderSvg(file, opts);
91
+ const { Resvg } = await import('@resvg/resvg-js');
92
+ const widthMatch = svgString.match(/width="([^"]+)"/);
93
+ const naturalWidth = widthMatch ? parseFloat(widthMatch[1]) : 800;
94
+ const scale = typeof opts.scale === 'number' && Number.isFinite(opts.scale)
95
+ ? opts.scale
96
+ : 1;
97
+ const safeScale = Math.min(Math.max(scale, 0.1), 10);
98
+ const scaledWidth = Math.max(1, Math.round(naturalWidth * safeScale));
99
+ // resvg-js does not parse @font-face declarations from the SVG, so we
100
+ // still need the packaged Excalidraw font files to keep text rendering sane.
101
+ const fontDir = getExcalidrawFontDir();
102
+ const resvg = new Resvg(svgString, {
103
+ fitTo: {
104
+ mode: 'width',
105
+ value: scaledWidth,
106
+ },
107
+ background: opts.exportBackground ? opts.viewBackgroundColor : undefined,
108
+ font: {
109
+ loadSystemFonts: false,
110
+ fontDirs: [fontDir],
111
+ },
112
+ });
113
+ const pngData = resvg.render();
114
+ const pngBuffer = pngData.asPng();
115
+ return Buffer.from(pngBuffer);
116
+ });
117
+ }
118
+ /**
119
+ * Convert an Excalidraw file to the specified image format.
120
+ *
121
+ * This is the main entry-point that routes to {@link convertToSVG} or
122
+ * {@link convertToPNG} based on `options.format`.
123
+ *
124
+ * @param file - The Excalidraw file to convert.
125
+ * @param options - Export options; `format` is required (`'svg'` | `'png'`).
126
+ * @returns An SVG string when `format` is `'svg'`, or a PNG `Buffer` when `'png'`.
127
+ */
128
+ export async function convertImage(file, options) {
129
+ if (options.format === 'png') {
130
+ return convertToPNG(file, options);
131
+ }
132
+ return convertToSVG(file, options);
133
+ }
134
+ /**
135
+ * Replace a file path's extension with a new one.
136
+ *
137
+ * If the path has no extension (no dot, or dot at position 0 like `.gitignore`),
138
+ * the new extension is appended instead.
139
+ *
140
+ * @param filePath - The original file path (may include directories).
141
+ * @param newExt - The new extension **without** the leading dot (e.g. `'svg'`).
142
+ * @returns The file path with its extension swapped.
143
+ *
144
+ * @example
145
+ * swapExtension('diagram.excalidraw', 'png') // → 'diagram.png'
146
+ * swapExtension('/tmp/out.json', 'svg') // → '/tmp/out.svg'
147
+ */
148
+ export function swapExtension(filePath, newExt) {
149
+ const parsed = parse(filePath);
150
+ return format({ ...parsed, base: undefined, ext: `.${newExt}` });
151
+ }
152
+ async function withExporterRuntime(callback) {
153
+ return withDOMPolyfill(async () => {
154
+ const originalConsoleError = console.error;
155
+ console.error = (...args) => {
156
+ const msg = String(args[0] || '');
157
+ if (msg.includes('font-face') || msg.includes('Path2D'))
158
+ return;
159
+ originalConsoleError.apply(console, args);
160
+ };
161
+ try {
162
+ return await callback();
163
+ }
164
+ finally {
165
+ console.error = originalConsoleError;
166
+ }
167
+ });
168
+ }
169
+ async function renderSvg(file, opts) {
170
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
171
+ const utils = await import('@excalidraw/utils');
172
+ const exportToSvg = utils.exportToSvg;
173
+ const appState = {
174
+ ...file.appState,
175
+ exportBackground: opts.exportBackground,
176
+ viewBackgroundColor: opts.viewBackgroundColor,
177
+ exportWithDarkMode: opts.dark,
178
+ exportEmbedScene: opts.exportEmbedScene,
179
+ };
180
+ const svg = await exportToSvg({
181
+ elements: file.elements,
182
+ appState: appState,
183
+ files: (file.files || {}),
184
+ exportPadding: opts.padding,
185
+ });
186
+ return svg.outerHTML;
187
+ }
188
+ //# sourceMappingURL=image-exporter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image-exporter.js","sourceRoot":"","sources":["../../src/exporter/image-exporter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AA6B3E;;GAEG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAA4B;IAC7D,MAAM,EAAE,KAAK;IACb,gBAAgB,EAAE,IAAI;IACtB,mBAAmB,EAAE,SAAS;IAC9B,IAAI,EAAE,KAAK;IACX,gBAAgB,EAAE,KAAK;IACvB,OAAO,EAAE,EAAE;IACX,KAAK,EAAE,CAAC;CACT,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,SAAS,cAAc,CACrB,IAAoB,EACpB,OAAsB;IAEtB,OAAO;QACL,GAAG,sBAAsB;QACzB,GAAG,OAAO;QACV,6CAA6C;QAC7C,mBAAmB,EACjB,OAAO,CAAC,mBAAmB;YAC3B,IAAI,CAAC,QAAQ,EAAE,mBAAmB;YAClC,sBAAsB,CAAC,mBAAmB;KAC7C,CAAC;AACJ,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,IAAoB,EACpB,OAAgC;IAEhC,MAAM,IAAI,GAAG,cAAc,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;IACjE,OAAO,mBAAmB,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;AAC1D,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,oBAAoB;IAC3B,OAAO,qBAAqB,EAAE,CAAC;AACjC,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,IAAoB,EACpB,OAAgC;IAEhC,MAAM,IAAI,GAAG,cAAc,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;IACjE,OAAO,mBAAmB,CAAC,KAAK,IAAI,EAAE;QACpC,MAAM,SAAS,GAAG,MAAM,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAC9C,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,CAAC;QAElD,MAAM,UAAU,GAAG,SAAS,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;QACtD,MAAM,YAAY,GAAG,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;QAElE,MAAM,KAAK,GACT,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC;YAC3D,CAAC,CAAC,IAAI,CAAC,KAAK;YACZ,CAAC,CAAC,CAAC,CAAC;QACR,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;QACrD,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,SAAS,CAAC,CAAC,CAAC;QAEtE,sEAAsE;QACtE,6EAA6E;QAC7E,MAAM,OAAO,GAAG,oBAAoB,EAAE,CAAC;QAEvC,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,SAAS,EAAE;YACjC,KAAK,EAAE;gBACL,IAAI,EAAE,OAAgB;gBACtB,KAAK,EAAE,WAAW;aACnB;YACD,UAAU,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC,SAAS;YACxE,IAAI,EAAE;gBACJ,eAAe,EAAE,KAAK;gBACtB,QAAQ,EAAE,CAAC,OAAO,CAAC;aACpB;SACF,CAAC,CAAC;QAEH,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;QAC/B,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;QAElC,OAAO,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,IAAoB,EACpB,OAAsB;IAEtB,IAAI,OAAO,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;QAC7B,OAAO,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AACrC,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,aAAa,CAAC,QAAgB,EAAE,MAAc;IAC5D,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC/B,OAAO,MAAM,CAAC,EAAE,GAAG,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,IAAI,MAAM,EAAE,EAAE,CAAC,CAAC;AACnE,CAAC;AAED,KAAK,UAAU,mBAAmB,CAAI,QAA0B;IAC9D,OAAO,eAAe,CAAC,KAAK,IAAI,EAAE;QAChC,MAAM,oBAAoB,GAAG,OAAO,CAAC,KAAK,CAAC;QAC3C,OAAO,CAAC,KAAK,GAAG,CAAC,GAAG,IAAe,EAAE,EAAE;YACrC,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YAClC,IAAI,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC;gBAAE,OAAO;YAChE,oBAAoB,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QAC5C,CAAC,CAAC;QAEF,IAAI,CAAC;YACH,OAAO,MAAM,QAAQ,EAAE,CAAC;QAC1B,CAAC;gBAAS,CAAC;YACT,OAAO,CAAC,KAAK,GAAG,oBAAoB,CAAC;QACvC,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,SAAS,CACtB,IAAoB,EACpB,IAA6B;IAE7B,8DAA8D;IAC9D,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAQ,CAAC;IACvD,MAAM,WAAW,GAAG,KAAK,CAAC,WAKU,CAAC;IAErC,MAAM,QAAQ,GAAG;QACf,GAAG,IAAI,CAAC,QAAQ;QAChB,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;QACvC,mBAAmB,EAAE,IAAI,CAAC,mBAAmB;QAC7C,kBAAkB,EAAE,IAAI,CAAC,IAAI;QAC7B,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;KACxC,CAAC;IAEF,MAAM,GAAG,GAAG,MAAM,WAAW,CAAC;QAC5B,QAAQ,EAAE,IAAI,CAAC,QAAqB;QACpC,QAAQ,EAAE,QAAmC;QAC7C,KAAK,EAAE,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAA4B;QACpD,aAAa,EAAE,IAAI,CAAC,OAAO;KAC5B,CAAC,CAAC;IAEH,OAAO,GAAG,CAAC,SAAS,CAAC;AACvB,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Exporter module - re-exports
3
+ */
4
+ export { convertToSVG, convertToPNG, convertImage, swapExtension, DEFAULT_EXPORT_OPTIONS, } from './image-exporter.js';
5
+ export type { ExportOptions } from './image-exporter.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/exporter/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,sBAAsB,GACvB,MAAM,qBAAqB,CAAC;AAE7B,YAAY,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Exporter module - re-exports
3
+ */
4
+ export { convertToSVG, convertToPNG, convertImage, swapExtension, DEFAULT_EXPORT_OPTIONS, } from './image-exporter.js';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/exporter/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,sBAAsB,GACvB,MAAM,qBAAqB,CAAC"}
@@ -11,14 +11,18 @@ import { calculateStartBinding, calculateEndBinding } from '../layout/arrow-rout
11
11
  function mapEdgeStyle(style) {
12
12
  if (!style)
13
13
  return {};
14
- return {
15
- strokeColor: style.strokeColor,
16
- strokeWidth: style.strokeWidth,
17
- strokeStyle: style.strokeStyle,
18
- roughness: style.roughness,
19
- startArrowhead: style.startArrowhead ?? null,
20
- endArrowhead: style.endArrowhead ?? 'arrow',
21
- };
14
+ const result = {};
15
+ if (style.strokeColor !== undefined)
16
+ result.strokeColor = style.strokeColor;
17
+ if (style.strokeWidth !== undefined)
18
+ result.strokeWidth = style.strokeWidth;
19
+ if (style.strokeStyle !== undefined)
20
+ result.strokeStyle = style.strokeStyle;
21
+ if (style.roughness !== undefined)
22
+ result.roughness = style.roughness;
23
+ result.startArrowhead = style.startArrowhead ?? null;
24
+ result.endArrowhead = style.endArrowhead ?? 'arrow';
25
+ return result;
22
26
  }
23
27
  /**
24
28
  * Create an arrow element
@@ -1 +1 @@
1
- {"version":3,"file":"connection-factory.js","sourceRoot":"","sources":["../../src/factory/connection-factory.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"connection-factory.js","sourceRoot":"","sources":["../../src/factory/connection-factory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Image Factory
3
+ *
4
+ * Creates Excalidraw image elements and handles image file data.
5
+ */
6
+ import type { ExcalidrawImage, ExcalidrawFileData } from '../types/excalidraw.js';
7
+ import type { LayoutedNode, LayoutedImage } from '../types/dsl.js';
8
+ /**
9
+ * Resolve sticker name to actual path using library
10
+ */
11
+ export declare function resolveStickerPath(stickerSrc: string, libraryPath?: string): string;
12
+ /**
13
+ * Create file data for an image
14
+ * For local files: reads and base64 encodes
15
+ * For URLs: stores the URL directly (Excalidraw supports this)
16
+ */
17
+ export declare function createFileData(src: string, fileId: string, libraryPath?: string): ExcalidrawFileData | null;
18
+ /**
19
+ * Create an image element for a layouted node
20
+ */
21
+ export declare function createImageElement(node: LayoutedNode, fileId: string): ExcalidrawImage;
22
+ /**
23
+ * Create an image element for a layouted positioned image
24
+ */
25
+ export declare function createPositionedImageElement(image: LayoutedImage, fileId: string): ExcalidrawImage;
26
+ /**
27
+ * Generate a unique file ID
28
+ */
29
+ export declare function generateFileId(): string;
30
+ /**
31
+ * Get image dimensions (for layout calculation)
32
+ * Returns explicit dimensions if provided, otherwise defaults
33
+ */
34
+ export declare function getImageDimensions(src: string, explicitWidth?: number, explicitHeight?: number): {
35
+ width: number;
36
+ height: number;
37
+ };
38
+ //# sourceMappingURL=image-factory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image-factory.d.ts","sourceRoot":"","sources":["../../src/factory/image-factory.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,KAAK,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAClF,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AA+CnE;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAwBnF;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,EACd,WAAW,CAAC,EAAE,MAAM,GACnB,kBAAkB,GAAG,IAAI,CA0C3B;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,YAAY,EAClB,MAAM,EAAE,MAAM,GACb,eAAe,CAajB;AAED;;GAEG;AACH,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,aAAa,EACpB,MAAM,EAAE,MAAM,GACb,eAAe,CAajB;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,MAAM,EACX,aAAa,CAAC,EAAE,MAAM,EACtB,cAAc,CAAC,EAAE,MAAM,GACtB;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAYnC"}
@@ -0,0 +1,172 @@
1
+ /**
2
+ * Image Factory
3
+ *
4
+ * Creates Excalidraw image elements and handles image file data.
5
+ */
6
+ import * as fs from 'fs';
7
+ import * as path from 'path';
8
+ import { nanoid } from 'nanoid';
9
+ import { createBaseElement } from './element-factory.js';
10
+ /**
11
+ * Default image dimensions
12
+ */
13
+ const DEFAULT_IMAGE_WIDTH = 100;
14
+ const DEFAULT_IMAGE_HEIGHT = 100;
15
+ /**
16
+ * MIME type mapping by file extension
17
+ */
18
+ const MIME_TYPES = {
19
+ '.png': 'image/png',
20
+ '.jpg': 'image/jpeg',
21
+ '.jpeg': 'image/jpeg',
22
+ '.gif': 'image/gif',
23
+ '.webp': 'image/webp',
24
+ '.svg': 'image/svg+xml',
25
+ '.bmp': 'image/bmp',
26
+ '.ico': 'image/x-icon',
27
+ };
28
+ /**
29
+ * Get MIME type from file path or URL.
30
+ * Strips query parameters and hash fragments before extracting the extension.
31
+ */
32
+ function getMimeType(src) {
33
+ // Remove query params and hash fragments that would pollute the extension
34
+ const cleaned = src.split('?')[0].split('#')[0];
35
+ const ext = path.extname(cleaned).toLowerCase();
36
+ return MIME_TYPES[ext] || 'image/png';
37
+ }
38
+ /**
39
+ * Check if source is a URL
40
+ */
41
+ function isUrl(src) {
42
+ return src.startsWith('http://') || src.startsWith('https://');
43
+ }
44
+ /**
45
+ * Check if source is a sticker reference
46
+ */
47
+ function isSticker(src) {
48
+ return src.startsWith('sticker:');
49
+ }
50
+ /**
51
+ * Resolve sticker name to actual path using library
52
+ */
53
+ export function resolveStickerPath(stickerSrc, libraryPath) {
54
+ const name = stickerSrc.replace('sticker:', '');
55
+ if (!libraryPath) {
56
+ // No library specified, return as-is (will fail gracefully)
57
+ return name;
58
+ }
59
+ // Try common extensions
60
+ const extensions = ['.png', '.svg', '.jpg', '.jpeg', '.gif', '.webp'];
61
+ for (const ext of extensions) {
62
+ const fullPath = path.join(libraryPath, `${name}${ext}`);
63
+ if (fs.existsSync(fullPath)) {
64
+ return fullPath;
65
+ }
66
+ }
67
+ // Try with the name as-is (might already have extension)
68
+ const directPath = path.join(libraryPath, name);
69
+ if (fs.existsSync(directPath)) {
70
+ return directPath;
71
+ }
72
+ return name;
73
+ }
74
+ /**
75
+ * Create file data for an image
76
+ * For local files: reads and base64 encodes
77
+ * For URLs: stores the URL directly (Excalidraw supports this)
78
+ */
79
+ export function createFileData(src, fileId, libraryPath) {
80
+ // Handle sticker references
81
+ let resolvedSrc = src;
82
+ if (isSticker(src)) {
83
+ resolvedSrc = resolveStickerPath(src, libraryPath);
84
+ }
85
+ // Remote URLs are not supported - Excalidraw requires base64-encoded data URLs
86
+ if (isUrl(resolvedSrc)) {
87
+ console.warn(`Remote URLs are not supported for images: ${resolvedSrc}\n` +
88
+ ` Download the image locally and use a file path instead.`);
89
+ return null;
90
+ }
91
+ // For local files, read and base64 encode
92
+ try {
93
+ const absolutePath = path.isAbsolute(resolvedSrc)
94
+ ? resolvedSrc
95
+ : path.resolve(process.cwd(), resolvedSrc);
96
+ if (!fs.existsSync(absolutePath)) {
97
+ console.warn(`Image file not found: ${absolutePath}`);
98
+ return null;
99
+ }
100
+ const buffer = fs.readFileSync(absolutePath);
101
+ const base64 = buffer.toString('base64');
102
+ const mimeType = getMimeType(resolvedSrc);
103
+ const dataURL = `data:${mimeType};base64,${base64}`;
104
+ return {
105
+ mimeType,
106
+ id: fileId,
107
+ dataURL,
108
+ created: Date.now(),
109
+ };
110
+ }
111
+ catch (error) {
112
+ console.warn(`Failed to read image file: ${resolvedSrc}`, error);
113
+ return null;
114
+ }
115
+ }
116
+ /**
117
+ * Create an image element for a layouted node
118
+ */
119
+ export function createImageElement(node, fileId) {
120
+ return {
121
+ ...createBaseElement('image', node.x, node.y, node.width, node.height, {
122
+ id: node.id,
123
+ roundness: null,
124
+ boundElements: null,
125
+ backgroundColor: 'transparent',
126
+ }),
127
+ type: 'image',
128
+ fileId,
129
+ status: 'saved',
130
+ scale: [1, 1],
131
+ };
132
+ }
133
+ /**
134
+ * Create an image element for a layouted positioned image
135
+ */
136
+ export function createPositionedImageElement(image, fileId) {
137
+ return {
138
+ ...createBaseElement('image', image.x, image.y, image.width, image.height, {
139
+ id: image.id,
140
+ roundness: null,
141
+ boundElements: null,
142
+ backgroundColor: 'transparent',
143
+ }),
144
+ type: 'image',
145
+ fileId,
146
+ status: 'saved',
147
+ scale: [1, 1],
148
+ };
149
+ }
150
+ /**
151
+ * Generate a unique file ID
152
+ */
153
+ export function generateFileId() {
154
+ return nanoid(21);
155
+ }
156
+ /**
157
+ * Get image dimensions (for layout calculation)
158
+ * Returns explicit dimensions if provided, otherwise defaults
159
+ */
160
+ export function getImageDimensions(src, explicitWidth, explicitHeight) {
161
+ // Use explicit dimensions if provided
162
+ if (explicitWidth && explicitHeight) {
163
+ return { width: explicitWidth, height: explicitHeight };
164
+ }
165
+ // For local files, we could probe the actual dimensions, but that adds complexity
166
+ // For now, use defaults and let users specify dimensions if needed
167
+ return {
168
+ width: explicitWidth || DEFAULT_IMAGE_WIDTH,
169
+ height: explicitHeight || DEFAULT_IMAGE_HEIGHT,
170
+ };
171
+ }
172
+ //# sourceMappingURL=image-factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image-factory.js","sourceRoot":"","sources":["../../src/factory/image-factory.ts"],"names":[],"mappings":"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"}
@@ -5,4 +5,5 @@ export { createBaseElement, resetIndexCounter, DEFAULT_ELEMENT_STYLE } from './e
5
5
  export { createNode, createRectangle, createDiamond, createEllipse } from './node-factory.js';
6
6
  export { createArrow, createArrowWithBindings } from './connection-factory.js';
7
7
  export { createText, createBoundText, createNodeLabel, createEdgeLabel } from './text-factory.js';
8
+ export { createImageElement, createPositionedImageElement, createFileData, generateFileId, getImageDimensions, resolveStickerPath, } from './image-factory.js';
8
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/factory/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AACnG,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAC9F,OAAO,EAAE,WAAW,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAC/E,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/factory/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AACnG,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAC9F,OAAO,EAAE,WAAW,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAC/E,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAClG,OAAO,EACL,kBAAkB,EAClB,4BAA4B,EAC5B,cAAc,EACd,cAAc,EACd,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,oBAAoB,CAAC"}
@@ -5,4 +5,5 @@ export { createBaseElement, resetIndexCounter, DEFAULT_ELEMENT_STYLE } from './e
5
5
  export { createNode, createRectangle, createDiamond, createEllipse } from './node-factory.js';
6
6
  export { createArrow, createArrowWithBindings } from './connection-factory.js';
7
7
  export { createText, createBoundText, createNodeLabel, createEdgeLabel } from './text-factory.js';
8
+ export { createImageElement, createPositionedImageElement, createFileData, generateFileId, getImageDimensions, resolveStickerPath, } from './image-factory.js';
8
9
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/factory/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AACnG,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAC9F,OAAO,EAAE,WAAW,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAC/E,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/factory/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AACnG,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAC9F,OAAO,EAAE,WAAW,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAC/E,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAClG,OAAO,EACL,kBAAkB,EAClB,4BAA4B,EAC5B,cAAc,EACd,cAAc,EACd,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,oBAAoB,CAAC"}
@@ -10,15 +10,22 @@ import { createBaseElement } from './element-factory.js';
10
10
  function mapStyle(style) {
11
11
  if (!style)
12
12
  return {};
13
- return {
14
- strokeColor: style.strokeColor,
15
- backgroundColor: style.backgroundColor,
16
- strokeWidth: style.strokeWidth,
17
- strokeStyle: style.strokeStyle,
18
- fillStyle: style.fillStyle,
19
- opacity: style.opacity,
20
- roughness: style.roughness,
21
- };
13
+ const result = {};
14
+ if (style.strokeColor !== undefined)
15
+ result.strokeColor = style.strokeColor;
16
+ if (style.backgroundColor !== undefined)
17
+ result.backgroundColor = style.backgroundColor;
18
+ if (style.strokeWidth !== undefined)
19
+ result.strokeWidth = style.strokeWidth;
20
+ if (style.strokeStyle !== undefined)
21
+ result.strokeStyle = style.strokeStyle;
22
+ if (style.fillStyle !== undefined)
23
+ result.fillStyle = style.fillStyle;
24
+ if (style.opacity !== undefined)
25
+ result.opacity = style.opacity;
26
+ if (style.roughness !== undefined)
27
+ result.roughness = style.roughness;
28
+ return result;
22
29
  }
23
30
  /**
24
31
  * Create a rectangle element