@hugobatist/smartcode 0.1.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 (60) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +292 -0
  3. package/dist/cli.js +4324 -0
  4. package/dist/cli.js.map +1 -0
  5. package/dist/index.d.ts +374 -0
  6. package/dist/index.js +1167 -0
  7. package/dist/index.js.map +1 -0
  8. package/dist/static/annotations-panel.js +133 -0
  9. package/dist/static/annotations-svg.js +108 -0
  10. package/dist/static/annotations.css +367 -0
  11. package/dist/static/annotations.js +367 -0
  12. package/dist/static/app-init.js +497 -0
  13. package/dist/static/breakpoints.css +69 -0
  14. package/dist/static/breakpoints.js +197 -0
  15. package/dist/static/clipboard.js +94 -0
  16. package/dist/static/collapse-ui.js +325 -0
  17. package/dist/static/command-history.js +89 -0
  18. package/dist/static/context-menu.js +334 -0
  19. package/dist/static/custom-renderer.js +201 -0
  20. package/dist/static/dagre-layout.js +291 -0
  21. package/dist/static/diagram-dom.js +241 -0
  22. package/dist/static/diagram-editor.js +368 -0
  23. package/dist/static/editor-panel.js +107 -0
  24. package/dist/static/editor-popovers.js +187 -0
  25. package/dist/static/event-bus.js +57 -0
  26. package/dist/static/export.js +181 -0
  27. package/dist/static/file-tree.js +470 -0
  28. package/dist/static/ghost-paths.js +397 -0
  29. package/dist/static/heatmap.css +116 -0
  30. package/dist/static/heatmap.js +308 -0
  31. package/dist/static/icons.js +66 -0
  32. package/dist/static/inline-edit.js +294 -0
  33. package/dist/static/interaction-state.js +155 -0
  34. package/dist/static/interaction-tracker.js +93 -0
  35. package/dist/static/live.html +239 -0
  36. package/dist/static/main-layout.css +220 -0
  37. package/dist/static/main.css +334 -0
  38. package/dist/static/mcp-sessions.js +202 -0
  39. package/dist/static/modal.css +109 -0
  40. package/dist/static/modal.js +171 -0
  41. package/dist/static/node-drag.js +293 -0
  42. package/dist/static/pan-zoom.js +199 -0
  43. package/dist/static/renderer.js +280 -0
  44. package/dist/static/search.css +103 -0
  45. package/dist/static/search.js +304 -0
  46. package/dist/static/selection.js +353 -0
  47. package/dist/static/session-player.css +137 -0
  48. package/dist/static/session-player.js +411 -0
  49. package/dist/static/sidebar.css +248 -0
  50. package/dist/static/svg-renderer.js +313 -0
  51. package/dist/static/svg-shapes.js +218 -0
  52. package/dist/static/tokens.css +76 -0
  53. package/dist/static/vendor/dagre-bundle.js +43 -0
  54. package/dist/static/vendor/dagre.min.js +3 -0
  55. package/dist/static/vendor/graphlib.min.js +2 -0
  56. package/dist/static/viewport-transform.js +107 -0
  57. package/dist/static/workspace-switcher.js +202 -0
  58. package/dist/static/ws-client.js +71 -0
  59. package/dist/static/ws-handler.js +125 -0
  60. package/package.json +74 -0
@@ -0,0 +1,57 @@
1
+ /**
2
+ * SmartCode Event Bus — lightweight pub/sub using native EventTarget API.
3
+ * All inter-module communication flows through this bus.
4
+ *
5
+ * Usage:
6
+ * SmartCodeEventBus.on('diagram:rendered', (data) => { ... });
7
+ * SmartCodeEventBus.emit('diagram:rendered', { svg });
8
+ * SmartCodeEventBus.off('diagram:rendered', handler);
9
+ * SmartCodeEventBus.once('diagram:rendered', (data) => { ... });
10
+ */
11
+ (function() {
12
+ 'use strict';
13
+
14
+ var target = new EventTarget();
15
+
16
+ // Store wrapped handlers so off() can remove the correct listener.
17
+ // WeakMap<originalHandler, Map<eventName, wrappedHandler>>
18
+ var handlerMap = new WeakMap();
19
+
20
+ function getWrapped(event, handler) {
21
+ var byEvent = handlerMap.get(handler);
22
+ if (!byEvent) return null;
23
+ return byEvent.get(event) || null;
24
+ }
25
+
26
+ function setWrapped(event, handler, wrapped) {
27
+ var byEvent = handlerMap.get(handler);
28
+ if (!byEvent) {
29
+ byEvent = new Map();
30
+ handlerMap.set(handler, byEvent);
31
+ }
32
+ byEvent.set(event, wrapped);
33
+ }
34
+
35
+ var SmartCodeEventBus = {
36
+ on: function(event, handler) {
37
+ var wrapped = function(e) { handler(e.detail); };
38
+ setWrapped(event, handler, wrapped);
39
+ target.addEventListener(event, wrapped);
40
+ },
41
+ off: function(event, handler) {
42
+ var wrapped = getWrapped(event, handler);
43
+ if (wrapped) {
44
+ target.removeEventListener(event, wrapped);
45
+ }
46
+ },
47
+ emit: function(event, data) {
48
+ target.dispatchEvent(new CustomEvent(event, { detail: data }));
49
+ },
50
+ once: function(event, handler) {
51
+ var wrapped = function(e) { handler(e.detail); };
52
+ target.addEventListener(event, wrapped, { once: true });
53
+ }
54
+ };
55
+
56
+ window.SmartCodeEventBus = SmartCodeEventBus;
57
+ })();
@@ -0,0 +1,181 @@
1
+ /**
2
+ * SmartCode Export -- SVG and PNG export of current diagram.
3
+ * Extracted from live.html (Phase 9 Plan 02).
4
+ *
5
+ * Dependencies: mermaid (CDN), renderer.js (SmartCodeRenderer.MERMAID_CONFIG)
6
+ * Dependents: none (triggered by UI buttons)
7
+ *
8
+ * Usage:
9
+ * SmartCodeExport.exportSVG();
10
+ * SmartCodeExport.exportPNG();
11
+ */
12
+ (function() {
13
+ 'use strict';
14
+
15
+ // ── Download helper ──
16
+ function download(blob, name) {
17
+ var a = document.createElement('a');
18
+ a.href = URL.createObjectURL(blob);
19
+ a.download = name;
20
+ a.click();
21
+ URL.revokeObjectURL(a.href);
22
+ if (window.toast) toast('Exported: ' + name);
23
+ }
24
+
25
+ // ── Ghost path cloning for export (QUAL-03) ──
26
+ // Copies visible ghost path SVG elements from the live SVG into the export SVG
27
+ // so PNG exports include ghost paths.
28
+ function copyGhostPathsToExport(exportSvg) {
29
+ if (!window.SmartCodeGhostPaths || !SmartCodeGhostPaths.isVisible()) return;
30
+
31
+ var liveSvg = document.querySelector('#preview svg');
32
+ if (!liveSvg) return;
33
+
34
+ var ghostEls = liveSvg.querySelectorAll('.ghost-path');
35
+ if (ghostEls.length === 0) return;
36
+
37
+ // Clone the ghost-arrow marker definition if present
38
+ var ghostMarker = liveSvg.querySelector('#ghost-arrow');
39
+ if (ghostMarker) {
40
+ var exportDefs = exportSvg.querySelector('defs');
41
+ if (!exportDefs) {
42
+ exportDefs = document.createElementNS('http://www.w3.org/2000/svg', 'defs');
43
+ exportSvg.insertBefore(exportDefs, exportSvg.firstChild);
44
+ }
45
+ // Only add if not already present
46
+ if (!exportDefs.querySelector('#ghost-arrow')) {
47
+ exportDefs.appendChild(ghostMarker.cloneNode(true));
48
+ }
49
+ }
50
+
51
+ // Clone each ghost path group into the export SVG
52
+ for (var i = 0; i < ghostEls.length; i++) {
53
+ exportSvg.appendChild(ghostEls[i].cloneNode(true));
54
+ }
55
+ }
56
+
57
+ // ── SVG Export ──
58
+ function exportSVG() {
59
+ var svg = document.querySelector('#preview svg');
60
+ if (!svg) return window.toast && toast('Nothing to export');
61
+ var blob = new Blob([svg.outerHTML], { type: 'image/svg+xml' });
62
+ var currentFile = (window.SmartCodeFileTree && SmartCodeFileTree.getCurrentFile()) || 'export';
63
+ download(blob, currentFile.replace('.mmd', '.svg'));
64
+ }
65
+
66
+ // ── PNG Export ──
67
+ // Uses SmartCodeRenderer.MERMAID_CONFIG to avoid triplicating the config object.
68
+ // Re-initializes mermaid with htmlLabels:false to avoid foreignObject Canvas taint,
69
+ // then restores original config after rendering.
70
+ async function exportPNG() {
71
+ var currentSvg = document.querySelector('#preview svg');
72
+ if (!currentSvg) return window.toast && toast('Nothing to export');
73
+
74
+ // Custom SVG: direct PNG export without mermaid re-render
75
+ if (window.DiagramDOM && DiagramDOM.getRendererType() === 'custom') {
76
+ var currentFile = (window.SmartCodeFileTree && SmartCodeFileTree.getCurrentFile()) || 'export';
77
+ var clone = currentSvg.cloneNode(true);
78
+ copyGhostPathsToExport(clone);
79
+ var canvas = document.createElement('canvas');
80
+ var ctx = canvas.getContext('2d');
81
+ var data = new XMLSerializer().serializeToString(clone);
82
+ var img = new Image();
83
+ img.onload = function() {
84
+ canvas.width = img.width * 2;
85
+ canvas.height = img.height * 2;
86
+ ctx.scale(2, 2);
87
+ ctx.drawImage(img, 0, 0);
88
+ canvas.toBlob(function(blob) {
89
+ download(blob, currentFile.replace('.mmd', '.png'));
90
+ }, 'image/png');
91
+ };
92
+ img.onerror = function() {
93
+ if (window.toast) toast('Error exporting PNG -- try SVG');
94
+ };
95
+ img.src = 'data:image/svg+xml;base64,' + btoa(unescape(encodeURIComponent(data)));
96
+ return;
97
+ }
98
+
99
+ var baseConfig = window.SmartCodeRenderer && SmartCodeRenderer.MERMAID_CONFIG;
100
+ if (!baseConfig) {
101
+ if (window.toast) toast('Error: renderer not loaded');
102
+ return;
103
+ }
104
+
105
+ var currentFile = (window.SmartCodeFileTree && SmartCodeFileTree.getCurrentFile()) || 'export';
106
+
107
+ try {
108
+ // Get current diagram source code (same pipeline as render())
109
+ var editor = document.getElementById('editor');
110
+ var code = editor.value;
111
+ var cleanCode = window.SmartCodeAnnotations
112
+ ? SmartCodeAnnotations.getCleanContent(code)
113
+ : code;
114
+ var styledCode = window.injectStatusStyles
115
+ ? injectStatusStyles(cleanCode)
116
+ : cleanCode;
117
+
118
+ // Build export config: clone base config with htmlLabels:false
119
+ var exportConfig = JSON.parse(JSON.stringify(baseConfig));
120
+ exportConfig.flowchart.htmlLabels = false;
121
+
122
+ // Temporarily re-initialize mermaid for Canvas-safe rendering
123
+ mermaid.initialize(exportConfig);
124
+
125
+ // Render a Canvas-safe SVG (no foreignObject)
126
+ var result = await mermaid.render('export-png-' + Date.now(), styledCode.trim());
127
+ var exportSvgStr = result.svg;
128
+
129
+ // Restore original mermaid config
130
+ mermaid.initialize(baseConfig);
131
+
132
+ // Parse export SVG to get dimensions
133
+ var tempDiv = document.createElement('div');
134
+ tempDiv.style.cssText = 'position:absolute;left:-9999px;top:-9999px;';
135
+ document.body.appendChild(tempDiv);
136
+ // Safe: SVG from mermaid.render(), not user input
137
+ tempDiv.textContent = '';
138
+ tempDiv.insertAdjacentHTML('afterbegin', exportSvgStr);
139
+ var exportSvg = tempDiv.querySelector('svg');
140
+
141
+ // Copy ghost paths into the export SVG (QUAL-03)
142
+ copyGhostPathsToExport(exportSvg);
143
+
144
+ var canvas = document.createElement('canvas');
145
+ var ctx = canvas.getContext('2d');
146
+ var data = new XMLSerializer().serializeToString(exportSvg);
147
+
148
+ document.body.removeChild(tempDiv);
149
+
150
+ var img = new Image();
151
+ img.onload = function() {
152
+ try {
153
+ canvas.width = img.width * 2;
154
+ canvas.height = img.height * 2;
155
+ ctx.scale(2, 2);
156
+ ctx.drawImage(img, 0, 0);
157
+ canvas.toBlob(function(blob) {
158
+ download(blob, currentFile.replace('.mmd', '.png'));
159
+ }, 'image/png');
160
+ } catch (taintErr) {
161
+ if (window.toast) toast('Error exporting PNG -- try SVG');
162
+ }
163
+ };
164
+ img.onerror = function() {
165
+ if (window.toast) toast('Error exporting PNG -- try SVG');
166
+ };
167
+ img.src = 'data:image/svg+xml;base64,' + btoa(unescape(encodeURIComponent(data)));
168
+ } catch (e) {
169
+ // Restore original config on error
170
+ if (baseConfig) mermaid.initialize(baseConfig);
171
+ if (window.toast) toast('Error exporting PNG -- try SVG');
172
+ }
173
+ }
174
+
175
+ // ── Public API ──
176
+ window.SmartCodeExport = { exportSVG: exportSVG, exportPNG: exportPNG };
177
+
178
+ // Backward compat -- onclick handlers in HTML call these directly
179
+ window.exportSVG = exportSVG;
180
+ window.exportPNG = exportPNG;
181
+ })();