@swiftbrowser/web 0.1.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 (84) hide show
  1. package/README.md +600 -0
  2. package/app/index.html +125 -0
  3. package/index.html +56 -0
  4. package/node/dist/node/apps.d.ts +58 -0
  5. package/node/dist/node/apps.d.ts.map +1 -0
  6. package/node/dist/node/apps.js +60 -0
  7. package/node/dist/node/apps.js.map +1 -0
  8. package/node/dist/node/config.d.ts +42 -0
  9. package/node/dist/node/config.d.ts.map +1 -0
  10. package/node/dist/node/config.js +99 -0
  11. package/node/dist/node/config.js.map +1 -0
  12. package/node/dist/node/examples.d.ts +39 -0
  13. package/node/dist/node/examples.d.ts.map +1 -0
  14. package/node/dist/node/examples.js +116 -0
  15. package/node/dist/node/examples.js.map +1 -0
  16. package/node/dist/node/index.d.ts +47 -0
  17. package/node/dist/node/index.d.ts.map +1 -0
  18. package/node/dist/node/index.js +52 -0
  19. package/node/dist/node/index.js.map +1 -0
  20. package/node/dist/plugins/app-manifests.d.ts +61 -0
  21. package/node/dist/plugins/app-manifests.d.ts.map +1 -0
  22. package/node/dist/plugins/app-manifests.js +168 -0
  23. package/node/dist/plugins/app-manifests.js.map +1 -0
  24. package/node/dist/plugins/asset-catalogs.d.ts +119 -0
  25. package/node/dist/plugins/asset-catalogs.d.ts.map +1 -0
  26. package/node/dist/plugins/asset-catalogs.js +488 -0
  27. package/node/dist/plugins/asset-catalogs.js.map +1 -0
  28. package/node/dist/plugins/bundle-resources.d.ts +49 -0
  29. package/node/dist/plugins/bundle-resources.d.ts.map +1 -0
  30. package/node/dist/plugins/bundle-resources.js +172 -0
  31. package/node/dist/plugins/bundle-resources.js.map +1 -0
  32. package/node/dist/plugins/swift-wasm.d.ts +33 -0
  33. package/node/dist/plugins/swift-wasm.d.ts.map +1 -0
  34. package/node/dist/plugins/swift-wasm.js +241 -0
  35. package/node/dist/plugins/swift-wasm.js.map +1 -0
  36. package/node/dist/src/assets.d.ts +60 -0
  37. package/node/dist/src/assets.d.ts.map +1 -0
  38. package/node/dist/src/assets.js +54 -0
  39. package/node/dist/src/assets.js.map +1 -0
  40. package/node/dist/src/devEvents.d.ts +31 -0
  41. package/node/dist/src/devEvents.d.ts.map +1 -0
  42. package/node/dist/src/devEvents.js +9 -0
  43. package/node/dist/src/devEvents.js.map +1 -0
  44. package/package.json +56 -0
  45. package/plugins/app-manifests.ts +192 -0
  46. package/plugins/asset-catalogs.ts +558 -0
  47. package/plugins/bundle-resources.ts +195 -0
  48. package/plugins/swift-wasm.ts +259 -0
  49. package/public/_headers +23 -0
  50. package/public/apple-touch-icon.png +0 -0
  51. package/public/icon.svg +14 -0
  52. package/public/manifest.webmanifest +14 -0
  53. package/src/animation.ts +521 -0
  54. package/src/assets.ts +86 -0
  55. package/src/chartDom.ts +481 -0
  56. package/src/devEvents.ts +35 -0
  57. package/src/deviceMode.ts +80 -0
  58. package/src/ghost.ts +25 -0
  59. package/src/interaction.ts +1113 -0
  60. package/src/landing.css +261 -0
  61. package/src/landing.ts +141 -0
  62. package/src/layout/chart.ts +477 -0
  63. package/src/layout/controls.ts +116 -0
  64. package/src/layout/engine.ts +3581 -0
  65. package/src/layout/index.ts +91 -0
  66. package/src/layout/measure.ts +86 -0
  67. package/src/layout/text.ts +124 -0
  68. package/src/layout/types.ts +153 -0
  69. package/src/layout/typography.ts +188 -0
  70. package/src/layoutDom.ts +549 -0
  71. package/src/layoutEvents.ts +110 -0
  72. package/src/locale.ts +64 -0
  73. package/src/main.ts +554 -0
  74. package/src/mock.ts +752 -0
  75. package/src/nodeQueries.ts +60 -0
  76. package/src/protocol.ts +1421 -0
  77. package/src/renderer.ts +2882 -0
  78. package/src/styles.css +2834 -0
  79. package/src/styles.ts +373 -0
  80. package/src/swipe.ts +110 -0
  81. package/src/symbols.ts +595 -0
  82. package/src/typography.ts +76 -0
  83. package/src/vite-env.d.ts +26 -0
  84. package/src/wasm.ts +400 -0
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Programmatic API of `@swiftbrowser/web`: run the dev server or build the
3
+ * static site for any set of apps (see ./apps.ts for what an app is).
4
+ *
5
+ * import { createDevServer, buildSite } from '@swiftbrowser/web';
6
+ *
7
+ * Both use this package's `Web/` directory as the Vite root (found relative
8
+ * to this module, so it works from `node_modules`) and build the Vite config
9
+ * from the options; `vite.config.ts` is not read.
10
+ */
11
+ import { type ViteDevServer } from 'vite';
12
+ import { type SiteOptions } from './config.js';
13
+ export type { AppSpec } from './apps.js';
14
+ export { APP_NAME, validateAppSpecs } from './apps.js';
15
+ export type { LandingApp, SiteOptions } from './config.js';
16
+ export { createViteConfig, landingApps, webRoot } from './config.js';
17
+ export interface DevServerOptions extends SiteOptions {
18
+ /** Defaults to 5173. */
19
+ port?: number;
20
+ /** As Vite's `server.host`: `true` listens on all addresses. */
21
+ host?: string | boolean;
22
+ /** Fail instead of trying the next port when `port` is taken (default true). */
23
+ strictPort?: boolean;
24
+ /** Open the landing page in a browser once listening. */
25
+ open?: boolean;
26
+ }
27
+ export interface BuildSiteOptions extends SiteOptions {
28
+ /** Output directory (absolute, or relative to the current working directory). */
29
+ outDir: string;
30
+ /** Empty `outDir` first (default true). */
31
+ emptyOutDir?: boolean;
32
+ /** Vite's log level for the build (`info` prints every emitted file). */
33
+ logLevel?: 'info' | 'warn' | 'error' | 'silent';
34
+ }
35
+ /**
36
+ * A configured, started Vite dev server (`listen` has been called) with the
37
+ * registry plugins for `options.apps`. Call `server.printUrls()` to show the
38
+ * addresses and `server.close()` to stop it.
39
+ */
40
+ export declare function createDevServer(options: DevServerOptions): Promise<ViteDevServer>;
41
+ /**
42
+ * `vite build` of the landing + app pages into `outDir`, with every app's
43
+ * wasm module, catalog JSON + images and web manifest (+ icon) written into
44
+ * it, so the directory is a complete static site.
45
+ */
46
+ export declare function buildSite(options: BuildSiteOptions): Promise<void>;
47
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAA2C,KAAK,aAAa,EAAE,MAAM,MAAM,CAAC;AACnF,OAAO,EAAoB,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAEjE,YAAY,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AACvD,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAErE,MAAM,WAAW,gBAAiB,SAAQ,WAAW;IACnD,wBAAwB;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gEAAgE;IAChE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACxB,gFAAgF;IAChF,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,yDAAyD;IACzD,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,gBAAiB,SAAQ,WAAW;IACnD,iFAAiF;IACjF,MAAM,EAAE,MAAM,CAAC;IACf,2CAA2C;IAC3C,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,yEAAyE;IACzE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;CACjD;AAED;;;;GAIG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,aAAa,CAAC,CAWvF;AAED;;;;GAIG;AACH,wBAAsB,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CASxE"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Programmatic API of `@swiftbrowser/web`: run the dev server or build the
3
+ * static site for any set of apps (see ./apps.ts for what an app is).
4
+ *
5
+ * import { createDevServer, buildSite } from '@swiftbrowser/web';
6
+ *
7
+ * Both use this package's `Web/` directory as the Vite root (found relative
8
+ * to this module, so it works from `node_modules`) and build the Vite config
9
+ * from the options; `vite.config.ts` is not read.
10
+ */
11
+ import path from 'node:path';
12
+ import { build, createServer } from 'vite';
13
+ import { createViteConfig } from './config.js';
14
+ export { APP_NAME, validateAppSpecs } from './apps.js';
15
+ export { createViteConfig, landingApps, webRoot } from './config.js';
16
+ /**
17
+ * A configured, started Vite dev server (`listen` has been called) with the
18
+ * registry plugins for `options.apps`. Call `server.printUrls()` to show the
19
+ * addresses and `server.close()` to stop it.
20
+ */
21
+ export async function createDevServer(options) {
22
+ const { port, host, strictPort, open, ...site } = options;
23
+ const config = createViteConfig(site);
24
+ const server = { ...config.server };
25
+ if (port !== undefined)
26
+ server.port = port;
27
+ if (host !== undefined)
28
+ server.host = host;
29
+ if (strictPort !== undefined)
30
+ server.strictPort = strictPort;
31
+ if (open !== undefined)
32
+ server.open = open;
33
+ const devServer = await createServer({ ...config, configFile: false, server });
34
+ await devServer.listen();
35
+ return devServer;
36
+ }
37
+ /**
38
+ * `vite build` of the landing + app pages into `outDir`, with every app's
39
+ * wasm module, catalog JSON + images and web manifest (+ icon) written into
40
+ * it, so the directory is a complete static site.
41
+ */
42
+ export async function buildSite(options) {
43
+ const { outDir, emptyOutDir, logLevel, ...site } = options;
44
+ const config = createViteConfig(site);
45
+ await build({
46
+ ...config,
47
+ configFile: false,
48
+ ...(logLevel ? { logLevel } : {}),
49
+ build: { ...config.build, outDir: path.resolve(outDir), emptyOutDir: emptyOutDir ?? true },
50
+ });
51
+ }
52
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,KAAK,EAAE,YAAY,EAA0C,MAAM,MAAM,CAAC;AACnF,OAAO,EAAE,gBAAgB,EAAoB,MAAM,aAAa,CAAC;AAGjE,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAEvD,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAsBrE;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,OAAyB;IAC7D,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;IAC1D,MAAM,MAAM,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,MAAM,GAAkB,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;IACnD,IAAI,IAAI,KAAK,SAAS;QAAE,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC;IAC3C,IAAI,IAAI,KAAK,SAAS;QAAE,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC;IAC3C,IAAI,UAAU,KAAK,SAAS;QAAE,MAAM,CAAC,UAAU,GAAG,UAAU,CAAC;IAC7D,IAAI,IAAI,KAAK,SAAS;QAAE,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC;IAC3C,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,EAAE,GAAG,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;IAC/E,MAAM,SAAS,CAAC,MAAM,EAAE,CAAC;IACzB,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,OAAyB;IACvD,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;IAC3D,MAAM,MAAM,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,KAAK,CAAC;QACV,GAAG,MAAM;QACT,UAAU,EAAE,KAAK;QACjB,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACjC,KAAK,EAAE,EAAE,GAAG,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,WAAW,IAAI,IAAI,EAAE;KAC3F,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * One web app manifest per registered app, served at
3
+ * `/manifests/<name>.webmanifest` (dev server and `vite build`), plus the
4
+ * app's own icon at `/manifests/<name>-icon.png` when its spec has one.
5
+ *
6
+ * "Add to Home Screen" in Safari takes the start URL from the page's manifest,
7
+ * not from the page's own URL. With the single `/manifest.webmanifest`
8
+ * (`start_url: /app/`) every home-screen icon therefore launched the default
9
+ * app, whichever one was open when it was added. `app/index.html` points
10
+ * `<link rel="manifest">` at the manifest of the app named by `?app=`, so each
11
+ * icon reopens its own app and is labelled with the app's display name.
12
+ *
13
+ * Safari takes the home-screen image from `<link rel="apple-touch-icon">`
14
+ * rather than from the manifest, so for apps with an icon the plugin also
15
+ * injects `window.__SB_APP_ICONS__` (name -> icon URL) into the app page; the
16
+ * inline script in app/index.html repoints that link.
17
+ */
18
+ import type { Plugin } from 'vite';
19
+ import { type AppSpec } from '../node/apps.js';
20
+ export declare const MANIFEST_DIR = "manifests";
21
+ /** The fields of an {@link AppSpec} a manifest is made from. */
22
+ export type ManifestSpec = Pick<AppSpec, 'name' | 'displayName' | 'description' | 'icon'>;
23
+ export interface AppManifest {
24
+ id: string;
25
+ name: string;
26
+ short_name: string;
27
+ description: string;
28
+ start_url: string;
29
+ scope: string;
30
+ display: 'standalone';
31
+ orientation: 'portrait';
32
+ background_color: string;
33
+ icons: {
34
+ src: string;
35
+ sizes: string;
36
+ type: string;
37
+ }[];
38
+ }
39
+ /** URL path of an app's manifest, as the app page links it. */
40
+ export declare function manifestPath(app: string): string;
41
+ /** URL path of an app's own icon (only served for specs with `icon`). */
42
+ export declare function manifestIconPath(app: string): string;
43
+ /** The app page URL that runs `app` (matches `appPath` in src/landing.ts). */
44
+ export declare function appStartUrl(app: string): string;
45
+ /** Default description, for a spec without one. */
46
+ export declare function defaultDescription(spec: ManifestSpec): string;
47
+ /**
48
+ * The manifest for one app. No `theme_color`: the status bar is translucent
49
+ * and the page draws its own background under it, and the light/dark
50
+ * `theme-color` metas in app/index.html cover the browser UI.
51
+ */
52
+ export declare function appManifest(spec: ManifestSpec | string): AppManifest;
53
+ export declare function appManifestJson(spec: ManifestSpec | string): string;
54
+ /** The app named by a manifest request URL, or null for any other URL. */
55
+ export declare function manifestRequestApp(url: string): string | null;
56
+ /** The app named by an icon request URL (`/manifests/<name>-icon.png`), or null. */
57
+ export declare function iconRequestApp(url: string): string | null;
58
+ /** `name -> icon URL` for the specs that bring their own icon (what the app page reads). */
59
+ export declare function appIconUrls(specs: readonly ManifestSpec[]): Record<string, string>;
60
+ export declare function appManifests(specs: readonly ManifestSpec[]): Plugin;
61
+ //# sourceMappingURL=app-manifests.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-manifests.d.ts","sourceRoot":"","sources":["../../../plugins/app-manifests.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AACnC,OAAO,EAA2B,KAAK,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAGxE,eAAO,MAAM,YAAY,cAAc,CAAC;AAExC,gEAAgE;AAChE,MAAM,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,GAAG,aAAa,GAAG,MAAM,CAAC,CAAC;AAE1F,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,YAAY,CAAC;IACtB,WAAW,EAAE,UAAU,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,KAAK,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACvD;AAED,+DAA+D;AAC/D,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,yEAAyE;AACzE,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED,8EAA8E;AAC9E,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED,mDAAmD;AACnD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,CAE7D;AAYD;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,GAAG,WAAW,CAsBpE;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,GAAG,MAAM,CAEnE;AAED,0EAA0E;AAC1E,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAG7D;AAED,oFAAoF;AACpF,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGzD;AAED,4FAA4F;AAC5F,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,YAAY,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAIlF;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,YAAY,EAAE,GAAG,MAAM,CAoEnE"}
@@ -0,0 +1,168 @@
1
+ /**
2
+ * One web app manifest per registered app, served at
3
+ * `/manifests/<name>.webmanifest` (dev server and `vite build`), plus the
4
+ * app's own icon at `/manifests/<name>-icon.png` when its spec has one.
5
+ *
6
+ * "Add to Home Screen" in Safari takes the start URL from the page's manifest,
7
+ * not from the page's own URL. With the single `/manifest.webmanifest`
8
+ * (`start_url: /app/`) every home-screen icon therefore launched the default
9
+ * app, whichever one was open when it was added. `app/index.html` points
10
+ * `<link rel="manifest">` at the manifest of the app named by `?app=`, so each
11
+ * icon reopens its own app and is labelled with the app's display name.
12
+ *
13
+ * Safari takes the home-screen image from `<link rel="apple-touch-icon">`
14
+ * rather than from the manifest, so for apps with an icon the plugin also
15
+ * injects `window.__SB_APP_ICONS__` (name -> icon URL) into the app page; the
16
+ * inline script in app/index.html repoints that link.
17
+ */
18
+ import { existsSync, readFileSync } from 'node:fs';
19
+ import { APP_NAME, displayNameOf } from '../node/apps.js';
20
+ import { readImageSize } from './asset-catalogs.js';
21
+ export const MANIFEST_DIR = 'manifests';
22
+ /** URL path of an app's manifest, as the app page links it. */
23
+ export function manifestPath(app) {
24
+ return `/${MANIFEST_DIR}/${app}.webmanifest`;
25
+ }
26
+ /** URL path of an app's own icon (only served for specs with `icon`). */
27
+ export function manifestIconPath(app) {
28
+ return `/${MANIFEST_DIR}/${app}-icon.png`;
29
+ }
30
+ /** The app page URL that runs `app` (matches `appPath` in src/landing.ts). */
31
+ export function appStartUrl(app) {
32
+ return `/app/?app=${encodeURIComponent(app)}`;
33
+ }
34
+ /** Default description, for a spec without one. */
35
+ export function defaultDescription(spec) {
36
+ return `The ${displayNameOf(spec)} app, compiled to WebAssembly and rendered in the browser.`;
37
+ }
38
+ /** `WxH` of a PNG on disk, or `any` when it cannot be read. */
39
+ function iconSizes(file) {
40
+ try {
41
+ const size = readImageSize(readFileSync(file), 'png');
42
+ return size ? `${size.width}x${size.height}` : 'any';
43
+ }
44
+ catch {
45
+ return 'any';
46
+ }
47
+ }
48
+ /**
49
+ * The manifest for one app. No `theme_color`: the status bar is translucent
50
+ * and the page draws its own background under it, and the light/dark
51
+ * `theme-color` metas in app/index.html cover the browser UI.
52
+ */
53
+ export function appManifest(spec) {
54
+ const app = typeof spec === 'string' ? { name: spec } : spec;
55
+ if (!APP_NAME.test(app.name))
56
+ throw new Error(`Invalid app name: ${JSON.stringify(app.name)}`);
57
+ const start = appStartUrl(app.name);
58
+ const displayName = displayNameOf(app);
59
+ return {
60
+ id: start,
61
+ name: displayName,
62
+ short_name: displayName,
63
+ description: app.description ?? defaultDescription(app),
64
+ start_url: start,
65
+ scope: '/app/',
66
+ display: 'standalone',
67
+ orientation: 'portrait',
68
+ background_color: '#000000',
69
+ icons: app.icon
70
+ ? [{ src: manifestIconPath(app.name), sizes: iconSizes(app.icon), type: 'image/png' }]
71
+ : [
72
+ { src: '/icon.svg', sizes: 'any', type: 'image/svg+xml' },
73
+ { src: '/apple-touch-icon.png', sizes: '180x180', type: 'image/png' },
74
+ ],
75
+ };
76
+ }
77
+ export function appManifestJson(spec) {
78
+ return JSON.stringify(appManifest(spec), null, 2) + '\n';
79
+ }
80
+ /** The app named by a manifest request URL, or null for any other URL. */
81
+ export function manifestRequestApp(url) {
82
+ const match = new RegExp(`^/${MANIFEST_DIR}/([A-Za-z0-9_-]+)\\.webmanifest(?:\\?|$)`).exec(url);
83
+ return match?.[1] ?? null;
84
+ }
85
+ /** The app named by an icon request URL (`/manifests/<name>-icon.png`), or null. */
86
+ export function iconRequestApp(url) {
87
+ const match = new RegExp(`^/${MANIFEST_DIR}/([A-Za-z0-9_-]+)-icon\\.png(?:\\?|$)`).exec(url);
88
+ return match?.[1] ?? null;
89
+ }
90
+ /** `name -> icon URL` for the specs that bring their own icon (what the app page reads). */
91
+ export function appIconUrls(specs) {
92
+ const icons = {};
93
+ for (const spec of specs)
94
+ if (spec.icon)
95
+ icons[spec.name] = manifestIconPath(spec.name);
96
+ return icons;
97
+ }
98
+ export function appManifests(specs) {
99
+ const byName = new Map(specs.map((spec) => [spec.name, spec]));
100
+ const icons = appIconUrls(specs);
101
+ const isAppPage = (pathname) => /(^|\/)app\/(index\.html)?$/.test(pathname.split('?')[0] ?? '');
102
+ return {
103
+ name: 'swiftbrowser:app-manifests',
104
+ configureServer(server) {
105
+ server.middlewares.use((req, res, next) => {
106
+ const url = req.url ?? '';
107
+ const app = manifestRequestApp(url);
108
+ if (app !== null) {
109
+ const spec = byName.get(app);
110
+ if (!spec) {
111
+ res.statusCode = 404;
112
+ res.end();
113
+ return;
114
+ }
115
+ res.setHeader('Content-Type', 'application/manifest+json');
116
+ res.setHeader('Cache-Control', 'no-cache');
117
+ res.end(appManifestJson(spec));
118
+ return;
119
+ }
120
+ const iconApp = iconRequestApp(url);
121
+ if (iconApp === null)
122
+ return next();
123
+ const icon = byName.get(iconApp)?.icon;
124
+ if (!icon || !existsSync(icon)) {
125
+ res.statusCode = 404;
126
+ res.end();
127
+ return;
128
+ }
129
+ res.setHeader('Content-Type', 'image/png');
130
+ res.setHeader('Cache-Control', 'no-cache');
131
+ res.end(readFileSync(icon));
132
+ });
133
+ },
134
+ transformIndexHtml(_html, ctx) {
135
+ // Only the app page needs the icon map, and only when some app has one.
136
+ if (Object.keys(icons).length === 0 || !isAppPage(ctx.path))
137
+ return;
138
+ return [
139
+ {
140
+ tag: 'script',
141
+ injectTo: 'head-prepend',
142
+ children: `window.__SB_APP_ICONS__ = ${JSON.stringify(icons)};`,
143
+ },
144
+ ];
145
+ },
146
+ generateBundle() {
147
+ for (const spec of specs) {
148
+ this.emitFile({
149
+ type: 'asset',
150
+ fileName: `${MANIFEST_DIR}/${spec.name}.webmanifest`,
151
+ source: appManifestJson(spec),
152
+ });
153
+ if (spec.icon) {
154
+ if (!existsSync(spec.icon)) {
155
+ this.warn(`${spec.name}: icon ${spec.icon} does not exist, skipped`);
156
+ continue;
157
+ }
158
+ this.emitFile({
159
+ type: 'asset',
160
+ fileName: `${MANIFEST_DIR}/${spec.name}-icon.png`,
161
+ source: readFileSync(spec.icon),
162
+ });
163
+ }
164
+ }
165
+ },
166
+ };
167
+ }
168
+ //# sourceMappingURL=app-manifests.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-manifests.js","sourceRoot":"","sources":["../../../plugins/app-manifests.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Serves every registered app's Xcode asset catalogs (the `*.xcassets`
3
+ * directories of its `AppSpec`) as one JSON manifest at `/catalog/<App>.json`
4
+ * plus the image files at `/catalog/<App>/<name>.<ext>` (dev server and
5
+ * `vite build`).
6
+ *
7
+ * The Swift side refers to catalog images and colors by name only
8
+ * (`Image("dough/plain-full")`, `Color("dough/plain-bg")`). The page fetches
9
+ * the manifest before loading the app (src/main.ts) so the layout engine
10
+ * knows every image's intrinsic size and the renderer can resolve the URL and
11
+ * the light/dark color values. See `AssetCatalog` in src/assets.ts.
12
+ *
13
+ * Catalog rules implemented here:
14
+ * - a folder whose `Contents.json` has `properties.provides-namespace: true`
15
+ * prefixes everything inside with `<folder>/` (nested folders chain);
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"`);
19
+ * - `<name>.colorset`: the entry without appearances is `light`, the one with
20
+ * `luminosity: dark` is `dark`; idiom and contrast variants are ignored.
21
+ */
22
+ import type { Plugin } from 'vite';
23
+ import { type AppSpec } from '../node/apps.js';
24
+ import { type AssetCatalog, type AssetColor } from '../src/assets.js';
25
+ export { CATALOG_DIR, catalogPath, assetFilePath } from '../src/assets.js';
26
+ export type { AssetCatalog } from '../src/assets.js';
27
+ /** One file the manifest refers to. */
28
+ export interface CatalogFile {
29
+ /** Published path without a leading slash (`catalog/App/dough__plain-full.png`). */
30
+ fileName: string;
31
+ /** Absolute path of the source file on disk. */
32
+ source: string;
33
+ contentType: string;
34
+ }
35
+ export interface BuiltCatalog {
36
+ manifest: AssetCatalog;
37
+ /** Keyed by `fileName`. */
38
+ files: Map<string, CatalogFile>;
39
+ /** Entries that were skipped and why (the plugin logs them). */
40
+ warnings: string[];
41
+ }
42
+ interface ImageSetContents {
43
+ images?: {
44
+ filename?: string;
45
+ idiom?: string;
46
+ scale?: string;
47
+ }[];
48
+ }
49
+ interface ColorSetContents {
50
+ colors?: {
51
+ idiom?: string;
52
+ appearances?: {
53
+ appearance?: string;
54
+ value?: string;
55
+ }[];
56
+ color?: {
57
+ 'color-space'?: string;
58
+ components?: {
59
+ red?: string;
60
+ green?: string;
61
+ blue?: string;
62
+ alpha?: string;
63
+ };
64
+ };
65
+ }[];
66
+ }
67
+ /**
68
+ * One colorset component as a 0...1 value. Xcode writes hex (`"0xC2"`),
69
+ * floats (`"0.439"`, `"1.000"`) or 0...255 integers (`"255"`). A bare `"0"`
70
+ * or `"1"` has no decimal point but is taken as 0 / 1 (full), as Xcode never
71
+ * writes 1/255 that way.
72
+ */
73
+ export declare function parseComponent(value: string | undefined, fallback?: number): number;
74
+ /** CSS `rgba(r, g, b, a)` for colorset components (r/g/b 0...255, a 0...1). */
75
+ export declare function componentsToCSS(components: {
76
+ red?: string;
77
+ green?: string;
78
+ blue?: string;
79
+ alpha?: string;
80
+ }): string;
81
+ /** The `light` / `dark` CSS colors of a colorset, or null when it has no usable entry. */
82
+ export declare function parseColorSet(contents: ColorSetContents): AssetColor | null;
83
+ export interface PixelSize {
84
+ width: number;
85
+ height: number;
86
+ }
87
+ /**
88
+ * Pixel size of a PNG (IHDR), JPEG (the first SOF segment), WebP (VP8,
89
+ * VP8L or VP8X chunk) or SVG (`width`/`height` attributes, else `viewBox`);
90
+ * null for anything else.
91
+ */
92
+ export declare function readImageSize(data: Buffer, ext: string): PixelSize | null;
93
+ /** The image entry to publish for an imageset, with its numeric scale. */
94
+ export declare function pickImage(contents: ImageSetContents): {
95
+ filename: string;
96
+ scale: number;
97
+ } | null;
98
+ /** Every `*.xcassets` directory under `dir` (recursive, skipping hidden directories). */
99
+ export declare function findAssetCatalogs(dir: string): string[];
100
+ /**
101
+ * Build the manifest of `app` from the given `.xcassets` directories (later
102
+ * catalogs do not override earlier names: the first definition wins, with a
103
+ * warning for the duplicate).
104
+ */
105
+ export declare function buildCatalog(app: string, catalogDirs: readonly string[]): BuiltCatalog;
106
+ /** The manifest of the app at `<examplesDir>/<App>` (all catalogs under it). */
107
+ export declare function buildAppCatalog(examplesDir: string, app: string): BuiltCatalog;
108
+ export declare function catalogJson(catalog: AssetCatalog): string;
109
+ /** The app named by a manifest request URL (`/catalog/<App>.json`), or null. */
110
+ export declare function catalogRequestApp(url: string): string | null;
111
+ /** The app and published file name of an asset file request, or null. */
112
+ export declare function catalogRequestFile(url: string): {
113
+ app: string;
114
+ fileName: string;
115
+ } | null;
116
+ /** The fields of an {@link AppSpec} the catalog plugin reads. */
117
+ export type CatalogSpec = Pick<AppSpec, 'name' | 'catalogs'>;
118
+ export declare function assetCatalogs(specs: readonly CatalogSpec[]): Plugin;
119
+ //# sourceMappingURL=asset-catalogs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"asset-catalogs.d.ts","sourceRoot":"","sources":["../../../plugins/asset-catalogs.ts"],"names":[],"mappings":"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"}