@deskwork/core 0.14.0 → 0.15.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,56 @@
1
+ import type { Entry, ReviewState, Stage } from '../schema/entry.ts';
2
+ /**
3
+ * Inputs for a freshly-minted entry sidecar.
4
+ *
5
+ * Both `deskwork add` and `deskwork ingest --apply` produce new entries
6
+ * that need a sidecar written under the Phase 30 contract. They differ
7
+ * in the optional fields (ingest knows an `artifactPath`; published
8
+ * candidates carry a `datePublishedDate`; legacy `Review` mapping
9
+ * produces a `reviewState`), but the required-field shape and the
10
+ * defaults (`keywords=[]`, `iterationByStage={}`, `createdAt=updatedAt=now`)
11
+ * are identical. This helper is the single point that knows the new-entry
12
+ * shape so both call sites stay aligned.
13
+ */
14
+ export interface CreateEntryParams {
15
+ readonly uuid: string;
16
+ readonly slug: string;
17
+ readonly title: string;
18
+ readonly description?: string;
19
+ readonly currentStage: Stage;
20
+ readonly source: string;
21
+ readonly reviewState?: ReviewState;
22
+ readonly artifactPath?: string;
23
+ /**
24
+ * YYYY-MM-DD; the helper converts to a full ISO datetime so the
25
+ * `Entry.datePublished` schema (`z.string().datetime()`) accepts it.
26
+ * Only honored when `currentStage === 'Published'`.
27
+ */
28
+ readonly datePublishedDate?: string;
29
+ readonly keywords?: readonly string[];
30
+ /**
31
+ * Test seam — defaults to `new Date()` when omitted. Lets unit tests
32
+ * pin `createdAt`/`updatedAt`/`datePublished`-derived ISO without
33
+ * stubbing globals.
34
+ */
35
+ readonly now?: Date;
36
+ }
37
+ /**
38
+ * Build a fresh `Entry` from the supplied params, write it to
39
+ * `.deskwork/entries/<uuid>.json`, and return the constructed Entry
40
+ * (callers don't need the return value but it's cheap to provide and
41
+ * useful in tests).
42
+ *
43
+ * Defaults:
44
+ * - `keywords` → `[]`
45
+ * - `iterationByStage` → `{}`
46
+ * - `createdAt` / `updatedAt` → `now.toISOString()`
47
+ * - `datePublished` (only if `currentStage === 'Published'` and
48
+ * `datePublishedDate` is supplied) → `${datePublishedDate}T00:00:00.000Z`
49
+ *
50
+ * Phase 30 contract: every UUID in `calendar.md` must have a sidecar.
51
+ * Both `deskwork add` and `deskwork ingest --apply` MUST pair their
52
+ * calendar.md write with a `createFreshEntrySidecar` call to satisfy
53
+ * doctor's `calendar-sidecar` validator.
54
+ */
55
+ export declare function createFreshEntrySidecar(projectRoot: string, params: CreateEntryParams): Promise<Entry>;
56
+ //# sourceMappingURL=create.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../src/entry/create.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAEpE;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,YAAY,EAAE,KAAK,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC;IACnC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B;;;;OAIG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC;;;;OAIG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,uBAAuB,CAC3C,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,iBAAiB,GACxB,OAAO,CAAC,KAAK,CAAC,CAqBhB"}
@@ -0,0 +1,42 @@
1
+ import { writeSidecar } from "../sidecar/write.js";
2
+ /**
3
+ * Build a fresh `Entry` from the supplied params, write it to
4
+ * `.deskwork/entries/<uuid>.json`, and return the constructed Entry
5
+ * (callers don't need the return value but it's cheap to provide and
6
+ * useful in tests).
7
+ *
8
+ * Defaults:
9
+ * - `keywords` → `[]`
10
+ * - `iterationByStage` → `{}`
11
+ * - `createdAt` / `updatedAt` → `now.toISOString()`
12
+ * - `datePublished` (only if `currentStage === 'Published'` and
13
+ * `datePublishedDate` is supplied) → `${datePublishedDate}T00:00:00.000Z`
14
+ *
15
+ * Phase 30 contract: every UUID in `calendar.md` must have a sidecar.
16
+ * Both `deskwork add` and `deskwork ingest --apply` MUST pair their
17
+ * calendar.md write with a `createFreshEntrySidecar` call to satisfy
18
+ * doctor's `calendar-sidecar` validator.
19
+ */
20
+ export async function createFreshEntrySidecar(projectRoot, params) {
21
+ const at = (params.now ?? new Date()).toISOString();
22
+ const entry = {
23
+ uuid: params.uuid,
24
+ slug: params.slug,
25
+ title: params.title,
26
+ ...(params.description ? { description: params.description } : {}),
27
+ keywords: params.keywords ? [...params.keywords] : [],
28
+ source: params.source,
29
+ currentStage: params.currentStage,
30
+ iterationByStage: {},
31
+ ...(params.reviewState !== undefined ? { reviewState: params.reviewState } : {}),
32
+ ...(params.artifactPath !== undefined ? { artifactPath: params.artifactPath } : {}),
33
+ ...(params.currentStage === 'Published' && params.datePublishedDate
34
+ ? { datePublished: `${params.datePublishedDate}T00:00:00.000Z` }
35
+ : {}),
36
+ createdAt: at,
37
+ updatedAt: at,
38
+ };
39
+ await writeSidecar(projectRoot, entry);
40
+ return entry;
41
+ }
42
+ //# sourceMappingURL=create.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create.js","sourceRoot":"","sources":["../../src/entry/create.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAuCnD;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,WAAmB,EACnB,MAAyB;IAEzB,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IACpD,MAAM,KAAK,GAAU;QACnB,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAClE,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE;QACrD,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,YAAY,EAAE,MAAM,CAAC,YAAY;QACjC,gBAAgB,EAAE,EAAE;QACpB,GAAG,CAAC,MAAM,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAChF,GAAG,CAAC,MAAM,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACnF,GAAG,CAAC,MAAM,CAAC,YAAY,KAAK,WAAW,IAAI,MAAM,CAAC,iBAAiB;YACjE,CAAC,CAAC,EAAE,aAAa,EAAE,GAAG,MAAM,CAAC,iBAAiB,gBAAgB,EAAE;YAChE,CAAC,CAAC,EAAE,CAAC;QACP,SAAS,EAAE,EAAE;QACb,SAAS,EAAE,EAAE;KACd,CAAC;IACF,MAAM,YAAY,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;IACvC,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"iterate.d.ts","sourceRoot":"","sources":["../../src/iterate/iterate.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAS,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAEvD,UAAU,cAAc;IACtB,IAAI,EAAE,MAAM,CAAC;CAEd;AAED,UAAU,aAAa;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,KAAK,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,WAAW,CAAC;CAC1B;AAaD,wBAAsB,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CAiFpG"}
1
+ {"version":3,"file":"iterate.d.ts","sourceRoot":"","sources":["../../src/iterate/iterate.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAS,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAEvD,UAAU,cAAc;IACtB,IAAI,EAAE,MAAM,CAAC;CAEd;AAED,UAAU,aAAa;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,KAAK,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,WAAW,CAAC;CAC1B;AAaD,wBAAsB,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CA8EpG"}
@@ -3,7 +3,6 @@ import { join } from 'node:path';
3
3
  import { readSidecar } from "../sidecar/read.js";
4
4
  import { writeSidecar } from "../sidecar/write.js";
5
5
  import { appendJournalEvent } from "../journal/append.js";
6
- import { readJournalEvents } from "../journal/read.js";
7
6
  import { getContentDir } from "../config.js";
8
7
  const STAGE_ARTIFACT_PATH = {
9
8
  Ideas: (slug, contentDir) => join(contentDir, slug, 'scrapbook', 'idea.md'),
@@ -38,17 +37,16 @@ export async function iterateEntry(projectRoot, opts) {
38
37
  artifactPath = pathFn(sidecar.slug, contentDir);
39
38
  }
40
39
  const markdown = await readFile(artifactPath, 'utf8');
41
- // Guard: refuse to iterate when on-disk content matches the most recent
42
- // iteration journal entry for this stage. Prevents no-op revision bumps
43
- // (the operator forgot to actually edit the file).
44
- const events = await readJournalEvents(projectRoot, { entryId: sidecar.uuid });
45
- const lastIteration = events
46
- .filter((e) => e.kind === 'iteration' && e.stage === sidecar.currentStage)
47
- .at(-1);
48
- if (lastIteration && lastIteration.kind === 'iteration' && lastIteration.markdown === markdown) {
49
- throw new Error(`Cannot iterate: ${artifactPath} content is unchanged since iteration v${lastIteration.version}. ` +
50
- 'Edit the file before iterating.');
51
- }
40
+ // Iteration is the operator's explicit "pin a new version" decision;
41
+ // the core helper records what was asked, not what the helper thinks
42
+ // counts as "real change." A real iteration can be motivated by
43
+ // marginalia, scrapbook additions, decisions captured outside the
44
+ // file body, or any reason the operator hasn't communicated to the
45
+ // system. Gating on a content-diff check earlier here put a hard
46
+ // error in front of the operator's review-surface Iterate button
47
+ // when they had added marginalia but not edited the file body.
48
+ // Removed (#188-followup): the orchestrating skill (`/deskwork:iterate`)
49
+ // is the right place to decide whether the file needs editing first.
52
50
  const priorVersion = sidecar.iterationByStage[sidecar.currentStage] ?? 0;
53
51
  const newVersion = priorVersion + 1;
54
52
  const at = new Date().toISOString();
@@ -1 +1 @@
1
- {"version":3,"file":"iterate.js","sourceRoot":"","sources":["../../src/iterate/iterate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAe7C,MAAM,mBAAmB,GAAyE;IAChG,KAAK,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,SAAS,CAAC;IAC3E,OAAO,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,SAAS,CAAC;IAC7E,SAAS,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,YAAY,CAAC;IAClF,QAAQ,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,EAAE,UAAU,CAAC;IAClE,KAAK,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,EAAE,UAAU,CAAC;IAC/D,SAAS,EAAE,IAAI;IACf,OAAO,EAAE,IAAI;IACb,SAAS,EAAE,IAAI;CAChB,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,WAAmB,EAAE,IAAoB;IAC1E,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IAE1D,IAAI,OAAO,CAAC,YAAY,KAAK,WAAW,EAAE,CAAC;QACzC,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;IACnE,CAAC;IACD,IAAI,OAAO,CAAC,YAAY,KAAK,SAAS,IAAI,OAAO,CAAC,YAAY,KAAK,WAAW,EAAE,CAAC;QAC/E,MAAM,IAAI,KAAK,CAAC,4BAA4B,OAAO,CAAC,YAAY,2CAA2C,CAAC,CAAC;IAC/G,CAAC;IAED,sEAAsE;IACtE,iEAAiE;IACjE,IAAI,YAAoB,CAAC;IACzB,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;QACzB,YAAY,GAAG,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IACzD,CAAC;SAAM,CAAC;QACN,MAAM,MAAM,GAAG,mBAAmB,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QACzD,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,2BAA2B,OAAO,CAAC,YAAY,6BAA6B,CAAC,CAAC;QAChG,CAAC;QACD,MAAM,UAAU,GAAG,aAAa,CAAC,WAAW,CAAC,CAAC;QAC9C,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAClD,CAAC;IACD,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IAEtD,wEAAwE;IACxE,wEAAwE;IACxE,mDAAmD;IACnD,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,WAAW,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAC/E,MAAM,aAAa,GAAG,MAAM;SACzB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,IAAI,CAAC,CAAC,KAAK,KAAK,OAAO,CAAC,YAAY,CAAC;SACzE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACV,IAAI,aAAa,IAAI,aAAa,CAAC,IAAI,KAAK,WAAW,IAAI,aAAa,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC/F,MAAM,IAAI,KAAK,CACb,mBAAmB,YAAY,0CAA0C,aAAa,CAAC,OAAO,IAAI;YAChG,iCAAiC,CACpC,CAAC;IACJ,CAAC;IAED,MAAM,YAAY,GAAG,OAAO,CAAC,gBAAgB,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;IACzE,MAAM,UAAU,GAAG,YAAY,GAAG,CAAC,CAAC;IAEpC,MAAM,EAAE,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAEpC,8EAA8E;IAC9E,MAAM,kBAAkB,CAAC,WAAW,EAAE;QACpC,IAAI,EAAE,WAAW;QACjB,EAAE;QACF,OAAO,EAAE,OAAO,CAAC,IAAI;QACrB,KAAK,EAAE,OAAO,CAAC,YAAY;QAC3B,OAAO,EAAE,UAAU;QACnB,QAAQ;KACT,CAAC,CAAC;IAEH,iBAAiB;IACjB,MAAM,OAAO,GAAU;QACrB,GAAG,OAAO;QACV,gBAAgB,EAAE,EAAE,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,UAAU,EAAE;QACrF,WAAW,EAAE,WAAW;QACxB,SAAS,EAAE,EAAE;KACd,CAAC;IACF,MAAM,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAEzC,qDAAqD;IACrD,IAAI,OAAO,CAAC,WAAW,KAAK,WAAW,EAAE,CAAC;QACxC,MAAM,kBAAkB,CAAC,WAAW,EAAE;YACpC,IAAI,EAAE,qBAAqB;YAC3B,EAAE;YACF,OAAO,EAAE,OAAO,CAAC,IAAI;YACrB,KAAK,EAAE,OAAO,CAAC,YAAY;YAC3B,IAAI,EAAE,OAAO,CAAC,WAAW,IAAI,IAAI;YACjC,EAAE,EAAE,WAAW;SAChB,CAAC,CAAC;IACL,CAAC;IAED,OAAO;QACL,OAAO,EAAE,OAAO,CAAC,IAAI;QACrB,KAAK,EAAE,OAAO,CAAC,YAAY;QAC3B,OAAO,EAAE,UAAU;QACnB,WAAW,EAAE,WAAW;KACzB,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"iterate.js","sourceRoot":"","sources":["../../src/iterate/iterate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Rewrite relative `<img src>` paths that point into the entry's
3
+ * scrapbook so the studio's review surface can serve them via the
4
+ * scrapbook-file route.
5
+ *
6
+ * Why this exists: an audit doc / draft / spec authored alongside a
7
+ * `scrapbook/` directory will reference its assets with relative URLs
8
+ * like `![alt](./scrapbook/figure-1.png)` or `![alt](scrapbook/figure-1.png)`.
9
+ * Those relative URLs render correctly in any normal markdown viewer
10
+ * (GitHub, VS Code, IDE preview) because the renderer resolves them
11
+ * against the file's location on disk. On the studio's review surface
12
+ * the page URL is `/dev/editorial-review/entry/<uuid>`, so the same
13
+ * relative URL would resolve to a path the studio doesn't serve. This
14
+ * plugin rewrites those `<img src>` values to the absolute scrapbook-file
15
+ * route URL, which the studio DOES serve.
16
+ *
17
+ * The markdown source stays portable. The plugin only fires when the
18
+ * renderer is given `{ entryId, site }` options (i.e. the studio's
19
+ * review surface). Other call sites (e.g. published-site rendering)
20
+ * leave the relative URLs alone.
21
+ *
22
+ * @typedef {object} Options
23
+ * @property {string} entryId Entry UUID. Required.
24
+ * @property {string} site Site/collection slug. Required.
25
+ *
26
+ * @param {Options} options
27
+ * @returns {(tree: any) => void}
28
+ */
29
+ export default function rehypeRewriteScrapbookImages(options) {
30
+ const { entryId, site } = options || {};
31
+ if (!entryId || !site) {
32
+ throw new Error(
33
+ 'rehypeRewriteScrapbookImages: { entryId, site } are required',
34
+ );
35
+ }
36
+
37
+ const baseUrl =
38
+ `/api/dev/scrapbook-file` +
39
+ `?site=${encodeURIComponent(site)}` +
40
+ `&entryId=${encodeURIComponent(entryId)}`;
41
+
42
+ /** @param {string} src */
43
+ function rewrite(src) {
44
+ // Match leading `./scrapbook/<filename>` or `scrapbook/<filename>`.
45
+ // Don't rewrite absolute URLs (`http://`, `https://`, `/api/...`),
46
+ // anchor links (`#...`), data URIs (`data:...`), or paths into a
47
+ // sibling directory other than scrapbook.
48
+ const m = src.match(/^(?:\.\/)?scrapbook\/([^/?#]+)$/);
49
+ if (!m) return null;
50
+ const filename = m[1];
51
+ return `${baseUrl}&name=${encodeURIComponent(filename)}`;
52
+ }
53
+
54
+ return function transformer(tree) {
55
+ visit(tree, 'element', (node) => {
56
+ if (!node || node.tagName !== 'img') return;
57
+ if (!node.properties || typeof node.properties.src !== 'string') return;
58
+ const newSrc = rewrite(node.properties.src);
59
+ if (newSrc) node.properties.src = newSrc;
60
+ });
61
+ };
62
+ }
63
+
64
+ /**
65
+ * Minimal hast visitor — walks every node depth-first, calls visitor
66
+ * for nodes whose `type` matches.
67
+ *
68
+ * @param {any} tree
69
+ * @param {string} typeFilter
70
+ * @param {(node: any) => void} fn
71
+ */
72
+ function visit(tree, typeFilter, fn) {
73
+ if (!tree) return;
74
+ if (tree.type === typeFilter) fn(tree);
75
+ if (Array.isArray(tree.children)) {
76
+ for (const child of tree.children) visit(child, typeFilter, fn);
77
+ }
78
+ }
@@ -14,6 +14,16 @@
14
14
  * the review surface needs the outline visible for annotate-and-iterate
15
15
  * work.
16
16
  */
17
+ /** Optional rendering context. When the renderer is invoked from a
18
+ * surface that has an entry binding (e.g. the studio's review surface),
19
+ * pass `{ entryId, site }` to enable rewriting of relative
20
+ * `./scrapbook/<file>` image URLs to the absolute scrapbook-file route
21
+ * URL the studio serves. Other surfaces leave relative URLs alone so
22
+ * the markdown source stays portable across renderers. */
23
+ export interface RenderOptions {
24
+ readonly entryId?: string;
25
+ readonly site?: string;
26
+ }
17
27
  export interface ParsedDraft {
18
28
  /** Frontmatter values. Values are whatever YAML parses them to. */
19
29
  frontmatter: Record<string, unknown>;
@@ -23,5 +33,5 @@ export interface ParsedDraft {
23
33
  /** Split a draft into its frontmatter and body. */
24
34
  export declare function parseDraftFrontmatter(markdown: string): ParsedDraft;
25
35
  /** Render a markdown string as HTML. */
26
- export declare function renderMarkdownToHtml(markdown: string): Promise<string>;
36
+ export declare function renderMarkdownToHtml(markdown: string, options?: RenderOptions): Promise<string>;
27
37
  //# sourceMappingURL=render.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/review/render.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAYH,MAAM,WAAW,WAAW;IAC1B,mEAAmE;IACnE,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAC;CACd;AAED,mDAAmD;AACnD,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,CAGnE;AAED,wCAAwC;AACxC,wBAAsB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAS5E"}
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/review/render.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAeH;;;;;2DAK2D;AAC3D,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,mEAAmE;IACnE,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAC;CACd;AAED,mDAAmD;AACnD,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,CAGnE;AAED,wCAAwC;AACxC,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,MAAM,CAAC,CA6BjB"}
@@ -16,6 +16,7 @@
16
16
  */
17
17
  import { unified } from 'unified';
18
18
  import remarkParse from 'remark-parse';
19
+ import remarkGfm from 'remark-gfm';
19
20
  import remarkRehype from 'remark-rehype';
20
21
  import rehypeStringify from 'rehype-stringify';
21
22
  import { parseFrontmatter } from "../frontmatter.js";
@@ -23,20 +24,41 @@ import { parseFrontmatter } from "../frontmatter.js";
23
24
  import remarkImageFigure from '../remark-image-figure.mjs';
24
25
  // @ts-expect-error — JS module without a .d.ts; the plugin is plain mdast traversal.
25
26
  import remarkStripFirstH1 from '../remark-strip-first-h1.mjs';
27
+ // @ts-expect-error — JS module without a .d.ts; the plugin is a plain hast visitor.
28
+ import rehypeRewriteScrapbookImages from '../rehype-rewrite-scrapbook-images.mjs';
26
29
  /** Split a draft into its frontmatter and body. */
27
30
  export function parseDraftFrontmatter(markdown) {
28
31
  const { data, body } = parseFrontmatter(markdown);
29
32
  return { frontmatter: data, body };
30
33
  }
31
34
  /** Render a markdown string as HTML. */
32
- export async function renderMarkdownToHtml(markdown) {
33
- const result = await unified()
35
+ export async function renderMarkdownToHtml(markdown, options = {}) {
36
+ // remark-gfm adds GitHub Flavored Markdown — tables, strikethrough,
37
+ // task lists, footnotes, autolinks. Operator-authored content
38
+ // routinely uses tables (audit docs, comparison matrices); without
39
+ // gfm those rendered as raw `| col | col |` text on the review
40
+ // surface.
41
+ // Studio-surface scrapbook URL rewrite — only fires when both
42
+ // `entryId` and `site` are provided. The markdown source is expected
43
+ // to use portable relative URLs like `./scrapbook/<file>`; the
44
+ // rewrite produces the absolute scrapbook-file route URL that the
45
+ // studio serves at runtime. Other call sites (published-site
46
+ // rendering, tests with no entry binding) leave the relative URLs
47
+ // alone so the markdown stays renderable in GitHub / VS Code / any
48
+ // other markdown viewer.
49
+ const studioRewrite = options.entryId && options.site
50
+ ? { entryId: options.entryId, site: options.site }
51
+ : null;
52
+ const base = unified()
34
53
  .use(remarkParse)
54
+ .use(remarkGfm)
35
55
  .use(remarkStripFirstH1)
36
56
  .use(remarkImageFigure)
37
- .use(remarkRehype)
38
- .use(rehypeStringify)
39
- .process(markdown);
57
+ .use(remarkRehype);
58
+ const withRewrite = studioRewrite
59
+ ? base.use(rehypeRewriteScrapbookImages, studioRewrite)
60
+ : base;
61
+ const result = await withRewrite.use(rehypeStringify).process(markdown);
40
62
  return String(result);
41
63
  }
42
64
  //# sourceMappingURL=render.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/review/render.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,WAAW,MAAM,cAAc,CAAC;AACvC,OAAO,YAAY,MAAM,eAAe,CAAC;AACzC,OAAO,eAAe,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,qFAAqF;AACrF,OAAO,iBAAiB,MAAM,4BAA4B,CAAC;AAC3D,qFAAqF;AACrF,OAAO,kBAAkB,MAAM,8BAA8B,CAAC;AAS9D,mDAAmD;AACnD,MAAM,UAAU,qBAAqB,CAAC,QAAgB;IACpD,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAClD,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AACrC,CAAC;AAED,wCAAwC;AACxC,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,QAAgB;IACzD,MAAM,MAAM,GAAG,MAAM,OAAO,EAAE;SAC3B,GAAG,CAAC,WAAW,CAAC;SAChB,GAAG,CAAC,kBAAkB,CAAC;SACvB,GAAG,CAAC,iBAAiB,CAAC;SACtB,GAAG,CAAC,YAAY,CAAC;SACjB,GAAG,CAAC,eAAe,CAAC;SACpB,OAAO,CAAC,QAAQ,CAAC,CAAC;IACrB,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC;AACxB,CAAC"}
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/review/render.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,WAAW,MAAM,cAAc,CAAC;AACvC,OAAO,SAAS,MAAM,YAAY,CAAC;AACnC,OAAO,YAAY,MAAM,eAAe,CAAC;AACzC,OAAO,eAAe,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,qFAAqF;AACrF,OAAO,iBAAiB,MAAM,4BAA4B,CAAC;AAC3D,qFAAqF;AACrF,OAAO,kBAAkB,MAAM,8BAA8B,CAAC;AAC9D,oFAAoF;AACpF,OAAO,4BAA4B,MAAM,wCAAwC,CAAC;AAoBlF,mDAAmD;AACnD,MAAM,UAAU,qBAAqB,CAAC,QAAgB;IACpD,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAClD,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AACrC,CAAC;AAED,wCAAwC;AACxC,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,QAAgB,EAChB,UAAyB,EAAE;IAE3B,oEAAoE;IACpE,8DAA8D;IAC9D,mEAAmE;IACnE,+DAA+D;IAC/D,WAAW;IACX,8DAA8D;IAC9D,qEAAqE;IACrE,+DAA+D;IAC/D,kEAAkE;IAClE,6DAA6D;IAC7D,kEAAkE;IAClE,mEAAmE;IACnE,yBAAyB;IACzB,MAAM,aAAa,GACjB,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,IAAI;QAC7B,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE;QAClD,CAAC,CAAC,IAAI,CAAC;IACX,MAAM,IAAI,GAAG,OAAO,EAAE;SACnB,GAAG,CAAC,WAAW,CAAC;SAChB,GAAG,CAAC,SAAS,CAAC;SACd,GAAG,CAAC,kBAAkB,CAAC;SACvB,GAAG,CAAC,iBAAiB,CAAC;SACtB,GAAG,CAAC,YAAY,CAAC,CAAC;IACrB,MAAM,WAAW,GAAG,aAAa;QAC/B,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,4BAA4B,EAAE,aAAa,CAAC;QACvD,CAAC,CAAC,IAAI,CAAC;IACT,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACxE,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC;AACxB,CAAC"}
@@ -31,31 +31,31 @@ export declare const DraftAnnotationSchema: z.ZodDiscriminatedUnion<"type", [z.Z
31
31
  workflowId: z.ZodString;
32
32
  id: z.ZodString;
33
33
  }, "strip", z.ZodTypeAny, {
34
+ id: string;
34
35
  type: "comment";
35
36
  version: number;
37
+ createdAt: string;
38
+ workflowId: string;
36
39
  range: {
37
40
  start: number;
38
41
  end: number;
39
42
  };
40
43
  text: string;
41
- createdAt: string;
42
- workflowId: string;
43
- id: string;
44
- category?: "voice-drift" | "missing-receipt" | "tutorial-framing" | "saas-vocabulary" | "fake-authority" | "structural" | "other" | undefined;
45
44
  anchor?: string | undefined;
45
+ category?: "other" | "voice-drift" | "missing-receipt" | "tutorial-framing" | "saas-vocabulary" | "fake-authority" | "structural" | undefined;
46
46
  }, {
47
+ id: string;
47
48
  type: "comment";
48
49
  version: number;
50
+ createdAt: string;
51
+ workflowId: string;
49
52
  range: {
50
53
  start: number;
51
54
  end: number;
52
55
  };
53
56
  text: string;
54
- createdAt: string;
55
- workflowId: string;
56
- id: string;
57
- category?: "voice-drift" | "missing-receipt" | "tutorial-framing" | "saas-vocabulary" | "fake-authority" | "structural" | "other" | undefined;
58
57
  anchor?: string | undefined;
58
+ category?: "other" | "voice-drift" | "missing-receipt" | "tutorial-framing" | "saas-vocabulary" | "fake-authority" | "structural" | undefined;
59
59
  }>, z.ZodObject<{
60
60
  type: z.ZodLiteral<"edit">;
61
61
  beforeVersion: z.ZodNumber;
@@ -65,18 +65,18 @@ export declare const DraftAnnotationSchema: z.ZodDiscriminatedUnion<"type", [z.Z
65
65
  workflowId: z.ZodString;
66
66
  id: z.ZodString;
67
67
  }, "strip", z.ZodTypeAny, {
68
+ id: string;
68
69
  type: "edit";
69
70
  createdAt: string;
70
71
  workflowId: string;
71
- id: string;
72
72
  beforeVersion: number;
73
73
  afterMarkdown: string;
74
74
  diff: string;
75
75
  }, {
76
+ id: string;
76
77
  type: "edit";
77
78
  createdAt: string;
78
79
  workflowId: string;
79
- id: string;
80
80
  beforeVersion: number;
81
81
  afterMarkdown: string;
82
82
  diff: string;
@@ -87,17 +87,17 @@ export declare const DraftAnnotationSchema: z.ZodDiscriminatedUnion<"type", [z.Z
87
87
  workflowId: z.ZodString;
88
88
  id: z.ZodString;
89
89
  }, "strip", z.ZodTypeAny, {
90
+ id: string;
90
91
  type: "approve";
91
92
  version: number;
92
93
  createdAt: string;
93
94
  workflowId: string;
94
- id: string;
95
95
  }, {
96
+ id: string;
96
97
  type: "approve";
97
98
  version: number;
98
99
  createdAt: string;
99
100
  workflowId: string;
100
- id: string;
101
101
  }>, z.ZodObject<{
102
102
  type: z.ZodLiteral<"reject">;
103
103
  version: z.ZodNumber;
@@ -106,18 +106,18 @@ export declare const DraftAnnotationSchema: z.ZodDiscriminatedUnion<"type", [z.Z
106
106
  workflowId: z.ZodString;
107
107
  id: z.ZodString;
108
108
  }, "strip", z.ZodTypeAny, {
109
+ id: string;
109
110
  type: "reject";
110
111
  version: number;
111
112
  createdAt: string;
112
113
  workflowId: string;
113
- id: string;
114
114
  reason?: string | undefined;
115
115
  }, {
116
+ id: string;
116
117
  type: "reject";
117
118
  version: number;
118
119
  createdAt: string;
119
120
  workflowId: string;
120
- id: string;
121
121
  reason?: string | undefined;
122
122
  }>, z.ZodObject<{
123
123
  type: z.ZodLiteral<"resolve">;
@@ -127,17 +127,17 @@ export declare const DraftAnnotationSchema: z.ZodDiscriminatedUnion<"type", [z.Z
127
127
  workflowId: z.ZodString;
128
128
  id: z.ZodString;
129
129
  }, "strip", z.ZodTypeAny, {
130
+ id: string;
130
131
  type: "resolve";
131
132
  createdAt: string;
132
133
  workflowId: string;
133
- id: string;
134
134
  commentId: string;
135
135
  resolved: boolean;
136
136
  }, {
137
+ id: string;
137
138
  type: "resolve";
138
139
  createdAt: string;
139
140
  workflowId: string;
140
- id: string;
141
141
  commentId: string;
142
142
  resolved: boolean;
143
143
  }>, z.ZodObject<{
@@ -150,20 +150,20 @@ export declare const DraftAnnotationSchema: z.ZodDiscriminatedUnion<"type", [z.Z
150
150
  workflowId: z.ZodString;
151
151
  id: z.ZodString;
152
152
  }, "strip", z.ZodTypeAny, {
153
+ id: string;
153
154
  type: "address";
154
155
  version: number;
155
156
  createdAt: string;
156
157
  workflowId: string;
157
- id: string;
158
158
  commentId: string;
159
159
  disposition: "addressed" | "deferred" | "wontfix";
160
160
  reason?: string | undefined;
161
161
  }, {
162
+ id: string;
162
163
  type: "address";
163
164
  version: number;
164
165
  createdAt: string;
165
166
  workflowId: string;
166
- id: string;
167
167
  commentId: string;
168
168
  disposition: "addressed" | "deferred" | "wontfix";
169
169
  reason?: string | undefined;