vintage-frames 0.16.2 → 0.17.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.
@@ -0,0 +1,77 @@
1
+ /**
2
+ * App files: an application on the shell as one PNG. The picture is the
3
+ * application's box; two iTXt chunks before IEND carry its manifest, as
4
+ * JSON, and its code, one ES module compressed with zlib. Any PNG tool reads
5
+ * the chunks and any decoder skips them.
6
+ *
7
+ * This is the reading half, and checking a version against a range. It is
8
+ * pure and runs the same under Node and in a page, through the platform's
9
+ * compression streams. Writing an app file, and the box, are
10
+ * `vintage-frames/build`'s.
11
+ */
12
+ /** The app file format this kit reads and writes. */
13
+ export declare const APP_FILE_FORMAT = 1;
14
+ /** The iTXt keywords of the manifest's chunk and the code's. */
15
+ export declare const MANIFEST_KEYWORD = "vintage-frames.app";
16
+ export declare const CODE_KEYWORD = "vintage-frames.code";
17
+ /** What an app file says about its application. */
18
+ export interface AppManifest {
19
+ /** The app file's own format, {@link APP_FILE_FORMAT}. */
20
+ format: number;
21
+ id: string;
22
+ name: string;
23
+ version: string;
24
+ /** The kit range the code was built and checked against: `^0.17.0`. */
25
+ requires: string;
26
+ author: string;
27
+ /** Its 32 × 32 icon: its PNG as a `data:` URL. */
28
+ icon: string;
29
+ }
30
+ /** An application, read from its app file. */
31
+ export interface AppFile {
32
+ manifest: AppManifest;
33
+ /** One ES module. Its default export is the application's factory. */
34
+ code: string;
35
+ }
36
+ /** The eight bytes every PNG starts with. */
37
+ export declare const PNG_SIGNATURE: Uint8Array<ArrayBuffer>;
38
+ /** The CRC-32 a PNG chunk ends with, over its type and data. */
39
+ export declare function crc32(bytes: Uint8Array): number;
40
+ /** One chunk of a PNG. */
41
+ export interface PngChunk {
42
+ type: string;
43
+ data: Uint8Array;
44
+ /** Where it sits in the file: its length's first byte, and the byte after its CRC. */
45
+ start: number;
46
+ end: number;
47
+ }
48
+ /**
49
+ * A PNG's chunks, IEND last, or null when it isn't a whole PNG: the
50
+ * signature is wrong, a chunk runs past the end, a CRC doesn't match, or
51
+ * there is no IEND. Anything after IEND is left out.
52
+ */
53
+ export declare function pngChunks(bytes: Uint8Array): PngChunk[] | null;
54
+ /** An iTXt chunk's keyword. */
55
+ export declare function itxtKeyword(data: Uint8Array): string;
56
+ /** zlib data, inflated. */
57
+ export declare function inflate(bytes: Uint8Array): Promise<Uint8Array>;
58
+ /** zlib data, deflated. */
59
+ export declare function deflate(bytes: Uint8Array): Promise<Uint8Array>;
60
+ /** A parsed manifest as one this kit reads, or what is wrong with it. */
61
+ export declare function manifestOf(json: unknown): AppManifest | string;
62
+ /**
63
+ * The manifest and code an app file carries, or why it isn't one: not a
64
+ * whole PNG, a chunk missing or doubled, a format this kit doesn't read, a
65
+ * field missing, or code that doesn't inflate.
66
+ */
67
+ export declare function inspectAppFile(bytes: Uint8Array): Promise<AppFile | string>;
68
+ /** The manifest and code an app file carries, or null for any other PNG. */
69
+ export declare function readAppFile(bytes: Uint8Array): Promise<AppFile | null>;
70
+ /**
71
+ * Whether `version` meets `range`: an exact version, or a caret range as
72
+ * npm reads it. `^1.2.3` takes 1.x from 1.2.3 on, `^0.2.3` takes 0.2.x from
73
+ * 0.2.3 on, and `^0.0.3` takes 0.0.3 alone. A prerelease meets a range only
74
+ * when the range names a prerelease of the same version. Anything else is
75
+ * false.
76
+ */
77
+ export declare function satisfies(version: string, range: string): boolean;
@@ -0,0 +1,161 @@
1
+ //#region src/shell/app-file.ts
2
+ var e = 1, t = "vintage-frames.app", n = "vintage-frames.code", r = [
3
+ "id",
4
+ "name",
5
+ "version",
6
+ "requires",
7
+ "author",
8
+ "icon"
9
+ ], i = Uint8Array.of(137, 80, 78, 71, 13, 10, 26, 10), a = Uint32Array.from({ length: 256 }, (e, t) => {
10
+ let n = t;
11
+ for (let e = 0; e < 8; e++) n = n & 1 ? 3988292384 ^ n >>> 1 : n >>> 1;
12
+ return n >>> 0;
13
+ });
14
+ function o(e) {
15
+ let t = 4294967295;
16
+ for (let n of e) t = a[(t ^ n) & 255] ^ t >>> 8;
17
+ return (t ^ 4294967295) >>> 0;
18
+ }
19
+ function s(e) {
20
+ if (e.length < 8 || i.some((t, n) => e[n] !== t)) return null;
21
+ let t = new DataView(e.buffer, e.byteOffset, e.byteLength), n = [], r = 8;
22
+ for (; r + 12 <= e.length;) {
23
+ let i = r + 12 + t.getUint32(r);
24
+ if (i > e.length || o(e.subarray(r + 4, i - 4)) !== t.getUint32(i - 4)) return null;
25
+ let a = String.fromCharCode(...e.subarray(r + 4, r + 8));
26
+ if (n.push({
27
+ type: a,
28
+ data: e.subarray(r + 8, i - 4),
29
+ start: r,
30
+ end: i
31
+ }), a === "IEND") return n;
32
+ r = i;
33
+ }
34
+ return null;
35
+ }
36
+ function c(e) {
37
+ let t = e.indexOf(0);
38
+ return t > 0 ? String.fromCharCode(...e.subarray(0, t)) : "";
39
+ }
40
+ var l = new TextDecoder("utf-8", { fatal: !0 });
41
+ async function u(e) {
42
+ let t = e.indexOf(0), n = e[t + 1], r = e[t + 2], i = e.indexOf(0, t + 3), a = i < 0 ? -1 : e.indexOf(0, i + 1);
43
+ if (t < 1 || a < 0 || n > 1 || r !== 0) throw Error("a broken iTXt chunk");
44
+ let o = e.subarray(a + 1);
45
+ return l.decode(n ? await d(o) : o);
46
+ }
47
+ async function d(e) {
48
+ let t = new Blob([e.slice()]).stream().pipeThrough(new DecompressionStream("deflate"));
49
+ return new Uint8Array(await new Response(t).arrayBuffer());
50
+ }
51
+ async function f(e) {
52
+ let t = new Blob([e.slice()]).stream().pipeThrough(new CompressionStream("deflate"));
53
+ return new Uint8Array(await new Response(t).arrayBuffer());
54
+ }
55
+ function p(e) {
56
+ if (!e || typeof e != "object") return "its manifest is not an object";
57
+ let t = e;
58
+ if (t.format !== 1) return typeof t.format == "number" ? `it is format ${t.format}, and this kit reads format 1` : "its manifest has no format";
59
+ let n = {
60
+ format: 1,
61
+ id: "",
62
+ name: "",
63
+ version: "",
64
+ requires: "",
65
+ author: "",
66
+ icon: ""
67
+ };
68
+ for (let e of r) {
69
+ let r = t[e];
70
+ if (typeof r != "string" || !r) return `its manifest has no ${e}`;
71
+ n[e] = r;
72
+ }
73
+ return n;
74
+ }
75
+ async function m(e) {
76
+ let r = s(e);
77
+ if (!r) return "it is not a whole PNG";
78
+ let i = /* @__PURE__ */ new Map();
79
+ for (let { type: e, data: t } of r) {
80
+ if (e !== "iTXt") continue;
81
+ let n = c(t);
82
+ if (n === "vintage-frames.app" || n === "vintage-frames.code") {
83
+ if (i.has(n)) return `it has two ${n} chunks`;
84
+ i.set(n, t);
85
+ }
86
+ }
87
+ let a = i.get(t), o = i.get(n);
88
+ if (!a && !o) return "it carries no application";
89
+ if (!a) return "its manifest is missing";
90
+ if (!o) return "its code is missing";
91
+ let l;
92
+ try {
93
+ l = JSON.parse(await u(a));
94
+ } catch {
95
+ return "its manifest does not read";
96
+ }
97
+ let d = p(l);
98
+ if (typeof d == "string") return d;
99
+ try {
100
+ return {
101
+ manifest: d,
102
+ code: await u(o)
103
+ };
104
+ } catch {
105
+ return "its code does not inflate";
106
+ }
107
+ }
108
+ async function h(e) {
109
+ let t = await m(e);
110
+ return typeof t == "string" ? null : t;
111
+ }
112
+ var g = /^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+[0-9A-Za-z.-]+)?$/;
113
+ function _(e) {
114
+ let t = g.exec(e.trim());
115
+ return t ? {
116
+ core: [
117
+ Number(t[1]),
118
+ Number(t[2]),
119
+ Number(t[3])
120
+ ],
121
+ pre: t[4] ? t[4].split(".") : []
122
+ } : null;
123
+ }
124
+ function v(e, t) {
125
+ for (let n = 0; n < 3; n++) if (e.core[n] !== t.core[n]) return e.core[n] - t.core[n];
126
+ if (!e.pre.length || !t.pre.length) return t.pre.length - e.pre.length;
127
+ for (let n = 0; n < Math.max(e.pre.length, t.pre.length); n++) {
128
+ let r = e.pre[n], i = t.pre[n];
129
+ if (r === void 0) return -1;
130
+ if (i === void 0) return 1;
131
+ if (r === i) continue;
132
+ let a = /^\d+$/.test(r), o = /^\d+$/.test(i);
133
+ return a && o ? Number(r) - Number(i) : a === o ? r < i ? -1 : 1 : a ? -1 : 1;
134
+ }
135
+ return 0;
136
+ }
137
+ function y(e, t) {
138
+ let n = t.trim().startsWith("^"), r = _(e), i = _(n ? t.trim().slice(1) : t);
139
+ if (!r || !i) return !1;
140
+ if (!n) return v(r, i) === 0;
141
+ if (r.pre.length && !(i.pre.length && r.core.every((e, t) => e === i.core[t]))) return !1;
142
+ let [a, o, s] = i.core, c = {
143
+ core: a ? [
144
+ a + 1,
145
+ 0,
146
+ 0
147
+ ] : o ? [
148
+ 0,
149
+ o + 1,
150
+ 0
151
+ ] : [
152
+ 0,
153
+ 0,
154
+ s + 1
155
+ ],
156
+ pre: []
157
+ };
158
+ return v(r, i) >= 0 && v(r, c) < 0;
159
+ }
160
+ //#endregion
161
+ export { e as APP_FILE_FORMAT, n as CODE_KEYWORD, t as MANIFEST_KEYWORD, i as PNG_SIGNATURE, o as crc32, f as deflate, d as inflate, m as inspectAppFile, c as itxtKeyword, p as manifestOf, s as pngChunks, h as readAppFile, y as satisfies };
@@ -25,3 +25,6 @@ export type { LocalStorageStateOptions, SavedSession, SavedWindow, SessionSnapsh
25
25
  export { BAND, CASCADE_SLOTS, CASCADE_STEP, ICON_CELL, ICON_COLUMN, ICON_INSET, ICON_ROW, NEAR, WINDOW_ORIGIN, cascadedBox, cascadeFrom, cascadeSlot, centeredBox, cleanUp, collisions, desktopLattice, fieldExtent, fillOrder, folderLattice, frameOf, isPin, latticeCell, latticeSlot, nearBox, nextFreeCell, pinOf, pinTo, trashCell, windowOrigin, } from './geometry.js';
26
26
  export type { Bands, Box, CascadeOptions, EdgePin, Frame, Lattice, LatticeOptions, Pin, Point, Policy, Size, } from './geometry.js';
27
27
  export { startClock, formatDate, formatTime, DATE_HOLD_MS } from './clock.js';
28
+ export { APP_FILE_FORMAT, readAppFile, satisfies } from './app-file.js';
29
+ export type { AppFile, AppManifest } from './app-file.js';
30
+ export { VERSION } from './version.js';
@@ -7,4 +7,6 @@ import { createShell as ae, defineApp as oe } from "./shell.js";
7
7
  import { fileByDrag as se } from "./filing.js";
8
8
  import { FINDER as ce, finder as le } from "./finder.js";
9
9
  import { indexedDbStorage as ue } from "./storage.js";
10
- export { e as APP_KIND, b as BAND, x as CASCADE_SLOTS, S as CASCADE_STEP, te as DATE_HOLD_MS, t as DISK, ce as FINDER, n as FOLDER, C as ICON_CELL, w as ICON_COLUMN, T as ICON_INSET, E as ICON_ROW, D as NEAR, r as TRASH, i as UNTITLED_FOLDER, O as WINDOW_ORIGIN, a as appIdOf, k as cascadeFrom, A as cascadeSlot, j as cascadedBox, M as centeredBox, o as childrenOf, N as cleanUp, P as collisions, s as containerOf, c as copyName, l as createCatalog, ae as createShell, Y as createWindowManager, oe as defineApp, u as descendantsOf, F as desktopLattice, d as enclosingFolders, I as fieldExtent, se as fileByDrag, L as fillOrder, le as finder, X as focusInto, R as folderLattice, ne as formatDate, re as formatTime, z as frameOf, ue as indexedDbStorage, f as isContainerKind, p as isInside, B as isPin, m as isTrashed, h as isVolume, g as itemCount, _ as itemOf, V as latticeCell, H as latticeSlot, Z as localStorageState, v as memoryStorage, Q as mergeSession, U as nearBox, y as nextFolderName, W as nextFreeCell, $ as openWindowsOf, G as pinOf, K as pinTo, ee as readSession, ie as startClock, q as trashCell, J as windowOrigin };
10
+ import { APP_FILE_FORMAT as de, readAppFile as fe, satisfies as pe } from "./app-file.js";
11
+ import { VERSION as me } from "./version.js";
12
+ export { de as APP_FILE_FORMAT, e as APP_KIND, b as BAND, x as CASCADE_SLOTS, S as CASCADE_STEP, te as DATE_HOLD_MS, t as DISK, ce as FINDER, n as FOLDER, C as ICON_CELL, w as ICON_COLUMN, T as ICON_INSET, E as ICON_ROW, D as NEAR, r as TRASH, i as UNTITLED_FOLDER, me as VERSION, O as WINDOW_ORIGIN, a as appIdOf, k as cascadeFrom, A as cascadeSlot, j as cascadedBox, M as centeredBox, o as childrenOf, N as cleanUp, P as collisions, s as containerOf, c as copyName, l as createCatalog, ae as createShell, Y as createWindowManager, oe as defineApp, u as descendantsOf, F as desktopLattice, d as enclosingFolders, I as fieldExtent, se as fileByDrag, L as fillOrder, le as finder, X as focusInto, R as folderLattice, ne as formatDate, re as formatTime, z as frameOf, ue as indexedDbStorage, f as isContainerKind, p as isInside, B as isPin, m as isTrashed, h as isVolume, g as itemCount, _ as itemOf, V as latticeCell, H as latticeSlot, Z as localStorageState, v as memoryStorage, Q as mergeSession, U as nearBox, y as nextFolderName, W as nextFreeCell, $ as openWindowsOf, G as pinOf, K as pinTo, fe as readAppFile, ee as readSession, pe as satisfies, ie as startClock, q as trashCell, J as windowOrigin };
@@ -1,10 +1,13 @@
1
1
  /**
2
2
  * `vintage-frames/shell/pure` — the shell's pure modules on their own: the
3
- * catalog, the geometry and the saved session. They import nothing from the
4
- * kit and touch no DOM at import, so a site's own pure modules and their
5
- * tests import them under Node. `vintage-frames/shell` exports the same
6
- * names.
3
+ * catalog, the geometry, the saved session, the app file reader and the
4
+ * kit's version. They import nothing from the kit and touch no DOM at
5
+ * import, so a site's own pure modules and their tests import them under
6
+ * Node. `vintage-frames/shell` exports the same names.
7
7
  */
8
8
  export * from './catalog.js';
9
9
  export * from './geometry.js';
10
10
  export * from './state.js';
11
+ export { APP_FILE_FORMAT, readAppFile, satisfies } from './app-file.js';
12
+ export type { AppFile, AppManifest } from './app-file.js';
13
+ export { VERSION } from './version.js';
@@ -1,4 +1,6 @@
1
1
  import { APP_KIND as e, DISK as t, FOLDER as n, TRASH as r, UNTITLED_FOLDER as i, appIdOf as a, childrenOf as o, containerOf as s, copyName as c, createCatalog as l, descendantsOf as u, enclosingFolders as d, isContainerKind as f, isInside as p, isTrashed as m, isVolume as h, itemCount as g, itemOf as _, memoryStorage as v, nextFolderName as y } from "./catalog.js";
2
2
  import { BAND as b, CASCADE_SLOTS as x, CASCADE_STEP as S, ICON_CELL as C, ICON_COLUMN as w, ICON_INSET as T, ICON_ROW as E, NEAR as D, WINDOW_ORIGIN as O, cascadeFrom as k, cascadeSlot as A, cascadedBox as j, centeredBox as M, cleanUp as N, collisions as P, desktopLattice as F, fieldExtent as I, fillOrder as L, folderLattice as R, frameOf as z, isPin as B, latticeCell as V, latticeSlot as H, nearBox as U, nextFreeCell as W, pinOf as G, pinTo as K, trashCell as q, windowOrigin as J } from "./geometry.js";
3
3
  import { localStorageState as Y, mergeSession as X, openWindowsOf as Z, readSession as Q } from "./state.js";
4
- export { e as APP_KIND, b as BAND, x as CASCADE_SLOTS, S as CASCADE_STEP, t as DISK, n as FOLDER, C as ICON_CELL, w as ICON_COLUMN, T as ICON_INSET, E as ICON_ROW, D as NEAR, r as TRASH, i as UNTITLED_FOLDER, O as WINDOW_ORIGIN, a as appIdOf, k as cascadeFrom, A as cascadeSlot, j as cascadedBox, M as centeredBox, o as childrenOf, N as cleanUp, P as collisions, s as containerOf, c as copyName, l as createCatalog, u as descendantsOf, F as desktopLattice, d as enclosingFolders, I as fieldExtent, L as fillOrder, R as folderLattice, z as frameOf, f as isContainerKind, p as isInside, B as isPin, m as isTrashed, h as isVolume, g as itemCount, _ as itemOf, V as latticeCell, H as latticeSlot, Y as localStorageState, v as memoryStorage, X as mergeSession, U as nearBox, y as nextFolderName, W as nextFreeCell, Z as openWindowsOf, G as pinOf, K as pinTo, Q as readSession, q as trashCell, J as windowOrigin };
4
+ import { APP_FILE_FORMAT as $, readAppFile as ee, satisfies as te } from "./app-file.js";
5
+ import { VERSION as ne } from "./version.js";
6
+ export { $ as APP_FILE_FORMAT, e as APP_KIND, b as BAND, x as CASCADE_SLOTS, S as CASCADE_STEP, t as DISK, n as FOLDER, C as ICON_CELL, w as ICON_COLUMN, T as ICON_INSET, E as ICON_ROW, D as NEAR, r as TRASH, i as UNTITLED_FOLDER, ne as VERSION, O as WINDOW_ORIGIN, a as appIdOf, k as cascadeFrom, A as cascadeSlot, j as cascadedBox, M as centeredBox, o as childrenOf, N as cleanUp, P as collisions, s as containerOf, c as copyName, l as createCatalog, u as descendantsOf, F as desktopLattice, d as enclosingFolders, I as fieldExtent, L as fillOrder, R as folderLattice, z as frameOf, f as isContainerKind, p as isInside, B as isPin, m as isTrashed, h as isVolume, g as itemCount, _ as itemOf, V as latticeCell, H as latticeSlot, Y as localStorageState, v as memoryStorage, X as mergeSession, U as nearBox, y as nextFolderName, W as nextFreeCell, Z as openWindowsOf, G as pinOf, K as pinTo, ee as readAppFile, Q as readSession, te as satisfies, q as trashCell, J as windowOrigin };
@@ -0,0 +1,2 @@
1
+ /** The kit's version, as published: package.json's `version`. `npm version` rewrites it (the `version` script). */
2
+ export declare const VERSION = "0.17.0";
@@ -0,0 +1,4 @@
1
+ //#region src/shell/version.ts
2
+ var e = "0.17.0";
3
+ //#endregion
4
+ export { e as VERSION };
@@ -0,0 +1,12 @@
1
+ /**
2
+ * VF Body as data. GENERATED by fonts/manifest-to-font.py from
3
+ * fonts/VF-Body.glyphs.txt: edit the manifest and rebuild, never this file.
4
+ *
5
+ * Each character's advance, placement and ink, in whole design px, for
6
+ * drawing the kit's type without a browser. The ink is the kit's own
7
+ * re-drawn strike in the style of Geneva 9pt, the design Susan Kare
8
+ * created for Apple's original Macintosh, and the same artwork the face's
9
+ * woff2 is built from (fonts/README.md).
10
+ */
11
+ import type { Strike } from './strike.js';
12
+ export declare const VF_BODY_STRIKE: Strike;