@swiftbrowser/web 0.1.0 → 0.2.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.
Files changed (98) hide show
  1. package/README.md +43 -6
  2. package/app/index.html +11 -0
  3. package/node/dist/node/apps.d.ts +16 -0
  4. package/node/dist/node/apps.d.ts.map +1 -1
  5. package/node/dist/node/apps.js +9 -0
  6. package/node/dist/node/apps.js.map +1 -1
  7. package/node/dist/node/config.d.ts +14 -1
  8. package/node/dist/node/config.d.ts.map +1 -1
  9. package/node/dist/node/config.js +20 -3
  10. package/node/dist/node/config.js.map +1 -1
  11. package/node/dist/node/examples.d.ts +2 -1
  12. package/node/dist/node/examples.d.ts.map +1 -1
  13. package/node/dist/node/examples.js +11 -2
  14. package/node/dist/node/examples.js.map +1 -1
  15. package/node/dist/plugins/app-manifests.d.ts +4 -1
  16. package/node/dist/plugins/app-manifests.d.ts.map +1 -1
  17. package/node/dist/plugins/app-manifests.js +3 -2
  18. package/node/dist/plugins/app-manifests.js.map +1 -1
  19. package/node/dist/plugins/asset-catalogs.d.ts +15 -3
  20. package/node/dist/plugins/asset-catalogs.d.ts.map +1 -1
  21. package/node/dist/plugins/asset-catalogs.js +111 -13
  22. package/node/dist/plugins/asset-catalogs.js.map +1 -1
  23. package/node/dist/plugins/included-sites.d.ts +26 -0
  24. package/node/dist/plugins/included-sites.d.ts.map +1 -0
  25. package/node/dist/plugins/included-sites.js +70 -0
  26. package/node/dist/plugins/included-sites.js.map +1 -0
  27. package/node/dist/plugins/pdfImages.d.ts +27 -0
  28. package/node/dist/plugins/pdfImages.d.ts.map +1 -0
  29. package/node/dist/plugins/pdfImages.js +145 -0
  30. package/node/dist/plugins/pdfImages.js.map +1 -0
  31. package/node/dist/plugins/swift-wasm.d.ts +19 -1
  32. package/node/dist/plugins/swift-wasm.d.ts.map +1 -1
  33. package/node/dist/plugins/swift-wasm.js +45 -7
  34. package/node/dist/plugins/swift-wasm.js.map +1 -1
  35. package/node/dist/plugins/symbolTemplates.d.ts +22 -0
  36. package/node/dist/plugins/symbolTemplates.d.ts.map +1 -0
  37. package/node/dist/plugins/symbolTemplates.js +83 -0
  38. package/node/dist/plugins/symbolTemplates.js.map +1 -0
  39. package/package.json +4 -2
  40. package/plugins/app-manifests.ts +3 -2
  41. package/plugins/asset-catalogs.ts +119 -14
  42. package/plugins/included-sites.ts +74 -0
  43. package/plugins/pdfImages.ts +163 -0
  44. package/plugins/swift-wasm.ts +52 -6
  45. package/plugins/symbolTemplates.ts +88 -0
  46. package/public/_headers +7 -0
  47. package/public/app/oauth-callback.html +62 -0
  48. package/src/animation.ts +235 -8
  49. package/src/appFiles.ts +201 -0
  50. package/src/base64.ts +43 -0
  51. package/src/bitmapPlan.ts +143 -0
  52. package/src/bitmapStore.ts +206 -0
  53. package/src/bitmapWorker.ts +41 -0
  54. package/src/bitmapWorkerProtocol.ts +15 -0
  55. package/src/bitmaps.ts +283 -0
  56. package/src/blockedHosts.ts +29 -0
  57. package/src/canvasDrawing.ts +361 -0
  58. package/src/chartDom.ts +2 -2
  59. package/src/chromeColor.ts +179 -0
  60. package/src/clipboard.ts +78 -0
  61. package/src/colorMultiply.ts +93 -0
  62. package/src/colorPicker.ts +44 -0
  63. package/src/corsProxy.ts +45 -0
  64. package/src/gaugeRing.ts +74 -0
  65. package/src/gif.ts +297 -0
  66. package/src/hostRequests.ts +426 -0
  67. package/src/imageOps.ts +592 -0
  68. package/src/interaction.ts +18 -1
  69. package/src/landing.ts +2 -2
  70. package/src/layout/chart.ts +9 -3
  71. package/src/layout/engine.ts +279 -25
  72. package/src/layout/index.ts +3 -1
  73. package/src/layout/text.ts +217 -1
  74. package/src/layout/types.ts +31 -0
  75. package/src/layout/typography.ts +24 -7
  76. package/src/layout/video.ts +24 -0
  77. package/src/layoutDom.ts +53 -3
  78. package/src/main.ts +124 -4
  79. package/src/media.ts +132 -0
  80. package/src/mock.ts +2 -1
  81. package/src/notifications.ts +109 -0
  82. package/src/pathShape.ts +156 -0
  83. package/src/protocol.ts +761 -12
  84. package/src/renderer.ts +584 -36
  85. package/src/richText.ts +65 -0
  86. package/src/scanner.ts +234 -0
  87. package/src/scrollTo.ts +123 -0
  88. package/src/styles.css +212 -7
  89. package/src/styles.ts +31 -0
  90. package/src/swiftData.ts +128 -0
  91. package/src/symbols.ts +564 -21
  92. package/src/translation.ts +126 -0
  93. package/src/video.ts +299 -0
  94. package/src/vite-env.d.ts +6 -0
  95. package/src/wasm.ts +227 -32
  96. package/src/webAuth.ts +267 -0
  97. package/src/webSocket.ts +148 -0
  98. package/src/zoneinfo.ts +269 -0
@@ -19,10 +19,28 @@
19
19
  * `vite build`: copies each spec's `wasm` into the output directory as
20
20
  * `<name>.wasm` (building it first when it is missing and the spec can), so
21
21
  * nothing has to ride along in `public/`. Files that are there anyway are
22
- * still copied by Vite as before.
22
+ * still copied by Vite as before. A module larger than `MAX_FILE_BYTES` (hosts
23
+ * cap a file's size: 25 MiB on Cloudflare Pages) is written as parts,
24
+ * `<name>.wasm.0`, `.1`…, with a manifest `<name>.wasm.parts.json`
25
+ * (`{ size, parts }`); the page joins them (src/wasm.ts).
23
26
  */
24
27
  import type { Plugin } from 'vite';
25
28
  import type { AppSpec } from '../node/apps.js';
29
+ /** The largest file a site holds: under Cloudflare Pages' 25 MiB, with room to spare. */
30
+ export declare const MAX_FILE_BYTES: number;
31
+ /** The manifest of a module written as parts (`<name>.wasm.parts.json`). */
32
+ export interface WasmParts {
33
+ /** The module's size in bytes. */
34
+ size: number;
35
+ /** The parts' file names, in order, next to the manifest. */
36
+ parts: string[];
37
+ }
38
+ /**
39
+ * Writes `source` to `outDir` as `<name>.wasm`, or, when larger than
40
+ * `maxBytes`, as parts of at most `maxBytes` each plus their manifest.
41
+ * Returns the files written.
42
+ */
43
+ export declare function writeModule(source: string, outDir: string, name: string, maxBytes?: number): string[];
26
44
  export interface SwiftWasmOptions {
27
45
  /** Debounce window for bursts of file changes, in ms. */
28
46
  debounceMs?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"swift-wasm.d.ts","sourceRoot":"","sources":["../../../plugins/swift-wasm.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAiC,MAAM,MAAM,CAAC;AAClE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAG/C,MAAM,WAAW,gBAAgB;IAC/B,yDAAyD;IACzD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,uEAAuE;AACvE,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGzD;AAcD,wBAAgB,SAAS,CAAC,KAAK,EAAE,SAAS,OAAO,EAAE,EAAE,OAAO,GAAE,gBAAqB,GAAG,MAAM,CA6M3F"}
1
+ {"version":3,"file":"swift-wasm.d.ts","sourceRoot":"","sources":["../../../plugins/swift-wasm.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAiC,MAAM,MAAM,CAAC;AAClE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAG/C,yFAAyF;AACzF,eAAO,MAAM,cAAc,QAAmB,CAAC;AAE/C,4EAA4E;AAC5E,MAAM,WAAW,SAAS;IACxB,kCAAkC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,6DAA6D;IAC7D,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,SAAiB,GAAG,MAAM,EAAE,CAwB7G;AAED,MAAM,WAAW,gBAAgB;IAC/B,yDAAyD;IACzD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,uEAAuE;AACvE,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGzD;AAcD,wBAAgB,SAAS,CAAC,KAAK,EAAE,SAAS,OAAO,EAAE,EAAE,OAAO,GAAE,gBAAqB,GAAG,MAAM,CA8M3F"}
@@ -19,10 +19,47 @@
19
19
  * `vite build`: copies each spec's `wasm` into the output directory as
20
20
  * `<name>.wasm` (building it first when it is missing and the spec can), so
21
21
  * nothing has to ride along in `public/`. Files that are there anyway are
22
- * still copied by Vite as before.
22
+ * still copied by Vite as before. A module larger than `MAX_FILE_BYTES` (hosts
23
+ * cap a file's size: 25 MiB on Cloudflare Pages) is written as parts,
24
+ * `<name>.wasm.0`, `.1`…, with a manifest `<name>.wasm.parts.json`
25
+ * (`{ size, parts }`); the page joins them (src/wasm.ts).
23
26
  */
24
- import { copyFileSync, createReadStream, existsSync, mkdirSync, readdirSync, rmSync, statSync } from 'node:fs';
27
+ import { closeSync, copyFileSync, createReadStream, existsSync, mkdirSync, openSync, readSync, readdirSync, rmSync, statSync, writeFileSync } from 'node:fs';
25
28
  import path from 'node:path';
29
+ /** The largest file a site holds: under Cloudflare Pages' 25 MiB, with room to spare. */
30
+ export const MAX_FILE_BYTES = 24 * 1024 * 1024;
31
+ /**
32
+ * Writes `source` to `outDir` as `<name>.wasm`, or, when larger than
33
+ * `maxBytes`, as parts of at most `maxBytes` each plus their manifest.
34
+ * Returns the files written.
35
+ */
36
+ export function writeModule(source, outDir, name, maxBytes = MAX_FILE_BYTES) {
37
+ const dest = path.join(outDir, `${name}.wasm`);
38
+ const size = statSync(source).size;
39
+ if (size <= maxBytes) {
40
+ if (path.resolve(source) !== path.resolve(dest))
41
+ copyFileSync(source, dest);
42
+ return [dest];
43
+ }
44
+ rmSync(dest, { force: true });
45
+ const parts = [];
46
+ const fd = openSync(source, 'r');
47
+ try {
48
+ const buffer = Buffer.alloc(maxBytes);
49
+ for (let offset = 0, index = 0; offset < size; offset += maxBytes, index++) {
50
+ const length = readSync(fd, buffer, 0, Math.min(maxBytes, size - offset), offset);
51
+ const part = `${name}.wasm.${index}`;
52
+ writeFileSync(path.join(outDir, part), buffer.subarray(0, length));
53
+ parts.push(part);
54
+ }
55
+ }
56
+ finally {
57
+ closeSync(fd);
58
+ }
59
+ const manifest = { size, parts };
60
+ writeFileSync(path.join(outDir, `${name}.wasm.parts.json`), JSON.stringify(manifest) + '\n');
61
+ return [...parts.map((part) => path.join(outDir, part)), path.join(outDir, `${name}.wasm.parts.json`)];
62
+ }
26
63
  /** The app named by a module request URL (`/<name>.wasm`), or null. */
27
64
  export function wasmRequestApp(url) {
28
65
  const match = /^\/([A-Za-z0-9_-]+)\.wasm(?:\?|$)/.exec(url);
@@ -165,15 +202,16 @@ export function swiftWasm(specs, options = {}) {
165
202
  continue;
166
203
  }
167
204
  mkdirSync(outDir, { recursive: true });
168
- const dest = path.join(outDir, `${spec.name}.wasm`);
169
- if (path.resolve(spec.wasm) !== path.resolve(dest))
170
- copyFileSync(spec.wasm, dest);
205
+ const written = writeModule(spec.wasm, outDir, spec.name);
206
+ if (written.length > 1)
207
+ log(`${spec.name}: ${written.length - 1} parts of at most ${MAX_FILE_BYTES} bytes (the host's file size limit)`);
171
208
  }
172
209
  // Modules of apps outside the registry (the examples' `public/*.wasm`,
173
210
  // copied with the public dir) are not part of this site.
174
- const known = new Set(specs.map((spec) => `${spec.name}.wasm`));
211
+ const known = new Set(specs.map((spec) => spec.name));
175
212
  for (const entry of readdirSync(outDir)) {
176
- if (entry.endsWith('.wasm') && !known.has(entry))
213
+ const module = /^([A-Za-z0-9_-]+)\.wasm(?:\.\d+|\.parts\.json)?$/.exec(entry);
214
+ if (module && !known.has(module[1]))
177
215
  rmSync(path.join(outDir, entry), { force: true });
178
216
  }
179
217
  };
@@ -1 +1 @@
1
- {"version":3,"file":"swift-wasm.js","sourceRoot":"","sources":["../../../plugins/swift-wasm.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"swift-wasm.js","sourceRoot":"","sources":["../../../plugins/swift-wasm.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Custom symbols (`.symbolset`) are SF Symbols templates: one SVG sheet
3
+ * holding notes, guides and the glyph in every weight and scale
4
+ * (`<g id="Regular-M">`, `<g id="Bold-L">`…). Drawn as a mask, the whole
5
+ * sheet shows as a gray smear. The page needs one glyph, so the build
6
+ * publishes the Regular-M variant (else another Regular one) on its own: its
7
+ * group, in a view box from the template's left to right margin lines for it
8
+ * (`left-margin-Regular-M`; older templates have one plain `left-margin`
9
+ * pair, Regular-M's) and the height of those lines, which is the symbol's box.
10
+ *
11
+ * An SVG that is not a template is published as it is.
12
+ */
13
+ export interface SymbolGlyph {
14
+ /** A standalone SVG of the glyph. */
15
+ svg: string;
16
+ /** The glyph's box in template units (100 per point at the template's point size). */
17
+ width: number;
18
+ height: number;
19
+ }
20
+ /** The glyph of an SF Symbols template, or null when `svg` is not one. */
21
+ export declare function symbolTemplateGlyph(svg: string): SymbolGlyph | null;
22
+ //# sourceMappingURL=symbolTemplates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"symbolTemplates.d.ts","sourceRoot":"","sources":["../../../plugins/symbolTemplates.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,MAAM,WAAW,WAAW;IAC1B,qCAAqC;IACrC,GAAG,EAAE,MAAM,CAAC;IACZ,sFAAsF;IACtF,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,0EAA0E;AAC1E,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAMnE"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Custom symbols (`.symbolset`) are SF Symbols templates: one SVG sheet
3
+ * holding notes, guides and the glyph in every weight and scale
4
+ * (`<g id="Regular-M">`, `<g id="Bold-L">`…). Drawn as a mask, the whole
5
+ * sheet shows as a gray smear. The page needs one glyph, so the build
6
+ * publishes the Regular-M variant (else another Regular one) on its own: its
7
+ * group, in a view box from the template's left to right margin lines for it
8
+ * (`left-margin-Regular-M`; older templates have one plain `left-margin`
9
+ * pair, Regular-M's) and the height of those lines, which is the symbol's box.
10
+ *
11
+ * An SVG that is not a template is published as it is.
12
+ */
13
+ /** The variants tried, in order. */
14
+ const VARIANTS = ['Regular-M', 'Regular-S', 'Regular-L', 'Medium-M', 'Semibold-M', 'Light-M'];
15
+ /** The glyph of an SF Symbols template, or null when `svg` is not one. */
16
+ export function symbolTemplateGlyph(svg) {
17
+ for (const variant of VARIANTS) {
18
+ const glyph = extractVariant(svg, variant);
19
+ if (glyph)
20
+ return glyph;
21
+ }
22
+ return null;
23
+ }
24
+ function extractVariant(svg, variant) {
25
+ const open = new RegExp(`<g\\s[^>]*id="${variant}"[^>]*>`).exec(svg);
26
+ if (!open)
27
+ return null;
28
+ const transform = /transform="([^"]*)"/.exec(open[0])?.[1];
29
+ const inner = groupContents(svg, open.index + open[0].length);
30
+ // Older templates have one pair of margins, `left-margin` and `right-margin`, for Regular-M.
31
+ const plain = variant === 'Regular-M';
32
+ const left = marginLine(svg, `left-margin-${variant}`) ?? (plain ? marginLine(svg, 'left-margin') : null);
33
+ const right = marginLine(svg, `right-margin-${variant}`) ?? (plain ? marginLine(svg, 'right-margin') : null);
34
+ if (inner === null || !left || !right)
35
+ return null;
36
+ const x = left.x;
37
+ const y = Math.min(left.y1, left.y2);
38
+ const width = right.x - left.x;
39
+ const height = Math.abs(left.y2 - left.y1);
40
+ if (!(width > 0 && height > 0))
41
+ return null;
42
+ // The template's classes style its preview; a mask needs only the shapes.
43
+ const shapes = inner.replace(/\sclass="[^"]*"/g, '').trim();
44
+ const n = (v) => String(Math.round(v * 1000) / 1000);
45
+ const box = `${n(x)} ${n(y)} ${n(width)} ${n(height)}`;
46
+ const group = transform ? `<g transform="${transform}">${shapes}</g>` : `<g>${shapes}</g>`;
47
+ return {
48
+ svg: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="${box}" width="${n(width)}" height="${n(height)}">${group}</svg>\n`,
49
+ width,
50
+ height,
51
+ };
52
+ }
53
+ /** What lies between `start` (just after a `<g …>`) and its matching `</g>`. */
54
+ function groupContents(svg, start) {
55
+ const tag = /<g[\s>]|<\/g>|<g\/>/g;
56
+ tag.lastIndex = start;
57
+ let depth = 1;
58
+ for (let match = tag.exec(svg); match; match = tag.exec(svg)) {
59
+ if (match[0] === '</g>')
60
+ depth--;
61
+ else if (match[0] !== '<g/>' && !isSelfClosing(svg, match.index))
62
+ depth++;
63
+ if (depth === 0)
64
+ return svg.slice(start, match.index);
65
+ }
66
+ return null;
67
+ }
68
+ function isSelfClosing(svg, index) {
69
+ const end = svg.indexOf('>', index);
70
+ return end > 0 && svg[end - 1] === '/';
71
+ }
72
+ /** A margin `<line>`'s x and vertical extent. */
73
+ function marginLine(svg, id) {
74
+ const line = new RegExp(`<line\\s[^>]*id="${id}"[^>]*>`).exec(svg)?.[0];
75
+ if (!line)
76
+ return null;
77
+ const attr = (name) => Number(new RegExp(`\\s${name}="(-?[\\d.]+)"`).exec(line)?.[1]);
78
+ const x = attr('x1');
79
+ const y1 = attr('y1');
80
+ const y2 = attr('y2');
81
+ return [x, y1, y2].every(Number.isFinite) ? { x, y1, y2 } : null;
82
+ }
83
+ //# sourceMappingURL=symbolTemplates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"symbolTemplates.js","sourceRoot":"","sources":["../../../plugins/symbolTemplates.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@swiftbrowser/web",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "type": "module",
5
5
  "description": "SwiftBrowser web renderer and dev server: applies render ops from a Swift/Wasm app to the DOM inside an iPhone frame.",
6
6
  "repository": {
7
7
  "type": "git",
8
- "url": "git+https://github.com/dabbott/SwiftBrowser.git",
8
+ "url": "git+https://github.com/noya-app/SwiftBrowser.git",
9
9
  "directory": "Web"
10
10
  },
11
11
  "main": "./node/dist/node/index.js",
@@ -26,6 +26,7 @@
26
26
  "app",
27
27
  "index.html",
28
28
  "public/_headers",
29
+ "public/app/oauth-callback.html",
29
30
  "public/apple-touch-icon.png",
30
31
  "public/icon.svg",
31
32
  "public/manifest.webmanifest",
@@ -43,6 +44,7 @@
43
44
  "dependencies": {
44
45
  "@bjorn3/browser_wasi_shim": "^0.4.2",
45
46
  "lucide": "^1.50.0",
47
+ "pdfjs-dist": "^5.7.284",
46
48
  "qrcode": "^1.5.4",
47
49
  "vite": "^7.1.7"
48
50
  },
@@ -121,9 +121,10 @@ export function appIconUrls(specs: readonly ManifestSpec[]): Record<string, stri
121
121
  return icons;
122
122
  }
123
123
 
124
- export function appManifests(specs: readonly ManifestSpec[]): Plugin {
124
+ export function appManifests(specs: readonly ManifestSpec[], included: readonly { name: string; icon?: string }[] = []): Plugin {
125
125
  const byName = new Map(specs.map((spec) => [spec.name, spec]));
126
- const icons = appIconUrls(specs);
126
+ // The apps of included sites (plugins/included-sites.ts) bring their icons.
127
+ const icons = { ...appIconUrls(specs), ...Object.fromEntries(included.flatMap((app) => (app.icon ? [[app.name, app.icon]] : []))) };
127
128
  const isAppPage = (pathname: string): boolean => /(^|\/)app\/(index\.html)?$/.test(pathname.split('?')[0] ?? '');
128
129
 
129
130
  return {
@@ -14,8 +14,11 @@
14
14
  * - a folder whose `Contents.json` has `properties.provides-namespace: true`
15
15
  * prefixes everything inside with `<folder>/` (nested folders chain);
16
16
  * - `<name>.imageset`: the `2x` entry is preferred (then `1x`, `3x`, then the
17
- * first entry with a file); points = pixels ÷ scale;
18
- * - `<name>.symbolset`: an SVG drawn as a template (`kind: "symbol"`);
17
+ * first entry with a file); points = pixels ÷ scale. A PDF (vector
18
+ * artwork) is published as the PNG pdf.js renders it to at 3×, its size
19
+ * in points from the page (pdfImages.ts);
20
+ * - `<name>.symbolset`: an SVG drawn as a template (`kind: "symbol"`); an SF
21
+ * Symbols template is published as its Regular glyph (symbolTemplates.ts);
19
22
  * - `<name>.colorset`: the entry without appearances is `light`, the one with
20
23
  * `luminosity: dark` is `dark`; idiom and contrast variants are ignored.
21
24
  */
@@ -24,6 +27,8 @@ import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';
24
27
  import path from 'node:path';
25
28
  import type { Plugin } from 'vite';
26
29
  import { APP_NAME, type AppSpec } from '../node/apps.js';
30
+ import { PDF_RENDER_SCALE, pdfSize, renderPdfImage } from './pdfImages.js';
31
+ import { symbolTemplateGlyph } from './symbolTemplates.js';
27
32
  import {
28
33
  CATALOG_DIR,
29
34
  assetFileName,
@@ -43,6 +48,12 @@ export interface CatalogFile {
43
48
  /** Absolute path of the source file on disk. */
44
49
  source: string;
45
50
  contentType: string;
51
+ /**
52
+ * `pdf`: the source is a PDF, published as the PNG it renders to
53
+ * (pdfImages.ts). `symbol`: an SF Symbols template, published as its
54
+ * Regular glyph (symbolTemplates.ts).
55
+ */
56
+ render?: 'pdf' | 'symbol';
46
57
  }
47
58
 
48
59
  export interface BuiltCatalog {
@@ -81,6 +92,8 @@ interface ColorSetContents {
81
92
  color?: {
82
93
  'color-space'?: string;
83
94
  components?: { red?: string; green?: string; blue?: string; alpha?: string };
95
+ /** A system color instead of components (`systemIndigoColor`). */
96
+ reference?: string;
84
97
  };
85
98
  }[];
86
99
  }
@@ -132,20 +145,62 @@ export function componentsToCSS(components: {
132
145
  }
133
146
 
134
147
  /** The `light` / `dark` CSS colors of a colorset, or null when it has no usable entry. */
148
+ /**
149
+ * The system colors a color set can name instead of giving components
150
+ * (Xcode's "System Indigo Color" is `"reference": "systemIndigoColor"`), in
151
+ * light and dark, as iOS draws them (the page's `--sb-color-*` values).
152
+ */
153
+ const SYSTEM_COLORS: Record<string, { light: string; dark: string }> = {
154
+ systemRedColor: { light: 'rgba(255, 59, 48, 1)', dark: 'rgba(255, 69, 58, 1)' },
155
+ systemOrangeColor: { light: 'rgba(255, 149, 0, 1)', dark: 'rgba(255, 159, 10, 1)' },
156
+ systemYellowColor: { light: 'rgba(255, 204, 0, 1)', dark: 'rgba(255, 214, 10, 1)' },
157
+ systemGreenColor: { light: 'rgba(52, 199, 89, 1)', dark: 'rgba(48, 209, 88, 1)' },
158
+ systemMintColor: { light: 'rgba(0, 199, 190, 1)', dark: 'rgba(99, 230, 226, 1)' },
159
+ systemTealColor: { light: 'rgba(48, 176, 199, 1)', dark: 'rgba(64, 200, 224, 1)' },
160
+ systemCyanColor: { light: 'rgba(50, 173, 230, 1)', dark: 'rgba(100, 210, 255, 1)' },
161
+ systemBlueColor: { light: 'rgba(0, 122, 255, 1)', dark: 'rgba(10, 132, 255, 1)' },
162
+ systemIndigoColor: { light: 'rgba(88, 86, 214, 1)', dark: 'rgba(94, 92, 230, 1)' },
163
+ systemPurpleColor: { light: 'rgba(175, 82, 222, 1)', dark: 'rgba(191, 90, 242, 1)' },
164
+ systemPinkColor: { light: 'rgba(255, 45, 85, 1)', dark: 'rgba(255, 55, 95, 1)' },
165
+ systemBrownColor: { light: 'rgba(162, 132, 94, 1)', dark: 'rgba(172, 142, 104, 1)' },
166
+ systemGrayColor: { light: 'rgba(142, 142, 147, 1)', dark: 'rgba(142, 142, 147, 1)' },
167
+ labelColor: { light: 'rgba(0, 0, 0, 1)', dark: 'rgba(255, 255, 255, 1)' },
168
+ secondaryLabelColor: { light: 'rgba(60, 60, 67, 0.6)', dark: 'rgba(235, 235, 245, 0.6)' },
169
+ systemBackgroundColor: { light: 'rgba(255, 255, 255, 1)', dark: 'rgba(0, 0, 0, 1)' },
170
+ secondarySystemBackgroundColor: { light: 'rgba(242, 242, 247, 1)', dark: 'rgba(28, 28, 30, 1)' },
171
+ systemGroupedBackgroundColor: { light: 'rgba(242, 242, 247, 1)', dark: 'rgba(0, 0, 0, 1)' },
172
+ whiteColor: { light: 'rgba(255, 255, 255, 1)', dark: 'rgba(255, 255, 255, 1)' },
173
+ blackColor: { light: 'rgba(0, 0, 0, 1)', dark: 'rgba(0, 0, 0, 1)' },
174
+ clearColor: { light: 'rgba(0, 0, 0, 0)', dark: 'rgba(0, 0, 0, 0)' },
175
+ };
176
+
135
177
  export function parseColorSet(contents: ColorSetContents): AssetColor | null {
136
178
  let light: string | undefined;
137
179
  let dark: string | undefined;
180
+ /** The dark form of a system color given for any appearance. */
181
+ let systemDark: string | undefined;
138
182
  for (const entry of contents.colors ?? []) {
139
183
  const components = entry.color?.components;
140
- if (!components) continue;
184
+ const system = entry.color?.reference ? SYSTEM_COLORS[entry.color.reference] : undefined;
185
+ if (!components && !system) continue;
141
186
  const appearances = entry.appearances ?? [];
142
187
  // Contrast ("high") variants are not rendered; skip entries that carry one.
143
188
  if (appearances.some((a) => a.appearance === 'contrast')) continue;
144
189
  const luminosity = appearances.find((a) => a.appearance === 'luminosity')?.value;
145
- const css = componentsToCSS(components);
190
+ if (system) {
191
+ // A system color adapts on its own; an explicit dark entry still wins.
192
+ if (luminosity === 'dark') dark ??= system.dark;
193
+ else if (luminosity === undefined) {
194
+ light ??= system.light;
195
+ systemDark ??= system.dark;
196
+ }
197
+ continue;
198
+ }
199
+ const css = componentsToCSS(components!);
146
200
  if (luminosity === 'dark') dark ??= css;
147
201
  else if (luminosity === undefined) light ??= css;
148
202
  }
203
+ dark ??= systemDark;
149
204
  if (light === undefined) {
150
205
  if (dark === undefined) return null;
151
206
  light = dark;
@@ -178,6 +233,9 @@ export function readImageSize(data: Buffer, ext: string): PixelSize | null {
178
233
  return webpSize(data);
179
234
  case 'svg':
180
235
  return svgSize(data.toString('utf8'));
236
+ case 'pdf':
237
+ // In points: the PDF is rendered at PDF_RENDER_SCALE (pdfImages.ts).
238
+ return pdfSize(data);
181
239
  default:
182
240
  return null;
183
241
  }
@@ -308,6 +366,12 @@ function extensionOf(file: string): string {
308
366
  }
309
367
 
310
368
  function addFile(scan: Scan, name: string, source: string, relativeToCatalog: string): AssetImage | null {
369
+ if (extensionOf(source) === 'pdf') {
370
+ // Vector artwork: published as the PNG pdf.js renders it to.
371
+ const fileName = `${CATALOG_DIR}/${scan.app}/${assetFileName(name, 'png')}`;
372
+ scan.files.set(fileName, { fileName, source, contentType: 'image/png', render: 'pdf' });
373
+ return { src: assetFilePath(scan.app, name, 'png'), width: 0, height: 0, scale: 1, kind: 'image' };
374
+ }
311
375
  const ext = extensionOf(source);
312
376
  const contentType = CONTENT_TYPES[ext];
313
377
  if (!contentType) {
@@ -333,15 +397,17 @@ function scanImageSet(scan: Scan, dir: string, name: string, label: string): voi
333
397
  }
334
398
  const entry = addFile(scan, name, source, label);
335
399
  if (!entry) return;
400
+ const isPdf = extensionOf(source) === 'pdf';
336
401
  const size = readImageSize(readFileSync(source), extensionOf(source));
337
402
  if (!size) {
338
403
  scan.warnings.push(`${label}: could not read the size of ${picked.filename}, skipped`);
339
- scan.files.delete(`${CATALOG_DIR}/${scan.app}/${assetFileName(name, extensionOf(source))}`);
404
+ scan.files.delete(`${CATALOG_DIR}/${scan.app}/${assetFileName(name, isPdf ? 'png' : extensionOf(source))}`);
340
405
  return;
341
406
  }
342
- entry.width = size.width / picked.scale;
343
- entry.height = size.height / picked.scale;
344
- entry.scale = picked.scale;
407
+ // A PDF's size is in points, and its PNG has PDF_RENDER_SCALE pixels per point.
408
+ entry.width = isPdf ? size.width : size.width / picked.scale;
409
+ entry.height = isPdf ? size.height : size.height / picked.scale;
410
+ entry.scale = isPdf ? PDF_RENDER_SCALE : picked.scale;
345
411
  scan.manifest.images[name] = entry;
346
412
  }
347
413
 
@@ -365,6 +431,16 @@ function scanSymbolSet(scan: Scan, dir: string, name: string, label: string): vo
365
431
  if (!entry) return;
366
432
  entry.kind = 'symbol';
367
433
  // The layout engine sizes symbols from the font, so the size is informative only.
434
+ const glyph = symbolTemplateGlyph(readFileSync(source, 'utf8'));
435
+ const file = scan.files.get(`${CATALOG_DIR}/${scan.app}/${assetFileName(name, 'svg')}`);
436
+ if (glyph && file) {
437
+ // An SF Symbols template: published as its Regular glyph.
438
+ file.render = 'symbol';
439
+ entry.width = glyph.width;
440
+ entry.height = glyph.height;
441
+ scan.manifest.images[name] = entry;
442
+ return;
443
+ }
368
444
  const size = readImageSize(readFileSync(source), 'svg');
369
445
  if (size) {
370
446
  entry.width = size.width;
@@ -494,6 +570,16 @@ export function catalogRequestFile(url: string): { app: string; fileName: string
494
570
  return { app: match[1], fileName: `${CATALOG_DIR}/${match[1]}/${match[2]}` };
495
571
  }
496
572
 
573
+ /** What a catalog file publishes: the file, or the PNG its PDF renders to. */
574
+ export function catalogFileContents(file: CatalogFile): Promise<Buffer> {
575
+ if (file.render === 'pdf') return renderPdfImage(file.source);
576
+ if (file.render === 'symbol') {
577
+ const glyph = symbolTemplateGlyph(readFileSync(file.source, 'utf8'));
578
+ if (glyph) return Promise.resolve(Buffer.from(glyph.svg));
579
+ }
580
+ return Promise.resolve(readFileSync(file.source));
581
+ }
582
+
497
583
  /** The fields of an {@link AppSpec} the catalog plugin reads. */
498
584
  export type CatalogSpec = Pick<AppSpec, 'name' | 'catalogs'>;
499
585
 
@@ -539,19 +625,38 @@ export function assetCatalogs(specs: readonly CatalogSpec[]): Plugin {
539
625
  res.end();
540
626
  return;
541
627
  }
542
- res.setHeader('Content-Type', entry.contentType);
543
- res.setHeader('Cache-Control', 'no-cache');
544
- res.end(readFileSync(entry.source));
628
+ catalogFileContents(entry).then(
629
+ (contents) => {
630
+ res.setHeader('Content-Type', entry.contentType);
631
+ res.setHeader('Cache-Control', 'no-cache');
632
+ res.end(contents);
633
+ },
634
+ (error: unknown) => {
635
+ server.config.logger.warn(`[asset-catalogs] ${file.app}: ${entry.source}: ${String(error)}`, { timestamp: true });
636
+ res.statusCode = 500;
637
+ res.end();
638
+ },
639
+ );
545
640
  });
546
641
  },
547
- generateBundle() {
642
+ async generateBundle() {
548
643
  for (const spec of specs) {
549
644
  const built = buildCatalog(spec.name, spec.catalogs);
550
645
  for (const warning of built.warnings) this.warn(`${spec.name}: ${warning}`);
551
- this.emitFile({ type: 'asset', fileName: `${CATALOG_DIR}/${spec.name}.json`, source: catalogJson(built.manifest) });
646
+ // Files first: an image whose PDF does not render leaves the manifest.
647
+ const sources = new Map<string, Buffer>();
552
648
  for (const file of built.files.values()) {
553
- this.emitFile({ type: 'asset', fileName: file.fileName, source: readFileSync(file.source) });
649
+ try {
650
+ sources.set(file.fileName, await catalogFileContents(file));
651
+ } catch (error) {
652
+ this.warn(`${spec.name}: ${path.basename(file.source)} could not be rendered (${String(error)}), skipped`);
653
+ }
554
654
  }
655
+ for (const [name, image] of Object.entries(built.manifest.images)) {
656
+ if (!sources.has(image.src.slice(1))) delete built.manifest.images[name];
657
+ }
658
+ this.emitFile({ type: 'asset', fileName: `${CATALOG_DIR}/${spec.name}.json`, source: catalogJson(built.manifest) });
659
+ for (const [fileName, source] of sources) this.emitFile({ type: 'asset', fileName, source });
555
660
  }
556
661
  },
557
662
  };
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Sites built elsewhere joining this one: an app built with the CLI from its
3
+ * own repository (`swiftbrowser build`, which calls `buildSite`) joins the
4
+ * examples' site, its card on the landing page and its files next to theirs.
5
+ *
6
+ * Every built site lists its apps' landing entries in `apps.json`. The
7
+ * including build reads that list into its own (`__SB_APPS__`, see
8
+ * node/config.ts) and, after writing its bundle, copies the other site's
9
+ * files in: its modules, catalogs, bundles and manifests. The pages and
10
+ * Vite's bundles (`index.html`, `app/`, `assets/`) are this site's own, and a
11
+ * file this site already has (`_headers`, the shared icons) is kept. A whole
12
+ * module (`<name>.wasm`) is written as swift-wasm.ts writes one, in parts when
13
+ * it is over the host's file size limit, so a site can be given its module
14
+ * after it was built (CI's deploy puts the optimized one in).
15
+ */
16
+
17
+ import { cpSync, existsSync, readdirSync, readFileSync } from 'node:fs';
18
+ import path from 'node:path';
19
+ import type { Plugin, ResolvedConfig } from 'vite';
20
+ import type { LandingApp } from '../node/config.js';
21
+ import { writeModule } from './swift-wasm.js';
22
+
23
+ /** The list of a built site's apps, at its root. */
24
+ export const SITE_APPS_FILE = 'apps.json';
25
+
26
+ /** What an including build does not copy from a site: its pages and bundles. */
27
+ const OWN = new Set(['index.html', 'app', 'assets', SITE_APPS_FILE]);
28
+
29
+ /** The landing entries of the site built into `dir`. Throws when it has none. */
30
+ export function readSiteApps(dir: string): LandingApp[] {
31
+ const file = path.join(dir, SITE_APPS_FILE);
32
+ if (!existsSync(file)) throw new Error(`${dir} is not a built site: it has no ${SITE_APPS_FILE}`);
33
+ const apps = JSON.parse(readFileSync(file, 'utf8')) as unknown;
34
+ if (!Array.isArray(apps)) throw new Error(`${file}: expected an array of apps`);
35
+ return apps as LandingApp[];
36
+ }
37
+
38
+ /** A whole module at a site's root: `<name>.wasm`. */
39
+ const MODULE = /^([A-Za-z0-9_-]+)\.wasm$/;
40
+
41
+ /** Copies a built site's files into `outDir`, except its pages and the files `outDir` has. */
42
+ export function copySiteFiles(site: string, outDir: string, maxModuleBytes?: number): void {
43
+ for (const entry of readdirSync(site)) {
44
+ const name = MODULE.exec(entry)?.[1];
45
+ if (name) writeModule(path.join(site, entry), outDir, name, maxModuleBytes);
46
+ }
47
+ cpSync(site, outDir, {
48
+ recursive: true,
49
+ force: false,
50
+ errorOnExist: false,
51
+ filter: (source) => {
52
+ const relative = path.relative(site, source);
53
+ return !OWN.has(relative.split(path.sep)[0] ?? '') && !MODULE.test(relative);
54
+ },
55
+ });
56
+ }
57
+
58
+ /** Writes `apps.json` (every app of the site, `apps`) and copies the included `sites` in. */
59
+ export function includedSites(apps: readonly LandingApp[], sites: readonly string[]): Plugin {
60
+ let outDir = '';
61
+ return {
62
+ name: 'swiftbrowser:included-sites',
63
+ apply: 'build',
64
+ configResolved(config: ResolvedConfig) {
65
+ outDir = path.resolve(config.root, config.build.outDir);
66
+ },
67
+ generateBundle() {
68
+ this.emitFile({ type: 'asset', fileName: SITE_APPS_FILE, source: `${JSON.stringify(apps, null, 2)}\n` });
69
+ },
70
+ closeBundle() {
71
+ for (const site of sites) copySiteFiles(site, outDir);
72
+ },
73
+ };
74
+ }