releasebird-javascript-sdk 1.0.61 β 1.0.63
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/.claude/settings.local.json +4 -1
- package/backend-image-service/DEPLOYMENT.md +15 -15
- package/backend-image-service/DEPLOYMENT_SUMMARY.txt +5 -5
- package/backend-image-service/analyze-payload-size.js +69 -0
- package/backend-image-service/deploy-to-eb.sh +1 -1
- package/backend-image-service/image-service/Dockerfile +8 -0
- package/backend-image-service/image-service/fonts.conf +39 -0
- package/backend-image-service/image-service/server.js +27 -8
- package/backend-image-service/quick-deploy.sh +1 -1
- package/backend-image-service/test-emoji-detailed.js +119 -0
- package/backend-image-service/test-emoji-simple.js +68 -0
- package/backend-image-service/test-emoji.html +51 -0
- package/build/index.js +1 -1
- package/emoji-test.png +0 -0
- package/package.json +1 -1
- package/published/1.0.62/index.js +1 -0
- package/published/1.0.63/index.js +1 -0
- package/published/latest/index.js +1 -1
- package/src/RbirdScreenshotManager.js +258 -23
|
@@ -33,7 +33,10 @@
|
|
|
33
33
|
"Bash(node test-java-backend.js:*)",
|
|
34
34
|
"Read(//Users/christianzillmann/IdeaProjects/releasebook-backend/src/main/java/io/releasebook/backend/web/rest/papi/**)",
|
|
35
35
|
"Read(//Users/christianzillmann/IdeaProjects/releasebook-backend/**)",
|
|
36
|
-
"Bash(node test-full-flow.js:*)"
|
|
36
|
+
"Bash(node test-full-flow.js:*)",
|
|
37
|
+
"Bash(node test-emoji-simple.js:*)",
|
|
38
|
+
"Bash(node:*)",
|
|
39
|
+
"WebFetch(domain:app.raisenext.de)"
|
|
37
40
|
],
|
|
38
41
|
"deny": [],
|
|
39
42
|
"ask": []
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
## π― Deine Environment
|
|
4
4
|
|
|
5
5
|
- **Application:** `releasebird-image-service`
|
|
6
|
-
- **Environment:** `Releasebird-image-service-env
|
|
6
|
+
- **Environment:** `Releasebird-image-service-env`
|
|
7
7
|
- **Region:** `eu-central-1` (Standard)
|
|
8
8
|
|
|
9
9
|
## π Quick Deployment (Empfohlen)
|
|
@@ -19,7 +19,7 @@ Das Script:
|
|
|
19
19
|
- β
Baut Docker Image
|
|
20
20
|
- β
Erstellt Deployment Package
|
|
21
21
|
- β
Uploaded zu S3
|
|
22
|
-
- β
Deployed zu `Releasebird-image-service-env
|
|
22
|
+
- β
Deployed zu `Releasebird-image-service-env`
|
|
23
23
|
- β
Wartet auf Completion
|
|
24
24
|
- β
Testet Health Endpoint
|
|
25
25
|
|
|
@@ -34,7 +34,7 @@ Mit Standard Script (mit Prompts):
|
|
|
34
34
|
./deploy-to-eb.sh
|
|
35
35
|
|
|
36
36
|
# Oder explizit:
|
|
37
|
-
./deploy-to-eb.sh Releasebird-image-service-env
|
|
37
|
+
./deploy-to-eb.sh Releasebird-image-service-env
|
|
38
38
|
```
|
|
39
39
|
|
|
40
40
|
## π§ͺ Vor dem Deployment testen
|
|
@@ -58,7 +58,7 @@ curl http://localhost:3000/health
|
|
|
58
58
|
|
|
59
59
|
```bash
|
|
60
60
|
aws elasticbeanstalk describe-environments \
|
|
61
|
-
--environment-names Releasebird-image-service-env
|
|
61
|
+
--environment-names Releasebird-image-service-env \
|
|
62
62
|
--query 'Environments[0].[EnvironmentName,Status,Health,CNAME]' \
|
|
63
63
|
--output table
|
|
64
64
|
```
|
|
@@ -68,10 +68,10 @@ aws elasticbeanstalk describe-environments \
|
|
|
68
68
|
```bash
|
|
69
69
|
# Aktuelle Logs
|
|
70
70
|
aws elasticbeanstalk logs \
|
|
71
|
-
--environment-name Releasebird-image-service-env
|
|
71
|
+
--environment-name Releasebird-image-service-env
|
|
72
72
|
|
|
73
73
|
# Logs streamen (mit EB CLI)
|
|
74
|
-
eb logs --stream -e Releasebird-image-service-env
|
|
74
|
+
eb logs --stream -e Releasebird-image-service-env
|
|
75
75
|
```
|
|
76
76
|
|
|
77
77
|
### Health Check
|
|
@@ -79,7 +79,7 @@ eb logs --stream -e Releasebird-image-service-env-1
|
|
|
79
79
|
```bash
|
|
80
80
|
# Environment URL holen
|
|
81
81
|
ENV_URL=$(aws elasticbeanstalk describe-environments \
|
|
82
|
-
--environment-names Releasebird-image-service-env
|
|
82
|
+
--environment-names Releasebird-image-service-env \
|
|
83
83
|
--query 'Environments[0].CNAME' \
|
|
84
84
|
--output text)
|
|
85
85
|
|
|
@@ -103,19 +103,19 @@ curl -X POST http://$ENV_URL/render \
|
|
|
103
103
|
```bash
|
|
104
104
|
# Environment Events anschauen
|
|
105
105
|
aws elasticbeanstalk describe-events \
|
|
106
|
-
--environment-name Releasebird-image-service-env
|
|
106
|
+
--environment-name Releasebird-image-service-env \
|
|
107
107
|
--max-items 20
|
|
108
108
|
|
|
109
109
|
# Logs holen
|
|
110
110
|
aws elasticbeanstalk logs \
|
|
111
|
-
--environment-name Releasebird-image-service-env
|
|
111
|
+
--environment-name Releasebird-image-service-env
|
|
112
112
|
```
|
|
113
113
|
|
|
114
114
|
### Health Check schlΓ€gt fehl
|
|
115
115
|
|
|
116
116
|
```bash
|
|
117
117
|
# SSH in Instance (mit EB CLI)
|
|
118
|
-
eb ssh -e Releasebird-image-service-env
|
|
118
|
+
eb ssh -e Releasebird-image-service-env
|
|
119
119
|
|
|
120
120
|
# Docker Logs anschauen
|
|
121
121
|
sudo docker logs $(sudo docker ps -q)
|
|
@@ -137,7 +137,7 @@ aws elasticbeanstalk describe-application-versions \
|
|
|
137
137
|
# Zu Version rollback
|
|
138
138
|
aws elasticbeanstalk update-environment \
|
|
139
139
|
--application-name releasebird-image-service \
|
|
140
|
-
--environment-name Releasebird-image-service-env
|
|
140
|
+
--environment-name Releasebird-image-service-env \
|
|
141
141
|
--version-label v20251028-143000 # Ersetze mit gewΓΌnschter Version
|
|
142
142
|
```
|
|
143
143
|
|
|
@@ -168,19 +168,19 @@ Nach dem Deployment:
|
|
|
168
168
|
|
|
169
169
|
# Status
|
|
170
170
|
aws elasticbeanstalk describe-environments \
|
|
171
|
-
--environment-names Releasebird-image-service-env
|
|
171
|
+
--environment-names Releasebird-image-service-env
|
|
172
172
|
|
|
173
173
|
# Logs
|
|
174
174
|
aws elasticbeanstalk logs \
|
|
175
|
-
--environment-name Releasebird-image-service-env
|
|
175
|
+
--environment-name Releasebird-image-service-env
|
|
176
176
|
|
|
177
177
|
# Restart Environment
|
|
178
178
|
aws elasticbeanstalk restart-app-server \
|
|
179
|
-
--environment-name Releasebird-image-service-env
|
|
179
|
+
--environment-name Releasebird-image-service-env
|
|
180
180
|
|
|
181
181
|
# Health
|
|
182
182
|
curl http://$(aws elasticbeanstalk describe-environments \
|
|
183
|
-
--environment-names Releasebird-image-service-env
|
|
183
|
+
--environment-names Releasebird-image-service-env \
|
|
184
184
|
--query 'Environments[0].CNAME' \
|
|
185
185
|
--output text)/health
|
|
186
186
|
```
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
Name: releasebird-image-service
|
|
14
14
|
|
|
15
15
|
π ENVIRONMENT
|
|
16
|
-
Name: Releasebird-image-service-env
|
|
16
|
+
Name: Releasebird-image-service-env
|
|
17
17
|
Region: eu-central-1 β
|
|
18
18
|
|
|
19
19
|
π QUICK DEPLOYMENT
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
2. Creates deployment package (.zip)
|
|
32
32
|
3. Uploads to S3 (eu-central-1)
|
|
33
33
|
4. Creates new application version
|
|
34
|
-
5. Deploys to Releasebird-image-service-env
|
|
34
|
+
5. Deploys to Releasebird-image-service-env
|
|
35
35
|
6. Waits for deployment completion
|
|
36
36
|
7. Tests health endpoint
|
|
37
37
|
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
β AWS CLI installed (aws configure done)
|
|
41
41
|
β Docker running
|
|
42
42
|
β Region: eu-central-1
|
|
43
|
-
β Environment exists: Releasebird-image-service-env
|
|
43
|
+
β Environment exists: Releasebird-image-service-env
|
|
44
44
|
β Application exists: releasebird-image-service
|
|
45
45
|
|
|
46
46
|
π§ͺ TEST LOCALLY FIRST
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
|
|
53
53
|
# Check Environment Status
|
|
54
54
|
aws elasticbeanstalk describe-environments \
|
|
55
|
-
--environment-names Releasebird-image-service-env
|
|
55
|
+
--environment-names Releasebird-image-service-env \
|
|
56
56
|
--region eu-central-1 \
|
|
57
57
|
--query 'Environments[0].[Status,Health,HealthStatus]'
|
|
58
58
|
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
|
|
67
67
|
# View Logs
|
|
68
68
|
aws elasticbeanstalk logs \
|
|
69
|
-
--environment-name Releasebird-image-service-env
|
|
69
|
+
--environment-name Releasebird-image-service-env \
|
|
70
70
|
--region eu-central-1
|
|
71
71
|
|
|
72
72
|
π§ ECR (Docker Registry)
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simulates the payload size when inlining all resources
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
// Example: A typical web app might have:
|
|
6
|
+
const assumptions = {
|
|
7
|
+
htmlSize: 50000, // 50 KB base HTML
|
|
8
|
+
cssFiles: 3, // 3 external CSS files
|
|
9
|
+
avgCssSize: 100000, // 100 KB per CSS file
|
|
10
|
+
images: 10, // 10 images
|
|
11
|
+
avgImageSize: 50000, // 50 KB per image
|
|
12
|
+
fonts: 2, // 2 web fonts
|
|
13
|
+
avgFontSize: 100000, // 100 KB per font
|
|
14
|
+
backgroundImages: 5, // 5 background images in CSS
|
|
15
|
+
avgBgImageSize: 30000 // 30 KB per background image
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
// Calculate base64 overhead (33% increase)
|
|
19
|
+
const base64Overhead = 1.33;
|
|
20
|
+
|
|
21
|
+
const totalCSS = assumptions.cssFiles * assumptions.avgCssSize;
|
|
22
|
+
const totalImages = assumptions.images * assumptions.avgImageSize;
|
|
23
|
+
const totalFonts = assumptions.fonts * assumptions.avgFontSize;
|
|
24
|
+
const totalBgImages = assumptions.backgroundImages * assumptions.avgBgImageSize;
|
|
25
|
+
|
|
26
|
+
const totalBinaryData = totalImages + totalFonts + totalBgImages;
|
|
27
|
+
const totalBinaryDataBase64 = totalBinaryData * base64Overhead;
|
|
28
|
+
|
|
29
|
+
const totalPayload = assumptions.htmlSize + totalCSS + totalBinaryDataBase64;
|
|
30
|
+
|
|
31
|
+
console.log('=== Payload Size Estimation ===\n');
|
|
32
|
+
console.log('Base HTML:', (assumptions.htmlSize / 1024).toFixed(1), 'KB');
|
|
33
|
+
console.log('CSS files:', assumptions.cssFiles, 'x', (assumptions.avgCssSize / 1024).toFixed(1), 'KB =', (totalCSS / 1024).toFixed(1), 'KB');
|
|
34
|
+
console.log('Images:', assumptions.images, 'x', (assumptions.avgImageSize / 1024).toFixed(1), 'KB =', (totalImages / 1024).toFixed(1), 'KB');
|
|
35
|
+
console.log('Fonts:', assumptions.fonts, 'x', (assumptions.avgFontSize / 1024).toFixed(1), 'KB =', (totalFonts / 1024).toFixed(1), 'KB');
|
|
36
|
+
console.log('Background images:', assumptions.backgroundImages, 'x', (assumptions.avgBgImageSize / 1024).toFixed(1), 'KB =', (totalBgImages / 1024).toFixed(1), 'KB');
|
|
37
|
+
console.log('\nBase64 overhead (33%):', ((totalBinaryDataBase64 - totalBinaryData) / 1024).toFixed(1), 'KB');
|
|
38
|
+
console.log('\n--- TOTAL UNCOMPRESSED ---');
|
|
39
|
+
console.log('Total payload:', (totalPayload / 1024).toFixed(1), 'KB');
|
|
40
|
+
console.log('Total payload:', (totalPayload / 1024 / 1024).toFixed(2), 'MB');
|
|
41
|
+
|
|
42
|
+
// With gzip compression (typically 70-90% for HTML/CSS, 0% for already compressed images)
|
|
43
|
+
const htmlCssCompression = 0.3; // 70% reduction
|
|
44
|
+
const htmlCssSize = assumptions.htmlSize + totalCSS;
|
|
45
|
+
const htmlCssCompressed = htmlCssSize * htmlCssCompression;
|
|
46
|
+
const imagesNoCompression = totalBinaryDataBase64; // Already base64, minimal compression
|
|
47
|
+
|
|
48
|
+
const totalCompressed = htmlCssCompressed + imagesNoCompression;
|
|
49
|
+
|
|
50
|
+
console.log('\n--- WITH GZIP COMPRESSION ---');
|
|
51
|
+
console.log('HTML+CSS compressed (70%):', (htmlCssCompressed / 1024).toFixed(1), 'KB');
|
|
52
|
+
console.log('Images (no compression):', (imagesNoCompression / 1024).toFixed(1), 'KB');
|
|
53
|
+
console.log('Total compressed:', (totalCompressed / 1024).toFixed(1), 'KB');
|
|
54
|
+
console.log('Total compressed:', (totalCompressed / 1024 / 1024).toFixed(2), 'MB');
|
|
55
|
+
|
|
56
|
+
console.log('\n--- COMPARISON ---');
|
|
57
|
+
if (totalCompressed < 50 * 1024 * 1024) {
|
|
58
|
+
console.log('β
Fits within 50MB nginx limit');
|
|
59
|
+
} else {
|
|
60
|
+
console.log('β EXCEEDS 50MB nginx limit!');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (totalCompressed < 10 * 1024 * 1024) {
|
|
64
|
+
console.log('β
Reasonable payload size (< 10MB)');
|
|
65
|
+
} else if (totalCompressed < 25 * 1024 * 1024) {
|
|
66
|
+
console.log('β οΈ Large payload (10-25MB) - may be slow');
|
|
67
|
+
} else {
|
|
68
|
+
console.log('β Very large payload (> 25MB) - will be very slow!');
|
|
69
|
+
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
set -e # Exit on error
|
|
7
7
|
|
|
8
|
-
ENVIRONMENT_NAME=${1:-Releasebird-image-service-env
|
|
8
|
+
ENVIRONMENT_NAME=${1:-Releasebird-image-service-env}
|
|
9
9
|
APPLICATION_NAME="releasebird-image-service"
|
|
10
10
|
REGION=${AWS_REGION:-eu-central-1}
|
|
11
11
|
VERSION_LABEL="v$(date +%Y%m%d-%H%M%S)"
|
|
@@ -12,6 +12,8 @@ RUN apt-get update && apt-get install -y \
|
|
|
12
12
|
fonts-noto-color-emoji \
|
|
13
13
|
fonts-noto-cjk \
|
|
14
14
|
fonts-noto-cjk-extra \
|
|
15
|
+
fonts-dejavu-core \
|
|
16
|
+
fontconfig \
|
|
15
17
|
libasound2 \
|
|
16
18
|
libatk-bridge2.0-0 \
|
|
17
19
|
libatk1.0-0 \
|
|
@@ -44,6 +46,12 @@ RUN npm ci --only=production
|
|
|
44
46
|
# Copy application
|
|
45
47
|
COPY server.js ./
|
|
46
48
|
|
|
49
|
+
# Copy font configuration
|
|
50
|
+
COPY fonts.conf /etc/fonts/local.conf
|
|
51
|
+
|
|
52
|
+
# Rebuild font cache
|
|
53
|
+
RUN fc-cache -fv
|
|
54
|
+
|
|
47
55
|
# Expose port
|
|
48
56
|
EXPOSE 3000
|
|
49
57
|
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
<?xml version="1.0"?>
|
|
2
|
+
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
|
|
3
|
+
<fontconfig>
|
|
4
|
+
<!-- Enable emoji rendering -->
|
|
5
|
+
<match target="pattern">
|
|
6
|
+
<test qual="any" name="family">
|
|
7
|
+
<string>sans-serif</string>
|
|
8
|
+
</test>
|
|
9
|
+
<edit name="family" mode="append" binding="weak">
|
|
10
|
+
<string>Noto Color Emoji</string>
|
|
11
|
+
</edit>
|
|
12
|
+
</match>
|
|
13
|
+
|
|
14
|
+
<match target="pattern">
|
|
15
|
+
<test qual="any" name="family">
|
|
16
|
+
<string>serif</string>
|
|
17
|
+
</test>
|
|
18
|
+
<edit name="family" mode="append" binding="weak">
|
|
19
|
+
<string>Noto Color Emoji</string>
|
|
20
|
+
</edit>
|
|
21
|
+
</match>
|
|
22
|
+
|
|
23
|
+
<match target="pattern">
|
|
24
|
+
<test qual="any" name="family">
|
|
25
|
+
<string>monospace</string>
|
|
26
|
+
</test>
|
|
27
|
+
<edit name="family" mode="append" binding="weak">
|
|
28
|
+
<string>Noto Color Emoji</string>
|
|
29
|
+
</edit>
|
|
30
|
+
</match>
|
|
31
|
+
|
|
32
|
+
<!-- Always prefer color emoji -->
|
|
33
|
+
<alias>
|
|
34
|
+
<family>emoji</family>
|
|
35
|
+
<prefer>
|
|
36
|
+
<family>Noto Color Emoji</family>
|
|
37
|
+
</prefer>
|
|
38
|
+
</alias>
|
|
39
|
+
</fontconfig>
|
|
@@ -34,7 +34,10 @@ async function initBrowser() {
|
|
|
34
34
|
'--disable-accelerated-2d-canvas',
|
|
35
35
|
'--no-first-run',
|
|
36
36
|
'--no-zygote',
|
|
37
|
-
'--disable-gpu'
|
|
37
|
+
'--disable-gpu',
|
|
38
|
+
'--font-render-hinting=none',
|
|
39
|
+
'--enable-font-antialiasing',
|
|
40
|
+
'--disable-lcd-text'
|
|
38
41
|
]
|
|
39
42
|
});
|
|
40
43
|
console.log('[Puppeteer] Browser launched successfully');
|
|
@@ -108,21 +111,37 @@ app.post('/render', async (req, res) => {
|
|
|
108
111
|
|
|
109
112
|
console.log(`[Screenshot] Viewport set to ${viewportWidth}x${viewportHeight}`);
|
|
110
113
|
|
|
111
|
-
//
|
|
112
|
-
|
|
114
|
+
// Inject emoji font CSS into HTML
|
|
115
|
+
const emojiCSS = `
|
|
116
|
+
<style>
|
|
117
|
+
* {
|
|
118
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Noto Color Emoji", "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", sans-serif !important;
|
|
119
|
+
}
|
|
120
|
+
</style>
|
|
121
|
+
`;
|
|
122
|
+
|
|
123
|
+
// Insert emoji CSS into HTML
|
|
124
|
+
let enhancedHTML = htmlContent;
|
|
125
|
+
if (htmlContent.includes('<head>')) {
|
|
126
|
+
enhancedHTML = htmlContent.replace('<head>', '<head>' + emojiCSS);
|
|
127
|
+
} else if (htmlContent.includes('<html>')) {
|
|
128
|
+
enhancedHTML = htmlContent.replace('<html>', '<html><head>' + emojiCSS + '</head>');
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Set content (using enhanced htmlContent with emoji fonts)
|
|
132
|
+
await page.setContent(enhancedHTML, {
|
|
113
133
|
waitUntil: 'networkidle0', // Wait for network to be idle
|
|
114
134
|
timeout: 30000
|
|
115
135
|
});
|
|
116
136
|
|
|
117
|
-
console.log('[Screenshot] HTML content loaded');
|
|
137
|
+
console.log('[Screenshot] HTML content loaded with emoji font support');
|
|
118
138
|
|
|
119
139
|
// Wait a bit for any animations/transitions
|
|
120
140
|
await new Promise(resolve => setTimeout(resolve, 500));
|
|
121
141
|
|
|
122
|
-
// Take screenshot
|
|
142
|
+
// Take screenshot (PNG for better emoji support)
|
|
123
143
|
const screenshot = await page.screenshot({
|
|
124
|
-
type: '
|
|
125
|
-
quality: 90,
|
|
144
|
+
type: 'png',
|
|
126
145
|
fullPage: false, // Only visible viewport
|
|
127
146
|
encoding: 'base64'
|
|
128
147
|
});
|
|
@@ -130,7 +149,7 @@ app.post('/render', async (req, res) => {
|
|
|
130
149
|
console.log('[Screenshot] Screenshot captured successfully');
|
|
131
150
|
|
|
132
151
|
// Return as data URL
|
|
133
|
-
const dataUrl = `data:image/
|
|
152
|
+
const dataUrl = `data:image/png;base64,${screenshot}`;
|
|
134
153
|
|
|
135
154
|
res.json({
|
|
136
155
|
screenshot: dataUrl,
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
const zlib = require('zlib');
|
|
2
|
+
const https = require('https');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
|
|
5
|
+
// Test 1: Simple text emoji
|
|
6
|
+
const test1 = `<!DOCTYPE html>
|
|
7
|
+
<html>
|
|
8
|
+
<head>
|
|
9
|
+
<meta charset="UTF-8">
|
|
10
|
+
</head>
|
|
11
|
+
<body style="font-size: 100px; padding: 50px;">
|
|
12
|
+
π π π
|
|
13
|
+
</body>
|
|
14
|
+
</html>`;
|
|
15
|
+
|
|
16
|
+
// Test 2: With explicit font-family
|
|
17
|
+
const test2 = `<!DOCTYPE html>
|
|
18
|
+
<html>
|
|
19
|
+
<head>
|
|
20
|
+
<meta charset="UTF-8">
|
|
21
|
+
<style>
|
|
22
|
+
body {
|
|
23
|
+
font-family: "Noto Color Emoji", sans-serif;
|
|
24
|
+
font-size: 100px;
|
|
25
|
+
padding: 50px;
|
|
26
|
+
}
|
|
27
|
+
</style>
|
|
28
|
+
</head>
|
|
29
|
+
<body>
|
|
30
|
+
π π π
|
|
31
|
+
</body>
|
|
32
|
+
</html>`;
|
|
33
|
+
|
|
34
|
+
// Test 3: Unicode emoji codes
|
|
35
|
+
const test3 = `<!DOCTYPE html>
|
|
36
|
+
<html>
|
|
37
|
+
<head>
|
|
38
|
+
<meta charset="UTF-8">
|
|
39
|
+
</head>
|
|
40
|
+
<body style="font-size: 100px; padding: 50px;">
|
|
41
|
+
😀 🎉 🚀
|
|
42
|
+
</body>
|
|
43
|
+
</html>`;
|
|
44
|
+
|
|
45
|
+
async function testEmoji(html, testName) {
|
|
46
|
+
return new Promise((resolve) => {
|
|
47
|
+
const compressed = zlib.gzipSync(Buffer.from(html, 'utf-8'));
|
|
48
|
+
const base64 = compressed.toString('base64');
|
|
49
|
+
|
|
50
|
+
const data = JSON.stringify({
|
|
51
|
+
htmlCompressed: base64,
|
|
52
|
+
compressed: true,
|
|
53
|
+
width: 600,
|
|
54
|
+
height: 400
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
const options = {
|
|
58
|
+
hostname: 'api.releasebird.com',
|
|
59
|
+
path: '/papi/images/screenshot/render',
|
|
60
|
+
method: 'POST',
|
|
61
|
+
headers: {
|
|
62
|
+
'Content-Type': 'application/json',
|
|
63
|
+
'Content-Length': Buffer.byteLength(data)
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
console.log(`\n=== ${testName} ===`);
|
|
68
|
+
|
|
69
|
+
const req = https.request(options, (res) => {
|
|
70
|
+
let result = '';
|
|
71
|
+
res.on('data', (chunk) => { result += chunk; });
|
|
72
|
+
res.on('end', () => {
|
|
73
|
+
try {
|
|
74
|
+
const parsed = JSON.parse(result);
|
|
75
|
+
if (parsed.screenshot) {
|
|
76
|
+
console.log('β
Screenshot generated');
|
|
77
|
+
console.log('Length:', parsed.screenshot.length);
|
|
78
|
+
|
|
79
|
+
const filename = `emoji-${testName.replace(/\s+/g, '-').toLowerCase()}.png`;
|
|
80
|
+
const base64Data = parsed.screenshot.replace(/^data:image\/\w+;base64,/, '');
|
|
81
|
+
fs.writeFileSync(filename, Buffer.from(base64Data, 'base64'));
|
|
82
|
+
console.log(`Saved to ${filename}`);
|
|
83
|
+
|
|
84
|
+
resolve(true);
|
|
85
|
+
} else {
|
|
86
|
+
console.log('β Error:', parsed.error);
|
|
87
|
+
resolve(false);
|
|
88
|
+
}
|
|
89
|
+
} catch (e) {
|
|
90
|
+
console.log('β Parse error:', e.message);
|
|
91
|
+
resolve(false);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
req.on('error', (err) => {
|
|
97
|
+
console.log('β Request failed:', err.message);
|
|
98
|
+
resolve(false);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
req.write(data);
|
|
102
|
+
req.end();
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
(async () => {
|
|
107
|
+
console.log('Testing emoji rendering with different approaches...\n');
|
|
108
|
+
|
|
109
|
+
await testEmoji(test1, 'Test 1 Simple');
|
|
110
|
+
await new Promise(r => setTimeout(r, 2000));
|
|
111
|
+
|
|
112
|
+
await testEmoji(test2, 'Test 2 Font Family');
|
|
113
|
+
await new Promise(r => setTimeout(r, 2000));
|
|
114
|
+
|
|
115
|
+
await testEmoji(test3, 'Test 3 Unicode');
|
|
116
|
+
|
|
117
|
+
console.log('\n\nPlease check the generated PNG files to see if emojis are visible.');
|
|
118
|
+
console.log('If they appear as boxes or missing, the font issue is confirmed.');
|
|
119
|
+
})();
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
const zlib = require('zlib');
|
|
2
|
+
const https = require('https');
|
|
3
|
+
|
|
4
|
+
// Very simple HTML with emojis
|
|
5
|
+
const html = `<!DOCTYPE html>
|
|
6
|
+
<html>
|
|
7
|
+
<head>
|
|
8
|
+
<meta charset="UTF-8">
|
|
9
|
+
<style>
|
|
10
|
+
body {
|
|
11
|
+
font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
|
|
12
|
+
font-size: 48px;
|
|
13
|
+
padding: 40px;
|
|
14
|
+
}
|
|
15
|
+
</style>
|
|
16
|
+
</head>
|
|
17
|
+
<body>
|
|
18
|
+
<p>Hello π World π</p>
|
|
19
|
+
<p>β
β β οΈ π‘ π₯</p>
|
|
20
|
+
<p>π π π π π</p>
|
|
21
|
+
</body>
|
|
22
|
+
</html>`;
|
|
23
|
+
|
|
24
|
+
const compressed = zlib.gzipSync(Buffer.from(html, 'utf-8'));
|
|
25
|
+
const base64 = compressed.toString('base64');
|
|
26
|
+
|
|
27
|
+
const data = JSON.stringify({
|
|
28
|
+
htmlCompressed: base64,
|
|
29
|
+
compressed: true,
|
|
30
|
+
width: 800,
|
|
31
|
+
height: 600
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const options = {
|
|
35
|
+
hostname: 'api.releasebird.com',
|
|
36
|
+
path: '/papi/images/screenshot/render',
|
|
37
|
+
method: 'POST',
|
|
38
|
+
headers: {
|
|
39
|
+
'Content-Type': 'application/json',
|
|
40
|
+
'Content-Length': Buffer.byteLength(data)
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
console.log('Testing emoji rendering with explicit font family...');
|
|
45
|
+
|
|
46
|
+
const req = https.request(options, (res) => {
|
|
47
|
+
let result = '';
|
|
48
|
+
res.on('data', (chunk) => { result += chunk; });
|
|
49
|
+
res.on('end', () => {
|
|
50
|
+
const parsed = JSON.parse(result);
|
|
51
|
+
if (parsed.screenshot) {
|
|
52
|
+
console.log('β
Screenshot generated');
|
|
53
|
+
console.log('Length:', parsed.screenshot.length);
|
|
54
|
+
|
|
55
|
+
// Save to file for inspection
|
|
56
|
+
const fs = require('fs');
|
|
57
|
+
const base64Data = parsed.screenshot.replace(/^data:image\/\w+;base64,/, '');
|
|
58
|
+
fs.writeFileSync('emoji-test.png', Buffer.from(base64Data, 'base64'));
|
|
59
|
+
console.log('Saved to emoji-test.png - please check if emojis are visible');
|
|
60
|
+
} else {
|
|
61
|
+
console.log('Error:', parsed);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
req.on('error', (err) => console.error('Error:', err.message));
|
|
67
|
+
req.write(data);
|
|
68
|
+
req.end();
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<style>
|
|
6
|
+
body {
|
|
7
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
8
|
+
padding: 40px;
|
|
9
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
10
|
+
}
|
|
11
|
+
.emoji-test {
|
|
12
|
+
background: white;
|
|
13
|
+
padding: 30px;
|
|
14
|
+
border-radius: 20px;
|
|
15
|
+
margin: 20px 0;
|
|
16
|
+
}
|
|
17
|
+
h1 { font-size: 48px; color: #333; }
|
|
18
|
+
.emoji-large { font-size: 64px; }
|
|
19
|
+
.emoji-row { margin: 20px 0; font-size: 32px; }
|
|
20
|
+
</style>
|
|
21
|
+
</head>
|
|
22
|
+
<body>
|
|
23
|
+
<div class="emoji-test">
|
|
24
|
+
<h1>π¨ Emoji Test π</h1>
|
|
25
|
+
|
|
26
|
+
<div class="emoji-large">
|
|
27
|
+
π π π π π π
π€£ π
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
<div class="emoji-row">
|
|
31
|
+
β€οΈ π π π π§‘ π π€ π€
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
<div class="emoji-row">
|
|
35
|
+
β
β β οΈ βΉοΈ π₯ π‘ π π
|
|
36
|
+
</div>
|
|
37
|
+
|
|
38
|
+
<div class="emoji-row">
|
|
39
|
+
π πΈ βοΈ π π π ποΈ π²
|
|
40
|
+
</div>
|
|
41
|
+
|
|
42
|
+
<div class="emoji-row">
|
|
43
|
+
π π π π π π π π«
|
|
44
|
+
</div>
|
|
45
|
+
|
|
46
|
+
<div class="emoji-row">
|
|
47
|
+
π π π π π€ πͺ π¦Ύ π«Ά
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
</body>
|
|
51
|
+
</html>
|