mitway-tagger 1.3.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.
package/dist/index.cjs ADDED
@@ -0,0 +1,909 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ createIframeNavigationPlugin: () => createIframeNavigationPlugin,
34
+ createJsxSourcePlugin: () => createJsxSourcePlugin,
35
+ createThemeBridgePlugin: () => createThemeBridgePlugin,
36
+ createVirtualOverridesPlugin: () => createVirtualOverridesPlugin,
37
+ createVisualEditorPlugin: () => createVisualEditorPlugin,
38
+ createmITwayServerConfig: () => createmITwayServerConfig,
39
+ default: () => index_default,
40
+ mitwayServerConfig: () => mitwayServerConfig,
41
+ mitwayTagger: () => mitwayTagger
42
+ });
43
+ module.exports = __toCommonJS(index_exports);
44
+
45
+ // src/features/jsxSource.ts
46
+ var VIRTUAL_JSX_RUNTIME = "virtual:mitway-jsx-runtime";
47
+ var RESOLVED_VIRTUAL_JSX_RUNTIME = "\0" + VIRTUAL_JSX_RUNTIME;
48
+ var ORIGINAL_JSX_RUNTIME = "\0__original_react_jsx_dev_runtime";
49
+ var JSX_RUNTIME_CODE = `
50
+ import * as OriginalRuntime from '\\0__original_react_jsx_dev_runtime';
51
+
52
+ // Symbol for storing source info on DOM nodes
53
+ const SOURCE_SYMBOL = Symbol.for('__mitwaySource__');
54
+
55
+ // Global map of source locations to DOM elements (using WeakRef)
56
+ if (typeof window !== 'undefined' && !window.mitwaySourceMap) {
57
+ window.mitwaySourceMap = new Map();
58
+ }
59
+
60
+ /**
61
+ * Creates a ref callback that attaches source info to the DOM node
62
+ */
63
+ function createSourceRef(source, existingRef) {
64
+ return (node) => {
65
+ if (node && source) {
66
+ // Attach source info directly to the DOM node
67
+ node[SOURCE_SYMBOL] = {
68
+ fileName: source.fileName,
69
+ lineNumber: source.lineNumber,
70
+ columnNumber: source.columnNumber,
71
+ };
72
+
73
+ // Add to global source map for lookup
74
+ if (typeof window !== 'undefined' && window.mitwaySourceMap) {
75
+ const key = source.fileName + ':' + source.lineNumber + ':' + source.columnNumber;
76
+
77
+ if (!window.mitwaySourceMap.has(key)) {
78
+ window.mitwaySourceMap.set(key, new Set());
79
+ }
80
+
81
+ // Use WeakRef to avoid memory leaks
82
+ const weakRef = new WeakRef(node);
83
+ window.mitwaySourceMap.get(key).add(weakRef);
84
+
85
+ // Cleanup dead refs periodically
86
+ const refs = window.mitwaySourceMap.get(key);
87
+ if (refs.size > 100) {
88
+ for (const ref of refs) {
89
+ if (!ref.deref()) {
90
+ refs.delete(ref);
91
+ }
92
+ }
93
+ }
94
+ }
95
+ }
96
+
97
+ // Call existing ref if present
98
+ if (existingRef) {
99
+ if (typeof existingRef === 'function') {
100
+ existingRef(node);
101
+ } else if (typeof existingRef === 'object') {
102
+ existingRef.current = node;
103
+ }
104
+ }
105
+ };
106
+ }
107
+
108
+ /**
109
+ * Custom jsxDEV that wraps the original with source tracking
110
+ */
111
+ export function jsxDEV(type, props, key, isStaticChildren, source, self) {
112
+ // Only track HTML elements and custom components, not fragments
113
+ if (source && type && typeof type !== 'symbol') {
114
+ const existingRef = props?.ref;
115
+ const newProps = {
116
+ ...props,
117
+ ref: createSourceRef(source, existingRef),
118
+ };
119
+
120
+ return OriginalRuntime.jsxDEV(type, newProps, key, isStaticChildren, source, self);
121
+ }
122
+
123
+ return OriginalRuntime.jsxDEV(type, props, key, isStaticChildren, source, self);
124
+ }
125
+
126
+ // Re-export everything else from the original runtime
127
+ export const Fragment = OriginalRuntime.Fragment;
128
+ export const jsx = OriginalRuntime.jsx;
129
+ export const jsxs = OriginalRuntime.jsxs;
130
+ `;
131
+ function createJsxSourcePlugin(options) {
132
+ return {
133
+ name: "mitway-tagger:jsx-source",
134
+ enforce: "pre",
135
+ resolveId(id, importer) {
136
+ if (id === ORIGINAL_JSX_RUNTIME || id === "\0__original_react_jsx_dev_runtime") {
137
+ return this.resolve("react/jsx-dev-runtime", importer, { skipSelf: true });
138
+ }
139
+ if (id === "react/jsx-dev-runtime") {
140
+ return RESOLVED_VIRTUAL_JSX_RUNTIME;
141
+ }
142
+ if (id === VIRTUAL_JSX_RUNTIME) {
143
+ return RESOLVED_VIRTUAL_JSX_RUNTIME;
144
+ }
145
+ return null;
146
+ },
147
+ load(id) {
148
+ if (id === RESOLVED_VIRTUAL_JSX_RUNTIME) {
149
+ return JSX_RUNTIME_CODE;
150
+ }
151
+ return null;
152
+ },
153
+ config() {
154
+ return {
155
+ // Ensure we're using jsxDEV in development
156
+ esbuild: {
157
+ jsx: "automatic",
158
+ jsxDev: true
159
+ }
160
+ };
161
+ }
162
+ };
163
+ }
164
+
165
+ // src/features/virtualOverrides.ts
166
+ var import_path = __toESM(require("path"), 1);
167
+ var virtualOverrides = /* @__PURE__ */ new Map();
168
+ function normalizePath(filePath) {
169
+ return filePath.replace(/\\/g, "/");
170
+ }
171
+ function getAbsolutePath(relativePath, root) {
172
+ if (import_path.default.isAbsolute(relativePath)) {
173
+ return normalizePath(relativePath);
174
+ }
175
+ return normalizePath(import_path.default.join(root, relativePath));
176
+ }
177
+ function findModuleByPath(server, filePath) {
178
+ const normalizedPath = normalizePath(filePath);
179
+ for (const [, mod] of server.moduleGraph.idToModuleMap) {
180
+ if (mod.file && normalizePath(mod.file) === normalizedPath) {
181
+ return mod;
182
+ }
183
+ }
184
+ const variations = [
185
+ normalizedPath,
186
+ "/" + normalizedPath,
187
+ normalizedPath.replace(/^\//, "")
188
+ ];
189
+ for (const variation of variations) {
190
+ const mod = server.moduleGraph.getModuleById(variation);
191
+ if (mod) return mod;
192
+ }
193
+ return void 0;
194
+ }
195
+ async function invalidateModule(server, filePath) {
196
+ const mod = findModuleByPath(server, filePath);
197
+ if (mod) {
198
+ server.moduleGraph.invalidateModule(mod);
199
+ if (mod.file) {
200
+ server.ws.send({
201
+ type: "update",
202
+ updates: [{
203
+ type: "js-update",
204
+ path: mod.url,
205
+ acceptedPath: mod.url,
206
+ timestamp: Date.now()
207
+ }]
208
+ });
209
+ }
210
+ return true;
211
+ }
212
+ server.ws.send({ type: "full-reload" });
213
+ return false;
214
+ }
215
+ function createVirtualOverridesPlugin() {
216
+ let server;
217
+ let root;
218
+ return {
219
+ name: "mitway-tagger:virtual-overrides",
220
+ enforce: "pre",
221
+ configResolved(config) {
222
+ root = config.root;
223
+ },
224
+ configureServer(_server) {
225
+ server = _server;
226
+ server.ws.on("mitway:override", async (data) => {
227
+ const absolutePath = getAbsolutePath(data.path, root);
228
+ console.log("[mitway-tagger] Setting override for:", absolutePath);
229
+ virtualOverrides.set(absolutePath, data.content);
230
+ await invalidateModule(server, absolutePath);
231
+ server.ws.send("mitway:override-applied", { path: data.path });
232
+ });
233
+ server.ws.on("mitway:clear-override", async (data) => {
234
+ const absolutePath = getAbsolutePath(data.path, root);
235
+ console.log("[mitway-tagger] Clearing override for:", absolutePath);
236
+ virtualOverrides.delete(absolutePath);
237
+ await invalidateModule(server, absolutePath);
238
+ server.ws.send("mitway:override-cleared", { path: data.path });
239
+ });
240
+ server.ws.on("mitway:clear-all-overrides", async () => {
241
+ console.log("[mitway-tagger] Clearing all overrides");
242
+ const paths = Array.from(virtualOverrides.keys());
243
+ virtualOverrides.clear();
244
+ for (const filePath of paths) {
245
+ await invalidateModule(server, filePath);
246
+ }
247
+ server.ws.send("mitway:all-overrides-cleared", { count: paths.length });
248
+ });
249
+ server.ws.on("mitway:get-overrides", () => {
250
+ const overrides = Array.from(virtualOverrides.entries()).map(([path2, content]) => ({
251
+ path: path2,
252
+ contentLength: content.length
253
+ }));
254
+ server.ws.send("mitway:overrides-list", { overrides });
255
+ });
256
+ },
257
+ /**
258
+ * Load hook - serves overridden content if available
259
+ */
260
+ load(id) {
261
+ const normalizedId = normalizePath(id);
262
+ if (virtualOverrides.has(normalizedId)) {
263
+ console.log("[mitway-tagger] Serving override for:", normalizedId);
264
+ return virtualOverrides.get(normalizedId);
265
+ }
266
+ const withoutSlash = normalizedId.replace(/^\//, "");
267
+ if (virtualOverrides.has(withoutSlash)) {
268
+ console.log("[mitway-tagger] Serving override for:", withoutSlash);
269
+ return virtualOverrides.get(withoutSlash);
270
+ }
271
+ return null;
272
+ },
273
+ /**
274
+ * Transform hook - can be used for additional processing
275
+ */
276
+ transform(code, id) {
277
+ return null;
278
+ }
279
+ };
280
+ }
281
+
282
+ // src/features/visualEditor.ts
283
+ var VISUAL_EDITOR_SCRIPT = `
284
+ <script>
285
+ (function() {
286
+ 'use strict';
287
+
288
+ // State
289
+ let isSelecting = false;
290
+ let selectedElement = null;
291
+ let originalStyles = new Map();
292
+ let highlightOverlay = null;
293
+ let selectionOverlay = null;
294
+
295
+ // Create highlight overlay element
296
+ function createOverlay(id, borderColor) {
297
+ const overlay = document.createElement('div');
298
+ overlay.id = id;
299
+ overlay.style.cssText = \`
300
+ position: fixed;
301
+ pointer-events: none;
302
+ border: 2px solid \${borderColor};
303
+ background: \${borderColor}10;
304
+ z-index: 999999;
305
+ transition: all 0.1s ease;
306
+ display: none;
307
+ \`;
308
+ document.body.appendChild(overlay);
309
+ return overlay;
310
+ }
311
+
312
+ // Initialize overlays
313
+ function initOverlays() {
314
+ if (!highlightOverlay) {
315
+ highlightOverlay = createOverlay('mitway-highlight-overlay', '#00BDFF');
316
+ }
317
+ if (!selectionOverlay) {
318
+ selectionOverlay = createOverlay('mitway-selection-overlay', '#00FF88');
319
+ selectionOverlay.style.border = '2px dashed #00FF88';
320
+ }
321
+ }
322
+
323
+ // Position overlay on element
324
+ function positionOverlay(overlay, element) {
325
+ if (!overlay || !element) return;
326
+ const rect = element.getBoundingClientRect();
327
+ overlay.style.top = rect.top + 'px';
328
+ overlay.style.left = rect.left + 'px';
329
+ overlay.style.width = rect.width + 'px';
330
+ overlay.style.height = rect.height + 'px';
331
+ overlay.style.display = 'block';
332
+ }
333
+
334
+ // Hide overlay
335
+ function hideOverlay(overlay) {
336
+ if (overlay) {
337
+ overlay.style.display = 'none';
338
+ }
339
+ }
340
+
341
+ // Get XPath for element
342
+ function getXPath(element) {
343
+ if (!element) return '';
344
+ if (element.id) return '//*[@id="' + element.id + '"]';
345
+ if (element === document.body) return '/html/body';
346
+
347
+ let ix = 0;
348
+ const siblings = element.parentNode ? element.parentNode.childNodes : [];
349
+
350
+ for (let i = 0; i < siblings.length; i++) {
351
+ const sibling = siblings[i];
352
+ if (sibling === element) {
353
+ const parentPath = getXPath(element.parentNode);
354
+ const tagName = element.tagName.toLowerCase();
355
+ return parentPath + '/' + tagName + '[' + (ix + 1) + ']';
356
+ }
357
+ if (sibling.nodeType === 1 && sibling.tagName === element.tagName) {
358
+ ix++;
359
+ }
360
+ }
361
+ return '';
362
+ }
363
+
364
+ // Get element by XPath
365
+ function getElementByXPath(xpath) {
366
+ try {
367
+ const result = document.evaluate(
368
+ xpath,
369
+ document,
370
+ null,
371
+ XPathResult.FIRST_ORDERED_NODE_TYPE,
372
+ null
373
+ );
374
+ return result.singleNodeValue;
375
+ } catch (e) {
376
+ return null;
377
+ }
378
+ }
379
+
380
+ // Check if element has dynamic styles (className with expressions)
381
+ function hasDynamicStyles(element) {
382
+ const classAttr = element.getAttribute('class') || '';
383
+ return classAttr.includes('\${') ||
384
+ classAttr.includes('?') ||
385
+ classAttr.includes('(') ||
386
+ element.className.includes('[object');
387
+ }
388
+
389
+ // Get computed styles for element
390
+ function getElementStyles(element) {
391
+ const computed = getComputedStyle(element);
392
+ return {
393
+ color: computed.color,
394
+ backgroundColor: computed.backgroundColor,
395
+ fontSize: computed.fontSize,
396
+ fontWeight: computed.fontWeight,
397
+ fontStyle: computed.fontStyle,
398
+ textAlign: computed.textAlign,
399
+ marginTop: computed.marginTop,
400
+ marginRight: computed.marginRight,
401
+ marginBottom: computed.marginBottom,
402
+ marginLeft: computed.marginLeft,
403
+ paddingTop: computed.paddingTop,
404
+ paddingRight: computed.paddingRight,
405
+ paddingBottom: computed.paddingBottom,
406
+ paddingLeft: computed.paddingLeft,
407
+ };
408
+ }
409
+
410
+ // Get source info from mitway-tagger jsxSource
411
+ function getSourceInfo(element) {
412
+ const SOURCE_SYMBOL = Symbol.for('__mitwaySource__');
413
+ let current = element;
414
+
415
+ // Walk up the tree to find the first element with source info
416
+ while (current && current !== document.body) {
417
+ if (current[SOURCE_SYMBOL]) {
418
+ return current[SOURCE_SYMBOL];
419
+ }
420
+ current = current.parentElement;
421
+ }
422
+
423
+ return null;
424
+ }
425
+
426
+ // Get element data for selection
427
+ function getElementData(element) {
428
+ const rect = element.getBoundingClientRect();
429
+ const sourceInfo = getSourceInfo(element);
430
+
431
+ return {
432
+ tagName: element.tagName,
433
+ textContent: element.textContent?.trim().substring(0, 500) || '',
434
+ className: element.className || '',
435
+ computedStyles: getElementStyles(element),
436
+ xpath: getXPath(element),
437
+ rect: {
438
+ top: rect.top,
439
+ left: rect.left,
440
+ width: rect.width,
441
+ height: rect.height,
442
+ },
443
+ hasDynamicStyles: hasDynamicStyles(element),
444
+ source: sourceInfo ? {
445
+ fileName: sourceInfo.fileName,
446
+ lineNumber: sourceInfo.lineNumber,
447
+ columnNumber: sourceInfo.columnNumber,
448
+ } : null,
449
+ };
450
+ }
451
+
452
+ // Store original inline styles
453
+ function storeOriginalStyles(element) {
454
+ if (!originalStyles.has(element)) {
455
+ originalStyles.set(element, element.getAttribute('style') || '');
456
+ }
457
+ }
458
+
459
+ // Apply preview styles to element
460
+ function applyPreviewStyles(element, styles) {
461
+ if (!element) return;
462
+ storeOriginalStyles(element);
463
+
464
+ Object.entries(styles).forEach(([key, value]) => {
465
+ if (value !== undefined && value !== null && value !== '') {
466
+ element.style[key] = value;
467
+ }
468
+ });
469
+
470
+ if (styles.textContent !== undefined) {
471
+ element.textContent = styles.textContent;
472
+ }
473
+
474
+ if (styles.classes !== undefined) {
475
+ element.className = styles.classes;
476
+ }
477
+ }
478
+
479
+ // Restore original styles
480
+ function restoreOriginalStyles(element) {
481
+ if (!element) return;
482
+ const original = originalStyles.get(element);
483
+ if (original !== undefined) {
484
+ element.setAttribute('style', original);
485
+ originalStyles.delete(element);
486
+ } else {
487
+ element.removeAttribute('style');
488
+ }
489
+ }
490
+
491
+ // Handle mouse move during selection
492
+ function handleMouseMove(event) {
493
+ if (!isSelecting) return;
494
+
495
+ const target = event.target;
496
+
497
+ if (target.id === 'mitway-highlight-overlay' ||
498
+ target.id === 'mitway-selection-overlay' ||
499
+ target.tagName === 'SCRIPT' ||
500
+ target.tagName === 'STYLE' ||
501
+ target.tagName === 'HTML') {
502
+ return;
503
+ }
504
+
505
+ positionOverlay(highlightOverlay, target);
506
+
507
+ window.parent?.postMessage({
508
+ type: 'VISUAL_EDITOR_ELEMENT_HOVER',
509
+ payload: {
510
+ tagName: target.tagName,
511
+ className: target.className,
512
+ }
513
+ }, '*');
514
+ }
515
+
516
+ // Handle click during selection
517
+ function handleClick(event) {
518
+ if (!isSelecting) return;
519
+
520
+ event.preventDefault();
521
+ event.stopPropagation();
522
+
523
+ const target = event.target;
524
+
525
+ if (target.id === 'mitway-highlight-overlay' ||
526
+ target.id === 'mitway-selection-overlay') {
527
+ return;
528
+ }
529
+
530
+ selectedElement = target;
531
+ isSelecting = false;
532
+
533
+ hideOverlay(highlightOverlay);
534
+ positionOverlay(selectionOverlay, target);
535
+
536
+ window.parent?.postMessage({
537
+ type: 'VISUAL_EDITOR_ELEMENT_SELECTED',
538
+ payload: getElementData(target)
539
+ }, '*');
540
+ }
541
+
542
+ // Enable selector mode
543
+ function enableSelector() {
544
+ initOverlays();
545
+ isSelecting = true;
546
+ selectedElement = null;
547
+ hideOverlay(selectionOverlay);
548
+ document.body.style.cursor = 'crosshair';
549
+ document.addEventListener('mousemove', handleMouseMove, true);
550
+ document.addEventListener('click', handleClick, true);
551
+ }
552
+
553
+ // Disable selector mode
554
+ function disableSelector() {
555
+ isSelecting = false;
556
+ selectedElement = null;
557
+ document.body.style.cursor = '';
558
+ document.removeEventListener('mousemove', handleMouseMove, true);
559
+ document.removeEventListener('click', handleClick, true);
560
+ hideOverlay(highlightOverlay);
561
+ hideOverlay(selectionOverlay);
562
+
563
+ originalStyles.forEach((_, element) => {
564
+ restoreOriginalStyles(element);
565
+ });
566
+ originalStyles.clear();
567
+ }
568
+
569
+ // Listen for messages from parent (mITway-App)
570
+ window.addEventListener('message', (event) => {
571
+ if (!event.data || typeof event.data.type !== 'string') return;
572
+
573
+ const { type, payload } = event.data;
574
+
575
+ switch (type) {
576
+ case 'VISUAL_EDITOR_ENABLE_SELECTOR':
577
+ enableSelector();
578
+ break;
579
+
580
+ case 'VISUAL_EDITOR_DISABLE_SELECTOR':
581
+ disableSelector();
582
+ break;
583
+
584
+ case 'VISUAL_EDITOR_PREVIEW_STYLES':
585
+ if (payload?.xpath) {
586
+ const element = getElementByXPath(payload.xpath);
587
+ if (element) {
588
+ applyPreviewStyles(element, payload.styles || {});
589
+ }
590
+ }
591
+ break;
592
+
593
+ case 'VISUAL_EDITOR_RESTORE_ORIGINAL':
594
+ if (payload?.xpath) {
595
+ const element = getElementByXPath(payload.xpath);
596
+ if (element) {
597
+ restoreOriginalStyles(element);
598
+ }
599
+ }
600
+ break;
601
+ }
602
+ });
603
+
604
+ // Notify parent that visual editor bridge is ready
605
+ window.parent?.postMessage({ type: 'VISUAL_EDITOR_BRIDGE_READY' }, '*');
606
+ })();
607
+ </script>`;
608
+ function createVisualEditorPlugin() {
609
+ return {
610
+ name: "mitway-tagger:visual-editor",
611
+ transformIndexHtml(html) {
612
+ return html.replace("</head>", VISUAL_EDITOR_SCRIPT + "\n</head>");
613
+ }
614
+ };
615
+ }
616
+
617
+ // src/features/iframeNavigation.ts
618
+ var IFRAME_NAVIGATION_SCRIPT = `
619
+ <script>
620
+ (function() {
621
+ 'use strict';
622
+
623
+ let lastPath = window.location.pathname + window.location.search + window.location.hash;
624
+
625
+ function notifyParent() {
626
+ const path = window.location.pathname + window.location.search + window.location.hash;
627
+
628
+ if (path !== lastPath) {
629
+ lastPath = path;
630
+
631
+ try {
632
+ window.parent.postMessage({
633
+ type: 'IFRAME_NAVIGATION',
634
+ url: path
635
+ }, '*');
636
+ } catch (e) {
637
+ // Silently fail if postMessage is blocked
638
+ }
639
+ }
640
+ }
641
+
642
+ // Intercept history methods
643
+ const originalPushState = history.pushState;
644
+ const originalReplaceState = history.replaceState;
645
+
646
+ history.pushState = function() {
647
+ originalPushState.apply(this, arguments);
648
+ setTimeout(notifyParent, 0);
649
+ };
650
+
651
+ history.replaceState = function() {
652
+ originalReplaceState.apply(this, arguments);
653
+ setTimeout(notifyParent, 0);
654
+ };
655
+
656
+ // Listen to navigation events
657
+ window.addEventListener('popstate', function() {
658
+ setTimeout(notifyParent, 0);
659
+ });
660
+
661
+ document.addEventListener('click', function() {
662
+ setTimeout(notifyParent, 100);
663
+ }, true);
664
+
665
+ // Initial notification
666
+ setTimeout(notifyParent, 500);
667
+
668
+ // Fallback check
669
+ setInterval(notifyParent, 500);
670
+
671
+ // Listen for parent navigation commands
672
+ window.addEventListener('message', function(event) {
673
+ if (event.data && event.data.type === 'NAVIGATE_TO') {
674
+ window.history.pushState(null, '', event.data.url);
675
+ window.dispatchEvent(new PopStateEvent('popstate'));
676
+ setTimeout(notifyParent, 0);
677
+ }
678
+ });
679
+ })();
680
+ </script>`;
681
+ function createIframeNavigationPlugin() {
682
+ return {
683
+ name: "mitway-tagger:iframe-navigation",
684
+ transformIndexHtml(html) {
685
+ return html.replace("</body>", `${IFRAME_NAVIGATION_SCRIPT}</body>`);
686
+ }
687
+ };
688
+ }
689
+
690
+ // src/features/themeBridge.ts
691
+ var THEME_BRIDGE_SCRIPT = `
692
+ <script>
693
+ (function() {
694
+ // Store original CSS variable values for restoration
695
+ let originalStyles = {};
696
+
697
+ // CSS variables used in the theme
698
+ // Base variables (without --color- prefix, used in :root)
699
+ const baseVars = [
700
+ '--background', '--foreground', '--card', '--card-foreground',
701
+ '--popover', '--popover-foreground', '--primary', '--primary-foreground',
702
+ '--secondary', '--secondary-foreground', '--muted', '--muted-foreground',
703
+ '--accent', '--accent-foreground', '--destructive', '--destructive-foreground',
704
+ '--border', '--input', '--ring',
705
+ '--chart-1', '--chart-2', '--chart-3', '--chart-4', '--chart-5',
706
+ '--sidebar', '--sidebar-foreground', '--sidebar-primary',
707
+ '--sidebar-primary-foreground', '--sidebar-accent', '--sidebar-accent-foreground',
708
+ '--sidebar-border', '--sidebar-ring'
709
+ ];
710
+
711
+ // Radius variables (no hsl wrapper needed)
712
+ const radiusVars = ['--radius', '--radius-sm', '--radius-md', '--radius-lg', '--radius-xl'];
713
+
714
+ // Capture original styles on first preview
715
+ function captureOriginalStyles() {
716
+ if (Object.keys(originalStyles).length > 0) return;
717
+ const root = document.documentElement;
718
+ const computed = getComputedStyle(root);
719
+ [...baseVars, ...radiusVars].forEach(prop => {
720
+ const value = computed.getPropertyValue(prop).trim();
721
+ if (value) originalStyles[prop] = value;
722
+ });
723
+ }
724
+
725
+ // Check if a value is a radius (not a color)
726
+ function isRadiusVar(key) {
727
+ return key.includes('radius');
728
+ }
729
+
730
+ // Normalize variable name to base format (--background, --primary, etc.)
731
+ function normalizeVarName(key) {
732
+ // Remove leading dashes if present
733
+ let normalized = key.replace(/^-+/, '');
734
+
735
+ // Remove 'color-' prefix if present (convert from Tailwind v4 format)
736
+ if (normalized.startsWith('color-')) {
737
+ normalized = normalized.replace('color-', '');
738
+ }
739
+
740
+ return '--' + normalized;
741
+ }
742
+
743
+ // Wrap color value with hsl() if needed
744
+ function wrapWithHsl(value, isRadius) {
745
+ if (isRadius) return value;
746
+
747
+ // Already has hsl/hsla/rgb/rgba/oklch wrapper
748
+ if (/^(hsl|hsla|rgb|rgba|oklch)\\(/.test(value)) {
749
+ return value;
750
+ }
751
+
752
+ // Wrap with hsl()
753
+ return 'hsl(' + value + ')';
754
+ }
755
+
756
+ // Apply theme colors to CSS variables
757
+ // Values are received WITHOUT hsl() wrapper from mITway-App
758
+ function applyTheme(theme) {
759
+ if (!theme) return;
760
+ const root = document.documentElement;
761
+
762
+ Object.entries(theme).forEach(([key, value]) => {
763
+ const cssVar = normalizeVarName(key);
764
+ const isRadius = isRadiusVar(key);
765
+ const finalValue = wrapWithHsl(value, isRadius);
766
+
767
+ // Set the base variable (--background, --primary, etc.)
768
+ root.style.setProperty(cssVar, finalValue);
769
+
770
+ // Also set with --color- prefix for @theme inline compatibility
771
+ if (!isRadius) {
772
+ const colorVar = '--color-' + cssVar.replace('--', '');
773
+ root.style.setProperty(colorVar, finalValue);
774
+ }
775
+ });
776
+ }
777
+
778
+ // Restore original CSS variables
779
+ function restoreOriginal() {
780
+ const root = document.documentElement;
781
+ Object.entries(originalStyles).forEach(([key, value]) => {
782
+ root.style.setProperty(key, value);
783
+ // Also restore --color- prefixed version
784
+ if (!isRadiusVar(key)) {
785
+ const colorVar = '--color-' + key.replace('--', '');
786
+ root.style.setProperty(colorVar, value);
787
+ }
788
+ });
789
+ }
790
+
791
+ // Listen for theme messages from parent (mITway-App)
792
+ window.addEventListener('message', (event) => {
793
+ // Accept messages from any origin (mITway-App domains)
794
+ if (!event.data || typeof event.data.type !== 'string') return;
795
+
796
+ switch (event.data.type) {
797
+ case 'PREVIEW_THEME':
798
+ captureOriginalStyles();
799
+ applyTheme(event.data.theme);
800
+ break;
801
+
802
+ case 'RESTORE_THEME':
803
+ restoreOriginal();
804
+ break;
805
+
806
+ case 'APPLY_THEME':
807
+ applyTheme(event.data.theme);
808
+ // Notify parent that theme was applied
809
+ window.parent?.postMessage({
810
+ type: 'THEME_APPLIED',
811
+ themeId: event.data.themeId
812
+ }, '*');
813
+ break;
814
+ }
815
+ });
816
+
817
+ // Notify parent that theme bridge is ready
818
+ window.parent?.postMessage({ type: 'THEME_BRIDGE_READY' }, '*');
819
+ })();
820
+ </script>`;
821
+ function createThemeBridgePlugin() {
822
+ return {
823
+ name: "mitway-tagger:theme-bridge",
824
+ transformIndexHtml(html) {
825
+ return html.replace("</head>", `${THEME_BRIDGE_SCRIPT}
826
+ </head>`);
827
+ }
828
+ };
829
+ }
830
+
831
+ // src/index.ts
832
+ var defaultOptions = {
833
+ jsxSource: true,
834
+ virtualOverrides: true,
835
+ visualEditor: true,
836
+ iframeNavigation: true,
837
+ themeBridge: true,
838
+ extensions: [".jsx", ".tsx"],
839
+ exclude: ["node_modules", ".git"]
840
+ };
841
+ function mitwayTagger(options = {}) {
842
+ const opts = { ...defaultOptions, ...options };
843
+ const plugins = [];
844
+ if (opts.jsxSource) {
845
+ plugins.push(createJsxSourcePlugin(opts));
846
+ }
847
+ if (opts.virtualOverrides) {
848
+ plugins.push(createVirtualOverridesPlugin());
849
+ }
850
+ if (opts.visualEditor) {
851
+ plugins.push(createVisualEditorPlugin());
852
+ }
853
+ if (opts.iframeNavigation) {
854
+ plugins.push(createIframeNavigationPlugin());
855
+ }
856
+ if (opts.themeBridge) {
857
+ plugins.push(createThemeBridgePlugin());
858
+ }
859
+ return plugins;
860
+ }
861
+ var index_default = mitwayTagger;
862
+ var mitwayServerConfig = {
863
+ host: "0.0.0.0",
864
+ port: 80,
865
+ cors: {
866
+ origin: [
867
+ "https://app.nttmitway.com",
868
+ "https://app.dev.nttmitway.com",
869
+ "http://app.mitway.local",
870
+ /^http:\/\/localhost(:\d+)?$/
871
+ ],
872
+ methods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
873
+ allowedHeaders: ["Content-Type", "Authorization"],
874
+ credentials: true
875
+ },
876
+ headers: {
877
+ "Content-Security-Policy": "frame-ancestors https://app.nttmitway.com https://app.dev.nttmitway.com http://app.mitway.local http://localhost:*"
878
+ },
879
+ allowedHosts: [".azurecontainerapps.io", ".nttmitway.com"]
880
+ };
881
+ function createmITwayServerConfig(options = {}) {
882
+ const { additionalOrigins = [], additionalHosts = [], port = 80 } = options;
883
+ const allOrigins = [...mitwayServerConfig.cors.origin, ...additionalOrigins];
884
+ const allHosts = [...mitwayServerConfig.allowedHosts, ...additionalHosts];
885
+ const frameAncestors = allOrigins.filter((o) => typeof o === "string").join(" ");
886
+ return {
887
+ host: "0.0.0.0",
888
+ port,
889
+ cors: {
890
+ ...mitwayServerConfig.cors,
891
+ origin: allOrigins
892
+ },
893
+ headers: {
894
+ "Content-Security-Policy": `frame-ancestors ${frameAncestors} http://localhost:*`
895
+ },
896
+ allowedHosts: allHosts
897
+ };
898
+ }
899
+ // Annotate the CommonJS export names for ESM import in node:
900
+ 0 && (module.exports = {
901
+ createIframeNavigationPlugin,
902
+ createJsxSourcePlugin,
903
+ createThemeBridgePlugin,
904
+ createVirtualOverridesPlugin,
905
+ createVisualEditorPlugin,
906
+ createmITwayServerConfig,
907
+ mitwayServerConfig,
908
+ mitwayTagger
909
+ });