@monoes/monodesign 1.2.11 → 1.2.12

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 (48) hide show
  1. package/cli/engine/browser/injected/index.mjs +16 -18
  2. package/cli/engine/cli/main.mjs +3 -3
  3. package/cli/engine/detect-antipatterns-browser.js +67 -47
  4. package/cli/engine/engines/regex/detect-text.mjs +6 -6
  5. package/cli/engine/engines/static-html/css-cascade.mjs +6 -5
  6. package/cli/engine/engines/static-html/detect-html.mjs +6 -6
  7. package/cli/engine/fix/index.mjs +3 -3
  8. package/cli/engine/node/file-system.mjs +1 -1
  9. package/cli/engine/registry/antipatterns.mjs +1 -1
  10. package/cli/engine/rules/checks.mjs +24 -25
  11. package/cli/engine/shared/color.mjs +2 -2
  12. package/cli/engine/shared/constants.mjs +1 -1
  13. package/cli/engine/shared/inline-ignores.mjs +2 -2
  14. package/cli/lib/monodesign-config.mjs +5 -5
  15. package/package.json +11 -10
  16. package/skill/scripts/context.mjs +4 -4
  17. package/skill/scripts/critique-storage.mjs +1 -1
  18. package/skill/scripts/detect-csp.mjs +1 -6
  19. package/skill/scripts/hook-admin.mjs +6 -6
  20. package/skill/scripts/hook-before-edit.mjs +4 -4
  21. package/skill/scripts/hook-lib.mjs +20 -11
  22. package/skill/scripts/hook.mjs +1 -1
  23. package/skill/scripts/lib/design-parser.mjs +9 -42
  24. package/skill/scripts/lib/is-generated.mjs +1 -1
  25. package/skill/scripts/lib/monodesign-paths.mjs +1 -1
  26. package/skill/scripts/live/event-validation.mjs +13 -13
  27. package/skill/scripts/live/manual-apply.mjs +4 -4
  28. package/skill/scripts/live/manual-edits-buffer.mjs +1 -1
  29. package/skill/scripts/live/session-store.mjs +5 -5
  30. package/skill/scripts/live/svelte-component.mjs +13 -13
  31. package/skill/scripts/live/sveltekit-adapter.mjs +4 -4
  32. package/skill/scripts/live/ui-core.mjs +1 -1
  33. package/skill/scripts/live-accept.mjs +24 -24
  34. package/skill/scripts/live-browser-dom.js +8 -7
  35. package/skill/scripts/live-browser-session.js +8 -7
  36. package/skill/scripts/live-browser.js +405 -432
  37. package/skill/scripts/live-commit-manual-edits.mjs +6 -6
  38. package/skill/scripts/live-copy-edit-agent.mjs +2 -2
  39. package/skill/scripts/live-discard-manual-edits.mjs +1 -1
  40. package/skill/scripts/live-inject.mjs +7 -7
  41. package/skill/scripts/live-insert.mjs +11 -11
  42. package/skill/scripts/live-manual-edit-evidence.mjs +4 -4
  43. package/skill/scripts/live-poll.mjs +5 -5
  44. package/skill/scripts/live-server.mjs +10 -10
  45. package/skill/scripts/live-wrap.mjs +31 -41
  46. package/skill/scripts/live.mjs +5 -5
  47. package/skill/scripts/palette.mjs +3 -1
  48. package/skill/scripts/pin.mjs +1 -1
@@ -73,6 +73,15 @@ export const SENSITIVE_PATH = new RegExp([
73
73
  // Hard-skip regex for generated, lock, minified, and build-output paths.
74
74
  export const GENERATED_PATH = /(?:\.generated\.[a-z]+$|\.d\.ts$|\.min\.[a-z]+$|[/\\]node_modules[/\\]|[/\\](?:dist|build|out|\.next|\.cache|coverage)[/\\]|[/\\]?[^/\\]+\.lock(?:\.json)?$)/i;
75
75
 
76
+ // GENERATED_PATH checked against the path inside the project, so a project
77
+ // that lives under e.g. ~/.cache/ or /srv/build/ is still scanned. Paths
78
+ // outside the project root fall back to the absolute path.
79
+ export function isGeneratedPath(filePath, projectRoot) {
80
+ const rel = path.relative(path.resolve(projectRoot), path.resolve(filePath));
81
+ const inside = rel !== '' && !rel.startsWith('..') && !path.isAbsolute(rel);
82
+ return GENERATED_PATH.test(inside ? path.sep + rel : filePath);
83
+ }
84
+
76
85
  export const TRUTHY = /^(1|true|yes|on)$/i;
77
86
 
78
87
  export const DEFAULT_CONFIG = Object.freeze({
@@ -184,7 +193,7 @@ export function resolveCacheCwd(primaryFile, sessionCwd) {
184
193
  export function resolveProjectPlatform(cwd) {
185
194
  try {
186
195
  const ctx = loadContext(cwd);
187
- return extractPlatform(ctx && ctx.product);
196
+ return extractPlatform(ctx?.product);
188
197
  } catch {
189
198
  return null;
190
199
  }
@@ -239,7 +248,7 @@ function applyDetectorConfigSource(config, raw) {
239
248
  if (raw.designSystem && typeof raw.designSystem === 'object' && !Array.isArray(raw.designSystem)) {
240
249
  config.designSystem = {
241
250
  ...config.designSystem,
242
- enabled: raw.designSystem.enabled === false ? false : true,
251
+ enabled: raw.designSystem.enabled !== false,
243
252
  };
244
253
  }
245
254
  if (Array.isArray(raw.ignoreRules)) {
@@ -302,10 +311,10 @@ export function matchConfiguredExtension(filePath, extensions) {
302
311
 
303
312
  function applyConfigSource(config, raw) {
304
313
  if (!raw || typeof raw !== 'object') return config;
305
- if (Object.prototype.hasOwnProperty.call(raw, 'enabled')) {
306
- config.enabled = raw.enabled === false ? false : true;
314
+ if (Object.hasOwn(raw, 'enabled')) {
315
+ config.enabled = raw.enabled !== false;
307
316
  }
308
- if (Object.prototype.hasOwnProperty.call(raw, 'quiet')) {
317
+ if (Object.hasOwn(raw, 'quiet')) {
309
318
  config.quiet = raw.quiet === true;
310
319
  }
311
320
  if (typeof raw.auditLog === 'string' && raw.auditLog.trim()) {
@@ -399,7 +408,7 @@ function splitColorArgs(body) {
399
408
  if (text.includes(',')) {
400
409
  const parts = text.split(',').map((part) => part.trim()).filter(Boolean);
401
410
  const last = parts[parts.length - 1];
402
- if (last && last.includes('/')) {
411
+ if (last?.includes('/')) {
403
412
  const split = last.split('/').map((part) => part.trim()).filter(Boolean);
404
413
  return [...parts.slice(0, -1), ...split];
405
414
  }
@@ -944,7 +953,7 @@ function clampGroupedToBudget(header, lines, footer, maxChars) {
944
953
  footer,
945
954
  ].join('\n');
946
955
 
947
- let working = lines.slice();
956
+ const working = lines.slice();
948
957
  let omitted = false;
949
958
  let assembled = assemble(working, omitted);
950
959
  while (assembled.length > maxChars && working.length > 1) {
@@ -967,7 +976,7 @@ function clampToBudget(header, lines, more, footer, maxChars) {
967
976
  return blocks.join('\n');
968
977
  };
969
978
 
970
- let working = lines.slice();
979
+ const working = lines.slice();
971
980
  let moreText = more;
972
981
  let assembled = assemble(working, moreText);
973
982
  while (assembled.length > maxChars && working.length > 1) {
@@ -1351,7 +1360,7 @@ export function writeAuditLog(env, entry, cwd = process.cwd()) {
1351
1360
  expanded = path.resolve(baseCwd, target);
1352
1361
  }
1353
1362
  fs.mkdirSync(path.dirname(expanded), { recursive: true });
1354
- const line = JSON.stringify({ ts: new Date().toISOString(), ...entry }) + '\n';
1363
+ const line = `${JSON.stringify({ ts: new Date().toISOString(), ...entry })}\n`;
1355
1364
  fs.appendFileSync(expanded, line);
1356
1365
  return true;
1357
1366
  } catch {
@@ -1573,7 +1582,7 @@ export async function runHook({ stdinJson, env = {}, cwd = process.cwd(), now =
1573
1582
  lastSkip = 'sensitive';
1574
1583
  continue;
1575
1584
  }
1576
- if (GENERATED_PATH.test(filePath)) {
1585
+ if (isGeneratedPath(filePath, projectCwd)) {
1577
1586
  lastSkip = 'generated';
1578
1587
  continue;
1579
1588
  }
@@ -1756,7 +1765,7 @@ export async function runHook({ stdinJson, env = {}, cwd = process.cwd(), now =
1756
1765
  return {
1757
1766
  exitCode: 0,
1758
1767
  stdout: '',
1759
- audit: { ...audit, error: String(err && err.message ? err.message : err) },
1768
+ audit: { ...audit, error: String(err?.message ? err.message : err) },
1760
1769
  };
1761
1770
  }
1762
1771
  }
@@ -51,7 +51,7 @@ main().catch((err) => {
51
51
  writeAuditLog(process.env, {
52
52
  ts: new Date().toISOString(),
53
53
  event: 'PostToolUse',
54
- error: String(err && err.message ? err.message : err),
54
+ error: String(err?.message ? err.message : err),
55
55
  });
56
56
  } catch { /* swallow */ }
57
57
  if (process.env.MONODESIGN_HOOK_DEBUG) {
@@ -130,9 +130,6 @@ function parseScalar(raw) {
130
130
 
131
131
  const HEX_RE = /#[0-9a-fA-F]{3,8}\b/g;
132
132
  const OKLCH_RE = /oklch\([^)]+\)/gi;
133
- const RGBA_RE = /rgba?\([^)]+\)/gi;
134
- const BOX_SHADOW_RE = /(?:box-shadow:\s*)?((?:-?\d[\w\d\s\-.,/()#%]*)+)/;
135
- const NAMED_RULE_RE = /\*\*(The [^*]+?Rule)\.\*\*\s*(.+)/;
136
133
 
137
134
  // ---------- Section splitting ----------
138
135
 
@@ -246,7 +243,7 @@ function collectBullets(lines) {
246
243
  }
247
244
  // continuation of a bullet (indented line)
248
245
  if (current && raw.match(/^\s{2,}\S/)) {
249
- current += ' ' + raw.trim();
246
+ current += ` ${raw.trim()}`;
250
247
  continue;
251
248
  }
252
249
  // blank line ends a bullet
@@ -415,7 +412,7 @@ function parseColorBullet(bullet) {
415
412
 
416
413
  // Case 1 (Monodesign): **Name** (value-with-maybe-nested-parens): description
417
414
  const bold = text.match(/^\*\*(.+?)\*\*\s*(.*)$/);
418
- if (bold && bold[2].startsWith('(')) {
415
+ if (bold?.[2].startsWith('(')) {
419
416
  const value = extractParenGroup(bold[2]);
420
417
  if (value !== null) {
421
418
  const after = bold[2].slice(value.length + 2).trimStart();
@@ -485,36 +482,6 @@ function detectFormat(v) {
485
482
  return 'unknown';
486
483
  }
487
484
 
488
- function scanInlineColors(lines) {
489
- const out = [];
490
- for (const line of lines) {
491
- if (!/^\s*[-*]\s/.test(line)) continue;
492
- const trimmed = line.replace(/^\s*[-*]\s+/, '');
493
- const color = parseColorBullet(trimmed);
494
- if (color) out.push(color);
495
- }
496
- return out;
497
- }
498
-
499
- function parseStitchInlineGroups(lines) {
500
- // Stitch writes: `* **Primary (`#00478d` to `#005eb8`):** Use for "..."`
501
- // Each bullet IS its own role. Group them under the spoken role name.
502
- const out = [];
503
- for (const line of lines) {
504
- if (!/^\s*[-*]\s/.test(line)) continue;
505
- const trimmed = line.replace(/^\s*[-*]\s+/, '').trim();
506
- const m = trimmed.match(
507
- /^\*\*([A-Z][a-zA-Z]+)\s*\(([^)]+)\):\*\*\s*(.*)$/
508
- );
509
- if (m) {
510
- const role = m[1];
511
- const color = buildColor(role, m[2], m[3]);
512
- out.push({ role, colors: [color] });
513
- }
514
- }
515
- return out;
516
- }
517
-
518
485
  function extractTypography(section) {
519
486
  if (!section) return null;
520
487
  const text = section.lines.join('\n');
@@ -611,7 +578,7 @@ function extractElevation(section) {
611
578
  const shadows = [];
612
579
  const seen = new Set();
613
580
  const dedupe = (entry) => {
614
- const key = (entry.name || '') + '::' + entry.value;
581
+ const key = `${entry.name || ''}::${entry.value}`;
615
582
  if (seen.has(key)) return;
616
583
  seen.add(key);
617
584
  shadows.push(entry);
@@ -660,7 +627,7 @@ function extractInlineShadows(text) {
660
627
  .trim();
661
628
  if (stripped) {
662
629
  name =
663
- stripped.charAt(0).toUpperCase() + stripped.slice(1) + ' shadow';
630
+ `${stripped.charAt(0).toUpperCase() + stripped.slice(1)} shadow`;
664
631
  }
665
632
  }
666
633
  out.push({
@@ -830,11 +797,11 @@ export function parseDesignMd(md) {
830
797
  schemaVersion: 2,
831
798
  title,
832
799
  frontmatter,
833
- overview: extractOverview(sections['Overview']),
834
- colors: extractColors(sections['Colors']),
835
- typography: extractTypography(sections['Typography']),
836
- elevation: extractElevation(sections['Elevation']),
837
- components: extractComponents(sections['Components']),
800
+ overview: extractOverview(sections.Overview),
801
+ colors: extractColors(sections.Colors),
802
+ typography: extractTypography(sections.Typography),
803
+ elevation: extractElevation(sections.Elevation),
804
+ components: extractComponents(sections.Components),
838
805
  dosDonts: extractDosDonts(sections["Do's and Don'ts"]),
839
806
  };
840
807
  }
@@ -46,7 +46,7 @@ function isGitIgnored(absPath, cwd) {
46
46
  stdio: 'ignore',
47
47
  });
48
48
  return true; // exit 0 = ignored
49
- } catch (err) {
49
+ } catch {
50
50
  // Exit code 1 = not ignored. Exit code 128 = not a git repo or other error.
51
51
  // In both cases, treat as "not known to be ignored."
52
52
  return false;
@@ -43,7 +43,7 @@ export function getLegacyLiveConfigPath(scriptsDir) {
43
43
  }
44
44
 
45
45
  export function resolveLiveConfigPath({ cwd = process.cwd(), scriptsDir, env = process.env, targetPath } = {}) {
46
- if (env.MONODESIGN_LIVE_CONFIG && env.MONODESIGN_LIVE_CONFIG.trim()) {
46
+ if (env.MONODESIGN_LIVE_CONFIG?.trim()) {
47
47
  const configured = env.MONODESIGN_LIVE_CONFIG.trim();
48
48
  return path.isAbsolute(configured) ? configured : path.resolve(cwd, configured);
49
49
  }
@@ -62,30 +62,30 @@ function validateInsertGenerate(msg) {
62
62
 
63
63
  function validateReplaceGenerate(msg) {
64
64
  if (!msg.action || !VISUAL_ACTIONS.includes(msg.action)) return 'generate: invalid action';
65
- if (!msg.element || !msg.element.outerHTML) return 'generate: missing element context';
65
+ if (!msg.element?.outerHTML) return 'generate: missing element context';
66
66
  return validateAnnotationFields(msg);
67
67
  }
68
68
 
69
69
  function validateManualEditEvent(msg, label) {
70
- if (!isValidId(msg.id)) return label + ': missing or malformed id';
71
- if (!msg.pageUrl || typeof msg.pageUrl !== 'string') return label + ': missing pageUrl';
72
- if (!msg.element || typeof msg.element !== 'object') return label + ': missing element';
73
- if (!Array.isArray(msg.ops) || msg.ops.length === 0) return label + ': ops must be non-empty array';
74
- if (msg.ops.length > 100) return label + ': too many ops (max 100)';
70
+ if (!isValidId(msg.id)) return `${label}: missing or malformed id`;
71
+ if (!msg.pageUrl || typeof msg.pageUrl !== 'string') return `${label}: missing pageUrl`;
72
+ if (!msg.element || typeof msg.element !== 'object') return `${label}: missing element`;
73
+ if (!Array.isArray(msg.ops) || msg.ops.length === 0) return `${label}: ops must be non-empty array`;
74
+ if (msg.ops.length > 100) return `${label}: too many ops (max 100)`;
75
75
  for (const op of msg.ops) {
76
- if (typeof op.ref !== 'string') return label + ': op.ref required';
77
- if (typeof op.tag !== 'string') return label + ': op.tag required';
78
- if (typeof op.originalText !== 'string') return label + ': op.originalText required';
76
+ if (typeof op.ref !== 'string') return `${label}: op.ref required`;
77
+ if (typeof op.tag !== 'string') return `${label}: op.tag required`;
78
+ if (typeof op.originalText !== 'string') return `${label}: op.originalText required`;
79
79
  if (op.deleted !== true && typeof op.newText !== 'string') {
80
- return label + ': text op requires newText';
80
+ return `${label}: text op requires newText`;
81
81
  }
82
82
  if (typeof op.newText === 'string') {
83
83
  if (op.deleted !== true && op.newText.trim().length === 0) {
84
- return label + ': newText cannot be empty';
84
+ return `${label}: newText cannot be empty`;
85
85
  }
86
86
  const forbidden = validateManualEditText(op.newText);
87
87
  if (forbidden) {
88
- return label + ': newText cannot contain ' + forbidden.join(' ') + ' (plain text only; ask the AI to insert markup)';
88
+ return `${label}: newText cannot contain ${forbidden.join(' ')} (plain text only; ask the AI to insert markup)`;
89
89
  }
90
90
  }
91
91
  }
@@ -132,6 +132,6 @@ export function validateEvent(msg) {
132
132
  if (msg.pageUrl !== undefined && typeof msg.pageUrl !== 'string') return 'steer: pageUrl must be string';
133
133
  return null;
134
134
  default:
135
- return 'Unknown event type: ' + msg.type;
135
+ return `Unknown event type: ${msg.type}`;
136
136
  }
137
137
  }
@@ -326,7 +326,7 @@ export function writeManualApplyEvidence(eventId, batch, cwd = process.cwd()) {
326
326
  const dir = manualApplyEvidenceDir(cwd);
327
327
  fs.mkdirSync(dir, { recursive: true });
328
328
  const evidencePath = path.join(dir, `${eventId}.json`);
329
- fs.writeFileSync(evidencePath, JSON.stringify(batch, null, 2) + '\n', 'utf-8');
329
+ fs.writeFileSync(evidencePath, `${JSON.stringify(batch, null, 2)}\n`, 'utf-8');
330
330
  return evidencePath;
331
331
  }
332
332
 
@@ -495,7 +495,7 @@ function invalidManualApplyResult(reason, eventId, extra = {}) {
495
495
  }
496
496
 
497
497
  export function validateManualApplyResultMessage(msg, deferred) {
498
- let data = msg?.data;
498
+ const data = msg?.data;
499
499
  const eventId = msg?.id || deferred?.event?.id || 'EVENT_ID';
500
500
  if (!data || typeof data !== 'object' || Array.isArray(data)) {
501
501
  return invalidManualApplyResult('missing_result_data', eventId);
@@ -743,7 +743,7 @@ export function writeManualApplyTransaction({ cwd = process.cwd(), pageUrl = nul
743
743
  }),
744
744
  };
745
745
  fs.mkdirSync(path.dirname(file), { recursive: true });
746
- fs.writeFileSync(`${file}.tmp`, JSON.stringify(transaction, null, 2) + '\n', 'utf-8');
746
+ fs.writeFileSync(`${file}.tmp`, `${JSON.stringify(transaction, null, 2)}\n`, 'utf-8');
747
747
  fs.renameSync(`${file}.tmp`, file);
748
748
  return transaction;
749
749
  }
@@ -935,5 +935,5 @@ export function compactManualLogText(value, max = 200) {
935
935
  if (typeof value !== 'string') return undefined;
936
936
  const normalized = value.replace(/\s+/g, ' ').trim();
937
937
  if (normalized.length <= max) return normalized;
938
- return normalized.slice(0, max) + `... [truncated ${normalized.length - max} chars]`;
938
+ return `${normalized.slice(0, max)}... [truncated ${normalized.length - max} chars]`;
939
939
  }
@@ -41,7 +41,7 @@ function readBufferInternal(cwd, { strict }) {
41
41
  return { version: BUFFER_VERSION, entries: parsed.entries };
42
42
  } catch (err) {
43
43
  if (strict && err?.code !== 'ENOENT') {
44
- throw new Error('manual_edit_buffer_unreadable: ' + (err.message || String(err)));
44
+ throw new Error(`manual_edit_buffer_unreadable: ${err.message || String(err)}`);
45
45
  }
46
46
  return { version: BUFFER_VERSION, entries: [] };
47
47
  }
@@ -51,7 +51,7 @@ export function createLiveSessionStore({ cwd = process.cwd(), sessionId } = {})
51
51
  ts: new Date().toISOString(),
52
52
  event: normalized,
53
53
  };
54
- fs.appendFileSync(journalPath, JSON.stringify(entry) + '\n');
54
+ fs.appendFileSync(journalPath, `${JSON.stringify(entry)}\n`);
55
55
  const next = applyEvent(prior.snapshot, entry, prior.diagnostics);
56
56
  snapshotCache.set(normalized.id, { snapshot: next, diagnostics: next.diagnostics || [], nextSeq: seq + 1 });
57
57
  writeSnapshot(snapshotPath, next);
@@ -92,15 +92,15 @@ function normalizeEvent(event, fallbackId) {
92
92
  }
93
93
 
94
94
  function getJournalPath(rootDir, id) {
95
- return path.join(rootDir, safeSessionId(id) + '.jsonl');
95
+ return path.join(rootDir, `${safeSessionId(id)}.jsonl`);
96
96
  }
97
97
 
98
98
  function getSnapshotPath(rootDir, id) {
99
- return path.join(rootDir, safeSessionId(id) + '.snapshot.json');
99
+ return path.join(rootDir, `${safeSessionId(id)}.snapshot.json`);
100
100
  }
101
101
 
102
102
  function safeSessionId(id) {
103
- if (!/^[A-Za-z0-9_-]{1,128}$/.test(id)) throw new Error('invalid session id: ' + id);
103
+ if (!/^[A-Za-z0-9_-]{1,128}$/.test(id)) throw new Error(`invalid session id: ${id}`);
104
104
  return id;
105
105
  }
106
106
 
@@ -289,5 +289,5 @@ function upsertArtifact(artifacts, artifact) {
289
289
  }
290
290
 
291
291
  function writeSnapshot(snapshotPath, snapshot) {
292
- fs.writeFileSync(snapshotPath, JSON.stringify(snapshot, null, 2) + '\n');
292
+ fs.writeFileSync(snapshotPath, `${JSON.stringify(snapshot, null, 2)}\n`);
293
293
  }
@@ -73,7 +73,7 @@ export function buildPropContract(expressions) {
73
73
 
74
74
  function derivePropName(expr, index) {
75
75
  const tail = expr.match(/(?:\.|\[)(\w+)\s*\]?$/);
76
- if (tail && tail[1] && /^[A-Za-z_$][\w$]*$/.test(tail[1])) {
76
+ if (tail?.[1] && /^[A-Za-z_$][\w$]*$/.test(tail[1])) {
77
77
  return tail[1];
78
78
  }
79
79
  return `prop${index}`;
@@ -166,7 +166,7 @@ export function scaffoldSvelteComponentSession({
166
166
  runtimeModule: `/${SVELTE_RUNTIME_FILE}`,
167
167
  };
168
168
 
169
- fs.writeFileSync(path.join(dir, 'manifest.json'), JSON.stringify(manifest, null, 2) + '\n', 'utf-8');
169
+ fs.writeFileSync(path.join(dir, 'manifest.json'), `${JSON.stringify(manifest, null, 2)}\n`, 'utf-8');
170
170
 
171
171
  for (let n = 1; n <= count; n++) {
172
172
  const variantFile = path.join(dir, `v${n}.svelte`);
@@ -216,7 +216,7 @@ export function scaffoldSvelteComponentInsertSession({
216
216
  runtimeModule: `/${SVELTE_RUNTIME_FILE}`,
217
217
  };
218
218
 
219
- fs.writeFileSync(path.join(dir, 'manifest.json'), JSON.stringify(manifest, null, 2) + '\n', 'utf-8');
219
+ fs.writeFileSync(path.join(dir, 'manifest.json'), `${JSON.stringify(manifest, null, 2)}\n`, 'utf-8');
220
220
 
221
221
  for (let n = 1; n <= count; n++) {
222
222
  const variantFile = path.join(dir, `v${n}.svelte`);
@@ -270,14 +270,14 @@ export function resolveSourceFile(sourceFile, cwd = process.cwd()) {
270
270
  throw new Error('Svelte-component source file escapes project root');
271
271
  }
272
272
  if (!fs.existsSync(full)) {
273
- throw new Error('Svelte-component source file not found: ' + sourceFile);
273
+ throw new Error(`Svelte-component source file not found: ${sourceFile}`);
274
274
  }
275
275
  return full;
276
276
  }
277
277
 
278
278
  function appendCssToSvelteStyle(lines, cssLines) {
279
279
  const closeIdx = findLastStyleCloseLine(lines);
280
- const prepared = ['', ...cssLines.map((line) => (line.trim() === '' ? '' : ' ' + line.trimStart()))];
280
+ const prepared = ['', ...cssLines.map((line) => (line.trim() === '' ? '' : ` ${line.trimStart()}`))];
281
281
  if (closeIdx === -1) {
282
282
  return [...lines, '', '<style>', ...prepared.slice(1), '</style>'];
283
283
  }
@@ -436,7 +436,7 @@ function rewriteAcceptedSvelteSelectorPart(selector, variantNum, paramValues, ro
436
436
  function rewriteParamSelectors(selector, paramValues) {
437
437
  let keep = true;
438
438
  const next = selector.replace(/\[data-p-([A-Za-z0-9_-]+)(?:=(["'])(.*?)\2)?\]/g, (_match, key, _quote, expected) => {
439
- if (!paramValues || !Object.prototype.hasOwnProperty.call(paramValues, key)) return '';
439
+ if (!paramValues || !Object.hasOwn(paramValues, key)) return '';
440
440
  const actual = paramValues[key];
441
441
  if (expected != null && String(actual) !== String(expected)) {
442
442
  keep = false;
@@ -537,7 +537,7 @@ export function inlineSvelteComponentAccept(manifest, variantNum, paramValues =
537
537
  const start = Number(manifest.sourceStartLine) - 1;
538
538
  const end = Number(manifest.sourceEndLine) - 1;
539
539
  if (!Number.isInteger(start) || !Number.isInteger(end) || start < 0 || end < start || end >= sourceLines.length) {
540
- return { handled: false, error: 'Invalid source line range for ' + manifest.sourceFile, ...resultBase };
540
+ return { handled: false, error: `Invalid source line range for ${manifest.sourceFile}`, ...resultBase };
541
541
  }
542
542
 
543
543
  const indent = sourceLines[start].match(/^(\s*)/)?.[1] || '';
@@ -561,7 +561,7 @@ export function inlineSvelteComponentAccept(manifest, variantNum, paramValues =
561
561
  try {
562
562
  fs.writeFileSync(sourceFile, newLines.join('\n'), 'utf-8');
563
563
  } catch (err) {
564
- return { handled: false, error: 'Failed to write Svelte source: ' + err.message, ...resultBase };
564
+ return { handled: false, error: `Failed to write Svelte source: ${err.message}`, ...resultBase };
565
565
  }
566
566
  removeSvelteComponentSession(manifest.id, cwd);
567
567
 
@@ -596,7 +596,7 @@ function inlineSvelteComponentInsertAccept({
596
596
  const sourceLines = sourceContent.split('\n');
597
597
  const insertIndex = Number(manifest.insertLine) - 1;
598
598
  if (!Number.isInteger(insertIndex) || insertIndex < 0 || insertIndex > sourceLines.length) {
599
- return { handled: false, error: 'Invalid insert line for ' + manifest.sourceFile, ...resultBase };
599
+ return { handled: false, error: `Invalid insert line for ${manifest.sourceFile}`, ...resultBase };
600
600
  }
601
601
 
602
602
  const nearbyLine = sourceLines[insertIndex] ?? sourceLines[insertIndex - 1] ?? '';
@@ -621,7 +621,7 @@ function inlineSvelteComponentInsertAccept({
621
621
  try {
622
622
  fs.writeFileSync(sourceFile, newLines.join('\n'), 'utf-8');
623
623
  } catch (err) {
624
- return { handled: false, error: 'Failed to write Svelte source: ' + err.message, ...resultBase };
624
+ return { handled: false, error: `Failed to write Svelte source: ${err.message}`, ...resultBase };
625
625
  }
626
626
  removeSvelteComponentSession(manifest.id, cwd);
627
627
 
@@ -675,7 +675,7 @@ function mergeOriginalTopLevelAttrs(markup, originalMarkup) {
675
675
  const nextOpen = variantOpen.prefix
676
676
  + variantOpen.tag
677
677
  + attrs
678
- + additions.map((attr) => ' ' + attr.trim()).join('')
678
+ + additions.map((attr) => ` ${attr.trim()}`).join('')
679
679
  + variantOpen.close;
680
680
  return markup.slice(0, variantOpen.index) + nextOpen + markup.slice(variantOpen.index + variantOpen.raw.length);
681
681
  }
@@ -761,7 +761,7 @@ export function writeDeferredAccept(entry, cwd = process.cwd()) {
761
761
  const data = readDeferredAccepts(cwd);
762
762
  data.accepts = (data.accepts || []).filter((item) => item.id !== entry.id);
763
763
  data.accepts.push({ ...entry, createdAt: new Date().toISOString() });
764
- fs.writeFileSync(file, JSON.stringify(data, null, 2) + '\n', 'utf-8');
764
+ fs.writeFileSync(file, `${JSON.stringify(data, null, 2)}\n`, 'utf-8');
765
765
  }
766
766
 
767
767
  export function applyDeferredSvelteComponentAccepts(cwd = process.cwd()) {
@@ -792,7 +792,7 @@ export function applyDeferredSvelteComponentAccepts(cwd = process.cwd()) {
792
792
  }
793
793
  }
794
794
  if (remaining.length > 0) {
795
- fs.writeFileSync(file, JSON.stringify({ accepts: remaining }, null, 2) + '\n', 'utf-8');
795
+ fs.writeFileSync(file, `${JSON.stringify({ accepts: remaining }, null, 2)}\n`, 'utf-8');
796
796
  } else {
797
797
  try { fs.rmSync(file, { force: true }); } catch {}
798
798
  }
@@ -103,9 +103,9 @@ export function patchSvelteLayout(content) {
103
103
  const scriptMatch = out.match(/<script(?:\s[^>]*)?>/i);
104
104
  if (scriptMatch) {
105
105
  const insertAt = scriptMatch.index + scriptMatch[0].length;
106
- out = out.slice(0, insertAt) + '\n ' + SVELTE_ROOT_IMPORT + out.slice(insertAt);
106
+ out = `${out.slice(0, insertAt)}\n ${SVELTE_ROOT_IMPORT}${out.slice(insertAt)}`;
107
107
  } else {
108
- out = `<script>\n ${SVELTE_ROOT_IMPORT}\n</script>\n\n` + out;
108
+ out = `<script>\n ${SVELTE_ROOT_IMPORT}\n</script>\n\n${out}`;
109
109
  }
110
110
  }
111
111
 
@@ -117,7 +117,7 @@ export function patchSvelteLayout(content) {
117
117
  if (match) {
118
118
  out = out.slice(0, match.index) + block + out.slice(match.index);
119
119
  } else {
120
- out = out.replace(/\s*$/, '\n\n' + block);
120
+ out = out.replace(/\s*$/, `\n\n${block}`);
121
121
  }
122
122
  }
123
123
 
@@ -134,7 +134,7 @@ export function unpatchSvelteLayout(content) {
134
134
  'g',
135
135
  );
136
136
  out = out.replace(blockRe, '$1');
137
- out = out.replace(new RegExp('^\\s*' + escapeRegExp(SVELTE_ROOT_IMPORT) + '\\s*\\n?', 'gm'), '');
137
+ out = out.replace(new RegExp(`^\\s*${escapeRegExp(SVELTE_ROOT_IMPORT)}\\s*\\n?`, 'gm'), '');
138
138
  out = out.replace(/<script>\s*<\/script>\s*\n?/g, '');
139
139
  return out.replace(/\n{3,}/g, '\n\n');
140
140
  }
@@ -140,7 +140,7 @@ export function getLiveUiElementById(id, env = globalThis) {
140
140
  if (found) return found;
141
141
  }
142
142
  if (root?.querySelector) {
143
- const found = root.querySelector('#' + escapeCssIdent(id));
143
+ const found = root.querySelector(`#${escapeCssIdent(id)}`);
144
144
  if (found) return found;
145
145
  }
146
146
  return doc?.getElementById?.(id) || null;