draply-dev 1.4.2 → 1.4.4

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/bin/cli.js CHANGED
@@ -211,7 +211,16 @@ const server = http.createServer((req, res) => {
211
211
  if (ctxEnd === -1 || e > ctxEnd) ctxEnd = e;
212
212
  }
213
213
  }
214
- if (ctxStart === -1) { ctxStart = 0; ctxEnd = Math.min(lines.length - 1, 150); }
214
+ if (ctxStart === -1 && items.some(c => c.type === 'create')) {
215
+ for (let i = lines.length - 1; i >= 0; i--) {
216
+ if (lines[i].includes('</body>')) {
217
+ ctxStart = Math.max(0, i - 20);
218
+ ctxEnd = Math.min(lines.length - 1, i + 20);
219
+ break;
220
+ }
221
+ }
222
+ }
223
+ if (ctxStart === -1) { ctxStart = 0; ctxEnd = Math.min(lines.length - 1, 300); }
215
224
 
216
225
  const snippet = lines.slice(ctxStart, ctxEnd + 1).join('\n');
217
226
 
@@ -315,9 +324,26 @@ Return ONLY the patch blocks.`;
315
324
  console.log(` \x1b[32m✓\x1b[0m Modified ${path.basename(filePath)} (${applied} patch(es))`);
316
325
  items.forEach(item => results.push({ selector: item.selector, ok: true }));
317
326
  } else {
318
- console.warn(` \x1b[33m⚠\x1b[0m AI matched 0 patches in ${path.basename(filePath)}`);
319
- items.forEach(item => results.push({ selector: item.selector, ok: false, reason: 'AI patch failed to match' }));
320
- }
327
+ console.warn(` \x1b[33m⚠\x1b[0m AI matched 0 patches in ${path.basename(filePath)}`);
328
+ console.log("Full AI response context for debugging:");
329
+ console.log(apiResult);
330
+
331
+ // Forced fallback for creation if AI suggested something but failed exact match
332
+ if (items.some(it => it.type === 'create') && patches.length > 0) {
333
+ console.log("Attempting forced creation fallback...");
334
+ const index = content.toLowerCase().lastIndexOf('</body>');
335
+ if (index >= 0) {
336
+ const creationItem = items.find(it => it.type === 'create');
337
+ const patched = content.slice(0, index) + creationItem.outerHTML + '\n' + content.slice(index);
338
+ const final = rawContent.includes('\r\n') ? patched.replace(/\n/g, '\r\n') : patched;
339
+ fs.writeFileSync(filePath, final, 'utf8');
340
+ console.log(` \x1b[32m✓\x1b[0m Forced creation applied to ${path.basename(filePath)}`);
341
+ items.forEach(item => results.push({ selector: item.selector, ok: true }));
342
+ return;
343
+ }
344
+ }
345
+ items.forEach(item => results.push({ selector: item.selector, ok: false, reason: 'AI patch failed to match' }));
346
+ }
321
347
  } catch (e) {
322
348
  console.error(` \x1b[31m✖\x1b[0m AI Error for ${path.basename(filePath)}:`, e.message);
323
349
  items.forEach(item => results.push({ selector: item.selector, ok: false, reason: e.message }));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "draply-dev",
3
- "version": "1.4.2",
3
+ "version": "1.4.4",
4
4
  "description": "Visual overlay for any frontend project — move, resize, restyle live in the browser, save to CSS",
5
5
  "author": "Arman",
6
6
  "type": "commonjs",
package/src/overlay.js CHANGED
@@ -924,7 +924,9 @@
924
924
  const cs = getComputedStyle(el);
925
925
  const newLeft = Math.round(parseFloat(cs.left)) + 'px';
926
926
  const newTop = Math.round(parseFloat(cs.top)) + 'px';
927
- rec(el, { left: newLeft, top: newTop }, { left: prevL, top: prevT });
927
+ if (newLeft !== prevL || newTop !== prevT) {
928
+ rec(el, { left: newLeft, top: newTop }, { left: prevL, top: prevT });
929
+ }
928
930
  });
929
931
  state.dragOrigPositions = [];
930
932
  dEl = null;
@@ -1006,12 +1008,15 @@
1006
1008
  left: Math.round(state.resizeOrigL) + 'px',
1007
1009
  top: Math.round(state.resizeOrigT) + 'px',
1008
1010
  };
1009
- rec(rzEl, {
1011
+ const newSize = {
1010
1012
  width: Math.round(parseFloat(cs.width)) + 'px',
1011
1013
  height: Math.round(parseFloat(cs.height)) + 'px',
1012
1014
  left: Math.round(parseFloat(cs.left)) + 'px',
1013
1015
  top: Math.round(parseFloat(cs.top)) + 'px',
1014
- }, prevProps);
1016
+ };
1017
+ if (newSize.width !== prevProps.width || newSize.height !== prevProps.height || newSize.left !== prevProps.left || newSize.top !== prevProps.top) {
1018
+ rec(rzEl, newSize, prevProps);
1019
+ }
1015
1020
  rzEl = null; rzDir = null;
1016
1021
  });
1017
1022
 
@@ -1480,10 +1485,11 @@
1480
1485
  if (!astDragEl) return;
1481
1486
  tip.classList.remove('v');
1482
1487
  const cs = getComputedStyle(astDragEl);
1483
- rec(astDragEl, {
1484
- left: Math.round(parseFloat(cs.left)) + 'px',
1485
- top: Math.round(parseFloat(cs.top)) + 'px',
1486
- });
1488
+ const newLeft = Math.round(parseFloat(cs.left)) + 'px';
1489
+ const newTop = Math.round(parseFloat(cs.top)) + 'px';
1490
+ if (newLeft !== (astDragOL + 'px') || newTop !== (astDragOT + 'px')) {
1491
+ rec(astDragEl, { left: newLeft, top: newTop });
1492
+ }
1487
1493
  astDragEl.style.cursor = 'grab';
1488
1494
  astDragEl = null;
1489
1495
  });
@@ -1537,6 +1543,15 @@
1537
1543
  const i = state.changes.findIndex(c => (c.pixelshiftId || c.selector) === key);
1538
1544
  if (i >= 0) Object.assign(state.changes[i].props, props); else state.changes.push(ch);
1539
1545
 
1546
+ // Deep check: only record if at least one property actually changed
1547
+ let changed = isCreate;
1548
+ if (!isCreate) {
1549
+ for (const p in props) {
1550
+ if (String(props[p]) !== String(prevProps[p])) { changed = true; break; }
1551
+ }
1552
+ }
1553
+ if (!changed) return;
1554
+
1540
1555
  // Push to history
1541
1556
  const hid = Date.now() + Math.random();
1542
1557
  history.push({ hid, el, props, prevProps, selector: key, isCreate });