draply-dev 1.3.8 → 1.3.9

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 (2) hide show
  1. package/bin/cli.js +30 -24
  2. package/package.json +1 -1
package/bin/cli.js CHANGED
@@ -291,41 +291,47 @@ ${snippet}
291
291
 
292
292
  CHANGES:
293
293
  ${changesBlock}
294
- IMPORTANT: Return ONLY a JSON array of search-and-replace pairs. Each pair format:
295
- {"search": "exact code to find", "replace": "modified code to replace it with"}
294
+ IMPORTANT: Return your changes wrapped in <patch> tags containing <search> and <replace> blocks. DO NOT use JSON.
296
295
 
297
296
  Rules:
298
- - "search" must be an EXACT substring from the file snippet above (copy it precisely).
299
- - Ensure all double quotes inside JSON string values are properly escaped (\\").
300
- - Do NOT include markdown fences, preambles, or explanations. Only the JSON array.
297
+ - The content inside <search> must be an EXACT substring from the file snippet above.
301
298
  - If adding properties to an existing CSS rule or JS object (like a style object), you MUST REPLACE the old values for those properties if they already exist. DO NOT CREATE DUPLICATE KEYS.
302
- - If the file is JSX, update the style object/prop. Do not duplicate properties inside object literals.
299
+ - If the file is JSX, update the style object/prop without duplicating properties.
303
300
 
304
301
  Example response:
305
- [
306
- {
307
- "search": "style={{ color: 'blue', opacity: 0.5 }}",
308
- "replace": "style={{ color: '#ff0000', opacity: 0.5 }}"
309
- }
310
- ]`;
302
+ <patch>
303
+ <search>
304
+ <section className="hero" style={{ padding: '10px' }}>
305
+ </search>
306
+ <replace>
307
+ <section className="hero" style={{ padding: '10px', color: '#ff0000' }}>
308
+ </replace>
309
+ </patch>
310
+
311
+ Return ONLY the patch blocks.`;
311
312
 
312
313
  try {
313
314
  const result = await callAI(cfg.apiKey, prompt, cfg.provider || 'groq');
314
315
 
315
- // Extract JSON array using regex to ignore any surrounding text/markdown
316
- let jsonStr = result.trim();
317
- const match = jsonStr.match(/\[[\s\S]*\]/);
318
- if (match) {
319
- jsonStr = match[0];
316
+ const patches = [];
317
+ const patchRegex = /<search>([\s\S]*?)<\/search>[\s\S]*?<replace>([\s\S]*?)<\/replace>/g;
318
+ let match;
319
+ while ((match = patchRegex.exec(result)) !== null) {
320
+ let s = match[1];
321
+ let r = match[2];
322
+ // Remove exactly one leading/trailing newline if AI added them around the tags
323
+ if (s.startsWith('\n')) s = s.substring(1);
324
+ if (s.endsWith('\n')) s = s.substring(0, s.length - 1);
325
+ if (r.startsWith('\n')) r = r.substring(1);
326
+ if (r.endsWith('\n')) r = r.substring(0, r.length - 1);
327
+
328
+ if (s.trim()) patches.push({ search: s, replace: r });
320
329
  }
321
330
 
322
- let patches;
323
- try {
324
- patches = JSON.parse(jsonStr);
325
- } catch (err) {
326
- console.log(` \x1b[31m✗\x1b[0m AI returned invalid JSON`);
327
- console.log(` Response: ${jsonStr.substring(0, 300)}`);
328
- items.forEach(item => results.push({ selector: item.selector, ok: false, reason: 'AI returned invalid JSON: ' + err.message }));
331
+ if (patches.length === 0) {
332
+ console.log(` \x1b[31m✗\x1b[0m AI returned no readable patches`);
333
+ console.log(` Response: ${result.substring(0, 300)}`);
334
+ items.forEach(item => results.push({ selector: item.selector, ok: false, reason: 'AI returned no format matches' }));
329
335
  continue;
330
336
  }
331
337
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "draply-dev",
3
- "version": "1.3.8",
3
+ "version": "1.3.9",
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",