releasebird-javascript-sdk 1.0.61 → 1.0.62

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.
@@ -33,7 +33,9 @@
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:*)"
37
39
  ],
38
40
  "deny": [],
39
41
  "ask": []
@@ -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
- // Set content (using decompressed htmlContent)
112
- await page.setContent(htmlContent, {
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: 'jpeg',
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/jpeg;base64,${screenshot}`;
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
+ &#x1F600; &#x1F389; &#x1F680;
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>