codeplay-common 4.7.5 → 4.7.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/.gitattributes +2 -2
- package/CHANGELOG.md +17 -0
- package/LICENSE +21 -21
- package/README.md +145 -120
- package/RELEASE_NOTES.md +15 -0
- package/files/buildCodeplay/{codeplayBeforeBuild-6.3.js → codeplayBeforeBuild-6.4.js} +313 -335
- package/files/buildCodeplay/release-sync.config.json +4 -4
- package/files/finalrelease +49 -49
- package/files/generate-ai-promo-video.js +23 -23
- package/files/iap-install-2.js +145 -145
- package/files/ionic.config.json +6 -6
- package/files/scripts/setup-baseline-profile.js +262 -262
- package/files/scripts-screenshot/screenshot/background-decorations.js +120 -120
- package/files/scripts-screenshot/screenshot/frame-samples.js +117 -117
- package/files/take-screen-image.js +49 -15
- package/files/take-screen-video.js +644 -644
- package/package.json +15 -15
- package/scripts/sync-files.js +106 -102
- package/scripts/uninstall.js +109 -109
|
@@ -1,120 +1,120 @@
|
|
|
1
|
-
const decorationShapes = Object.freeze({
|
|
2
|
-
ring: { className: 'ring', scale: 1, opacity: 0.28 },
|
|
3
|
-
doubleRing: { className: 'double-ring', scale: 1.08, opacity: 0.24 },
|
|
4
|
-
pill: { className: 'pill', scale: 1.15, opacity: 0.22 },
|
|
5
|
-
dots: { className: 'dots', scale: 0.72, opacity: 0.25 },
|
|
6
|
-
sparkle: { className: 'sparkle', scale: 0.72, opacity: 0.25 },
|
|
7
|
-
diamond: { className: 'diamond', scale: 0.78, opacity: 0.2 },
|
|
8
|
-
triangle: { className: 'triangle', scale: 0.8, opacity: 0.2 },
|
|
9
|
-
hexagon: { className: 'hexagon', scale: 0.9, opacity: 0.2 },
|
|
10
|
-
squircle: { className: 'squircle', scale: 0.9, opacity: 0.2 },
|
|
11
|
-
plus: { className: 'plus', scale: 0.7, opacity: 0.22 },
|
|
12
|
-
chevron: { className: 'chevron', scale: 0.82, opacity: 0.24 },
|
|
13
|
-
orbit: { className: 'orbit', scale: 1.25, opacity: 0.25 },
|
|
14
|
-
bars: { className: 'bars', scale: 0.82, opacity: 0.2 },
|
|
15
|
-
flower: { className: 'flower', scale: 0.8, opacity: 0.2 },
|
|
16
|
-
crescent: { className: 'crescent', scale: 0.82, opacity: 0.22 },
|
|
17
|
-
wave: { className: 'wave', scale: 1.18, opacity: 0.24 },
|
|
18
|
-
cube: { className: 'cube', scale: 0.88, opacity: 0.18 },
|
|
19
|
-
burst: { className: 'burst', scale: 0.72, opacity: 0.2 },
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
const decorationSets = Object.freeze([
|
|
23
|
-
['ring', 'sparkle', 'pill', 'dots', 'diamond', 'orbit'],
|
|
24
|
-
['doubleRing', 'triangle', 'bars', 'crescent', 'sparkle', 'pill'],
|
|
25
|
-
['hexagon', 'wave', 'dots', 'plus', 'ring', 'flower'],
|
|
26
|
-
['squircle', 'orbit', 'chevron', 'burst', 'pill', 'diamond'],
|
|
27
|
-
['flower', 'doubleRing', 'cube', 'dots', 'wave', 'plus'],
|
|
28
|
-
['crescent', 'sparkle', 'hexagon', 'bars', 'ring', 'chevron'],
|
|
29
|
-
['cube', 'pill', 'burst', 'orbit', 'triangle', 'dots'],
|
|
30
|
-
['wave', 'diamond', 'flower', 'doubleRing', 'squircle', 'sparkle'],
|
|
31
|
-
]);
|
|
32
|
-
|
|
33
|
-
const safeAnchors = Object.freeze([
|
|
34
|
-
[5, 11],
|
|
35
|
-
[91, 13],
|
|
36
|
-
[5, 38],
|
|
37
|
-
[92, 42],
|
|
38
|
-
[6, 70],
|
|
39
|
-
[91, 73],
|
|
40
|
-
[12, 91],
|
|
41
|
-
[85, 90],
|
|
42
|
-
]);
|
|
43
|
-
|
|
44
|
-
function getDecorationSeed(value) {
|
|
45
|
-
let hash = 2166136261;
|
|
46
|
-
for (const character of String(value)) {
|
|
47
|
-
hash ^= character.charCodeAt(0);
|
|
48
|
-
hash = Math.imul(hash, 16777619);
|
|
49
|
-
}
|
|
50
|
-
return hash >>> 0;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
function createSeededRandom(seed) {
|
|
54
|
-
let state = seed >>> 0;
|
|
55
|
-
return () => {
|
|
56
|
-
state += 0x6D2B79F5;
|
|
57
|
-
let value = state;
|
|
58
|
-
value = Math.imul(value ^ (value >>> 15), value | 1);
|
|
59
|
-
value ^= value + Math.imul(value ^ (value >>> 7), value | 61);
|
|
60
|
-
return ((value ^ (value >>> 14)) >>> 0) / 4294967296;
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
function createPromotionalDecorations(palette) {
|
|
65
|
-
const random = createSeededRandom(palette.seed);
|
|
66
|
-
const selectedSet = decorationSets[palette.seed % decorationSets.length];
|
|
67
|
-
const objectCount = 5 + (palette.seed % 2);
|
|
68
|
-
const anchorOffset = palette.seed % safeAnchors.length;
|
|
69
|
-
const objects = selectedSet.slice(0, objectCount).map((shapeName, index) => {
|
|
70
|
-
const shape = decorationShapes[shapeName];
|
|
71
|
-
const [baseX, baseY] = safeAnchors[(index + anchorOffset) % safeAnchors.length];
|
|
72
|
-
const size = (3.4 + random() * 4.8) * shape.scale;
|
|
73
|
-
const left = Math.max(1, Math.min(94, baseX + (random() - 0.5) * 5));
|
|
74
|
-
const top = Math.max(2, Math.min(92, baseY + (random() - 0.5) * 6));
|
|
75
|
-
const rotation = Math.round(random() * 150 - 75);
|
|
76
|
-
const color = index % 2 ? palette.secondary : palette.accent;
|
|
77
|
-
return `<span class="promo-object ${shape.className}" style="left:${left.toFixed(1)}%;top:${top.toFixed(1)}%;width:${size.toFixed(1)}vmin;transform:rotate(${rotation}deg);color:${color};opacity:${shape.opacity};"></span>`;
|
|
78
|
-
}).join('');
|
|
79
|
-
|
|
80
|
-
return `<div class="promo-decor" aria-hidden="true">${objects}</div>`;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
function getPromotionalDecorationStyles() {
|
|
84
|
-
return `
|
|
85
|
-
.promo-decor { position: absolute; z-index: 0; inset: 0; overflow: hidden; pointer-events: none; }
|
|
86
|
-
.promo-object { position: absolute; display: block; aspect-ratio: 1; }
|
|
87
|
-
.promo-object::before,
|
|
88
|
-
.promo-object::after { content: ''; position: absolute; }
|
|
89
|
-
.promo-object.ring { border: clamp(2px, 0.28vw, 6px) solid currentColor; border-radius: 50%; }
|
|
90
|
-
.promo-object.double-ring { border: clamp(2px, 0.24vw, 5px) solid currentColor; border-radius: 50%; }
|
|
91
|
-
.promo-object.double-ring::after { inset: 20%; border: clamp(1px, 0.15vw, 3px) solid currentColor; border-radius: 50%; }
|
|
92
|
-
.promo-object.pill { aspect-ratio: 2.3; border-radius: 999px; background: currentColor; }
|
|
93
|
-
.promo-object.dots { border-radius: 50%; background: currentColor; box-shadow: 1.2vmin 0 0 -0.22vmin currentColor, 0 1.2vmin 0 -0.22vmin currentColor, 1.2vmin 1.2vmin 0 -0.22vmin currentColor; }
|
|
94
|
-
.promo-object.sparkle { background: currentColor; clip-path: polygon(50% 0, 61% 39%, 100% 50%, 61% 61%, 50% 100%, 39% 61%, 0 50%, 39% 39%); }
|
|
95
|
-
.promo-object.diamond { border: clamp(2px, 0.25vw, 5px) solid currentColor; border-radius: 18%; transform-origin: center; }
|
|
96
|
-
.promo-object.triangle { background: currentColor; clip-path: polygon(50% 4%, 96% 91%, 4% 91%); }
|
|
97
|
-
.promo-object.hexagon { background: currentColor; clip-path: polygon(25% 7%, 75% 7%, 100% 50%, 75% 93%, 25% 93%, 0 50%); }
|
|
98
|
-
.promo-object.squircle { border: clamp(2px, 0.25vw, 5px) solid currentColor; border-radius: 32%; }
|
|
99
|
-
.promo-object.plus { background: currentColor; clip-path: polygon(36% 0, 64% 0, 64% 36%, 100% 36%, 100% 64%, 64% 64%, 64% 100%, 36% 100%, 36% 64%, 0 64%, 0 36%, 36% 36%); }
|
|
100
|
-
.promo-object.chevron { background: currentColor; clip-path: polygon(0 18%, 50% 66%, 100% 18%, 100% 48%, 50% 96%, 0 48%); }
|
|
101
|
-
.promo-object.orbit { aspect-ratio: 1.8; border: clamp(2px, 0.23vw, 5px) solid currentColor; border-radius: 50%; }
|
|
102
|
-
.promo-object.orbit::after { top: 50%; left: 88%; width: 20%; aspect-ratio: 1; transform: translate(-50%, -50%); border-radius: 50%; background: currentColor; }
|
|
103
|
-
.promo-object.bars { background: repeating-linear-gradient(90deg, currentColor 0 12%, transparent 12% 24%); border-radius: 18%; }
|
|
104
|
-
.promo-object.flower { background: currentColor; clip-path: polygon(50% 25%, 65% 5%, 76% 28%, 100% 24%, 88% 50%, 100% 76%, 76% 72%, 65% 95%, 50% 75%, 35% 95%, 24% 72%, 0 76%, 12% 50%, 0 24%, 24% 28%, 35% 5%); }
|
|
105
|
-
.promo-object.crescent { border-radius: 50%; box-shadow: inset 1.7vmin -0.45vmin 0 0 currentColor; }
|
|
106
|
-
.promo-object.wave { aspect-ratio: 2.2; border-top: clamp(3px, 0.35vw, 7px) solid currentColor; border-radius: 50%; }
|
|
107
|
-
.promo-object.wave::after { top: 28%; left: 38%; width: 62%; height: 48%; border-bottom: clamp(3px, 0.35vw, 7px) solid currentColor; border-radius: 50%; }
|
|
108
|
-
.promo-object.cube { background: currentColor; clip-path: polygon(50% 0, 94% 24%, 94% 74%, 50% 100%, 6% 74%, 6% 24%); }
|
|
109
|
-
.promo-object.cube::after { inset: 17% 20%; background: rgba(255,255,255,0.42); clip-path: polygon(50% 0, 100% 24%, 100% 70%, 50% 100%, 0 70%, 0 24%); }
|
|
110
|
-
.promo-object.burst { background: currentColor; clip-path: polygon(50% 0, 59% 34%, 85% 15%, 66% 41%, 100% 50%, 66% 59%, 85% 85%, 59% 66%, 50% 100%, 41% 66%, 15% 85%, 34% 59%, 0 50%, 34% 41%, 15% 15%, 41% 34%); }
|
|
111
|
-
`;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
module.exports = {
|
|
115
|
-
decorationShapes,
|
|
116
|
-
decorationSets,
|
|
117
|
-
getDecorationSeed,
|
|
118
|
-
createPromotionalDecorations,
|
|
119
|
-
getPromotionalDecorationStyles,
|
|
120
|
-
};
|
|
1
|
+
const decorationShapes = Object.freeze({
|
|
2
|
+
ring: { className: 'ring', scale: 1, opacity: 0.28 },
|
|
3
|
+
doubleRing: { className: 'double-ring', scale: 1.08, opacity: 0.24 },
|
|
4
|
+
pill: { className: 'pill', scale: 1.15, opacity: 0.22 },
|
|
5
|
+
dots: { className: 'dots', scale: 0.72, opacity: 0.25 },
|
|
6
|
+
sparkle: { className: 'sparkle', scale: 0.72, opacity: 0.25 },
|
|
7
|
+
diamond: { className: 'diamond', scale: 0.78, opacity: 0.2 },
|
|
8
|
+
triangle: { className: 'triangle', scale: 0.8, opacity: 0.2 },
|
|
9
|
+
hexagon: { className: 'hexagon', scale: 0.9, opacity: 0.2 },
|
|
10
|
+
squircle: { className: 'squircle', scale: 0.9, opacity: 0.2 },
|
|
11
|
+
plus: { className: 'plus', scale: 0.7, opacity: 0.22 },
|
|
12
|
+
chevron: { className: 'chevron', scale: 0.82, opacity: 0.24 },
|
|
13
|
+
orbit: { className: 'orbit', scale: 1.25, opacity: 0.25 },
|
|
14
|
+
bars: { className: 'bars', scale: 0.82, opacity: 0.2 },
|
|
15
|
+
flower: { className: 'flower', scale: 0.8, opacity: 0.2 },
|
|
16
|
+
crescent: { className: 'crescent', scale: 0.82, opacity: 0.22 },
|
|
17
|
+
wave: { className: 'wave', scale: 1.18, opacity: 0.24 },
|
|
18
|
+
cube: { className: 'cube', scale: 0.88, opacity: 0.18 },
|
|
19
|
+
burst: { className: 'burst', scale: 0.72, opacity: 0.2 },
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
const decorationSets = Object.freeze([
|
|
23
|
+
['ring', 'sparkle', 'pill', 'dots', 'diamond', 'orbit'],
|
|
24
|
+
['doubleRing', 'triangle', 'bars', 'crescent', 'sparkle', 'pill'],
|
|
25
|
+
['hexagon', 'wave', 'dots', 'plus', 'ring', 'flower'],
|
|
26
|
+
['squircle', 'orbit', 'chevron', 'burst', 'pill', 'diamond'],
|
|
27
|
+
['flower', 'doubleRing', 'cube', 'dots', 'wave', 'plus'],
|
|
28
|
+
['crescent', 'sparkle', 'hexagon', 'bars', 'ring', 'chevron'],
|
|
29
|
+
['cube', 'pill', 'burst', 'orbit', 'triangle', 'dots'],
|
|
30
|
+
['wave', 'diamond', 'flower', 'doubleRing', 'squircle', 'sparkle'],
|
|
31
|
+
]);
|
|
32
|
+
|
|
33
|
+
const safeAnchors = Object.freeze([
|
|
34
|
+
[5, 11],
|
|
35
|
+
[91, 13],
|
|
36
|
+
[5, 38],
|
|
37
|
+
[92, 42],
|
|
38
|
+
[6, 70],
|
|
39
|
+
[91, 73],
|
|
40
|
+
[12, 91],
|
|
41
|
+
[85, 90],
|
|
42
|
+
]);
|
|
43
|
+
|
|
44
|
+
function getDecorationSeed(value) {
|
|
45
|
+
let hash = 2166136261;
|
|
46
|
+
for (const character of String(value)) {
|
|
47
|
+
hash ^= character.charCodeAt(0);
|
|
48
|
+
hash = Math.imul(hash, 16777619);
|
|
49
|
+
}
|
|
50
|
+
return hash >>> 0;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function createSeededRandom(seed) {
|
|
54
|
+
let state = seed >>> 0;
|
|
55
|
+
return () => {
|
|
56
|
+
state += 0x6D2B79F5;
|
|
57
|
+
let value = state;
|
|
58
|
+
value = Math.imul(value ^ (value >>> 15), value | 1);
|
|
59
|
+
value ^= value + Math.imul(value ^ (value >>> 7), value | 61);
|
|
60
|
+
return ((value ^ (value >>> 14)) >>> 0) / 4294967296;
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function createPromotionalDecorations(palette) {
|
|
65
|
+
const random = createSeededRandom(palette.seed);
|
|
66
|
+
const selectedSet = decorationSets[palette.seed % decorationSets.length];
|
|
67
|
+
const objectCount = 5 + (palette.seed % 2);
|
|
68
|
+
const anchorOffset = palette.seed % safeAnchors.length;
|
|
69
|
+
const objects = selectedSet.slice(0, objectCount).map((shapeName, index) => {
|
|
70
|
+
const shape = decorationShapes[shapeName];
|
|
71
|
+
const [baseX, baseY] = safeAnchors[(index + anchorOffset) % safeAnchors.length];
|
|
72
|
+
const size = (3.4 + random() * 4.8) * shape.scale;
|
|
73
|
+
const left = Math.max(1, Math.min(94, baseX + (random() - 0.5) * 5));
|
|
74
|
+
const top = Math.max(2, Math.min(92, baseY + (random() - 0.5) * 6));
|
|
75
|
+
const rotation = Math.round(random() * 150 - 75);
|
|
76
|
+
const color = index % 2 ? palette.secondary : palette.accent;
|
|
77
|
+
return `<span class="promo-object ${shape.className}" style="left:${left.toFixed(1)}%;top:${top.toFixed(1)}%;width:${size.toFixed(1)}vmin;transform:rotate(${rotation}deg);color:${color};opacity:${shape.opacity};"></span>`;
|
|
78
|
+
}).join('');
|
|
79
|
+
|
|
80
|
+
return `<div class="promo-decor" aria-hidden="true">${objects}</div>`;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function getPromotionalDecorationStyles() {
|
|
84
|
+
return `
|
|
85
|
+
.promo-decor { position: absolute; z-index: 0; inset: 0; overflow: hidden; pointer-events: none; }
|
|
86
|
+
.promo-object { position: absolute; display: block; aspect-ratio: 1; }
|
|
87
|
+
.promo-object::before,
|
|
88
|
+
.promo-object::after { content: ''; position: absolute; }
|
|
89
|
+
.promo-object.ring { border: clamp(2px, 0.28vw, 6px) solid currentColor; border-radius: 50%; }
|
|
90
|
+
.promo-object.double-ring { border: clamp(2px, 0.24vw, 5px) solid currentColor; border-radius: 50%; }
|
|
91
|
+
.promo-object.double-ring::after { inset: 20%; border: clamp(1px, 0.15vw, 3px) solid currentColor; border-radius: 50%; }
|
|
92
|
+
.promo-object.pill { aspect-ratio: 2.3; border-radius: 999px; background: currentColor; }
|
|
93
|
+
.promo-object.dots { border-radius: 50%; background: currentColor; box-shadow: 1.2vmin 0 0 -0.22vmin currentColor, 0 1.2vmin 0 -0.22vmin currentColor, 1.2vmin 1.2vmin 0 -0.22vmin currentColor; }
|
|
94
|
+
.promo-object.sparkle { background: currentColor; clip-path: polygon(50% 0, 61% 39%, 100% 50%, 61% 61%, 50% 100%, 39% 61%, 0 50%, 39% 39%); }
|
|
95
|
+
.promo-object.diamond { border: clamp(2px, 0.25vw, 5px) solid currentColor; border-radius: 18%; transform-origin: center; }
|
|
96
|
+
.promo-object.triangle { background: currentColor; clip-path: polygon(50% 4%, 96% 91%, 4% 91%); }
|
|
97
|
+
.promo-object.hexagon { background: currentColor; clip-path: polygon(25% 7%, 75% 7%, 100% 50%, 75% 93%, 25% 93%, 0 50%); }
|
|
98
|
+
.promo-object.squircle { border: clamp(2px, 0.25vw, 5px) solid currentColor; border-radius: 32%; }
|
|
99
|
+
.promo-object.plus { background: currentColor; clip-path: polygon(36% 0, 64% 0, 64% 36%, 100% 36%, 100% 64%, 64% 64%, 64% 100%, 36% 100%, 36% 64%, 0 64%, 0 36%, 36% 36%); }
|
|
100
|
+
.promo-object.chevron { background: currentColor; clip-path: polygon(0 18%, 50% 66%, 100% 18%, 100% 48%, 50% 96%, 0 48%); }
|
|
101
|
+
.promo-object.orbit { aspect-ratio: 1.8; border: clamp(2px, 0.23vw, 5px) solid currentColor; border-radius: 50%; }
|
|
102
|
+
.promo-object.orbit::after { top: 50%; left: 88%; width: 20%; aspect-ratio: 1; transform: translate(-50%, -50%); border-radius: 50%; background: currentColor; }
|
|
103
|
+
.promo-object.bars { background: repeating-linear-gradient(90deg, currentColor 0 12%, transparent 12% 24%); border-radius: 18%; }
|
|
104
|
+
.promo-object.flower { background: currentColor; clip-path: polygon(50% 25%, 65% 5%, 76% 28%, 100% 24%, 88% 50%, 100% 76%, 76% 72%, 65% 95%, 50% 75%, 35% 95%, 24% 72%, 0 76%, 12% 50%, 0 24%, 24% 28%, 35% 5%); }
|
|
105
|
+
.promo-object.crescent { border-radius: 50%; box-shadow: inset 1.7vmin -0.45vmin 0 0 currentColor; }
|
|
106
|
+
.promo-object.wave { aspect-ratio: 2.2; border-top: clamp(3px, 0.35vw, 7px) solid currentColor; border-radius: 50%; }
|
|
107
|
+
.promo-object.wave::after { top: 28%; left: 38%; width: 62%; height: 48%; border-bottom: clamp(3px, 0.35vw, 7px) solid currentColor; border-radius: 50%; }
|
|
108
|
+
.promo-object.cube { background: currentColor; clip-path: polygon(50% 0, 94% 24%, 94% 74%, 50% 100%, 6% 74%, 6% 24%); }
|
|
109
|
+
.promo-object.cube::after { inset: 17% 20%; background: rgba(255,255,255,0.42); clip-path: polygon(50% 0, 100% 24%, 100% 70%, 50% 100%, 0 70%, 0 24%); }
|
|
110
|
+
.promo-object.burst { background: currentColor; clip-path: polygon(50% 0, 59% 34%, 85% 15%, 66% 41%, 100% 50%, 66% 59%, 85% 85%, 59% 66%, 50% 100%, 41% 66%, 15% 85%, 34% 59%, 0 50%, 34% 41%, 15% 15%, 41% 34%); }
|
|
111
|
+
`;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
module.exports = {
|
|
115
|
+
decorationShapes,
|
|
116
|
+
decorationSets,
|
|
117
|
+
getDecorationSeed,
|
|
118
|
+
createPromotionalDecorations,
|
|
119
|
+
getPromotionalDecorationStyles,
|
|
120
|
+
};
|
|
@@ -1,117 +1,117 @@
|
|
|
1
|
-
const fs = require('node:fs');
|
|
2
|
-
const path = require('node:path');
|
|
3
|
-
const sharp = require('sharp');
|
|
4
|
-
|
|
5
|
-
const frameStyles = {
|
|
6
|
-
android: {
|
|
7
|
-
graphite: { label: 'A · Graphite Android', detail: 'Slim dark bezel', outer: '#151a24', edge: '#626d7f', inner: '#080b12', radius: 47 },
|
|
8
|
-
cobalt: { label: 'B · Cobalt Android', detail: 'Blue accent bezel', outer: '#1945bc', edge: '#8aa9ff', inner: '#07102f', radius: 43 },
|
|
9
|
-
},
|
|
10
|
-
ios: {
|
|
11
|
-
titanium: { label: 'C · Titanium iPhone', detail: 'Light metal edge', outer: '#c7ced6', edge: '#eef2f6', inner: '#222936', radius: 53 },
|
|
12
|
-
midnight: { label: 'D · Midnight iPhone', detail: 'Dark rounded edge', outer: '#202333', edge: '#586076', inner: '#080b12', radius: 53 },
|
|
13
|
-
},
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
function getStatusBarSvg(platform, time) {
|
|
17
|
-
if (platform === 'ios') {
|
|
18
|
-
return `<rect x="12" y="22" width="316" height="40" fill="#f5f7fc"/>
|
|
19
|
-
<text x="29" y="47" font-family="Arial,sans-serif" font-size="14" font-weight="700" fill="#050505">${time}</text>
|
|
20
|
-
<circle cx="246" cy="40" r="2" fill="#c5c7cb"/><circle cx="254" cy="40" r="2" fill="#c5c7cb"/>
|
|
21
|
-
<circle cx="262" cy="40" r="2" fill="#c5c7cb"/><circle cx="270" cy="40" r="2" fill="#c5c7cb"/>
|
|
22
|
-
<path d="M275 35 Q284 27 293 35 M278 39 Q284 34 290 39 M282 43 Q284 41 286 43" fill="none" stroke="#050505" stroke-width="2.5" stroke-linecap="round"/>
|
|
23
|
-
<rect x="295" y="33" width="17" height="13" rx="3" fill="none" stroke="#a7aaae" stroke-width="1.5"/>
|
|
24
|
-
<rect x="297" y="35" width="13" height="9" rx="2" fill="#050505"/>
|
|
25
|
-
<rect x="313" y="37" width="2" height="5" rx="1" fill="#a7aaae"/>`;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
return `<rect x="12" y="22" width="316" height="40" fill="#9075ed"/>
|
|
29
|
-
<text x="29" y="47" font-family="Arial,sans-serif" font-size="14" fill="#ffffff">${time}</text>
|
|
30
|
-
<circle cx="86" cy="41" r="5" fill="none" stroke="#ffffff" stroke-width="1.2"/>
|
|
31
|
-
<circle cx="84" cy="40" r="0.8" fill="#ffffff"/><circle cx="88" cy="40" r="0.8" fill="#ffffff"/>
|
|
32
|
-
<g transform="translate(-15,0)">
|
|
33
|
-
<text x="200" y="36" font-family="Arial,sans-serif" font-size="7" font-weight="700" fill="#ffffff">0.26</text>
|
|
34
|
-
<text x="200" y="44" font-family="Arial,sans-serif" font-size="6" font-weight="700" fill="#ffffff">KB/s</text>
|
|
35
|
-
<path d="M222 43 L235 33 L235 43 Z M242 43 L254 33 L254 43 Z" fill="#ffffff"/>
|
|
36
|
-
<text x="257" y="39" font-family="Arial,sans-serif" font-size="7" font-weight="700" fill="#ffffff">Vo</text>
|
|
37
|
-
<text x="257" y="46" font-family="Arial,sans-serif" font-size="6" font-weight="700" fill="#ffffff">WiFi</text>
|
|
38
|
-
<path d="M274 35 Q283 27 292 35 M277 39 Q283 34 289 39 M281 43 Q283 41 285 43" fill="none" stroke="#ffffff" stroke-width="2" stroke-linecap="round"/>
|
|
39
|
-
<rect x="296" y="34" width="19" height="11" rx="2" fill="none" stroke="#ffffff" stroke-width="1.4"/>
|
|
40
|
-
<path d="M305 33 L301 40 L306 40 L304 46 L312 38 L307 38 L310 33 Z" fill="#ffffff"/>
|
|
41
|
-
<text x="317" y="43" font-family="Arial,sans-serif" font-size="7" fill="#ffffff">87%</text>
|
|
42
|
-
</g>`;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function createFallbackScreenshot(platform) {
|
|
46
|
-
const width = platform === 'ios' ? 1320 : 1080;
|
|
47
|
-
const height = platform === 'ios' ? 2868 : 2400;
|
|
48
|
-
const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}">
|
|
49
|
-
<rect width="100%" height="100%" fill="#f5f7fc"/>
|
|
50
|
-
<rect x="8%" y="26%" width="84%" height="20%" rx="60" fill="#d7ddff"/>
|
|
51
|
-
<text x="50%" y="37%" text-anchor="middle" font-family="Arial,sans-serif" font-size="62" font-weight="700" fill="#4446c6">Image Compressor</text>
|
|
52
|
-
<rect x="8%" y="62%" width="84%" height="8%" rx="55" fill="#5145e7"/>
|
|
53
|
-
<text x="50%" y="67%" text-anchor="middle" font-family="Arial,sans-serif" font-size="42" font-weight="700" fill="#ffffff">Select images</text>
|
|
54
|
-
</svg>`;
|
|
55
|
-
return sharp(Buffer.from(svg)).png().toBuffer();
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
async function getSampleScreenshot(autoScreenshotDirectory, platform) {
|
|
59
|
-
const directory = path.join(autoScreenshotDirectory, 'Store-image-Screenshot', platform === 'ios' ? 'iPhone' : 'Android');
|
|
60
|
-
if (fs.existsSync(directory)) {
|
|
61
|
-
const screenshot = fs.readdirSync(directory).filter((name) => /\.png$/i.test(name)).sort()[0];
|
|
62
|
-
if (screenshot) return fs.readFileSync(path.join(directory, screenshot));
|
|
63
|
-
}
|
|
64
|
-
return createFallbackScreenshot(platform);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
function createSampleCard(style, platform, screenshotUrl, index) {
|
|
68
|
-
const screenRadius = platform === 'ios' ? 40 : 34;
|
|
69
|
-
const sampleTime = platform === 'ios' ? (index ? '12:21' : '12:20') : (index ? '10:56' : '10:55');
|
|
70
|
-
const camera = platform === 'ios'
|
|
71
|
-
? '<rect x="130" y="27" width="80" height="24" rx="12" fill="#05070b"/>'
|
|
72
|
-
: '';
|
|
73
|
-
const navigation = platform === 'android'
|
|
74
|
-
? '<rect x="12" y="717" width="316" height="16" fill="#f4f7f8"/><rect x="107" y="725" width="126" height="3" rx="1.5" fill="#7a7b7c"/>'
|
|
75
|
-
: '';
|
|
76
|
-
|
|
77
|
-
return `<g transform="translate(${index * 510},0)">
|
|
78
|
-
<rect x="12" y="12" width="486" height="926" rx="25" fill="#ffffff" stroke="#dce2ee"/>
|
|
79
|
-
<text x="35" y="52" fill="#172137" font-family="Arial,sans-serif" font-size="24" font-weight="700">${style.label}</text>
|
|
80
|
-
<text x="35" y="80" fill="#6c7890" font-family="Arial,sans-serif" font-size="14">${style.detail} · ${platform === 'ios' ? 'iOS' : 'Android'} status bar</text>
|
|
81
|
-
<g transform="translate(85,115)">
|
|
82
|
-
<rect x="1" y="7" width="338" height="753" rx="47" fill="#0a1225" opacity="0.2"/>
|
|
83
|
-
<rect x="1" y="1" width="338" height="753" rx="${style.radius}" fill="${style.outer}" stroke="${style.edge}" stroke-width="2"/>
|
|
84
|
-
<rect x="7" y="7" width="326" height="741" rx="${style.radius - 5}" fill="${style.inner}"/>
|
|
85
|
-
<clipPath id="screen-${index}"><rect x="12" y="22" width="316" height="711" rx="${screenRadius}"/></clipPath>
|
|
86
|
-
<g clip-path="url(#screen-${index})">
|
|
87
|
-
<rect x="12" y="22" width="316" height="711" fill="#f5f7fc"/>
|
|
88
|
-
<image href="${screenshotUrl}" x="12" y="62" width="316" height="671" preserveAspectRatio="xMidYMin slice"/>
|
|
89
|
-
${getStatusBarSvg(platform, sampleTime)}
|
|
90
|
-
${navigation}
|
|
91
|
-
</g>
|
|
92
|
-
${camera}
|
|
93
|
-
<rect x="338" y="177" width="4" height="66" rx="2" fill="${style.edge}"/>
|
|
94
|
-
</g>
|
|
95
|
-
</g>`;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
async function createFrameSamples(autoScreenshotDirectory) {
|
|
99
|
-
fs.mkdirSync(autoScreenshotDirectory, { recursive: true });
|
|
100
|
-
const paths = [];
|
|
101
|
-
|
|
102
|
-
for (const platform of ['android', 'ios']) {
|
|
103
|
-
const screenshot = await getSampleScreenshot(autoScreenshotDirectory, platform);
|
|
104
|
-
const screenshotUrl = `data:image/png;base64,${screenshot.toString('base64')}`;
|
|
105
|
-
const cards = Object.values(frameStyles[platform])
|
|
106
|
-
.map((style, index) => createSampleCard(style, platform, screenshotUrl, index))
|
|
107
|
-
.join('');
|
|
108
|
-
const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="1020" height="950" viewBox="0 0 1020 950"><rect width="1020" height="950" fill="#eef2f9"/>${cards}</svg>`;
|
|
109
|
-
const output = path.join(autoScreenshotDirectory, `${platform}-frame-options.png`);
|
|
110
|
-
await sharp(Buffer.from(svg)).png().toFile(output);
|
|
111
|
-
paths.push(output);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
return paths;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
module.exports = { frameStyles, createFrameSamples };
|
|
1
|
+
const fs = require('node:fs');
|
|
2
|
+
const path = require('node:path');
|
|
3
|
+
const sharp = require('sharp');
|
|
4
|
+
|
|
5
|
+
const frameStyles = {
|
|
6
|
+
android: {
|
|
7
|
+
graphite: { label: 'A · Graphite Android', detail: 'Slim dark bezel', outer: '#151a24', edge: '#626d7f', inner: '#080b12', radius: 47 },
|
|
8
|
+
cobalt: { label: 'B · Cobalt Android', detail: 'Blue accent bezel', outer: '#1945bc', edge: '#8aa9ff', inner: '#07102f', radius: 43 },
|
|
9
|
+
},
|
|
10
|
+
ios: {
|
|
11
|
+
titanium: { label: 'C · Titanium iPhone', detail: 'Light metal edge', outer: '#c7ced6', edge: '#eef2f6', inner: '#222936', radius: 53 },
|
|
12
|
+
midnight: { label: 'D · Midnight iPhone', detail: 'Dark rounded edge', outer: '#202333', edge: '#586076', inner: '#080b12', radius: 53 },
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
function getStatusBarSvg(platform, time) {
|
|
17
|
+
if (platform === 'ios') {
|
|
18
|
+
return `<rect x="12" y="22" width="316" height="40" fill="#f5f7fc"/>
|
|
19
|
+
<text x="29" y="47" font-family="Arial,sans-serif" font-size="14" font-weight="700" fill="#050505">${time}</text>
|
|
20
|
+
<circle cx="246" cy="40" r="2" fill="#c5c7cb"/><circle cx="254" cy="40" r="2" fill="#c5c7cb"/>
|
|
21
|
+
<circle cx="262" cy="40" r="2" fill="#c5c7cb"/><circle cx="270" cy="40" r="2" fill="#c5c7cb"/>
|
|
22
|
+
<path d="M275 35 Q284 27 293 35 M278 39 Q284 34 290 39 M282 43 Q284 41 286 43" fill="none" stroke="#050505" stroke-width="2.5" stroke-linecap="round"/>
|
|
23
|
+
<rect x="295" y="33" width="17" height="13" rx="3" fill="none" stroke="#a7aaae" stroke-width="1.5"/>
|
|
24
|
+
<rect x="297" y="35" width="13" height="9" rx="2" fill="#050505"/>
|
|
25
|
+
<rect x="313" y="37" width="2" height="5" rx="1" fill="#a7aaae"/>`;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return `<rect x="12" y="22" width="316" height="40" fill="#9075ed"/>
|
|
29
|
+
<text x="29" y="47" font-family="Arial,sans-serif" font-size="14" fill="#ffffff">${time}</text>
|
|
30
|
+
<circle cx="86" cy="41" r="5" fill="none" stroke="#ffffff" stroke-width="1.2"/>
|
|
31
|
+
<circle cx="84" cy="40" r="0.8" fill="#ffffff"/><circle cx="88" cy="40" r="0.8" fill="#ffffff"/>
|
|
32
|
+
<g transform="translate(-15,0)">
|
|
33
|
+
<text x="200" y="36" font-family="Arial,sans-serif" font-size="7" font-weight="700" fill="#ffffff">0.26</text>
|
|
34
|
+
<text x="200" y="44" font-family="Arial,sans-serif" font-size="6" font-weight="700" fill="#ffffff">KB/s</text>
|
|
35
|
+
<path d="M222 43 L235 33 L235 43 Z M242 43 L254 33 L254 43 Z" fill="#ffffff"/>
|
|
36
|
+
<text x="257" y="39" font-family="Arial,sans-serif" font-size="7" font-weight="700" fill="#ffffff">Vo</text>
|
|
37
|
+
<text x="257" y="46" font-family="Arial,sans-serif" font-size="6" font-weight="700" fill="#ffffff">WiFi</text>
|
|
38
|
+
<path d="M274 35 Q283 27 292 35 M277 39 Q283 34 289 39 M281 43 Q283 41 285 43" fill="none" stroke="#ffffff" stroke-width="2" stroke-linecap="round"/>
|
|
39
|
+
<rect x="296" y="34" width="19" height="11" rx="2" fill="none" stroke="#ffffff" stroke-width="1.4"/>
|
|
40
|
+
<path d="M305 33 L301 40 L306 40 L304 46 L312 38 L307 38 L310 33 Z" fill="#ffffff"/>
|
|
41
|
+
<text x="317" y="43" font-family="Arial,sans-serif" font-size="7" fill="#ffffff">87%</text>
|
|
42
|
+
</g>`;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function createFallbackScreenshot(platform) {
|
|
46
|
+
const width = platform === 'ios' ? 1320 : 1080;
|
|
47
|
+
const height = platform === 'ios' ? 2868 : 2400;
|
|
48
|
+
const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}">
|
|
49
|
+
<rect width="100%" height="100%" fill="#f5f7fc"/>
|
|
50
|
+
<rect x="8%" y="26%" width="84%" height="20%" rx="60" fill="#d7ddff"/>
|
|
51
|
+
<text x="50%" y="37%" text-anchor="middle" font-family="Arial,sans-serif" font-size="62" font-weight="700" fill="#4446c6">Image Compressor</text>
|
|
52
|
+
<rect x="8%" y="62%" width="84%" height="8%" rx="55" fill="#5145e7"/>
|
|
53
|
+
<text x="50%" y="67%" text-anchor="middle" font-family="Arial,sans-serif" font-size="42" font-weight="700" fill="#ffffff">Select images</text>
|
|
54
|
+
</svg>`;
|
|
55
|
+
return sharp(Buffer.from(svg)).png().toBuffer();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async function getSampleScreenshot(autoScreenshotDirectory, platform) {
|
|
59
|
+
const directory = path.join(autoScreenshotDirectory, 'Store-image-Screenshot', platform === 'ios' ? 'iPhone' : 'Android');
|
|
60
|
+
if (fs.existsSync(directory)) {
|
|
61
|
+
const screenshot = fs.readdirSync(directory).filter((name) => /\.png$/i.test(name)).sort()[0];
|
|
62
|
+
if (screenshot) return fs.readFileSync(path.join(directory, screenshot));
|
|
63
|
+
}
|
|
64
|
+
return createFallbackScreenshot(platform);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function createSampleCard(style, platform, screenshotUrl, index) {
|
|
68
|
+
const screenRadius = platform === 'ios' ? 40 : 34;
|
|
69
|
+
const sampleTime = platform === 'ios' ? (index ? '12:21' : '12:20') : (index ? '10:56' : '10:55');
|
|
70
|
+
const camera = platform === 'ios'
|
|
71
|
+
? '<rect x="130" y="27" width="80" height="24" rx="12" fill="#05070b"/>'
|
|
72
|
+
: '';
|
|
73
|
+
const navigation = platform === 'android'
|
|
74
|
+
? '<rect x="12" y="717" width="316" height="16" fill="#f4f7f8"/><rect x="107" y="725" width="126" height="3" rx="1.5" fill="#7a7b7c"/>'
|
|
75
|
+
: '';
|
|
76
|
+
|
|
77
|
+
return `<g transform="translate(${index * 510},0)">
|
|
78
|
+
<rect x="12" y="12" width="486" height="926" rx="25" fill="#ffffff" stroke="#dce2ee"/>
|
|
79
|
+
<text x="35" y="52" fill="#172137" font-family="Arial,sans-serif" font-size="24" font-weight="700">${style.label}</text>
|
|
80
|
+
<text x="35" y="80" fill="#6c7890" font-family="Arial,sans-serif" font-size="14">${style.detail} · ${platform === 'ios' ? 'iOS' : 'Android'} status bar</text>
|
|
81
|
+
<g transform="translate(85,115)">
|
|
82
|
+
<rect x="1" y="7" width="338" height="753" rx="47" fill="#0a1225" opacity="0.2"/>
|
|
83
|
+
<rect x="1" y="1" width="338" height="753" rx="${style.radius}" fill="${style.outer}" stroke="${style.edge}" stroke-width="2"/>
|
|
84
|
+
<rect x="7" y="7" width="326" height="741" rx="${style.radius - 5}" fill="${style.inner}"/>
|
|
85
|
+
<clipPath id="screen-${index}"><rect x="12" y="22" width="316" height="711" rx="${screenRadius}"/></clipPath>
|
|
86
|
+
<g clip-path="url(#screen-${index})">
|
|
87
|
+
<rect x="12" y="22" width="316" height="711" fill="#f5f7fc"/>
|
|
88
|
+
<image href="${screenshotUrl}" x="12" y="62" width="316" height="671" preserveAspectRatio="xMidYMin slice"/>
|
|
89
|
+
${getStatusBarSvg(platform, sampleTime)}
|
|
90
|
+
${navigation}
|
|
91
|
+
</g>
|
|
92
|
+
${camera}
|
|
93
|
+
<rect x="338" y="177" width="4" height="66" rx="2" fill="${style.edge}"/>
|
|
94
|
+
</g>
|
|
95
|
+
</g>`;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
async function createFrameSamples(autoScreenshotDirectory) {
|
|
99
|
+
fs.mkdirSync(autoScreenshotDirectory, { recursive: true });
|
|
100
|
+
const paths = [];
|
|
101
|
+
|
|
102
|
+
for (const platform of ['android', 'ios']) {
|
|
103
|
+
const screenshot = await getSampleScreenshot(autoScreenshotDirectory, platform);
|
|
104
|
+
const screenshotUrl = `data:image/png;base64,${screenshot.toString('base64')}`;
|
|
105
|
+
const cards = Object.values(frameStyles[platform])
|
|
106
|
+
.map((style, index) => createSampleCard(style, platform, screenshotUrl, index))
|
|
107
|
+
.join('');
|
|
108
|
+
const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="1020" height="950" viewBox="0 0 1020 950"><rect width="1020" height="950" fill="#eef2f9"/>${cards}</svg>`;
|
|
109
|
+
const output = path.join(autoScreenshotDirectory, `${platform}-frame-options.png`);
|
|
110
|
+
await sharp(Buffer.from(svg)).png().toFile(output);
|
|
111
|
+
paths.push(output);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return paths;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
module.exports = { frameStyles, createFrameSamples };
|
|
@@ -1211,12 +1211,33 @@ async function capturePageSnapshot(client) {
|
|
|
1211
1211
|
};
|
|
1212
1212
|
|
|
1213
1213
|
const serializeDocument = async (sourceDocument) => {
|
|
1214
|
-
const
|
|
1215
|
-
const
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1214
|
+
const originalElements = [];
|
|
1215
|
+
const clonedElements = [];
|
|
1216
|
+
const cloneWithShadowRoots = (original) => {
|
|
1217
|
+
const clone = original.cloneNode(false);
|
|
1218
|
+
if (original.nodeType === Node.ELEMENT_NODE) {
|
|
1219
|
+
originalElements.push(original);
|
|
1220
|
+
clonedElements.push(clone);
|
|
1221
|
+
}
|
|
1222
|
+
for (const child of original.childNodes) {
|
|
1223
|
+
clone.appendChild(cloneWithShadowRoots(child));
|
|
1224
|
+
}
|
|
1225
|
+
if (original.shadowRoot) {
|
|
1226
|
+
const template = sourceDocument.createElement('template');
|
|
1227
|
+
template.setAttribute('shadowrootmode', 'open');
|
|
1228
|
+
for (const stylesheet of original.shadowRoot.adoptedStyleSheets || []) {
|
|
1229
|
+
const style = sourceDocument.createElement('style');
|
|
1230
|
+
style.textContent = [...stylesheet.cssRules].map((rule) => rule.cssText).join('\\n');
|
|
1231
|
+
template.content.appendChild(style);
|
|
1232
|
+
}
|
|
1233
|
+
for (const child of original.shadowRoot.childNodes) {
|
|
1234
|
+
template.content.appendChild(cloneWithShadowRoots(child));
|
|
1235
|
+
}
|
|
1236
|
+
clone.prepend(template);
|
|
1237
|
+
}
|
|
1238
|
+
return clone;
|
|
1239
|
+
};
|
|
1240
|
+
const clonedRoot = cloneWithShadowRoots(sourceDocument.documentElement);
|
|
1220
1241
|
|
|
1221
1242
|
clonedRoot.setAttribute(
|
|
1222
1243
|
'data-responsive-window-scroll-y',
|
|
@@ -1234,9 +1255,13 @@ async function capturePageSnapshot(client) {
|
|
|
1234
1255
|
clone.setAttribute('data-responsive-scroll-left', String(original.scrollLeft));
|
|
1235
1256
|
}
|
|
1236
1257
|
|
|
1237
|
-
if (original.classList.contains('swiper-initialized')) {
|
|
1258
|
+
if (original.classList.contains('swiper-initialized') || original.swiper) {
|
|
1238
1259
|
clone.setAttribute('data-responsive-swiper-width', String(original.clientWidth));
|
|
1239
1260
|
clone.setAttribute('data-responsive-swiper-height', String(original.clientHeight));
|
|
1261
|
+
if (original.swiper) {
|
|
1262
|
+
clone.setAttribute('data-responsive-swiper-active-index', String(original.swiper.activeIndex));
|
|
1263
|
+
clone.setAttribute('data-responsive-swiper-direction', original.swiper.params.direction);
|
|
1264
|
+
}
|
|
1240
1265
|
}
|
|
1241
1266
|
|
|
1242
1267
|
const tagName = original.tagName?.toLowerCase();
|
|
@@ -1321,7 +1346,7 @@ async function capturePageSnapshot(client) {
|
|
|
1321
1346
|
}
|
|
1322
1347
|
}));
|
|
1323
1348
|
|
|
1324
|
-
|
|
1349
|
+
clonedElements.filter((element) => element.matches('script, link[rel="modulepreload"]')).forEach(
|
|
1325
1350
|
(element) => element.remove(),
|
|
1326
1351
|
);
|
|
1327
1352
|
clonedRoot.querySelectorAll('meta[http-equiv="Content-Security-Policy"]').forEach(
|
|
@@ -1560,25 +1585,34 @@ async function waitForReplayLayout(client, snapshot) {
|
|
|
1560
1585
|
new Promise((resolve) => setTimeout(resolve, 5000)),
|
|
1561
1586
|
]);
|
|
1562
1587
|
|
|
1563
|
-
const
|
|
1564
|
-
|
|
1588
|
+
const replayRoots = [];
|
|
1589
|
+
const collectRoots = (root) => {
|
|
1590
|
+
replayRoots.push(root);
|
|
1591
|
+
root.querySelectorAll('*').forEach((element) => {
|
|
1592
|
+
if (element.shadowRoot) collectRoots(element.shadowRoot);
|
|
1593
|
+
});
|
|
1594
|
+
};
|
|
1595
|
+
replayDocuments.forEach(collectRoots);
|
|
1596
|
+
const replayElements = (selector) => replayRoots.flatMap((root) => (
|
|
1597
|
+
[...root.querySelectorAll(selector)]
|
|
1565
1598
|
));
|
|
1566
1599
|
|
|
1567
1600
|
replayElements('[data-responsive-swiper-width]').forEach((swiper) => {
|
|
1568
|
-
const wrapper = [...swiper.children].find((element) => (
|
|
1601
|
+
const wrapper = swiper.shadowRoot?.querySelector('.swiper-wrapper') || [...swiper.children].find((element) => (
|
|
1569
1602
|
element.classList.contains('swiper-wrapper')
|
|
1570
1603
|
));
|
|
1571
1604
|
|
|
1572
1605
|
if (!wrapper) return;
|
|
1573
1606
|
|
|
1574
|
-
const slides = [...wrapper.children].filter((element) => (
|
|
1575
|
-
element.
|
|
1607
|
+
const slides = [...(swiper.shadowRoot ? swiper.children : wrapper.children)].filter((element) => (
|
|
1608
|
+
element.matches('.swiper-slide, swiper-slide')
|
|
1576
1609
|
));
|
|
1577
1610
|
const sourceWidth = Number(swiper.dataset.responsiveSwiperWidth);
|
|
1578
1611
|
const sourceHeight = Number(swiper.dataset.responsiveSwiperHeight);
|
|
1579
1612
|
const widthScale = sourceWidth > 0 ? swiper.clientWidth / sourceWidth : 1;
|
|
1580
1613
|
const heightScale = sourceHeight > 0 ? swiper.clientHeight / sourceHeight : 1;
|
|
1581
|
-
const isVertical = swiper.
|
|
1614
|
+
const isVertical = swiper.dataset.responsiveSwiperDirection === 'vertical'
|
|
1615
|
+
|| swiper.classList.contains('swiper-vertical');
|
|
1582
1616
|
|
|
1583
1617
|
slides.forEach((slide) => {
|
|
1584
1618
|
if (!slide.dataset.responsiveSwiperWidth && slide.style.width) {
|
|
@@ -1601,7 +1635,7 @@ async function waitForReplayLayout(client, snapshot) {
|
|
|
1601
1635
|
}
|
|
1602
1636
|
});
|
|
1603
1637
|
|
|
1604
|
-
const activeSlide = slides.find((slide) => (
|
|
1638
|
+
const activeSlide = slides[Number(swiper.dataset.responsiveSwiperActiveIndex)] || slides.find((slide) => (
|
|
1605
1639
|
slide.classList.contains('swiper-slide-active')
|
|
1606
1640
|
)) || slides[0];
|
|
1607
1641
|
|