bricks-builder-mcp 3.11.2 → 3.11.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 +43 -19
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "bricks-builder-mcp",
4
- "version": "3.11.2",
4
+ "version": "3.11.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 (verify_element), upload optimisé WebP. Communauté Discord : https://discord.gg/rX22zHRzH",
6
6
  "homepage": "https://discord.gg/rX22zHRzH",
7
7
  "main": "server.js",
package/server.js CHANGED
@@ -2254,13 +2254,17 @@ mcpServer.setRequestHandler(CallToolRequestSchema, async (request) => {
2254
2254
  }
2255
2255
 
2256
2256
  try {
2257
- await page.goto(pageUrl, { waitUntil: 'domcontentloaded', timeout: 30000 });
2258
- // Wait : fonts + lazy load (networkidle pour les images lazy)
2259
- try {
2260
- await page.waitForLoadState('networkidle', { timeout: 8000 });
2261
- } catch {} // pas grave si certaines requêtes restent en cours
2262
- await page.waitForTimeout(1500);
2263
- // Scroll bottom puis top pour déclencher les lazy-load IntersectionObserver
2257
+ await page.goto(pageUrl, { waitUntil: 'load', timeout: 30000 });
2258
+ await page.waitForTimeout(1000);
2259
+ // v3.11.3 — Forcer toutes les <img loading="lazy"> en eager pour
2260
+ // déclencher leur chargement IMMÉDIATEMENT (sans attendre l'IntersectionObserver).
2261
+ // Sinon Bricks lazy-load les images et mon audit court trop tôt.
2262
+ await page.evaluate(() => {
2263
+ document.querySelectorAll('img[loading="lazy"]').forEach(img => {
2264
+ img.loading = 'eager';
2265
+ });
2266
+ });
2267
+ // Scroll bottom→top pour déclencher les autres lazy-load (background-image, custom JS)
2264
2268
  await page.evaluate(() => {
2265
2269
  return new Promise(resolve => {
2266
2270
  const totalHeight = document.documentElement.scrollHeight;
@@ -2272,19 +2276,23 @@ mcpServer.setRequestHandler(CallToolRequestSchema, async (request) => {
2272
2276
  if (scrolled >= totalHeight) {
2273
2277
  clearInterval(timer);
2274
2278
  window.scrollTo(0, 0);
2275
- setTimeout(resolve, 800);
2279
+ setTimeout(resolve, 500);
2276
2280
  }
2277
- }, 100);
2281
+ }, 80);
2278
2282
  });
2279
2283
  });
2280
- // v3.11.2 attendre que TOUTES les <img> soient chargées avant l'audit
2281
- // sinon les lazy-loaded apparaissent comme "container vide"
2284
+ // networkidle après le scroll pour laisser les images se télécharger
2285
+ try {
2286
+ await page.waitForLoadState('networkidle', { timeout: 12000 });
2287
+ } catch {}
2288
+ // v3.11.3 — vrai check : naturalWidth > 0 (pas juste img.complete qui est trompeur).
2289
+ // img.complete = true pour les imgs qui ne se sont pas chargées du tout.
2282
2290
  try {
2283
2291
  await page.waitForFunction(
2284
- () => Array.from(document.images).every(i => i.complete),
2285
- { timeout: 10000 }
2292
+ () => Array.from(document.images).every(i => i.naturalWidth > 0 || !i.src),
2293
+ { timeout: 8000 }
2286
2294
  );
2287
- } catch {} // si une img reste cassée, on continue (elle sera flaggée en broken_image)
2295
+ } catch {} // si une img reste vraiment cassée, on continue (elle sera flaggée en broken_image)
2288
2296
  await page.waitForTimeout(500);
2289
2297
 
2290
2298
  // 3) Collecte d'issues globales sur toute la page
@@ -2302,26 +2310,42 @@ mcpServer.setRequestHandler(CallToolRequestSchema, async (request) => {
2302
2310
 
2303
2311
  // === Empty containers ===
2304
2312
  if (cfg.empty_containers) {
2313
+ // v3.11.4 — debug : on remonte le outerHTML pour identifier les faux positifs
2314
+ let debugCount = 0;
2305
2315
  allBrxe.forEach(b => {
2306
2316
  const rect = b.getBoundingClientRect();
2307
2317
  if (rect.width < 50 || rect.height < 50) return;
2308
2318
  const area = rect.width * rect.height;
2309
2319
  if (area < 2500) return;
2310
- // Ignorer les éléments en dehors du viewport rendu (hauteur fullpage)
2311
2320
  const hasText = (b.textContent || '').trim().length > 0;
2312
- const hasMedia = b.querySelector('img, picture, svg, video, iframe') !== null;
2321
+ const hasMedia = b.querySelector('img, picture, svg, video, iframe, canvas') !== null;
2313
2322
  const hasInteractive = b.querySelector('a, button, input, select, textarea') !== null;
2314
2323
  const bcs = getComputedStyle(b);
2315
2324
  const hasBgImg = bcs.backgroundImage && bcs.backgroundImage !== 'none';
2316
- if (!hasText && !hasMedia && !hasInteractive && !hasBgImg) {
2317
- issues.push({
2325
+ // v3.11.4 détecte AUSSI les background-image sur les descendants directs (Bricks rend souvent
2326
+ // l'image en CSS bg sur un enfant, pas sur le wrapper)
2327
+ const hasChildBgImg = !hasBgImg && Array.from(b.children).some(c => {
2328
+ const ccs = getComputedStyle(c);
2329
+ return ccs.backgroundImage && ccs.backgroundImage !== 'none';
2330
+ });
2331
+ if (!hasText && !hasMedia && !hasInteractive && !hasBgImg && !hasChildBgImg) {
2332
+ const issue = {
2318
2333
  type: 'empty_container',
2319
2334
  severity: 'warning',
2320
2335
  element: b.id || (Array.from(b.classList).find(c => c.startsWith('brxe-')) || '?'),
2321
2336
  label: `Container vide ${Math.round(rect.width)}×${Math.round(rect.height)}px`,
2322
2337
  hint: "Bloc visible sans contenu — souvent un wrapper écrasé par align-items: stretch. Fixer aspect-ratio ou ajouter du contenu.",
2323
2338
  bbox: absBbox(rect),
2324
- });
2339
+ };
2340
+ // DEBUG : 3 premiers seulement (sinon trop verbeux)
2341
+ if (debugCount < 3) {
2342
+ issue._debugOuterHTML = (b.outerHTML || '').substring(0, 400);
2343
+ issue._debugTagName = b.tagName;
2344
+ issue._debugChildrenCount = b.children.length;
2345
+ issue._debugChildren = Array.from(b.children).slice(0, 3).map(c => `<${c.tagName.toLowerCase()}${c.id ? '#' + c.id : ''}${c.className ? '.' + (typeof c.className === 'string' ? c.className.split(' ').slice(0,2).join('.') : '') : ''}>`);
2346
+ debugCount++;
2347
+ }
2348
+ issues.push(issue);
2325
2349
  }
2326
2350
  });
2327
2351
  }