bricks-builder-mcp 3.11.1 → 3.11.3

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 +48 -13
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "bricks-builder-mcp",
4
- "version": "3.11.1",
4
+ "version": "3.11.3",
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
@@ -229,9 +229,15 @@ function buildSiblingCoherenceChecks(audit) {
229
229
  const all = [audit.self, ...siblings];
230
230
 
231
231
  // 1) text-align mixé entre frères directs
232
- // Si un seul frère a un text-align différent, c'est souvent un bug visuel
233
- // (ex: H2 left + sous-titre center sans intention design).
234
- const aligns = [...new Set(all.map(s => s['text-align']).filter(Boolean))];
232
+ // v3.11.2 : `start` et `left` sont équivalents en LTR (idem `end`/`right`),
233
+ // on les normalise avant de comparer pour éviter les faux positifs.
234
+ // (LTR par défaut, le check est sur des sites WordPress majoritairement français)
235
+ const normalizeAlign = (val) => {
236
+ if (val === 'start') return 'left';
237
+ if (val === 'end') return 'right';
238
+ return val;
239
+ };
240
+ const aligns = [...new Set(all.map(s => normalizeAlign(s['text-align'])).filter(Boolean))];
235
241
  if (aligns.length > 1) {
236
242
  checks.push({
237
243
  ok: false,
@@ -2248,13 +2254,17 @@ mcpServer.setRequestHandler(CallToolRequestSchema, async (request) => {
2248
2254
  }
2249
2255
 
2250
2256
  try {
2251
- await page.goto(pageUrl, { waitUntil: 'domcontentloaded', timeout: 30000 });
2252
- // Wait : fonts + lazy load (networkidle pour les images lazy)
2253
- try {
2254
- await page.waitForLoadState('networkidle', { timeout: 8000 });
2255
- } catch {} // pas grave si certaines requêtes restent en cours
2256
- await page.waitForTimeout(1500);
2257
- // Scroll bottom puis top pour déclencher les lazy-load
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)
2258
2268
  await page.evaluate(() => {
2259
2269
  return new Promise(resolve => {
2260
2270
  const totalHeight = document.documentElement.scrollHeight;
@@ -2266,11 +2276,24 @@ mcpServer.setRequestHandler(CallToolRequestSchema, async (request) => {
2266
2276
  if (scrolled >= totalHeight) {
2267
2277
  clearInterval(timer);
2268
2278
  window.scrollTo(0, 0);
2269
- setTimeout(resolve, 800);
2279
+ setTimeout(resolve, 500);
2270
2280
  }
2271
- }, 100);
2281
+ }, 80);
2272
2282
  });
2273
2283
  });
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.
2290
+ try {
2291
+ await page.waitForFunction(
2292
+ () => Array.from(document.images).every(i => i.naturalWidth > 0 || !i.src),
2293
+ { timeout: 8000 }
2294
+ );
2295
+ } catch {} // si une img reste vraiment cassée, on continue (elle sera flaggée en broken_image)
2296
+ await page.waitForTimeout(500);
2274
2297
 
2275
2298
  // 3) Collecte d'issues globales sur toute la page
2276
2299
  const auditResult = await page.evaluate((cfg) => {
@@ -2341,13 +2364,25 @@ mcpServer.setRequestHandler(CallToolRequestSchema, async (request) => {
2341
2364
 
2342
2365
  // === Sibling coherence ===
2343
2366
  if (cfg.sibling_coherence) {
2367
+ // v3.11.2 : start === left, end === right en LTR (équivalents CSS)
2368
+ const dir = getComputedStyle(document.documentElement).direction || 'ltr';
2369
+ const normalizeAlign = (val) => {
2370
+ if (dir === 'ltr') {
2371
+ if (val === 'start') return 'left';
2372
+ if (val === 'end') return 'right';
2373
+ } else {
2374
+ if (val === 'start') return 'right';
2375
+ if (val === 'end') return 'left';
2376
+ }
2377
+ return val;
2378
+ };
2344
2379
  allBrxe.forEach(parent => {
2345
2380
  const realChildren = Array.from(parent.children).filter(c =>
2346
2381
  (c.id && c.id.startsWith('brxe-')) ||
2347
2382
  Array.from(c.classList).some(cls => cls.startsWith('brxe-'))
2348
2383
  );
2349
2384
  if (realChildren.length < 2) return;
2350
- const aligns = [...new Set(realChildren.map(c => getComputedStyle(c).textAlign))];
2385
+ const aligns = [...new Set(realChildren.map(c => normalizeAlign(getComputedStyle(c).textAlign)))];
2351
2386
  if (aligns.length > 1) {
2352
2387
  const rect = parent.getBoundingClientRect();
2353
2388
  issues.push({