codeplay-common 4.8.3 → 4.8.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.
@@ -927,21 +927,21 @@ async function getWebViewTarget(localPort) {
927
927
  && target.url !== 'about:blank'
928
928
  ));
929
929
 
930
- const visibleTarget = pageTargets.find((target) => {
930
+ for (const target of pageTargets) {
931
+ const client = new CdpClient(target.webSocketDebuggerUrl);
931
932
  try {
932
- return JSON.parse(target.description || '{}').visible !== false;
933
+ await client.connect();
934
+ const details = await getPageDetails(client);
935
+ if (details.width > 0 && details.height > 0 && details.hasAppPage) {
936
+ return target;
937
+ }
933
938
  } catch {
934
- return true;
939
+ // A target may close while discovering the active app WebView.
940
+ } finally {
941
+ client.close();
935
942
  }
936
- });
937
-
938
- const target = visibleTarget || pageTargets[0];
939
-
940
- if (!target) {
941
- throw new Error('No rendered page was found in the app WebView.');
942
943
  }
943
-
944
- return target;
944
+ throw new Error('No visible Framework7 app page was found. Open the app page and retry; ad WebViews cannot be captured.');
945
945
  }
946
946
 
947
947
  async function getPageDetails(client) {
@@ -952,6 +952,14 @@ async function getPageDetails(client) {
952
952
  width: innerWidth,
953
953
  height: innerHeight,
954
954
  devicePixelRatio: devicePixelRatio,
955
+ hasAppPage: [...document.querySelectorAll('.view .page')].some((page) => {
956
+ const bounds = page.getBoundingClientRect();
957
+ const style = getComputedStyle(page);
958
+ return style.display !== 'none' && style.visibility !== 'hidden'
959
+ && bounds.width > 0 && bounds.height > 0
960
+ && bounds.bottom > 0 && bounds.right > 0
961
+ && bounds.top < innerHeight && bounds.left < innerWidth;
962
+ }),
955
963
  readyState: document.readyState
956
964
  })`,
957
965
  returnByValue: true,
@@ -1041,7 +1049,7 @@ async function capturePageSnapshot(client) {
1041
1049
  ? element.closest('label, .item-content, .input')
1042
1050
  : element;
1043
1051
  const preferredLabel = labelRoot?.querySelector(
1044
- '.item-title, .button-label, strong, .dialog-button-text',
1052
+ '.item-title, .button-label, strong, .dialog-button-text, .homeboxtitle',
1045
1053
  );
1046
1054
  const textRoot = preferredLabel || labelRoot || element;
1047
1055
  const clone = textRoot.cloneNode(true);
@@ -1065,7 +1073,7 @@ async function capturePageSnapshot(client) {
1065
1073
  if (!root) return [];
1066
1074
  const records = [];
1067
1075
  const seen = new Set();
1068
- const selector = 'button, a.button, [role="button"], .list-button, .dialog-button';
1076
+ const selector = 'button, .button, [role="button"], .list-button, .dialog-button';
1069
1077
  for (const element of root.querySelectorAll(selector)) {
1070
1078
  if (!isVisible(element)) continue;
1071
1079
  const label = getElementLabel(element);
@@ -1137,6 +1145,9 @@ async function capturePageSnapshot(client) {
1137
1145
  const activePage = visiblePages.find((page) => page.classList.contains('page-current'))
1138
1146
  || visiblePages[visiblePages.length - 1]
1139
1147
  || null;
1148
+ if (!activePage) {
1149
+ throw new Error('No visible app page was found; screenshot information was not captured.');
1150
+ }
1140
1151
  const overlaySelector = [
1141
1152
  '.dialog.modal-in',
1142
1153
  '.popup.modal-in',
@@ -1161,12 +1172,12 @@ async function capturePageSnapshot(client) {
1161
1172
  ].join(',');
1162
1173
  const pageHeadings = collectUiText(
1163
1174
  activePage,
1164
- 'h1, h2, h3, .navbar .title, .t-section-heading, .headTitle',
1175
+ 'h1, h2, h3, .navbar .title, .t-section-heading, .headTitle, .home-hero-title, .home-section-title',
1165
1176
  10,
1166
1177
  );
1167
1178
  const pageControls = collectUiText(
1168
1179
  activePage,
1169
- 'button, [role="button"], label, .item-title, .item-subtitle, .list-button, option:checked',
1180
+ 'button, [role="button"], label, .item-title, .item-subtitle, .list-button, option:checked, .homeboxtitle',
1170
1181
  30,
1171
1182
  );
1172
1183
  const overlayText = collectUiText(activeOverlay, textSelector, 35);
@@ -1184,6 +1195,8 @@ async function capturePageSnapshot(client) {
1184
1195
  params: Object.keys(f7Route.params || {}),
1185
1196
  query: Object.keys(f7Route.query || {}),
1186
1197
  } : null;
1198
+ const themeAttribute = document.documentElement.getAttribute('data-theme')
1199
+ || document.body.getAttribute('data-theme');
1187
1200
  const screenInfo = {
1188
1201
  documentTitle: normalizeUiText(document.title),
1189
1202
  route: {
@@ -1195,16 +1208,16 @@ async function capturePageSnapshot(client) {
1195
1208
  dataName: activePage.getAttribute('data-name') || '',
1196
1209
  id: activePage.id || '',
1197
1210
  classes: getStableClasses(activePage),
1198
- navbarTitle: collectUiText(activePage, '.navbar .title', 1)[0] || '',
1211
+ navbarTitle: collectUiText(activePage, '.navbar .title, .navbar .home-brand-text', 1)[0] || '',
1199
1212
  headings: pageHeadings,
1200
1213
  sections: collectUiText(
1201
1214
  activePage,
1202
- 'h1, h2, h3, legend, .t-section-heading, .t-output-choice-heading, .headTitle',
1215
+ 'h1, h2, h3, legend, .t-section-heading, .t-output-choice-heading, .headTitle, .home-hero-title, .home-section-title',
1203
1216
  20,
1204
1217
  ),
1205
1218
  descriptions: collectUiText(
1206
1219
  activePage,
1207
- 'p, small, .item-subtitle, .item-after, .t-settings-footnote',
1220
+ 'p, small, .item-subtitle, .item-after, .t-settings-footnote, .home-hero-kicker, .home-hero-subtitle, .home-stat, .homebox-meta',
1208
1221
  30,
1209
1222
  ),
1210
1223
  controls: pageControls,
@@ -1232,10 +1245,12 @@ async function capturePageSnapshot(client) {
1232
1245
  )),
1233
1246
  inputs: overlayInputs,
1234
1247
  } : null,
1235
- theme: document.documentElement.classList.contains('theme-dark')
1236
- || document.body.classList.contains('theme-dark')
1237
- ? 'dark'
1238
- : 'light',
1248
+ theme: themeAttribute === 'dark' || themeAttribute === 'light'
1249
+ ? themeAttribute
1250
+ : document.documentElement.classList.contains('theme-dark')
1251
+ || document.body.classList.contains('theme-dark')
1252
+ ? 'dark'
1253
+ : 'light',
1239
1254
  viewport: {
1240
1255
  width: innerWidth,
1241
1256
  height: innerHeight,
@@ -3365,7 +3380,25 @@ async function captureFramedScreenshot(
3365
3380
  await client.send('Runtime.evaluate', {
3366
3381
  expression: `new Promise((resolve) => {
3367
3382
  const image = document.querySelector('img');
3368
- const ready = () => requestAnimationFrame(() => requestAnimationFrame(resolve));
3383
+ const ready = () => requestAnimationFrame(() => {
3384
+ const copy = document.querySelector('.promo-copy');
3385
+ const device = document.querySelector('.device');
3386
+ if (copy && device && window.innerHeight > window.innerWidth) {
3387
+ const gap = Math.max(16, Math.min(40, window.innerHeight * 0.02));
3388
+ const deviceTop = copy.getBoundingClientRect().bottom + gap;
3389
+ const deviceBounds = device.getBoundingClientRect();
3390
+ const availableHeight = window.innerHeight * 0.97 - deviceTop;
3391
+ const availableWidth = window.innerWidth * 0.9;
3392
+ const scale = Math.min(1, availableHeight / deviceBounds.height, availableWidth / deviceBounds.width);
3393
+ if (scale > 0) {
3394
+ device.style.top = deviceTop + 'px';
3395
+ device.style.bottom = 'auto';
3396
+ device.style.transformOrigin = 'top center';
3397
+ device.style.transform = 'translateX(-50%) scale(' + scale + ')';
3398
+ }
3399
+ }
3400
+ requestAnimationFrame(resolve);
3401
+ });
3369
3402
  if (image.complete) ready();
3370
3403
  else {
3371
3404
  image.addEventListener('load', ready, { once: true });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeplay-common",
3
- "version": "4.8.3",
3
+ "version": "4.8.4",
4
4
  "description": "Common build scripts and files",
5
5
  "scripts": {
6
6
  "postinstall": "node scripts/sync-files.js",