clay-server 2.25.0-beta.1 → 2.25.0

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/lib/pages.js CHANGED
@@ -2,7 +2,7 @@ function pinPageHtml() {
2
2
  return '<!DOCTYPE html><html lang="en"><head>' +
3
3
  '<meta charset="UTF-8">' +
4
4
  '<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">' +
5
- '<meta name="apple-mobile-web-app-capable" content="yes">' +
5
+ '<meta name="mobile-web-app-capable" content="yes">' +
6
6
  '<link rel="icon" type="image/png" href="/favicon-banded.png">' +
7
7
  '<link rel="apple-touch-icon" href="/apple-touch-icon.png">' +
8
8
  '<title>Clay</title>' +
@@ -3,12 +3,12 @@
3
3
  <head>
4
4
  <meta charset="UTF-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
6
- <meta name="apple-mobile-web-app-capable" content="yes">
6
+ <meta name="mobile-web-app-capable" content="yes">
7
7
  <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
8
8
  <script>
9
9
  (function(){
10
10
  var isIOS=/iPad|iPhone|iPod/.test(navigator.userAgent)||(navigator.platform==="MacIntel"&&navigator.maxTouchPoints>1);
11
- if(!isIOS){var l=document.createElement("link");l.rel="manifest";l.href="manifest.json";document.head.appendChild(l)}
11
+ if(!isIOS){var l=document.createElement("link");l.rel="manifest";l.href="/manifest.json";document.head.appendChild(l)}
12
12
  })();
13
13
  </script>
14
14
  <meta name="theme-color" content="#282a36">
@@ -546,7 +546,9 @@ function exportDebateAsPdf() {
546
546
  popup.document.close();
547
547
 
548
548
  popup.onload = function () {
549
- popup.document.fonts.ready.then(function () {
549
+ var fontReady = popup.document.fonts ? popup.document.fonts.ready : Promise.resolve();
550
+ var timeout = new Promise(function (r) { setTimeout(r, 3000); });
551
+ Promise.race([fontReady, timeout]).then(function () {
550
552
  popup.focus();
551
553
  popup.print();
552
554
  if (typeof popup.onafterprint !== "undefined") {
@@ -187,7 +187,22 @@ export function svgToPngDataUrl(svgEl) {
187
187
  var svgBlob = new Blob([svgStr], { type: "image/svg+xml;charset=utf-8" });
188
188
  var url = URL.createObjectURL(svgBlob);
189
189
 
190
+ // Inline external styles into SVG to avoid tainted canvas from cross-origin refs
191
+ var styleSheets = "";
192
+ try {
193
+ var computed = svgEl.querySelectorAll("style");
194
+ for (var si = 0; si < computed.length; si++) {
195
+ styleSheets += computed[si].textContent;
196
+ }
197
+ } catch (e) {}
198
+ // Strip any external references (url(), @import) that would taint the canvas
199
+ svgStr = svgStr.replace(/@import\s+url\([^)]*\)[^;]*;?/g, "");
200
+ svgBlob = new Blob([svgStr], { type: "image/svg+xml;charset=utf-8" });
201
+ URL.revokeObjectURL(url);
202
+ url = URL.createObjectURL(svgBlob);
203
+
190
204
  var img = new Image();
205
+ img.crossOrigin = "anonymous";
191
206
  img.onload = function () {
192
207
  var canvas = document.createElement("canvas");
193
208
  canvas.width = w;
@@ -197,7 +212,12 @@ export function svgToPngDataUrl(svgEl) {
197
212
  ctx.fillRect(0, 0, w, h);
198
213
  ctx.drawImage(img, 0, 0, w, h);
199
214
  URL.revokeObjectURL(url);
200
- resolve(canvas.toDataURL("image/png"));
215
+ try {
216
+ resolve(canvas.toDataURL("image/png"));
217
+ } catch (e) {
218
+ // Tainted canvas fallback: return original SVG as data URL
219
+ resolve("data:image/svg+xml;charset=utf-8," + encodeURIComponent(svgStr));
220
+ }
201
221
  };
202
222
  img.onerror = function () {
203
223
  URL.revokeObjectURL(url);
@@ -276,8 +296,11 @@ export function exportMarkdownAsPdf(markdownEl, filename) {
276
296
  popup.document.close();
277
297
 
278
298
  popup.onload = function () {
279
- // Wait for web fonts (Pretendard, Roboto Mono) before printing
280
- popup.document.fonts.ready.then(function () {
299
+ // Wait for web fonts (Pretendard, Roboto Mono) before printing.
300
+ // Timeout after 3s so PDF export still works when CDN fonts are unreachable.
301
+ var fontReady = popup.document.fonts ? popup.document.fonts.ready : Promise.resolve();
302
+ var timeout = new Promise(function (resolve) { setTimeout(resolve, 3000); });
303
+ Promise.race([fontReady, timeout]).then(function () {
281
304
  popup.focus();
282
305
  popup.print();
283
306
  if (typeof popup.onafterprint !== "undefined") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clay-server",
3
- "version": "2.25.0-beta.1",
3
+ "version": "2.25.0",
4
4
  "description": "Self-hosted Claude Code in your browser. Multi-session, multi-user, push notifications.",
5
5
  "bin": {
6
6
  "clay-server": "./bin/cli.js",