@yashwant.dharmdas/elementor-mcp 3.2.5 → 3.2.7
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.
- package/dist/index.js +81 -15
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1090,28 +1090,95 @@ function createMcpServer(sites) {
|
|
|
1090
1090
|
await page.setViewport({ width: vpWidth, height: vpHeight, deviceScaleFactor: 1 });
|
|
1091
1091
|
// Navigate and wait for network to go idle
|
|
1092
1092
|
await page.goto(pageUrl, { waitUntil: "networkidle2", timeout: 45_000 });
|
|
1093
|
-
// ── Auto-scroll
|
|
1093
|
+
// ── Auto-scroll with multi-pass stabilization ────────────────────
|
|
1094
|
+
// Many Elementor pages lazy-load content on scroll (images, Swiper
|
|
1095
|
+
// carousels, reveal animations). A single scroll pass is not enough —
|
|
1096
|
+
// the page can grow as content loads. We keep scrolling until the
|
|
1097
|
+
// total page height stops increasing between passes.
|
|
1094
1098
|
if (auto_scroll !== false) {
|
|
1095
1099
|
await page.evaluate(async () => {
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1100
|
+
const getHeight = () => Math.max(document.body.scrollHeight, document.documentElement.scrollHeight, document.body.offsetHeight, document.documentElement.offsetHeight);
|
|
1101
|
+
const scrollOnce = () => new Promise((resolve) => {
|
|
1102
|
+
let y = 0;
|
|
1103
|
+
const step = 300;
|
|
1099
1104
|
const timer = setInterval(() => {
|
|
1100
|
-
const
|
|
1101
|
-
window.scrollBy(0,
|
|
1102
|
-
|
|
1103
|
-
if (
|
|
1105
|
+
const h = getHeight();
|
|
1106
|
+
window.scrollBy(0, step);
|
|
1107
|
+
y += step;
|
|
1108
|
+
if (y >= h) {
|
|
1104
1109
|
clearInterval(timer);
|
|
1105
1110
|
resolve();
|
|
1106
1111
|
}
|
|
1107
|
-
},
|
|
1112
|
+
}, 60);
|
|
1108
1113
|
});
|
|
1114
|
+
// Repeat until height stabilizes (max 4 passes)
|
|
1115
|
+
let lastHeight = 0;
|
|
1116
|
+
for (let i = 0; i < 4; i++) {
|
|
1117
|
+
window.scrollTo(0, 0);
|
|
1118
|
+
await new Promise(r => setTimeout(r, 150));
|
|
1119
|
+
await scrollOnce();
|
|
1120
|
+
// Wait at the bottom for lazy content to trigger
|
|
1121
|
+
await new Promise(r => setTimeout(r, 800));
|
|
1122
|
+
const h = getHeight();
|
|
1123
|
+
if (h === lastHeight)
|
|
1124
|
+
break;
|
|
1125
|
+
lastHeight = h;
|
|
1126
|
+
}
|
|
1127
|
+
// Back to top for the capture
|
|
1128
|
+
window.scrollTo(0, 0);
|
|
1109
1129
|
});
|
|
1110
|
-
// Scroll back to top for the capture
|
|
1111
|
-
await page.evaluate(() => window.scrollTo(0, 0));
|
|
1112
1130
|
}
|
|
1113
|
-
// ──
|
|
1131
|
+
// ── Force-load all <img> tags + Elementor lazy backgrounds ────────
|
|
1114
1132
|
await page.evaluate(async () => {
|
|
1133
|
+
// 1. Strip loading="lazy" so the browser loads everything eagerly
|
|
1134
|
+
document.querySelectorAll('img[loading="lazy"]').forEach((img) => {
|
|
1135
|
+
img.setAttribute("loading", "eager");
|
|
1136
|
+
});
|
|
1137
|
+
// 2. Resolve data-src → src for libraries that defer image loading
|
|
1138
|
+
document.querySelectorAll("img[data-src]").forEach((img) => {
|
|
1139
|
+
const ds = img.getAttribute("data-src");
|
|
1140
|
+
if (ds && !img.getAttribute("src"))
|
|
1141
|
+
img.setAttribute("src", ds);
|
|
1142
|
+
});
|
|
1143
|
+
// 3. Force-load Elementor's lazy background images
|
|
1144
|
+
// Elementor uses class .elementor-element-bg-lazyload + sets a
|
|
1145
|
+
// CSS variable --e-bg-lazyload, OR data-bg / data-background-image
|
|
1146
|
+
const bgEls = document.querySelectorAll(".elementor-element-bg-lazyload, [data-bg], [data-background-image]");
|
|
1147
|
+
bgEls.forEach((el) => {
|
|
1148
|
+
const url = el.getAttribute("data-bg") ||
|
|
1149
|
+
el.getAttribute("data-background-image") ||
|
|
1150
|
+
getComputedStyle(el).getPropertyValue("--e-bg-lazyload").trim().replace(/^url\(["']?|["']?\)$/g, "");
|
|
1151
|
+
if (url && url !== "none" && !el.style.backgroundImage) {
|
|
1152
|
+
el.style.backgroundImage = `url("${url}")`;
|
|
1153
|
+
}
|
|
1154
|
+
el.classList.remove("elementor-element-bg-lazyload");
|
|
1155
|
+
});
|
|
1156
|
+
// 4. Force-show Elementor reveal-animation elements that are still
|
|
1157
|
+
// hidden (opacity:0 / .elementor-invisible) waiting for scroll trigger
|
|
1158
|
+
document.querySelectorAll(".elementor-invisible").forEach((el) => {
|
|
1159
|
+
el.classList.remove("elementor-invisible");
|
|
1160
|
+
el.style.opacity = "1";
|
|
1161
|
+
el.style.visibility = "visible";
|
|
1162
|
+
el.style.transform = "none";
|
|
1163
|
+
});
|
|
1164
|
+
// 5. Disable CSS animations / transitions during capture so nothing
|
|
1165
|
+
// is mid-flight when the screenshot fires
|
|
1166
|
+
const style = document.createElement("style");
|
|
1167
|
+
style.id = "__mcp_screenshot_overrides__";
|
|
1168
|
+
style.textContent = `
|
|
1169
|
+
*, *::before, *::after {
|
|
1170
|
+
animation-duration: 0s !important;
|
|
1171
|
+
animation-delay: 0s !important;
|
|
1172
|
+
transition-duration: 0s !important;
|
|
1173
|
+
transition-delay: 0s !important;
|
|
1174
|
+
}
|
|
1175
|
+
.elementor-invisible { opacity: 1 !important; visibility: visible !important; }
|
|
1176
|
+
`;
|
|
1177
|
+
document.head.appendChild(style);
|
|
1178
|
+
// 6. Wake up any IntersectionObserver-based loaders one more time
|
|
1179
|
+
window.dispatchEvent(new Event("scroll"));
|
|
1180
|
+
window.dispatchEvent(new Event("resize"));
|
|
1181
|
+
// 7. Wait for ALL <img> tags (now eager) to finish loading
|
|
1115
1182
|
const images = Array.from(document.querySelectorAll("img"));
|
|
1116
1183
|
await Promise.all(images.map((img) => {
|
|
1117
1184
|
if (img.complete && img.naturalWidth > 0)
|
|
@@ -1119,13 +1186,12 @@ function createMcpServer(sites) {
|
|
|
1119
1186
|
return new Promise((resolve) => {
|
|
1120
1187
|
img.addEventListener("load", () => resolve(), { once: true });
|
|
1121
1188
|
img.addEventListener("error", () => resolve(), { once: true });
|
|
1122
|
-
// Safety timeout per image
|
|
1123
1189
|
setTimeout(() => resolve(), 5000);
|
|
1124
1190
|
});
|
|
1125
1191
|
}));
|
|
1126
1192
|
});
|
|
1127
|
-
// Extra settle time for fonts,
|
|
1128
|
-
await new Promise(resolve => setTimeout(resolve, wait ??
|
|
1193
|
+
// Extra settle time for fonts, video posters, and bg image decoding
|
|
1194
|
+
await new Promise(resolve => setTimeout(resolve, wait ?? 2500));
|
|
1129
1195
|
const fmt = format ?? "jpeg";
|
|
1130
1196
|
const baseOptions = { type: fmt, fullPage: !max_height && (full_page ?? true) };
|
|
1131
1197
|
if (max_height)
|
package/package.json
CHANGED