bricks-builder-mcp 3.6.4 → 3.6.5

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/package.json +1 -1
  2. package/server.js +52 -10
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "bricks-builder-mcp",
4
- "version": "3.6.4",
4
+ "version": "3.6.5",
5
5
  "description": "Serveur MCP pour piloter Bricks Builder (WordPress) depuis Claude — édition de pages, gestion d'éléments, réordonnancement des sections, vérification visuelle + technique (verify_element).",
6
6
  "main": "server.js",
7
7
  "bin": {
package/server.js CHANGED
@@ -109,8 +109,8 @@ function normaliseColor(s) {
109
109
  return s;
110
110
  }
111
111
 
112
- // Normaliser les valeurs CSS pour comparaison (rgba/spaces/units/hex)
113
- function normaliseCssValue(val) {
112
+ // Normaliser les valeurs CSS pour comparaison (rgba/spaces/units/hex/vh)
113
+ function normaliseCssValue(val, viewportContext) {
114
114
  if (val == null) return '';
115
115
  let s = String(val).trim().toLowerCase();
116
116
  s = s.replace(/\s+/g, '');
@@ -126,6 +126,23 @@ function normaliseCssValue(val) {
126
126
  return normaliseColor(s);
127
127
  }
128
128
 
129
+ // vh / vw → px en fonction du viewport actuel (getComputedStyle renvoie en px)
130
+ if (viewportContext) {
131
+ const vhMatch = s.match(/^(\d+(?:\.\d+)?)vh$/);
132
+ if (vhMatch && viewportContext.height) {
133
+ return Math.round(parseFloat(vhMatch[1]) * viewportContext.height / 100) + 'px';
134
+ }
135
+ const vwMatch = s.match(/^(\d+(?:\.\d+)?)vw$/);
136
+ if (vwMatch && viewportContext.width) {
137
+ return Math.round(parseFloat(vwMatch[1]) * viewportContext.width / 100) + 'px';
138
+ }
139
+ // svh, dvh, lvh : on assimile à vh pour l'instant (approximatif mais OK pour la plupart des cas)
140
+ const svhMatch = s.match(/^(\d+(?:\.\d+)?)(?:svh|dvh|lvh)$/);
141
+ if (svhMatch && viewportContext.height) {
142
+ return Math.round(parseFloat(svhMatch[1]) * viewportContext.height / 100) + 'px';
143
+ }
144
+ }
145
+
129
146
  // Normalise "0px" et "0" et "0%"
130
147
  if (s === '0' || s === '0px' || s === '0%') return '0';
131
148
  // Si valeur sans unité fournie (ex "32") et getComputedStyle renvoie "32px"
@@ -1436,6 +1453,13 @@ mcpServer.setRequestHandler(CallToolRequestSchema, async (request) => {
1436
1453
  const pageId = args.pageId;
1437
1454
  const elementId = args.elementId;
1438
1455
  const viewport = args.viewport || "desktop";
1456
+ const viewportSizes = {
1457
+ desktop: { width: 1920, height: 1080 },
1458
+ tablet: { width: 991, height: 1200 },
1459
+ mobile_landscape: { width: 767, height: 600 },
1460
+ mobile_portrait: { width: 478, height: 800 },
1461
+ };
1462
+ const viewportContext = viewportSizes[viewport] || viewportSizes.desktop;
1439
1463
 
1440
1464
  // 1) Récupérer infos plugin (URL, sélecteur, expected styles)
1441
1465
  const info = await callWordPressAPI("/verify-element-info", "POST", { pageId, elementId });
@@ -1581,12 +1605,12 @@ mcpServer.setRequestHandler(CallToolRequestSchema, async (request) => {
1581
1605
  });
1582
1606
  }
1583
1607
 
1584
- // Compare chaque expected
1608
+ // Compare chaque expected (viewport-aware pour vh/vw)
1585
1609
  const expected = info.expected || {};
1586
1610
  for (const [prop, expectedVal] of Object.entries(expected)) {
1587
1611
  const got = computed[prop];
1588
1612
  if (got === undefined) continue;
1589
- const ok = normaliseCssValue(got) === normaliseCssValue(expectedVal);
1613
+ const ok = normaliseCssValue(got, viewportContext) === normaliseCssValue(expectedVal, viewportContext);
1590
1614
  const check = { ok, label: `${prop} = ${expectedVal}` };
1591
1615
  if (!ok) {
1592
1616
  check.expected = expectedVal;
@@ -1597,16 +1621,34 @@ mcpServer.setRequestHandler(CallToolRequestSchema, async (request) => {
1597
1621
  checks.push(check);
1598
1622
  }
1599
1623
 
1600
- // Console errors
1601
- if (consoleErrors.length > 0) {
1624
+ // Console errors : séparer les vrais bugs JS des erreurs réseau (429/timeout)
1625
+ // qui dépendent du serveur, pas du code de l'élément.
1626
+ const realErrors = consoleErrors.filter(e =>
1627
+ !e.includes('429') &&
1628
+ !e.includes('net::ERR_') &&
1629
+ !e.includes('Failed to load resource')
1630
+ );
1631
+ const networkErrors = consoleErrors.filter(e =>
1632
+ e.includes('429') || e.includes('net::ERR_') || e.includes('Failed to load resource')
1633
+ );
1634
+
1635
+ if (realErrors.length > 0) {
1602
1636
  checks.push({
1603
1637
  ok: false,
1604
- label: `${consoleErrors.length} erreur(s) console`,
1605
- got: consoleErrors.slice(0, 3),
1606
- hint: "Vérifie les ressources 404 (font, image, script)",
1638
+ label: `${realErrors.length} erreur(s) JS dans la console`,
1639
+ got: realErrors.slice(0, 3),
1640
+ hint: "Erreur JavaScript détectée pas lié au serveur",
1607
1641
  });
1608
1642
  } else {
1609
- checks.push({ ok: true, label: "Aucune erreur console" });
1643
+ checks.push({ ok: true, label: "Aucune erreur JS console" });
1644
+ }
1645
+ // Erreurs réseau : info seulement, pas un échec
1646
+ if (networkErrors.length > 0) {
1647
+ checks.push({
1648
+ ok: true,
1649
+ label: `${networkErrors.length} erreur(s) réseau (429/load) — non bloquant`,
1650
+ got: networkErrors.slice(0, 2),
1651
+ });
1610
1652
  }
1611
1653
 
1612
1654
  // Overflow horizontal