bricks-builder-mcp 3.6.2 → 3.6.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/server.js +66 -5
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "bricks-builder-mcp",
4
- "version": "3.6.2",
4
+ "version": "3.6.4",
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
@@ -83,12 +83,49 @@ process.on('SIGINT', () => {
83
83
  process.exit(0);
84
84
  });
85
85
 
86
- // Normaliser les valeurs CSS pour comparaison (rgba/spaces/units)
86
+ // Hex rgb/rgba pour matcher getComputedStyle qui renvoie toujours rgb()
87
+ function hexToRgb(hex) {
88
+ hex = hex.replace('#', '');
89
+ if (hex.length === 3) {
90
+ hex = hex.split('').map(c => c + c).join('');
91
+ }
92
+ if (hex.length !== 6 && hex.length !== 8) return null;
93
+ const r = parseInt(hex.substring(0, 2), 16);
94
+ const g = parseInt(hex.substring(2, 4), 16);
95
+ const b = parseInt(hex.substring(4, 6), 16);
96
+ if (isNaN(r) || isNaN(g) || isNaN(b)) return null;
97
+ if (hex.length === 8) {
98
+ const a = parseInt(hex.substring(6, 8), 16) / 255;
99
+ return `rgba(${r},${g},${b},${a.toFixed(2)})`;
100
+ }
101
+ return `rgb(${r},${g},${b})`;
102
+ }
103
+
104
+ // Normaliser une valeur rgba/rgb (supprime espaces, arrondit alpha)
105
+ function normaliseColor(s) {
106
+ s = s.replace(/\s+/g, '');
107
+ // rgba(0,0,0,0) → transparent
108
+ if (s === 'rgba(0,0,0,0)' || s === 'transparent') return 'transparent';
109
+ return s;
110
+ }
111
+
112
+ // Normaliser les valeurs CSS pour comparaison (rgba/spaces/units/hex)
87
113
  function normaliseCssValue(val) {
88
114
  if (val == null) return '';
89
115
  let s = String(val).trim().toLowerCase();
90
- // Supprime espaces internes (rgba(0, 0, 0) → rgba(0,0,0))
91
116
  s = s.replace(/\s+/g, '');
117
+
118
+ // Hex → rgb pour matcher getComputedStyle
119
+ if (/^#[0-9a-f]{3,8}$/.test(s)) {
120
+ const rgb = hexToRgb(s);
121
+ if (rgb) return normaliseColor(rgb);
122
+ }
123
+
124
+ // Couleurs rgb/rgba : normaliser pour comparer
125
+ if (s.startsWith('rgb')) {
126
+ return normaliseColor(s);
127
+ }
128
+
92
129
  // Normalise "0px" et "0" et "0%"
93
130
  if (s === '0' || s === '0px' || s === '0%') return '0';
94
131
  // Si valeur sans unité fournie (ex "32") et getComputedStyle renvoie "32px"
@@ -1438,12 +1475,24 @@ mcpServer.setRequestHandler(CallToolRequestSchema, async (request) => {
1438
1475
 
1439
1476
  const element = await page.$(info.selector);
1440
1477
  if (!element) {
1478
+ // Diagnostic : qu'a-t-on réellement chargé ?
1479
+ const diagnostics = await page.evaluate(() => ({
1480
+ actualUrl: window.location.href,
1481
+ title: document.title,
1482
+ bodyClass: document.body?.className || '',
1483
+ brxeCount: document.querySelectorAll('[class*="brxe-"]').length,
1484
+ firstBrxe: document.querySelector('[class*="brxe-"]')?.className || null,
1485
+ htmlSnippet: document.documentElement.outerHTML.substring(0, 500),
1486
+ }));
1441
1487
  result = {
1442
1488
  success: false,
1443
- error: `Élément ${info.selector} introuvable dans le DOM (caché par CSS, parent invisible, ou non rendu côté front)`,
1489
+ error: `Élément ${info.selector} introuvable dans le DOM`,
1444
1490
  url: info.url,
1445
1491
  selector: info.selector,
1446
- hint: "Vérifie que la page est publiée et que l'élément n'a pas _hidden ou _display: none.",
1492
+ diagnostics,
1493
+ hint: diagnostics.brxeCount === 0
1494
+ ? "Aucune classe .brxe-* trouvée — la page n'a probablement pas chargé le contenu Bricks (cert SSL, redirect, 404, page d'erreur)"
1495
+ : `${diagnostics.brxeCount} éléments .brxe-* trouvés mais pas ${info.selector} — l'ID dans la DB ne correspond pas au rendu`,
1447
1496
  };
1448
1497
  await page.close();
1449
1498
  break;
@@ -1456,6 +1505,16 @@ mcpServer.setRequestHandler(CallToolRequestSchema, async (request) => {
1456
1505
  computed = await element.evaluate(el => {
1457
1506
  const cs = getComputedStyle(el);
1458
1507
  const rect = el.getBoundingClientRect();
1508
+ // Enfants "réels" = ceux qui ont une classe brxe-{id} ou id brxe-*
1509
+ // Exclut les <video>, <picture> et autres ajoutés par Bricks (bg vidéo, overlay auto, etc.)
1510
+ const realChildren = Array.from(el.children).filter(child => {
1511
+ if (child.id && child.id.startsWith('brxe-')) return true;
1512
+ return Array.from(child.classList).some(cls => cls.startsWith('brxe-'));
1513
+ });
1514
+ const bricksInternalChildren = Array.from(el.children).filter(child => {
1515
+ return !((child.id && child.id.startsWith('brxe-')) ||
1516
+ Array.from(child.classList).some(cls => cls.startsWith('brxe-')));
1517
+ }).map(c => c.tagName.toLowerCase() + (c.className ? '.' + c.className.split(' ').join('.') : ''));
1459
1518
  return {
1460
1519
  display: cs.display,
1461
1520
  'flex-direction': cs.flexDirection,
@@ -1488,7 +1547,9 @@ mcpServer.setRequestHandler(CallToolRequestSchema, async (request) => {
1488
1547
  'border-bottom-left-radius': cs.borderBottomLeftRadius,
1489
1548
  visibility: cs.visibility,
1490
1549
  opacity: cs.opacity,
1491
- childrenInDom: el.children.length,
1550
+ childrenInDom: realChildren.length,
1551
+ childrenTotalDom: el.children.length,
1552
+ bricksInternalChildren: bricksInternalChildren,
1492
1553
  isVisible: rect.width > 0 && rect.height > 0 && cs.visibility !== 'hidden' && cs.opacity !== '0',
1493
1554
  hasOverflowX: el.scrollWidth > el.clientWidth,
1494
1555
  };