@deskwork/studio 0.15.0 → 0.16.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/dist/components/scrapbook-item.d.ts +20 -0
- package/dist/components/scrapbook-item.d.ts.map +1 -1
- package/dist/components/scrapbook-item.js +21 -2
- package/dist/components/scrapbook-item.js.map +1 -1
- package/dist/pages/dashboard/affordances.d.ts.map +1 -1
- package/dist/pages/dashboard/affordances.js +13 -1
- package/dist/pages/dashboard/affordances.js.map +1 -1
- package/dist/pages/dashboard/affordances.ts +13 -1
- package/dist/pages/review-scrapbook-drawer.d.ts.map +1 -1
- package/dist/pages/review-scrapbook-drawer.js +10 -1
- package/dist/pages/review-scrapbook-drawer.js.map +1 -1
- package/dist/pages/review-scrapbook-drawer.ts +11 -1
- package/dist/pages/scrapbook/dispatch.d.ts +50 -0
- package/dist/pages/scrapbook/dispatch.d.ts.map +1 -0
- package/dist/pages/scrapbook/dispatch.js +104 -0
- package/dist/pages/scrapbook/dispatch.js.map +1 -0
- package/dist/pages/scrapbook/image-readers.d.ts +24 -0
- package/dist/pages/scrapbook/image-readers.d.ts.map +1 -0
- package/dist/pages/scrapbook/image-readers.js +135 -0
- package/dist/pages/scrapbook/image-readers.js.map +1 -0
- package/dist/pages/scrapbook/index.d.ts +21 -0
- package/dist/pages/scrapbook/index.d.ts.map +1 -0
- package/dist/pages/scrapbook/index.js +96 -0
- package/dist/pages/scrapbook/index.js.map +1 -0
- package/dist/pages/scrapbook/render.d.ts +68 -0
- package/dist/pages/scrapbook/render.d.ts.map +1 -0
- package/dist/pages/scrapbook/render.js +315 -0
- package/dist/pages/scrapbook/render.js.map +1 -0
- package/dist/pages/scrapbook/text-helpers.d.ts +40 -0
- package/dist/pages/scrapbook/text-helpers.d.ts.map +1 -0
- package/dist/pages/scrapbook/text-helpers.js +92 -0
- package/dist/pages/scrapbook/text-helpers.js.map +1 -0
- package/dist/pages/scrapbook/types.d.ts +26 -0
- package/dist/pages/scrapbook/types.d.ts.map +1 -0
- package/dist/pages/scrapbook/types.js +12 -0
- package/dist/pages/scrapbook/types.js.map +1 -0
- package/dist/pages/scrapbook.d.ts +8 -8
- package/dist/pages/scrapbook.d.ts.map +1 -1
- package/dist/pages/scrapbook.js +8 -600
- package/dist/pages/scrapbook.js.map +1 -1
- package/dist/pages/scrapbook.ts +11 -660
- package/dist/routes/api.d.ts.map +1 -1
- package/dist/routes/api.js +111 -2
- package/dist/routes/api.js.map +1 -1
- package/dist/routes/entry-annotation-body.d.ts +29 -0
- package/dist/routes/entry-annotation-body.d.ts.map +1 -1
- package/dist/routes/entry-annotation-body.js +80 -0
- package/dist/routes/entry-annotation-body.js.map +1 -1
- package/dist/routes/scrapbook-file.d.ts +1 -1
- package/dist/routes/scrapbook-file.js +1 -1
- package/dist/routes/scrapbook-mutation-dispatch.d.ts +29 -0
- package/dist/routes/scrapbook-mutation-dispatch.d.ts.map +1 -0
- package/dist/routes/scrapbook-mutation-dispatch.js +63 -0
- package/dist/routes/scrapbook-mutation-dispatch.js.map +1 -0
- package/dist/routes/scrapbook-mutation-envelope.d.ts +93 -0
- package/dist/routes/scrapbook-mutation-envelope.d.ts.map +1 -0
- package/dist/routes/scrapbook-mutation-envelope.js +147 -0
- package/dist/routes/scrapbook-mutation-envelope.js.map +1 -0
- package/dist/routes/scrapbook-mutations.d.ts +25 -7
- package/dist/routes/scrapbook-mutations.d.ts.map +1 -1
- package/dist/routes/scrapbook-mutations.js +67 -92
- package/dist/routes/scrapbook-mutations.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +16 -2
- package/dist/server.js.map +1 -1
- package/package.json +2 -2
- package/dist/pages/review.d.ts +0 -68
- package/dist/pages/review.d.ts.map +0 -1
- package/dist/pages/review.js +0 -561
- package/dist/pages/review.js.map +0 -1
- package/dist/pages/review.ts +0 -710
|
@@ -52,6 +52,16 @@ export interface ScrapbookAddress {
|
|
|
52
52
|
* viewer uses in its URL.
|
|
53
53
|
*/
|
|
54
54
|
path: string;
|
|
55
|
+
/**
|
|
56
|
+
* Optional UUID of the calendar entry whose scrapbook this addresses.
|
|
57
|
+
* When present, the standalone-viewer URL appends `?entryId=<uuid>` so
|
|
58
|
+
* the server resolves the listing via `scrapbookDirForEntry` —
|
|
59
|
+
* symmetric to the mutation API's entry-aware addressing (#191/#205).
|
|
60
|
+
*
|
|
61
|
+
* Falls back to slug-template addressing when absent (legacy callers
|
|
62
|
+
* and ad-hoc / organizational paths that aren't tracked entries).
|
|
63
|
+
*/
|
|
64
|
+
entryId?: string;
|
|
55
65
|
}
|
|
56
66
|
/**
|
|
57
67
|
* Read the first slice of a text/JSON scrapbook file for inline
|
|
@@ -79,6 +89,11 @@ export interface ScrapbookItemRendererOptions {
|
|
|
79
89
|
* read-only binary endpoint. The endpoint is read-only by design —
|
|
80
90
|
* Phase 16's image / PDF previews need a stable URL, but full
|
|
81
91
|
* scrapbook CRUD remains in the standalone viewer's surface.
|
|
92
|
+
*
|
|
93
|
+
* When `address.entryId` is present, sends `entryId=<uuid>` so the
|
|
94
|
+
* server resolves via the entry's sidecar (entry-aware addressing —
|
|
95
|
+
* #205, symmetric to the mutation API). Slug-template addressing
|
|
96
|
+
* (`path=`) is the fallback when no entry id is available.
|
|
82
97
|
*/
|
|
83
98
|
export declare function scrapbookFileUrl(address: ScrapbookAddress, filename: string, opts?: {
|
|
84
99
|
secret?: boolean;
|
|
@@ -86,6 +101,11 @@ export declare function scrapbookFileUrl(address: ScrapbookAddress, filename: st
|
|
|
86
101
|
/**
|
|
87
102
|
* Build the URL to the standalone scrapbook viewer for an address —
|
|
88
103
|
* the operator's "open scrapbook" jumping-off point.
|
|
104
|
+
*
|
|
105
|
+
* When `address.entryId` is present, appends `?entryId=<uuid>` so the
|
|
106
|
+
* server route resolves the listing via `scrapbookDirForEntry`
|
|
107
|
+
* (entry-aware addressing — #205). Slug-only fallback is preserved
|
|
108
|
+
* when no entry id is available.
|
|
89
109
|
*/
|
|
90
110
|
export declare function scrapbookViewerUrl(address: ScrapbookAddress): string;
|
|
91
111
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scrapbook-item.d.ts","sourceRoot":"","sources":["../../src/components/scrapbook-item.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAEH,OAAO,EAGL,KAAK,aAAa,EAEnB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAgB,KAAK,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAM9D,gDAAgD;AAChD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,IAAI,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"scrapbook-item.d.ts","sourceRoot":"","sources":["../../src/components/scrapbook-item.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAEH,OAAO,EAGL,KAAK,aAAa,EAEnB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAgB,KAAK,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAM9D,gDAAgD;AAChD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;;;;;;;OAQG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAC7B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,KACb,MAAM,GAAG,IAAI,CAAC;AAEnB,MAAM,WAAW,4BAA4B;IAC3C;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,gBAAgB,CAAC;CACxC;AASD;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,gBAAgB,EACzB,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GAC9B,MAAM,CAYR;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,gBAAgB,GAAG,MAAM,CAQpE;AA+DD;;;;;;;;;GASG;AACH,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,gBAAgB,EACzB,IAAI,EAAE,aAAa,EACnB,IAAI,GAAE,4BAAiC,GACtC,OAAO,CA8DT;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAMT"}
|
|
@@ -53,13 +53,23 @@ const TEXT_PREVIEW_LINES = 8;
|
|
|
53
53
|
* read-only binary endpoint. The endpoint is read-only by design —
|
|
54
54
|
* Phase 16's image / PDF previews need a stable URL, but full
|
|
55
55
|
* scrapbook CRUD remains in the standalone viewer's surface.
|
|
56
|
+
*
|
|
57
|
+
* When `address.entryId` is present, sends `entryId=<uuid>` so the
|
|
58
|
+
* server resolves via the entry's sidecar (entry-aware addressing —
|
|
59
|
+
* #205, symmetric to the mutation API). Slug-template addressing
|
|
60
|
+
* (`path=`) is the fallback when no entry id is available.
|
|
56
61
|
*/
|
|
57
62
|
export function scrapbookFileUrl(address, filename, opts = {}) {
|
|
58
63
|
const params = new URLSearchParams({
|
|
59
64
|
site: address.site,
|
|
60
|
-
path: address.path,
|
|
61
65
|
name: filename,
|
|
62
66
|
});
|
|
67
|
+
if (address.entryId !== undefined && address.entryId.length > 0) {
|
|
68
|
+
params.set('entryId', address.entryId);
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
params.set('path', address.path);
|
|
72
|
+
}
|
|
63
73
|
if (opts.secret)
|
|
64
74
|
params.set('secret', '1');
|
|
65
75
|
return `/api/dev/scrapbook-file?${params.toString()}`;
|
|
@@ -67,11 +77,20 @@ export function scrapbookFileUrl(address, filename, opts = {}) {
|
|
|
67
77
|
/**
|
|
68
78
|
* Build the URL to the standalone scrapbook viewer for an address —
|
|
69
79
|
* the operator's "open scrapbook" jumping-off point.
|
|
80
|
+
*
|
|
81
|
+
* When `address.entryId` is present, appends `?entryId=<uuid>` so the
|
|
82
|
+
* server route resolves the listing via `scrapbookDirForEntry`
|
|
83
|
+
* (entry-aware addressing — #205). Slug-only fallback is preserved
|
|
84
|
+
* when no entry id is available.
|
|
70
85
|
*/
|
|
71
86
|
export function scrapbookViewerUrl(address) {
|
|
72
87
|
// The path is already kebab-case + slash-separated; encodeURI keeps
|
|
73
88
|
// the slashes literal while escaping anything else (defensive).
|
|
74
|
-
|
|
89
|
+
const base = `/dev/scrapbook/${address.site}/${encodeURI(address.path)}`;
|
|
90
|
+
if (address.entryId !== undefined && address.entryId.length > 0) {
|
|
91
|
+
return `${base}?entryId=${encodeURIComponent(address.entryId)}`;
|
|
92
|
+
}
|
|
93
|
+
return base;
|
|
75
94
|
}
|
|
76
95
|
// ---------------------------------------------------------------------------
|
|
77
96
|
// Per-kind preview detection
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scrapbook-item.js","sourceRoot":"","sources":["../../src/components/scrapbook-item.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAEH,OAAO,EACL,kBAAkB,EAClB,UAAU,GAGX,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,EAAgB,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"scrapbook-item.js","sourceRoot":"","sources":["../../src/components/scrapbook-item.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAEH,OAAO,EACL,kBAAkB,EAClB,UAAU,GAGX,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,EAAgB,MAAM,kBAAkB,CAAC;AAqD9D,MAAM,qBAAqB,GAAG,GAAG,CAAC;AAClC,MAAM,kBAAkB,GAAG,CAAC,CAAC;AAE7B,8EAA8E;AAC9E,cAAc;AACd,8EAA8E;AAE9E;;;;;;;;;;GAUG;AACH,MAAM,UAAU,gBAAgB,CAC9B,OAAyB,EACzB,QAAgB,EAChB,OAA6B,EAAE;IAE/B,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC;QACjC,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,IAAI,EAAE,QAAQ;KACf,CAAC,CAAC;IACH,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChE,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IACzC,CAAC;SAAM,CAAC;QACN,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,CAAC;IACD,IAAI,IAAI,CAAC,MAAM;QAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IAC3C,OAAO,2BAA2B,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC;AACxD,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAyB;IAC1D,oEAAoE;IACpE,gEAAgE;IAChE,MAAM,IAAI,GAAG,kBAAkB,OAAO,CAAC,IAAI,IAAI,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;IACzE,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChE,OAAO,GAAG,IAAI,YAAY,kBAAkB,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;IAClE,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,8EAA8E;AAC9E,6BAA6B;AAC7B,8EAA8E;AAE9E,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC;IAC/B,MAAM;IACN,MAAM;IACN,OAAO;IACP,MAAM;IACN,OAAO;IACP,MAAM;CACP,CAAC,CAAC;AAEH,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;AAEzC,SAAS,QAAQ,CAAC,QAAgB;IAChC,MAAM,GAAG,GAAG,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACtC,OAAO,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;AAC1D,CAAC;AAED,SAAS,eAAe,CAAC,QAAgB;IACvC,OAAO,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;AAClD,CAAC;AAED,SAAS,aAAa,CAAC,QAAgB;IACrC,OAAO,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;AAChD,CAAC;AAED,SAAS,SAAS,CAAC,IAAuB;IACxC,OAAO,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;AACrD,CAAC;AAED,8EAA8E;AAC9E,yBAAyB;AACzB,8EAA8E;AAE9E,SAAS,iBAAiB,CAAC,GAAW,EAAE,KAAa;IACnD,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IAC9C,iEAAiE;IACjE,iEAAiE;IACjE,mDAAmD;IACnD,MAAM,SAAS,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,KAAK,IAAI,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC;IACtE,OAAO,SAAS,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACjE,CAAC;AAED,SAAS,cAAc,CACrB,QAAgB,EAChB,OAAqC;IAErC,MAAM,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAC3C,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACzB,MAAM,GAAG,GAAG,OAAO,CAAC,qBAAqB,IAAI,qBAAqB,CAAC;IACnE,MAAM,GAAG,GAAG,MAAM,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IAClC,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC9B,OAAO,iBAAiB,CAAC,GAAG,EAAE,kBAAkB,CAAC,CAAC;AACpD,CAAC;AAED,8EAA8E;AAC9E,yBAAyB;AACzB,8EAA8E;AAE9E;;;;;;;;;GASG;AACH,MAAM,UAAU,0BAA0B,CACxC,OAAyB,EACzB,IAAmB,EACnB,OAAqC,EAAE;IAEvC,MAAM,OAAO,GAAG,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IACrD,MAAM,QAAQ,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvC,MAAM,SAAS,GAAG,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAEjD,IAAI,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/B,OAAO,MAAM,CAAC,IAAI,CAAA;qEAC+C,IAAI,CAAC,IAAI;6CACjC,OAAO;6BACvB,IAAI,CAAC,IAAI;iEAC2B,OAAO;;oCAEpC,IAAI,CAAC,IAAI;oCACT,QAAQ;qCACP,SAAS;aACjC,CAAC,CAAC;IACb,CAAC;IAED,IAAI,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7B,OAAO,MAAM,CAAC,IAAI,CAAA;qEAC+C,IAAI,CAAC,IAAI;;;8CAGhC,OAAO,oCAAoC,IAAI,CAAC,IAAI;;oCAE9D,QAAQ;qCACP,SAAS;gDACE,OAAO,sBAAsB,IAAI,CAAC,IAAI;uCAC/C,IAAI,CAAC,IAAI;aACnC,CAAC,CAAC;IACb,CAAC;IAED,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAChD,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAC/C,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;YACpB,OAAO,MAAM,CAAC,IAAI,CAAA;4DACoC,IAAI,CAAC,IAAI,oBAAoB,IAAI,CAAC,IAAI;sCAC5D,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;;gDAEV,OAAO,oCAAoC,IAAI,CAAC,IAAI;;sCAE9D,QAAQ;uCACP,SAAS;+CACD,MAAM;eACtC,CAAC,CAAC;QACb,CAAC;QACD,4DAA4D;IAC9D,CAAC;IAED,oEAAoE;IACpE,2DAA2D;IAC3D,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,iCAAiC,CAAC;IAC7E,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IACxE,OAAO,MAAM,CAAC,IAAI,CAAA;oCACgB,IAAI,CAAC,IAAI,oBAAoB,IAAI,CAAC,IAAI;kCACxC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;;4CAEV,IAAI,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,IAAI;;kCAE/C,QAAQ;mCACP,SAAS;WACjC,CAAC,CAAC;AACb,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,uBAAuB,CACrC,OAA0B;IAE1B,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC;IACvE,OAAO,MAAM,CAAC,IAAI,CAAA;;yFAEqE,IAAI;WAClF,CAAC,CAAC;AACb,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"affordances.d.ts","sourceRoot":"","sources":["../../../src/pages/dashboard/affordances.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAgB,KAAK,OAAO,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"affordances.d.ts","sourceRoot":"","sources":["../../../src/pages/dashboard/affordances.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAgB,KAAK,OAAO,EAAE,MAAM,YAAY,CAAC;AAExD,OAAO,KAAK,EAAE,KAAK,EAAS,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAQ7E;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,WAAW,GAAG,SAAS,GAAG,OAAO,CAK9E;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAE7D;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAkD3E"}
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* universal-verb skills are the canonical action path.
|
|
9
9
|
*/
|
|
10
10
|
import { html, unsafe } from "../html.js";
|
|
11
|
+
import { scrapbookViewerUrl } from "../../components/scrapbook-item.js";
|
|
11
12
|
const REVIEW_STATE_LABEL = {
|
|
12
13
|
'in-review': 'in review',
|
|
13
14
|
iterating: 'iterating',
|
|
@@ -62,7 +63,18 @@ export function renderRowActions(entry, defaultSite) {
|
|
|
62
63
|
// primary value is the dashboard ↔ scrapbook entry point existing at
|
|
63
64
|
// all, and most projects have a single site). Slug already contains
|
|
64
65
|
// any hierarchical path segments.
|
|
65
|
-
|
|
66
|
+
//
|
|
67
|
+
// #205: thread the entry's UUID through `scrapbookViewerUrl` so the
|
|
68
|
+
// standalone viewer's server route resolves the listing via
|
|
69
|
+
// `scrapbookDirForEntry` for entries whose on-disk path doesn't match
|
|
70
|
+
// the slug template (e.g. feature-doc layouts under
|
|
71
|
+
// `docs/<version>/<status>/<slug>/`). Falls back to slug-template
|
|
72
|
+
// addressing for entries without an id binding.
|
|
73
|
+
const scrapLink = scrapbookViewerUrl({
|
|
74
|
+
site: defaultSite,
|
|
75
|
+
path: entry.slug,
|
|
76
|
+
entryId: entry.uuid,
|
|
77
|
+
});
|
|
66
78
|
if (isLinearActiveStage(stage)) {
|
|
67
79
|
buttons.push(html `<a class="er-btn er-btn-small" href="${reviewLink}"
|
|
68
80
|
title="open the review surface for ${entry.slug}">open →</a>`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"affordances.js","sourceRoot":"","sources":["../../../src/pages/dashboard/affordances.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,EAAgB,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"affordances.js","sourceRoot":"","sources":["../../../src/pages/dashboard/affordances.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
import { html, unsafe, type RawHtml } from '../html.ts';
|
|
12
|
+
import { scrapbookViewerUrl } from '../../components/scrapbook-item.ts';
|
|
12
13
|
import type { Entry, Stage, ReviewState } from '@deskwork/core/schema/entry';
|
|
13
14
|
|
|
14
15
|
const REVIEW_STATE_LABEL: Record<ReviewState, string> = {
|
|
@@ -68,7 +69,18 @@ export function renderRowActions(entry: Entry, defaultSite: string): RawHtml {
|
|
|
68
69
|
// primary value is the dashboard ↔ scrapbook entry point existing at
|
|
69
70
|
// all, and most projects have a single site). Slug already contains
|
|
70
71
|
// any hierarchical path segments.
|
|
71
|
-
|
|
72
|
+
//
|
|
73
|
+
// #205: thread the entry's UUID through `scrapbookViewerUrl` so the
|
|
74
|
+
// standalone viewer's server route resolves the listing via
|
|
75
|
+
// `scrapbookDirForEntry` for entries whose on-disk path doesn't match
|
|
76
|
+
// the slug template (e.g. feature-doc layouts under
|
|
77
|
+
// `docs/<version>/<status>/<slug>/`). Falls back to slug-template
|
|
78
|
+
// addressing for entries without an id binding.
|
|
79
|
+
const scrapLink = scrapbookViewerUrl({
|
|
80
|
+
site: defaultSite,
|
|
81
|
+
path: entry.slug,
|
|
82
|
+
entryId: entry.uuid,
|
|
83
|
+
});
|
|
72
84
|
|
|
73
85
|
if (isLinearActiveStage(stage)) {
|
|
74
86
|
buttons.push(html`<a class="er-btn er-btn-small" href="${reviewLink}"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"review-scrapbook-drawer.d.ts","sourceRoot":"","sources":["../../src/pages/review-scrapbook-drawer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAYH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAOtD,OAAO,EAA4B,KAAK,OAAO,EAAE,MAAM,WAAW,CAAC;AAqFnE,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,aAAa,EAClB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,aAAa,GAAG,IAAI,EAC3B,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,YAAY,GACnB,OAAO,
|
|
1
|
+
{"version":3,"file":"review-scrapbook-drawer.d.ts","sourceRoot":"","sources":["../../src/pages/review-scrapbook-drawer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAYH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAOtD,OAAO,EAA4B,KAAK,OAAO,EAAE,MAAM,WAAW,CAAC;AAqFnE,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,aAAa,EAClB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,aAAa,GAAG,IAAI,EAC3B,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,YAAY,GACnB,OAAO,CAuET"}
|
|
@@ -101,6 +101,15 @@ export function renderScrapbookDrawer(ctx, site, entry, slug, index) {
|
|
|
101
101
|
const secretItems = summary?.secretItems ?? [];
|
|
102
102
|
const total = items.length + secretItems.length;
|
|
103
103
|
const loader = makeInlineTextLoader(ctx, site, entry, slug, index);
|
|
104
|
+
// #205: prefer entry-aware addressing for the "open viewer ↗" link
|
|
105
|
+
// when this drawer renders for a tracked calendar entry. The standalone
|
|
106
|
+
// viewer's server route resolves the listing via `scrapbookDirForEntry`
|
|
107
|
+
// when `entryId` is present, matching the entry-aware mutation API.
|
|
108
|
+
// Falls back to slug-template addressing when the entry has no id
|
|
109
|
+
// binding (pre-doctor entries, legacy / organizational paths).
|
|
110
|
+
const viewerAddress = entry !== null && entry.id !== undefined && entry.id !== ''
|
|
111
|
+
? { site, path: slug, entryId: entry.id }
|
|
112
|
+
: { site, path: slug };
|
|
104
113
|
return unsafe(html `
|
|
105
114
|
<aside class="er-scrapbook-drawer" data-scrapbook-drawer aria-label="Scrapbook for this entry">
|
|
106
115
|
<header class="er-scrapbook-drawer-handle" data-drawer-toggle role="button" tabindex="0"
|
|
@@ -110,7 +119,7 @@ export function renderScrapbookDrawer(ctx, site, entry, slug, index) {
|
|
|
110
119
|
<span class="er-scrapbook-drawer-peek" aria-hidden="true">
|
|
111
120
|
${unsafe(renderPeek(items, secretItems))}
|
|
112
121
|
</span>
|
|
113
|
-
<a class="er-scrapbook-drawer-open" href="${scrapbookViewerUrl(
|
|
122
|
+
<a class="er-scrapbook-drawer-open" href="${scrapbookViewerUrl(viewerAddress)}"
|
|
114
123
|
title="Open the standalone scrapbook viewer"
|
|
115
124
|
onclick="event.stopPropagation()">open viewer ↗</a>
|
|
116
125
|
<button class="er-scrapbook-drawer-toggle" type="button" data-drawer-toggle
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"review-scrapbook-drawer.js","sourceRoot":"","sources":["../../src/pages/review-scrapbook-drawer.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"review-scrapbook-drawer.js","sourceRoot":"","sources":["../../src/pages/review-scrapbook-drawer.ts"],"names":[],"mappings":"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"}
|
|
@@ -156,6 +156,16 @@ export function renderScrapbookDrawer(
|
|
|
156
156
|
const secretItems = summary?.secretItems ?? [];
|
|
157
157
|
const total = items.length + secretItems.length;
|
|
158
158
|
const loader = makeInlineTextLoader(ctx, site, entry, slug, index);
|
|
159
|
+
// #205: prefer entry-aware addressing for the "open viewer ↗" link
|
|
160
|
+
// when this drawer renders for a tracked calendar entry. The standalone
|
|
161
|
+
// viewer's server route resolves the listing via `scrapbookDirForEntry`
|
|
162
|
+
// when `entryId` is present, matching the entry-aware mutation API.
|
|
163
|
+
// Falls back to slug-template addressing when the entry has no id
|
|
164
|
+
// binding (pre-doctor entries, legacy / organizational paths).
|
|
165
|
+
const viewerAddress: { site: string; path: string; entryId?: string } =
|
|
166
|
+
entry !== null && entry.id !== undefined && entry.id !== ''
|
|
167
|
+
? { site, path: slug, entryId: entry.id }
|
|
168
|
+
: { site, path: slug };
|
|
159
169
|
|
|
160
170
|
return unsafe(html`
|
|
161
171
|
<aside class="er-scrapbook-drawer" data-scrapbook-drawer aria-label="Scrapbook for this entry">
|
|
@@ -166,7 +176,7 @@ export function renderScrapbookDrawer(
|
|
|
166
176
|
<span class="er-scrapbook-drawer-peek" aria-hidden="true">
|
|
167
177
|
${unsafe(renderPeek(items, secretItems))}
|
|
168
178
|
</span>
|
|
169
|
-
<a class="er-scrapbook-drawer-open" href="${scrapbookViewerUrl(
|
|
179
|
+
<a class="er-scrapbook-drawer-open" href="${scrapbookViewerUrl(viewerAddress)}"
|
|
170
180
|
title="Open the standalone scrapbook viewer"
|
|
171
181
|
onclick="event.stopPropagation()">open viewer ↗</a>
|
|
172
182
|
<button class="er-scrapbook-drawer-toggle" type="button" data-drawer-toggle
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scrapbook page listing dispatch — entry-aware vs slug-template
|
|
3
|
+
* resolution. Mirrors the post-#191 envelope/dispatch split for
|
|
4
|
+
* mutations: dispatch chooses the addressing mode, render stays free
|
|
5
|
+
* of the resolution branch.
|
|
6
|
+
*/
|
|
7
|
+
import { type ScrapbookSummary } from '@deskwork/core/scrapbook';
|
|
8
|
+
import type { StudioContext } from '../../routes/api.ts';
|
|
9
|
+
/**
|
|
10
|
+
* Error class surfaced by the page route to translate into HTTP status
|
|
11
|
+
* codes (`server.ts` maps these onto 400/404 responses).
|
|
12
|
+
*/
|
|
13
|
+
export declare class ScrapbookPageError extends Error {
|
|
14
|
+
readonly status: 400 | 404;
|
|
15
|
+
constructor(message: string, status: 400 | 404);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* #168 Phase 34 ship-pass — when the scrapbook path matches a tracked
|
|
19
|
+
* calendar entry with a stamped UUID, return the entry's id so the aside
|
|
20
|
+
* can render a "← back to review" link AND the client can address
|
|
21
|
+
* mutations via `entryId` (#191 fix). Returns null when no entry matches
|
|
22
|
+
* (organizational subdirs, ad-hoc paths, or pre-doctor entries lacking
|
|
23
|
+
* an id) — the link is then omitted and mutations fall back to slug-
|
|
24
|
+
* template addressing.
|
|
25
|
+
*
|
|
26
|
+
* Failures (calendar absent, parse error) fall through to null so a
|
|
27
|
+
* transient calendar issue never blocks the scrapbook render.
|
|
28
|
+
*/
|
|
29
|
+
export declare function lookupEntryId(ctx: StudioContext, site: string, path: string): string | null;
|
|
30
|
+
/**
|
|
31
|
+
* #205 — listing + dir-resolution dispatch. Two addressing modes:
|
|
32
|
+
*
|
|
33
|
+
* - Entry-id mode: `entryId` is validated as a UUID, the sidecar is
|
|
34
|
+
* read, and the listing resolves via `listScrapbookForEntry` so
|
|
35
|
+
* non-kebab-case entries (feature-doc layouts, dotted version
|
|
36
|
+
* segments, etc.) read items from the entry's artifact-parent
|
|
37
|
+
* `scrapbook/` directory. Symmetric to the entry-aware mutation API.
|
|
38
|
+
* - Slug mode: legacy / organizational paths under the site's content
|
|
39
|
+
* dir. Resolves via `scrapbookDirAtPath` + `listScrapbook` (the
|
|
40
|
+
* pre-#205 behavior).
|
|
41
|
+
*
|
|
42
|
+
* Returns the resolved `scrapbookDir` (absolute) plus the listing
|
|
43
|
+
* summary so the caller threads both through to render helpers.
|
|
44
|
+
*/
|
|
45
|
+
export declare function resolveListing(ctx: StudioContext, site: string, path: string, entryId: string | null): Promise<{
|
|
46
|
+
scrapbookDir: string;
|
|
47
|
+
result: ScrapbookSummary;
|
|
48
|
+
resolvedEntryId: string | null;
|
|
49
|
+
}>;
|
|
50
|
+
//# sourceMappingURL=dispatch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../../../src/pages/scrapbook/dispatch.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,EAKL,KAAK,gBAAgB,EACtB,MAAM,0BAA0B,CAAC;AAGlC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD;;;GAGG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,QAAQ,CAAC,MAAM,EAAE,GAAG,GAAG,GAAG,CAAC;gBACf,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,GAAG;CAK/C;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,aAAa,EAClB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,MAAM,GAAG,IAAI,CAYf;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,cAAc,CAClC,GAAG,EAAE,aAAa,EAClB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,GAAG,IAAI,GACrB,OAAO,CAAC;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,gBAAgB,CAAC;IAAC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CA0C7F"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scrapbook page listing dispatch — entry-aware vs slug-template
|
|
3
|
+
* resolution. Mirrors the post-#191 envelope/dispatch split for
|
|
4
|
+
* mutations: dispatch chooses the addressing mode, render stays free
|
|
5
|
+
* of the resolution branch.
|
|
6
|
+
*/
|
|
7
|
+
import { existsSync } from 'node:fs';
|
|
8
|
+
import { readCalendar } from '@deskwork/core/calendar';
|
|
9
|
+
import { findEntry } from '@deskwork/core/calendar-mutations';
|
|
10
|
+
import { resolveCalendarPath } from '@deskwork/core/paths';
|
|
11
|
+
import { listScrapbook, listScrapbookForEntry, scrapbookDirAtPath, scrapbookDirForEntry, } from '@deskwork/core/scrapbook';
|
|
12
|
+
import { readSidecar } from '@deskwork/core/sidecar';
|
|
13
|
+
import { UUID_RE } from "../../routes/scrapbook-mutation-envelope.js";
|
|
14
|
+
/**
|
|
15
|
+
* Error class surfaced by the page route to translate into HTTP status
|
|
16
|
+
* codes (`server.ts` maps these onto 400/404 responses).
|
|
17
|
+
*/
|
|
18
|
+
export class ScrapbookPageError extends Error {
|
|
19
|
+
status;
|
|
20
|
+
constructor(message, status) {
|
|
21
|
+
super(message);
|
|
22
|
+
this.status = status;
|
|
23
|
+
this.name = 'ScrapbookPageError';
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* #168 Phase 34 ship-pass — when the scrapbook path matches a tracked
|
|
28
|
+
* calendar entry with a stamped UUID, return the entry's id so the aside
|
|
29
|
+
* can render a "← back to review" link AND the client can address
|
|
30
|
+
* mutations via `entryId` (#191 fix). Returns null when no entry matches
|
|
31
|
+
* (organizational subdirs, ad-hoc paths, or pre-doctor entries lacking
|
|
32
|
+
* an id) — the link is then omitted and mutations fall back to slug-
|
|
33
|
+
* template addressing.
|
|
34
|
+
*
|
|
35
|
+
* Failures (calendar absent, parse error) fall through to null so a
|
|
36
|
+
* transient calendar issue never blocks the scrapbook render.
|
|
37
|
+
*/
|
|
38
|
+
export function lookupEntryId(ctx, site, path) {
|
|
39
|
+
if (!(site in ctx.config.sites))
|
|
40
|
+
return null;
|
|
41
|
+
try {
|
|
42
|
+
const calendarPath = resolveCalendarPath(ctx.projectRoot, ctx.config, site);
|
|
43
|
+
if (!existsSync(calendarPath))
|
|
44
|
+
return null;
|
|
45
|
+
const cal = readCalendar(calendarPath);
|
|
46
|
+
const entry = findEntry(cal, path);
|
|
47
|
+
if (!entry || !entry.id)
|
|
48
|
+
return null;
|
|
49
|
+
return entry.id;
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* #205 — listing + dir-resolution dispatch. Two addressing modes:
|
|
57
|
+
*
|
|
58
|
+
* - Entry-id mode: `entryId` is validated as a UUID, the sidecar is
|
|
59
|
+
* read, and the listing resolves via `listScrapbookForEntry` so
|
|
60
|
+
* non-kebab-case entries (feature-doc layouts, dotted version
|
|
61
|
+
* segments, etc.) read items from the entry's artifact-parent
|
|
62
|
+
* `scrapbook/` directory. Symmetric to the entry-aware mutation API.
|
|
63
|
+
* - Slug mode: legacy / organizational paths under the site's content
|
|
64
|
+
* dir. Resolves via `scrapbookDirAtPath` + `listScrapbook` (the
|
|
65
|
+
* pre-#205 behavior).
|
|
66
|
+
*
|
|
67
|
+
* Returns the resolved `scrapbookDir` (absolute) plus the listing
|
|
68
|
+
* summary so the caller threads both through to render helpers.
|
|
69
|
+
*/
|
|
70
|
+
export async function resolveListing(ctx, site, path, entryId) {
|
|
71
|
+
if (entryId !== null) {
|
|
72
|
+
if (!UUID_RE.test(entryId)) {
|
|
73
|
+
throw new ScrapbookPageError(`invalid entryId`, 400);
|
|
74
|
+
}
|
|
75
|
+
let entry;
|
|
76
|
+
try {
|
|
77
|
+
entry = await readSidecar(ctx.projectRoot, entryId);
|
|
78
|
+
}
|
|
79
|
+
catch (e) {
|
|
80
|
+
// readSidecar throws "sidecar not found" with ENOENT; map to 404.
|
|
81
|
+
const reason = e instanceof Error ? e.message : String(e);
|
|
82
|
+
if (/sidecar not found/i.test(reason)) {
|
|
83
|
+
throw new ScrapbookPageError(reason, 404);
|
|
84
|
+
}
|
|
85
|
+
throw e;
|
|
86
|
+
}
|
|
87
|
+
const scrapbookDir = scrapbookDirForEntry(ctx.projectRoot, ctx.config, site, { id: entry.uuid, slug: entry.slug });
|
|
88
|
+
const result = listScrapbookForEntry(ctx.projectRoot, ctx.config, site, { id: entry.uuid, slug: entry.slug });
|
|
89
|
+
return { scrapbookDir, result, resolvedEntryId: entry.uuid };
|
|
90
|
+
}
|
|
91
|
+
// Slug-mode: legacy back-compat. listScrapbook returns
|
|
92
|
+
// { exists: false, items: [] } for missing dirs, so an empty
|
|
93
|
+
// scrapbook is not an error path. Real errors (slug validation,
|
|
94
|
+
// scrapbookDir resolution failures, FS permission issues)
|
|
95
|
+
// propagate to the studio's error handler.
|
|
96
|
+
const scrapbookDir = scrapbookDirAtPath(ctx.projectRoot, ctx.config, site, path);
|
|
97
|
+
const result = listScrapbook(ctx.projectRoot, ctx.config, site, path);
|
|
98
|
+
// Best-effort lookup so the back-link to the review surface still
|
|
99
|
+
// renders for slug-template entries that happen to match a calendar
|
|
100
|
+
// entry by slug.
|
|
101
|
+
const resolvedEntryId = lookupEntryId(ctx, site, path);
|
|
102
|
+
return { scrapbookDir, result, resolvedEntryId };
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=dispatch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispatch.js","sourceRoot":"","sources":["../../../src/pages/scrapbook/dispatch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scrapbook image-format readers — pure functions on Buffer headers.
|
|
3
|
+
*
|
|
4
|
+
* Recognizes PNG, JPEG, WebP, and GIF; returns null for unrecognized
|
|
5
|
+
* signatures or truncated/malformed buffers. Used by the scrapbook
|
|
6
|
+
* card meta to render `{W} × {H}` next to the image kind chip.
|
|
7
|
+
*
|
|
8
|
+
* Each format is parsed from its file-header structure (no external
|
|
9
|
+
* dependency); each branch returns null on any unexpected byte rather
|
|
10
|
+
* than throwing, so a corrupt image still renders with empty meta.
|
|
11
|
+
*/
|
|
12
|
+
export interface ImageDimensions {
|
|
13
|
+
readonly width: number;
|
|
14
|
+
readonly height: number;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Read width × height from a buffer. Recognizes PNG, JPEG, WebP, and
|
|
18
|
+
* GIF; returns null for unrecognized signatures or truncated/malformed
|
|
19
|
+
* buffers.
|
|
20
|
+
*/
|
|
21
|
+
export declare function readImageDimensions(buf: Buffer): ImageDimensions | null;
|
|
22
|
+
export declare function readJpegDimensions(buf: Buffer): ImageDimensions | null;
|
|
23
|
+
export declare function readWebpDimensions(buf: Buffer): ImageDimensions | null;
|
|
24
|
+
//# sourceMappingURL=image-readers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-readers.d.ts","sourceRoot":"","sources":["../../../src/pages/scrapbook/image-readers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAiCvE;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAoCtE;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAyCtE"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scrapbook image-format readers — pure functions on Buffer headers.
|
|
3
|
+
*
|
|
4
|
+
* Recognizes PNG, JPEG, WebP, and GIF; returns null for unrecognized
|
|
5
|
+
* signatures or truncated/malformed buffers. Used by the scrapbook
|
|
6
|
+
* card meta to render `{W} × {H}` next to the image kind chip.
|
|
7
|
+
*
|
|
8
|
+
* Each format is parsed from its file-header structure (no external
|
|
9
|
+
* dependency); each branch returns null on any unexpected byte rather
|
|
10
|
+
* than throwing, so a corrupt image still renders with empty meta.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Read width × height from a buffer. Recognizes PNG, JPEG, WebP, and
|
|
14
|
+
* GIF; returns null for unrecognized signatures or truncated/malformed
|
|
15
|
+
* buffers.
|
|
16
|
+
*/
|
|
17
|
+
export function readImageDimensions(buf) {
|
|
18
|
+
if (buf.length < 12)
|
|
19
|
+
return null;
|
|
20
|
+
// PNG: 89 50 4E 47 0D 0A 1A 0A then IHDR (chunk-length 4, "IHDR" 4,
|
|
21
|
+
// width 4, height 4 — width@16, height@20).
|
|
22
|
+
if (buf[0] === 0x89 && buf[1] === 0x50 && buf[2] === 0x4e && buf[3] === 0x47) {
|
|
23
|
+
if (buf.length < 24)
|
|
24
|
+
return null;
|
|
25
|
+
return { width: buf.readUInt32BE(16), height: buf.readUInt32BE(20) };
|
|
26
|
+
}
|
|
27
|
+
// GIF: "GIF87a" or "GIF89a" + logical screen descriptor (width LE @6,
|
|
28
|
+
// height LE @8).
|
|
29
|
+
if (buf[0] === 0x47 && buf[1] === 0x49 && buf[2] === 0x46 &&
|
|
30
|
+
buf[3] === 0x38 && (buf[4] === 0x37 || buf[4] === 0x39) && buf[5] === 0x61) {
|
|
31
|
+
if (buf.length < 10)
|
|
32
|
+
return null;
|
|
33
|
+
return { width: buf.readUInt16LE(6), height: buf.readUInt16LE(8) };
|
|
34
|
+
}
|
|
35
|
+
// JPEG: starts FF D8. Width/height live in a Start-Of-Frame marker
|
|
36
|
+
// (FF C0–CF, excluding DHT C4 / JPG C8 / DAC CC). Walk markers
|
|
37
|
+
// skipping their payloads until the SOF is found.
|
|
38
|
+
if (buf[0] === 0xff && buf[1] === 0xd8) {
|
|
39
|
+
return readJpegDimensions(buf);
|
|
40
|
+
}
|
|
41
|
+
// WebP: "RIFF" {size} "WEBP" then a chunk (VP8 / VP8L / VP8X).
|
|
42
|
+
if (buf[0] === 0x52 && buf[1] === 0x49 && buf[2] === 0x46 && buf[3] === 0x46 &&
|
|
43
|
+
buf[8] === 0x57 && buf[9] === 0x45 && buf[10] === 0x42 && buf[11] === 0x50) {
|
|
44
|
+
return readWebpDimensions(buf);
|
|
45
|
+
}
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
export function readJpegDimensions(buf) {
|
|
49
|
+
// Marker walk: skip FF D8 (SOI), then each marker is FF Xn followed
|
|
50
|
+
// by a 2-byte big-endian segment length (which includes its own 2
|
|
51
|
+
// bytes). The SOF segment's payload is: 1 byte precision, 2 bytes
|
|
52
|
+
// height, 2 bytes width (the rest is component info).
|
|
53
|
+
let i = 2;
|
|
54
|
+
while (i + 4 <= buf.length) {
|
|
55
|
+
if (buf[i] !== 0xff)
|
|
56
|
+
return null;
|
|
57
|
+
let marker = buf[i + 1] ?? 0;
|
|
58
|
+
// Skip fill bytes (0xff padding before the actual marker byte).
|
|
59
|
+
while (marker === 0xff && i + 2 < buf.length) {
|
|
60
|
+
i++;
|
|
61
|
+
marker = buf[i + 1] ?? 0;
|
|
62
|
+
}
|
|
63
|
+
i += 2;
|
|
64
|
+
// Standalone markers (no length): RST0–7 (D0–D7) and SOI/EOI/TEM.
|
|
65
|
+
if (marker === 0xd9 || marker === 0xd8 || marker === 0x01)
|
|
66
|
+
return null;
|
|
67
|
+
if (marker >= 0xd0 && marker <= 0xd7)
|
|
68
|
+
continue;
|
|
69
|
+
if (i + 2 > buf.length)
|
|
70
|
+
return null;
|
|
71
|
+
const segLen = buf.readUInt16BE(i);
|
|
72
|
+
// SOF markers carry the dimensions. Exclusions per JPEG spec:
|
|
73
|
+
// C4 (DHT — Huffman tables), C8 (JPG reserved), CC (DAC — arithmetic
|
|
74
|
+
// coding conditioning).
|
|
75
|
+
const isSof = marker >= 0xc0 && marker <= 0xcf &&
|
|
76
|
+
marker !== 0xc4 && marker !== 0xc8 && marker !== 0xcc;
|
|
77
|
+
if (isSof) {
|
|
78
|
+
if (i + 7 > buf.length)
|
|
79
|
+
return null;
|
|
80
|
+
return {
|
|
81
|
+
width: buf.readUInt16BE(i + 5),
|
|
82
|
+
height: buf.readUInt16BE(i + 3),
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
i += segLen;
|
|
86
|
+
}
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
export function readWebpDimensions(buf) {
|
|
90
|
+
// Three sub-formats (per RFC 6386 / VP8L spec / WebP container spec):
|
|
91
|
+
// - "VP8 " (lossy): header @20-22: signature 9D 01 2A, then
|
|
92
|
+
// 14-bit width LE @23, 14-bit height LE @25
|
|
93
|
+
// (each masked to 14 bits — top 2 bits are
|
|
94
|
+
// horizontal/vertical scale).
|
|
95
|
+
// - "VP8L" (lossless): header @20: signature 0x2F, then 32 bits
|
|
96
|
+
// packed: width-1 (14 bits) + height-1 (14
|
|
97
|
+
// bits) + alpha-flag + version (4 bits).
|
|
98
|
+
// - "VP8X" (extended): flags @20, reserved @21-23, width-1 (24
|
|
99
|
+
// bits LE) @24, height-1 (24 bits LE) @27.
|
|
100
|
+
// Need at least the RIFF header + chunk fourcc; per-variant length
|
|
101
|
+
// checks below cover the variant-specific payload sizes.
|
|
102
|
+
if (buf.length < 16)
|
|
103
|
+
return null;
|
|
104
|
+
const fourcc = buf.subarray(12, 16).toString('ascii');
|
|
105
|
+
if (fourcc === 'VP8 ') {
|
|
106
|
+
if (buf.length < 30)
|
|
107
|
+
return null;
|
|
108
|
+
if (buf[23] !== 0x9d || buf[24] !== 0x01 || buf[25] !== 0x2a)
|
|
109
|
+
return null;
|
|
110
|
+
const w = buf.readUInt16LE(26) & 0x3fff;
|
|
111
|
+
const h = buf.readUInt16LE(28) & 0x3fff;
|
|
112
|
+
return { width: w, height: h };
|
|
113
|
+
}
|
|
114
|
+
if (fourcc === 'VP8L') {
|
|
115
|
+
if (buf.length < 25)
|
|
116
|
+
return null;
|
|
117
|
+
if (buf[20] !== 0x2f)
|
|
118
|
+
return null;
|
|
119
|
+
// Read 4 bytes LE at offset 21, then unpack.
|
|
120
|
+
const packed = buf.readUInt32LE(21);
|
|
121
|
+
const widthMinus1 = packed & 0x3fff;
|
|
122
|
+
const heightMinus1 = (packed >>> 14) & 0x3fff;
|
|
123
|
+
return { width: widthMinus1 + 1, height: heightMinus1 + 1 };
|
|
124
|
+
}
|
|
125
|
+
if (fourcc === 'VP8X') {
|
|
126
|
+
if (buf.length < 30)
|
|
127
|
+
return null;
|
|
128
|
+
// 24-bit little-endian: low byte + (mid << 8) + (high << 16).
|
|
129
|
+
const w = ((buf[24] ?? 0) | ((buf[25] ?? 0) << 8) | ((buf[26] ?? 0) << 16)) + 1;
|
|
130
|
+
const h = ((buf[27] ?? 0) | ((buf[28] ?? 0) << 8) | ((buf[29] ?? 0) << 16)) + 1;
|
|
131
|
+
return { width: w, height: h };
|
|
132
|
+
}
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=image-readers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-readers.js","sourceRoot":"","sources":["../../../src/pages/scrapbook/image-readers.ts"],"names":[],"mappings":"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"}
|