@ubox-tools/deploy-xperience 1.1.21 → 1.1.23

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 (3) hide show
  1. package/README.md +3 -2
  2. package/deploy.js +25 -51
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -106,15 +106,16 @@ When `--ubox-id` is provided, the search/create step is skipped entirely and the
106
106
 
107
107
  ## Proxy / Source Transformation
108
108
 
109
- Before injecting source files, `generateProxy()` applies three transforms to each file:
109
+ Before injecting source files, `generateProxy()` applies transforms to each file:
110
110
 
111
111
  | Transform | Applies to | What it does |
112
112
  |---|---|---|
113
- | Parameter substitution | JS | Replaces `const KEY = "value"` with `const KEY = "{parameter:KEY}"` for every key in `parameters.json` |
114
113
  | Asset path substitution | JS, CSS | Replaces `../assets/file.ext` references with `{resources:type/file.ext}` tokens |
115
114
  | Emoji escaping | JS | Converts non-ASCII characters to `\uXXXX` Unicode escape sequences |
116
115
  | Local tag stripping | HTML | Removes local `<link href>` and `<script src>` tags (CDN URLs are kept) |
117
116
 
117
+ > **Parameter tokens are embedded at authoring time** — `data.js` uses inline `{parameter:key}` tokens with local fallbacks. No deploy-time regex substitution is performed.
118
+
118
119
  ## Project Layout Expected
119
120
 
120
121
  ```
package/deploy.js CHANGED
@@ -238,15 +238,7 @@ function generateProxy(appName) {
238
238
  const isHTML = ext === 'html';
239
239
 
240
240
  if (isJS || isCSS) {
241
- // 1. Parameter token substitution (JS only — parameters live in JS files)
242
- if (isJS) {
243
- for (const key of Object.keys(params)) {
244
- const re = new RegExp(`((?:const|let|var)\\s+${key}\\s*=\\s*)(?:"[^"]*"|'[^']*')`, 'g');
245
- content = content.replace(re, `$1"{parameter:${key}}"`);
246
- }
247
- }
248
-
249
- // 2. Asset path substitution: "...assets/file.ext" → "{resources:type/file.ext}"
241
+ // 1. Asset path substitution: "...assets/file.ext" "{resources:type/file.ext}"
250
242
  const assetInStringRe = /(['"])(?:\.\.\/)*assets\/([^'"]+)\1/g;
251
243
  content = content.replace(assetInStringRe, (match, quote, assetFile) => {
252
244
  const assetExt = path.extname(assetFile).slice(1).toLowerCase();
@@ -416,33 +408,22 @@ async function uploadFile(page, absPath) {
416
408
  await client.detach();
417
409
  }
418
410
 
419
- /** Inject text content into the active Monaco/CodeMirror/Ace editor.
420
- * @param {string} filename Source filename (e.g. "index.html") — used to pick
421
- * the right Monaco model by URI when multiple models are
422
- * pre-loaded (e.g. after visiting the Parameters tab). */
423
- async function injectToEditor(page, content, filename) {
411
+ /** Inject text content into the active Monaco/CodeMirror/Ace editor. */
412
+ async function injectToEditor(page, content) {
424
413
  // Try Monaco API
425
- const monacoResult = await page.evaluate((text, fn) => {
426
- if (!window.monaco?.editor) return null;
414
+ const monacoOk = await page.evaluate(text => {
415
+ if (!window.monaco?.editor) return false;
427
416
  const models = window.monaco.editor.getModels();
428
- if (!models?.length) return null;
429
-
430
- // Best: match model by filename in its URI avoids the models[0] trap when
431
- // multiple models are pre-loaded (happens after visiting the Parameters tab).
432
- if (fn) {
433
- const m = models.find(m => m.uri?.toString().includes(fn));
434
- if (m) { m.setValue(text); return 'uri'; }
435
- }
436
-
437
- // Safe fallback: single model is always the active one (lazy-load case).
438
- if (models.length === 1) { models[0].setValue(text); return 'single'; }
439
-
440
- // Multiple models, no URI match — fall through to keyboard injection.
441
- return `multi:${models.length}:${models.map(m => m.uri?.toString()).join('|')}`;
442
- }, content, filename ?? null);
443
-
444
- if (monacoResult === 'uri' || monacoResult === 'single') return;
445
- if (monacoResult) console.log(` [editor] Monaco ${monacoResult} → keyboard fallback`);
417
+ if (!models?.length) return false;
418
+ // Use the LAST model, not the first. When the Parameters tab is visited before
419
+ // the source editor, Monaco pre-loads a read-only preview model (model/1) first.
420
+ // The actual edit model (model/4) is created later and sits at the end of the
421
+ // list. For apps with no parameters (lazy-load), there is only one model, so
422
+ // last === first and behaviour is unchanged.
423
+ models[models.length - 1].setValue(text);
424
+ return true;
425
+ }, content);
426
+ if (monacoOk) return;
446
427
 
447
428
  // Try CodeMirror API
448
429
  const cmOk = await page.evaluate(text => {
@@ -452,23 +433,16 @@ async function injectToEditor(page, content, filename) {
452
433
  }, content);
453
434
  if (cmOk) return;
454
435
 
455
- // Keyboard injection: click the visible editor, Ctrl+A, Ctrl+V.
456
- // Targets whatever editor is currently focused (active tab) — model-agnostic.
436
+ // Fallback: clipboard paste into Ace / generic textarea
457
437
  writeClipboard(content);
458
- const edPos = await page.evaluate(() => {
459
- for (const sel of ['.monaco-editor', '.ace_editor', '.cm-editor', 'textarea']) {
460
- const el = Array.from(document.querySelectorAll(sel))
461
- .find(e => { const r = e.getBoundingClientRect(); return r.width > 10 && r.height > 10; });
462
- if (el) {
463
- el.scrollIntoView({ block: 'nearest' });
464
- const r = el.getBoundingClientRect();
465
- return { x: Math.round(r.x + r.width / 2), y: Math.round(r.y + r.height / 2) };
466
- }
467
- }
468
- return null;
469
- });
470
- if (!edPos) throw new Error('No code editor found on page');
471
- await page.mouse.click(edPos.x, edPos.y);
438
+ const ed = await page.$('.ace_editor, .cm-editor, .monaco-editor, textarea');
439
+ if (!ed) throw new Error('No code editor found on page');
440
+ const edRect = await page.evaluate(el => {
441
+ el.scrollIntoView({ block: 'nearest' });
442
+ const r = el.getBoundingClientRect();
443
+ return { x: Math.round(r.x + r.width / 2), y: Math.round(r.y + r.height / 2) };
444
+ }, ed);
445
+ await page.mouse.click(edRect.x, edRect.y);
472
446
  await sleep(200);
473
447
  await page.keyboard.down('Control');
474
448
  await page.keyboard.press('a');
@@ -705,7 +679,7 @@ async function injectSource(page, proxy) {
705
679
  console.log(` ${filename} → ${tabLabel}`);
706
680
  await clickByText(page, tabLabel);
707
681
  await sleep(1000);
708
- await injectToEditor(page, proxy[filename], filename);
682
+ await injectToEditor(page, proxy[filename]);
709
683
  await sleep(500);
710
684
  }
711
685
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ubox-tools/deploy-xperience",
3
- "version": "1.1.21",
3
+ "version": "1.1.23",
4
4
  "description": "Deploy a Ubox experience to studio.ubox.world",
5
5
  "bin": { "deploy-xperience": "./deploy.js" },
6
6
  "dependencies": { "puppeteer": "*" },