@deskwork/studio 0.13.0 → 0.14.1
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/pages/content-detail.d.ts.map +1 -1
- package/dist/pages/content-detail.js +5 -4
- package/dist/pages/content-detail.js.map +1 -1
- package/dist/pages/content-detail.ts +5 -4
- package/dist/pages/content.d.ts.map +1 -1
- package/dist/pages/content.js +4 -6
- package/dist/pages/content.js.map +1 -1
- package/dist/pages/content.ts +4 -6
- package/dist/pages/dashboard/affordances.d.ts +6 -1
- package/dist/pages/dashboard/affordances.d.ts.map +1 -1
- package/dist/pages/dashboard/affordances.js +17 -2
- package/dist/pages/dashboard/affordances.js.map +1 -1
- package/dist/pages/dashboard/affordances.ts +18 -2
- package/dist/pages/dashboard/header.js +2 -2
- package/dist/pages/dashboard/header.ts +2 -2
- package/dist/pages/dashboard/section.d.ts +2 -2
- package/dist/pages/dashboard/section.d.ts.map +1 -1
- package/dist/pages/dashboard/section.js +5 -5
- package/dist/pages/dashboard/section.js.map +1 -1
- package/dist/pages/dashboard/section.ts +9 -5
- package/dist/pages/dashboard.d.ts.map +1 -1
- package/dist/pages/dashboard.js +3 -2
- package/dist/pages/dashboard.js.map +1 -1
- package/dist/pages/dashboard.ts +3 -2
- package/dist/pages/entry-review/data.d.ts +54 -0
- package/dist/pages/entry-review/data.d.ts.map +1 -0
- package/dist/pages/entry-review/data.js +116 -0
- package/dist/pages/entry-review/data.js.map +1 -0
- package/dist/pages/entry-review/decision-strip.d.ts +37 -0
- package/dist/pages/entry-review/decision-strip.d.ts.map +1 -0
- package/dist/pages/entry-review/decision-strip.js +137 -0
- package/dist/pages/entry-review/decision-strip.js.map +1 -0
- package/dist/pages/entry-review/edit-panes.d.ts +12 -0
- package/dist/pages/entry-review/edit-panes.d.ts.map +1 -0
- package/dist/pages/entry-review/edit-panes.js +28 -0
- package/dist/pages/entry-review/edit-panes.js.map +1 -0
- package/dist/pages/entry-review/edit-toolbar.d.ts +20 -0
- package/dist/pages/entry-review/edit-toolbar.d.ts.map +1 -0
- package/dist/pages/entry-review/edit-toolbar.js +46 -0
- package/dist/pages/entry-review/edit-toolbar.js.map +1 -0
- package/dist/pages/entry-review/index.d.ts +50 -0
- package/dist/pages/entry-review/index.d.ts.map +1 -0
- package/dist/pages/entry-review/index.js +219 -0
- package/dist/pages/entry-review/index.js.map +1 -0
- package/dist/pages/entry-review/marginalia.d.ts +28 -0
- package/dist/pages/entry-review/marginalia.d.ts.map +1 -0
- package/dist/pages/entry-review/marginalia.js +67 -0
- package/dist/pages/entry-review/marginalia.js.map +1 -0
- package/dist/pages/entry-review/not-found.d.ts +9 -0
- package/dist/pages/entry-review/not-found.d.ts.map +1 -0
- package/dist/pages/entry-review/not-found.js +34 -0
- package/dist/pages/entry-review/not-found.js.map +1 -0
- package/dist/pages/entry-review/outline-drawer.d.ts +12 -0
- package/dist/pages/entry-review/outline-drawer.d.ts.map +1 -0
- package/dist/pages/entry-review/outline-drawer.js +28 -0
- package/dist/pages/entry-review/outline-drawer.js.map +1 -0
- package/dist/pages/entry-review/shortcuts.d.ts +14 -0
- package/dist/pages/entry-review/shortcuts.d.ts.map +1 -0
- package/dist/pages/entry-review/shortcuts.js +36 -0
- package/dist/pages/entry-review/shortcuts.js.map +1 -0
- package/dist/pages/entry-review/version-strip.d.ts +33 -0
- package/dist/pages/entry-review/version-strip.d.ts.map +1 -0
- package/dist/pages/entry-review/version-strip.js +81 -0
- package/dist/pages/entry-review/version-strip.js.map +1 -0
- package/dist/pages/entry-review.d.ts +6 -21
- package/dist/pages/entry-review.d.ts.map +1 -1
- package/dist/pages/entry-review.js +6 -144
- package/dist/pages/entry-review.js.map +1 -1
- package/dist/pages/entry-review.ts +11 -181
- package/dist/pages/index.d.ts.map +1 -1
- package/dist/pages/index.js +6 -10
- package/dist/pages/index.js.map +1 -1
- package/dist/pages/index.ts +6 -10
- package/dist/pages/scrapbook.d.ts.map +1 -1
- package/dist/pages/scrapbook.js +208 -11
- package/dist/pages/scrapbook.js.map +1 -1
- package/dist/pages/scrapbook.ts +209 -10
- package/dist/pages/shortform-review.d.ts +32 -0
- package/dist/pages/shortform-review.d.ts.map +1 -0
- package/dist/pages/shortform-review.js +270 -0
- package/dist/pages/shortform-review.js.map +1 -0
- package/dist/pages/shortform-review.ts +342 -0
- package/dist/routes/api.d.ts +8 -0
- package/dist/routes/api.d.ts.map +1 -1
- package/dist/routes/api.js +115 -0
- package/dist/routes/api.js.map +1 -1
- package/dist/routes/entry-annotation-body.d.ts +26 -0
- package/dist/routes/entry-annotation-body.d.ts.map +1 -0
- package/dist/routes/entry-annotation-body.js +152 -0
- package/dist/routes/entry-annotation-body.js.map +1 -0
- package/dist/server.d.ts +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +56 -193
- 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
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Top-level renderer for the entry-keyed press-check surface
|
|
3
|
+
* (Phase 34a Layer 2 — `/dev/editorial-review/entry/<uuid>`).
|
|
4
|
+
*
|
|
5
|
+
* Wires every chrome component (folio, version strip, edit toolbar,
|
|
6
|
+
* edit panes, outline drawer, marginalia column + tab, decision strip,
|
|
7
|
+
* scrapbook drawer, shortcuts overlay, rendered preview) against the
|
|
8
|
+
* entry-keyed Layer 1 data layer (sidecar + history-journal iterations
|
|
9
|
+
* + entry-keyed annotations).
|
|
10
|
+
*
|
|
11
|
+
* The relocated chrome shares the existing `editorial-review.css`
|
|
12
|
+
* stylesheet with the legacy longform surface — the chrome IS the
|
|
13
|
+
* existing chrome being relocated. The body data attribute is
|
|
14
|
+
* `data-review-ui="longform"` so the existing `er-*` rules in
|
|
15
|
+
* editorial-review.css cascade correctly.
|
|
16
|
+
*
|
|
17
|
+
* `entry-review.css` (the existing per-stage controller stylesheet)
|
|
18
|
+
* stays linked because the 404 not-found variant + future per-entry
|
|
19
|
+
* affordance polish lives there. The two class families coexist —
|
|
20
|
+
* `.er-*` from the relocated chrome and `.er-entry-*` from the stage
|
|
21
|
+
* controller — without collision.
|
|
22
|
+
*
|
|
23
|
+
* The StudioContext threads through so the scrapbook drawer can
|
|
24
|
+
* resolve the entry's site + content index (per-request memoized via
|
|
25
|
+
* `getRequestContentIndex`).
|
|
26
|
+
*/
|
|
27
|
+
import { existsSync } from 'node:fs';
|
|
28
|
+
import { parseDraftFrontmatter, renderMarkdownToHtml, } from '@deskwork/core/review/render';
|
|
29
|
+
import { splitOutline } from '@deskwork/core/outline-split';
|
|
30
|
+
import { resolveCalendarPath } from '@deskwork/core/paths';
|
|
31
|
+
import { readCalendar } from '@deskwork/core/calendar';
|
|
32
|
+
import { findEntryById } from '@deskwork/core/calendar-mutations';
|
|
33
|
+
import { getAffordances } from "../../lib/stage-affordances.js";
|
|
34
|
+
import { html, unsafe, escapeHtml, gloss } from "../html.js";
|
|
35
|
+
import { layout } from "../layout.js";
|
|
36
|
+
import { renderEditorialFolio } from "../chrome.js";
|
|
37
|
+
import { renderScrapbookDrawer } from "../review-scrapbook-drawer.js";
|
|
38
|
+
import { loadEntryReviewData } from "./data.js";
|
|
39
|
+
import { renderVersionsStrip } from "./version-strip.js";
|
|
40
|
+
import { renderEditToolbar } from "./edit-toolbar.js";
|
|
41
|
+
import { renderEditPanes } from "./edit-panes.js";
|
|
42
|
+
import { renderOutlineDrawer } from "./outline-drawer.js";
|
|
43
|
+
import { renderMarginalia, renderMarginaliaTab } from "./marginalia.js";
|
|
44
|
+
import { renderDecisionStrip } from "./decision-strip.js";
|
|
45
|
+
import { renderShortcutsOverlay } from "./shortcuts.js";
|
|
46
|
+
import { renderEntryNotFound } from "./not-found.js";
|
|
47
|
+
function stringField(v) {
|
|
48
|
+
return typeof v === 'string' ? v : undefined;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Prepare the article body + the optional outline drawer content. Mirrors
|
|
52
|
+
* `pages/review.ts:prepareRender` but without the workflow-keyed
|
|
53
|
+
* contentKind switch — the entry-keyed surface is always longform-shaped
|
|
54
|
+
* (shortform stays on its own retirement track).
|
|
55
|
+
*/
|
|
56
|
+
async function prepareRender(markdown) {
|
|
57
|
+
const parsed = parseDraftFrontmatter(markdown);
|
|
58
|
+
const fm = parsed.frontmatter;
|
|
59
|
+
const split = splitOutline(parsed.body);
|
|
60
|
+
const bodyHtml = await renderMarkdownToHtml(split.body);
|
|
61
|
+
// Inject the description as a dek after the body's first <h1>.
|
|
62
|
+
const description = stringField(fm.description);
|
|
63
|
+
const dekHtml = description
|
|
64
|
+
? `<p class="er-dispatch-dek">${escapeHtml(description)}</p>`
|
|
65
|
+
: '';
|
|
66
|
+
const h1Close = bodyHtml.indexOf('</h1>');
|
|
67
|
+
const renderedHtml = dekHtml && h1Close >= 0
|
|
68
|
+
? bodyHtml.slice(0, h1Close + 5) + dekHtml + bodyHtml.slice(h1Close + 5)
|
|
69
|
+
: dekHtml + bodyHtml;
|
|
70
|
+
const outlineHtml = split.outline
|
|
71
|
+
? await renderMarkdownToHtml(split.outline)
|
|
72
|
+
: '';
|
|
73
|
+
return { fm, bodyHtml: renderedHtml, outlineHtml };
|
|
74
|
+
}
|
|
75
|
+
function buildState(data) {
|
|
76
|
+
const stage = data.entry.currentStage;
|
|
77
|
+
const currentVersion = data.entry.iterationByStage[stage] ?? null;
|
|
78
|
+
return {
|
|
79
|
+
entryId: data.entry.uuid,
|
|
80
|
+
slug: data.entry.slug,
|
|
81
|
+
site: data.site,
|
|
82
|
+
currentStage: stage,
|
|
83
|
+
currentVersion,
|
|
84
|
+
markdown: data.markdown,
|
|
85
|
+
historical: data.historical !== null,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* The entry's site, surfaced through the `EntryReviewData` resolver,
|
|
90
|
+
* may not match the calendar entry shape the scrapbook drawer expects
|
|
91
|
+
* — the drawer accepts a CalendarEntry-shaped object directly. When the
|
|
92
|
+
* entry is found in a configured calendar, we pass it through; otherwise
|
|
93
|
+
* the drawer falls back to slug-template path resolution.
|
|
94
|
+
*/
|
|
95
|
+
function lookupCalendarEntryStrict(ctx, site, entryId) {
|
|
96
|
+
try {
|
|
97
|
+
const calendarPath = resolveCalendarPath(ctx.projectRoot, ctx.config, site);
|
|
98
|
+
if (!existsSync(calendarPath))
|
|
99
|
+
return null;
|
|
100
|
+
const cal = readCalendar(calendarPath);
|
|
101
|
+
const found = findEntryById(cal, entryId);
|
|
102
|
+
return found ?? null;
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Render the entry-keyed press-check surface for `entryId`. Returns a
|
|
110
|
+
* 404 shell when the sidecar can't be resolved; otherwise renders the
|
|
111
|
+
* full press-check chrome backed by Layer 1's data layer.
|
|
112
|
+
*/
|
|
113
|
+
export async function renderEntryReviewPage(ctx, entryId, query = {}, getIndex) {
|
|
114
|
+
let data;
|
|
115
|
+
try {
|
|
116
|
+
data = await loadEntryReviewData(ctx, entryId, {
|
|
117
|
+
version: query.version ?? null,
|
|
118
|
+
stage: query.stage ?? null,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
catch (err) {
|
|
122
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
123
|
+
return { status: 404, html: renderEntryNotFound(entryId, reason) };
|
|
124
|
+
}
|
|
125
|
+
const { fm, bodyHtml, outlineHtml } = await prepareRender(data.markdown);
|
|
126
|
+
const affordances = getAffordances(data.entry);
|
|
127
|
+
const state = buildState(data);
|
|
128
|
+
const titleField = stringField(fm.title) ?? `Draft: ${data.entry.slug}`;
|
|
129
|
+
// Calendar-entry lookup for the scrapbook drawer. The data loader
|
|
130
|
+
// already attempted this; we re-derive the strict CalendarEntry here
|
|
131
|
+
// because the drawer's signature wants the wider type.
|
|
132
|
+
const reviewEntry = data.calendarEntry !== null
|
|
133
|
+
? data.calendarEntry
|
|
134
|
+
: lookupCalendarEntryStrict(ctx, data.site, entryId);
|
|
135
|
+
const reviewIndex = getIndex ? getIndex(data.site) : undefined;
|
|
136
|
+
// Pick a folio spine label that names the entry concisely. The
|
|
137
|
+
// legacy surface used `longform · <slug>`; preserve it so the
|
|
138
|
+
// visual signature stays continuous with the existing chrome.
|
|
139
|
+
const folioSpine = `longform · ${data.entry.slug}`;
|
|
140
|
+
const stageLabel = data.entry.currentStage;
|
|
141
|
+
const historicalBadge = data.historical
|
|
142
|
+
? unsafe(html `<span class="er-strip-historical" title="Historical version (read-only)">historical · v${data.historical.versionNumber}</span>`)
|
|
143
|
+
: unsafe('');
|
|
144
|
+
// The page-grid composes the article column + the marginalia rail.
|
|
145
|
+
// Mirrors the legacy longform layout (`.er-page-grid` with the
|
|
146
|
+
// `.er-draft-frame` + `.er-page-gutter` + `.er-marginalia` triplet).
|
|
147
|
+
const pageGrid = html `
|
|
148
|
+
<div class="er-page-grid">
|
|
149
|
+
<div class="er-draft-frame">
|
|
150
|
+
<div id="draft-body" data-draft-body
|
|
151
|
+
title="Double-click to edit · select text to leave a margin note">${unsafe(bodyHtml)}</div>
|
|
152
|
+
${renderEditPanes()}
|
|
153
|
+
</div>
|
|
154
|
+
<div class="er-page-gutter" aria-hidden="true"></div>
|
|
155
|
+
${renderMarginalia()}
|
|
156
|
+
</div>`;
|
|
157
|
+
const scrapbookDrawer = renderScrapbookDrawer(ctx, data.site, reviewEntry, data.entry.slug, reviewIndex);
|
|
158
|
+
const versionStrip = renderVersionsStrip({
|
|
159
|
+
iterations: data.iterations,
|
|
160
|
+
entry: data.entry,
|
|
161
|
+
historicalVersion: data.historical?.versionNumber ?? null,
|
|
162
|
+
historicalStage: data.historical?.stage ?? null,
|
|
163
|
+
});
|
|
164
|
+
const decisionStrip = renderDecisionStrip({
|
|
165
|
+
entry: data.entry,
|
|
166
|
+
affordances,
|
|
167
|
+
historical: data.historical !== null,
|
|
168
|
+
});
|
|
169
|
+
const body = html `
|
|
170
|
+
<div data-review-ui="longform" class="er-review-shell">
|
|
171
|
+
${renderEditorialFolio('longform', folioSpine)}
|
|
172
|
+
<div class="er-strip">
|
|
173
|
+
<div class="er-strip-inner">
|
|
174
|
+
<a class="er-strip-back" href="/dev/editorial-studio" title="Back to the editorial studio">← studio</a>
|
|
175
|
+
<span class="er-strip-galley">${gloss('galley')} <em>№ ${state.currentVersion ?? '—'}</em></span>
|
|
176
|
+
<span class="er-strip-slug">${data.site} / ${data.entry.slug}</span>
|
|
177
|
+
${versionStrip}
|
|
178
|
+
<span class="er-strip-center">
|
|
179
|
+
<span class="er-stamp er-stamp-big er-stamp-${stageLabel.toLowerCase()}" data-state-label data-stage="${stageLabel}">
|
|
180
|
+
${stageLabel}
|
|
181
|
+
</span>
|
|
182
|
+
${historicalBadge}
|
|
183
|
+
<span class="er-strip-hint">select text to <span class="er-gloss" data-term="marginalia" tabindex="0" role="button" aria-describedby="glossary-marginalia">mark</span> · double-click to edit · <kbd>?</kbd> for shortcuts</span>
|
|
184
|
+
</span>
|
|
185
|
+
${decisionStrip}
|
|
186
|
+
</div>
|
|
187
|
+
</div>
|
|
188
|
+
${renderEditToolbar(outlineHtml.length > 0)}
|
|
189
|
+
<article class="er-page" data-entry-uuid="${data.entry.uuid}">
|
|
190
|
+
${unsafe(pageGrid)}
|
|
191
|
+
</article>
|
|
192
|
+
${renderMarginaliaTab()}
|
|
193
|
+
<button class="er-pencil-btn" data-add-comment-btn hidden type="button">Mark</button>
|
|
194
|
+
${renderOutlineDrawer(outlineHtml)}
|
|
195
|
+
${scrapbookDrawer}
|
|
196
|
+
<div class="er-toast" data-toast hidden></div>
|
|
197
|
+
${renderShortcutsOverlay()}
|
|
198
|
+
<div class="er-poll-indicator" data-poll>auto-refresh · 8s</div>
|
|
199
|
+
</div>`;
|
|
200
|
+
return {
|
|
201
|
+
status: 200,
|
|
202
|
+
html: layout({
|
|
203
|
+
title: `${titleField} — Review`,
|
|
204
|
+
cssHrefs: [
|
|
205
|
+
'/static/css/editorial-review.css',
|
|
206
|
+
'/static/css/editorial-nav.css',
|
|
207
|
+
'/static/css/entry-review.css',
|
|
208
|
+
'/static/css/blog-figure.css',
|
|
209
|
+
'/static/css/review-viewport.css',
|
|
210
|
+
'/static/css/scrap-row.css',
|
|
211
|
+
],
|
|
212
|
+
bodyAttrs: 'data-review-ui="entry-review"',
|
|
213
|
+
bodyHtml: body,
|
|
214
|
+
embeddedJson: [{ id: 'entry-review-state', data: state }],
|
|
215
|
+
scriptModules: ['entry-review-client'],
|
|
216
|
+
}),
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/pages/entry-review/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EACL,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAE5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAElE,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAEhE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAgB,MAAM,YAAY,CAAC;AAC3E,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAwB,MAAM,WAAW,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACxE,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AA0BrD,SAAS,WAAW,CAAC,CAAU;IAC7B,OAAO,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC/C,CAAC;AAED;;;;;GAKG;AACH,KAAK,UAAU,aAAa,CAAC,QAAgB;IAC3C,MAAM,MAAM,GAAG,qBAAqB,CAAC,QAAQ,CAAC,CAAC;IAC/C,MAAM,EAAE,GAAG,MAAM,CAAC,WAAW,CAAC;IAE9B,MAAM,KAAK,GAAG,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACxC,MAAM,QAAQ,GAAG,MAAM,oBAAoB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAExD,+DAA+D;IAC/D,MAAM,WAAW,GAAG,WAAW,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC;IAChD,MAAM,OAAO,GAAG,WAAW;QACzB,CAAC,CAAC,8BAA8B,UAAU,CAAC,WAAW,CAAC,MAAM;QAC7D,CAAC,CAAC,EAAE,CAAC;IACP,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1C,MAAM,YAAY,GAChB,OAAO,IAAI,OAAO,IAAI,CAAC;QACrB,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,CAAC,GAAG,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC;QACxE,CAAC,CAAC,OAAO,GAAG,QAAQ,CAAC;IAEzB,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO;QAC/B,CAAC,CAAC,MAAM,oBAAoB,CAAC,KAAK,CAAC,OAAO,CAAC;QAC3C,CAAC,CAAC,EAAE,CAAC;IAEP,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,YAAY,EAAE,WAAW,EAAE,CAAC;AACrD,CAAC;AAoBD,SAAS,UAAU,CAAC,IAAqB;IACvC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC;IACtC,MAAM,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC;IAClE,OAAO;QACL,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI;QACxB,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI;QACrB,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,YAAY,EAAE,KAAK;QACnB,cAAc;QACd,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,UAAU,EAAE,IAAI,CAAC,UAAU,KAAK,IAAI;KACrC,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,SAAS,yBAAyB,CAChC,GAAkB,EAClB,IAAY,EACZ,OAAe;IAEf,IAAI,CAAC;QACH,MAAM,YAAY,GAAG,mBAAmB,CAAC,GAAG,CAAC,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC5E,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC;YAAE,OAAO,IAAI,CAAC;QAC3C,MAAM,GAAG,GAAG,YAAY,CAAC,YAAY,CAAC,CAAC;QACvC,MAAM,KAAK,GAAG,aAAa,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAC1C,OAAO,KAAK,IAAI,IAAI,CAAC;IACvB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,GAAkB,EAClB,OAAe,EACf,QAA0B,EAAE,EAC5B,QAAiC;IAEjC,IAAI,IAAqB,CAAC;IAC1B,IAAI,CAAC;QACH,IAAI,GAAG,MAAM,mBAAmB,CAAC,GAAG,EAAE,OAAO,EAAE;YAC7C,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,IAAI;YAC9B,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,IAAI;SAC3B,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,MAAM,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAChE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,mBAAmB,CAAC,OAAO,EAAE,MAAM,CAAC,EAAE,CAAC;IACrE,CAAC;IAED,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACzE,MAAM,WAAW,GAAG,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC/C,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAC/B,MAAM,UAAU,GAAG,WAAW,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,UAAU,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;IAExE,kEAAkE;IAClE,qEAAqE;IACrE,uDAAuD;IACvD,MAAM,WAAW,GAAG,IAAI,CAAC,aAAa,KAAK,IAAI;QAC7C,CAAC,CAAC,IAAI,CAAC,aAAa;QACpB,CAAC,CAAC,yBAAyB,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACvD,MAAM,WAAW,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAE/D,+DAA+D;IAC/D,8DAA8D;IAC9D,8DAA8D;IAC9D,MAAM,UAAU,GAAG,cAAc,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;IACnD,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC;IAC3C,MAAM,eAAe,GAAG,IAAI,CAAC,UAAU;QACrC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAA,0FAA0F,IAAI,CAAC,UAAU,CAAC,aAAa,SAAS,CAAC;QAC9I,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAEf,mEAAmE;IACnE,+DAA+D;IAC/D,qEAAqE;IACrE,MAAM,QAAQ,GAAG,IAAI,CAAA;;;;8EAIuD,MAAM,CAAC,QAAQ,CAAC;UACpF,eAAe,EAAE;;;QAGnB,gBAAgB,EAAE;WACf,CAAC;IAEV,MAAM,eAAe,GAAY,qBAAqB,CACpD,GAAG,EACH,IAAI,CAAC,IAAI,EACT,WAAW,EACX,IAAI,CAAC,KAAK,CAAC,IAAI,EACf,WAAW,CACZ,CAAC;IAEF,MAAM,YAAY,GAAG,mBAAmB,CAAC;QACvC,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,iBAAiB,EAAE,IAAI,CAAC,UAAU,EAAE,aAAa,IAAI,IAAI;QACzD,eAAe,EAAE,IAAI,CAAC,UAAU,EAAE,KAAK,IAAI,IAAI;KAChD,CAAC,CAAC;IAEH,MAAM,aAAa,GAAG,mBAAmB,CAAC;QACxC,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,WAAW;QACX,UAAU,EAAE,IAAI,CAAC,UAAU,KAAK,IAAI;KACrC,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,IAAI,CAAA;;QAEX,oBAAoB,CAAC,UAAU,EAAE,UAAU,CAAC;;;;0CAIV,KAAK,CAAC,QAAQ,CAAC,UAAU,KAAK,CAAC,cAAc,IAAI,GAAG;wCACtD,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI;YAC1D,YAAY;;0DAEkC,UAAU,CAAC,WAAW,EAAE,kCAAkC,UAAU;gBAC9G,UAAU;;cAEZ,eAAe;;;YAGjB,aAAa;;;QAGjB,iBAAiB,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC;kDACC,IAAI,CAAC,KAAK,CAAC,IAAI;UACvD,MAAM,CAAC,QAAQ,CAAC;;QAElB,mBAAmB,EAAE;;QAErB,mBAAmB,CAAC,WAAW,CAAC;QAChC,eAAe;;QAEf,sBAAsB,EAAE;;WAErB,CAAC;IAEV,OAAO;QACL,MAAM,EAAE,GAAG;QACX,IAAI,EAAE,MAAM,CAAC;YACX,KAAK,EAAE,GAAG,UAAU,WAAW;YAC/B,QAAQ,EAAE;gBACR,kCAAkC;gBAClC,+BAA+B;gBAC/B,8BAA8B;gBAC9B,6BAA6B;gBAC7B,iCAAiC;gBACjC,2BAA2B;aAC5B;YACD,SAAS,EAAE,+BAA+B;YAC1C,QAAQ,EAAE,IAAI;YACd,YAAY,EAAE,CAAC,EAAE,EAAE,EAAE,oBAAoB,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;YACzD,aAAa,EAAE,CAAC,qBAAqB,CAAC;SACvC,CAAC;KACH,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Marginalia column + stow chevron + edge pull tab for the entry-keyed
|
|
3
|
+
* press-check surface (Phase 34a — T10).
|
|
4
|
+
*
|
|
5
|
+
* Relocated from `pages/review.ts`. Per `.claude/rules/affordance-placement.md`,
|
|
6
|
+
* the toggle for "show / hide the margin-notes column" lives ON the
|
|
7
|
+
* marginalia component:
|
|
8
|
+
*
|
|
9
|
+
* - `.er-marginalia-stow` chevron INSIDE the marginalia head — visible
|
|
10
|
+
* only when marginalia is visible (it's inside `.er-marginalia`,
|
|
11
|
+
* which is `display: none` when stowed).
|
|
12
|
+
* - `.er-marginalia-tab` pull tab on the right edge of the viewport,
|
|
13
|
+
* visible only when stowed (CSS rule `body[data-marginalia="hidden"]
|
|
14
|
+
* .er-marginalia-tab { display: block }`).
|
|
15
|
+
*
|
|
16
|
+
* Both affordances + Shift+M dispatch through the same client-side
|
|
17
|
+
* `toggleMarginalia` handler. Mirrors the outline-drawer's pull-tab
|
|
18
|
+
* pattern so the project's affordance vocabulary stays consistent.
|
|
19
|
+
*
|
|
20
|
+
* The marginalia composer + saved-mark list are populated by
|
|
21
|
+
* `entry-review-client.ts` after page load — the server emits the
|
|
22
|
+
* shell + the empty composer; the client fetches annotations from
|
|
23
|
+
* `/api/dev/editorial-review/entry/<uuid>/annotations` and renders.
|
|
24
|
+
*/
|
|
25
|
+
import { type RawHtml } from '../html.ts';
|
|
26
|
+
export declare function renderMarginaliaTab(): RawHtml;
|
|
27
|
+
export declare function renderMarginalia(): RawHtml;
|
|
28
|
+
//# sourceMappingURL=marginalia.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"marginalia.d.ts","sourceRoot":"","sources":["../../../src/pages/entry-review/marginalia.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAgB,KAAK,OAAO,EAAE,MAAM,YAAY,CAAC;AAExD,wBAAgB,mBAAmB,IAAI,OAAO,CAM7C;AAED,wBAAgB,gBAAgB,IAAI,OAAO,CAiC1C"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Marginalia column + stow chevron + edge pull tab for the entry-keyed
|
|
3
|
+
* press-check surface (Phase 34a — T10).
|
|
4
|
+
*
|
|
5
|
+
* Relocated from `pages/review.ts`. Per `.claude/rules/affordance-placement.md`,
|
|
6
|
+
* the toggle for "show / hide the margin-notes column" lives ON the
|
|
7
|
+
* marginalia component:
|
|
8
|
+
*
|
|
9
|
+
* - `.er-marginalia-stow` chevron INSIDE the marginalia head — visible
|
|
10
|
+
* only when marginalia is visible (it's inside `.er-marginalia`,
|
|
11
|
+
* which is `display: none` when stowed).
|
|
12
|
+
* - `.er-marginalia-tab` pull tab on the right edge of the viewport,
|
|
13
|
+
* visible only when stowed (CSS rule `body[data-marginalia="hidden"]
|
|
14
|
+
* .er-marginalia-tab { display: block }`).
|
|
15
|
+
*
|
|
16
|
+
* Both affordances + Shift+M dispatch through the same client-side
|
|
17
|
+
* `toggleMarginalia` handler. Mirrors the outline-drawer's pull-tab
|
|
18
|
+
* pattern so the project's affordance vocabulary stays consistent.
|
|
19
|
+
*
|
|
20
|
+
* The marginalia composer + saved-mark list are populated by
|
|
21
|
+
* `entry-review-client.ts` after page load — the server emits the
|
|
22
|
+
* shell + the empty composer; the client fetches annotations from
|
|
23
|
+
* `/api/dev/editorial-review/entry/<uuid>/annotations` and renders.
|
|
24
|
+
*/
|
|
25
|
+
import { html, unsafe } from "../html.js";
|
|
26
|
+
export function renderMarginaliaTab() {
|
|
27
|
+
return unsafe(html `
|
|
28
|
+
<button class="er-marginalia-tab" data-action="toggle-marginalia" type="button" aria-pressed="true" aria-label="Show margin notes (Shift+M)" title="Show margin notes (Shift+M)">
|
|
29
|
+
<span class="er-marginalia-tab-glyph" aria-hidden="true">‹</span>
|
|
30
|
+
<span class="er-marginalia-tab-label">Notes</span>
|
|
31
|
+
</button>`);
|
|
32
|
+
}
|
|
33
|
+
export function renderMarginalia() {
|
|
34
|
+
return unsafe(html `
|
|
35
|
+
<aside class="er-marginalia" data-comments-sidebar aria-label="Margin notes">
|
|
36
|
+
<p class="er-marginalia-head">
|
|
37
|
+
<button class="er-marginalia-stow" data-action="toggle-marginalia" type="button" aria-pressed="false" aria-label="Hide margin notes (Shift+M)" title="Hide margin notes (Shift+M)">
|
|
38
|
+
<span aria-hidden="true">›</span>
|
|
39
|
+
</button>
|
|
40
|
+
<span class="er-marginalia-head-label">Margin notes</span>
|
|
41
|
+
</p>
|
|
42
|
+
<p class="er-marginalia-empty" data-sidebar-empty>Select text in the draft to leave a <em>margin note</em>.</p>
|
|
43
|
+
<section class="er-marginalia-composer" data-comment-composer hidden aria-label="New margin note">
|
|
44
|
+
<p class="er-marginalia-composer-head">New mark</p>
|
|
45
|
+
<div class="er-marginalia-composer-quote" data-composer-quote></div>
|
|
46
|
+
<label class="er-marginalia-composer-label" for="comment-category">Mark as</label>
|
|
47
|
+
<select id="comment-category" class="er-marginalia-composer-select" data-comment-category>
|
|
48
|
+
<option value="other" selected>other</option>
|
|
49
|
+
<option value="voice-drift">voice-drift</option>
|
|
50
|
+
<option value="missing-receipt">missing-receipt</option>
|
|
51
|
+
<option value="tutorial-framing">tutorial-framing</option>
|
|
52
|
+
<option value="saas-vocabulary">saas-vocabulary</option>
|
|
53
|
+
<option value="fake-authority">fake-authority</option>
|
|
54
|
+
<option value="structural">structural</option>
|
|
55
|
+
</select>
|
|
56
|
+
<label class="er-marginalia-composer-label" for="comment-text">Note</label>
|
|
57
|
+
<textarea id="comment-text" class="er-marginalia-composer-textarea" data-comment-text rows="4"
|
|
58
|
+
placeholder="What needs attention here?"></textarea>
|
|
59
|
+
<div class="er-marginalia-composer-actions">
|
|
60
|
+
<button type="button" class="er-btn er-btn-small" data-action="cancel-comment">Cancel</button>
|
|
61
|
+
<button type="button" class="er-btn er-btn-small er-btn-primary" data-action="submit-comment">Leave mark</button>
|
|
62
|
+
</div>
|
|
63
|
+
</section>
|
|
64
|
+
<ol class="er-marginalia-list" data-sidebar-list></ol>
|
|
65
|
+
</aside>`);
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=marginalia.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"marginalia.js","sourceRoot":"","sources":["../../../src/pages/entry-review/marginalia.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,EAAgB,MAAM,YAAY,CAAC;AAExD,MAAM,UAAU,mBAAmB;IACjC,OAAO,MAAM,CAAC,IAAI,CAAA;;;;cAIN,CAAC,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,OAAO,MAAM,CAAC,IAAI,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aA+BP,CAAC,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 404 shell for the entry-keyed press-check surface (Phase 34a Layer 2).
|
|
3
|
+
*
|
|
4
|
+
* Carries the folio chrome so the cross-page nav stays consistent with
|
|
5
|
+
* every other surface (folio-cross-page.test.ts asserts every reachable
|
|
6
|
+
* URL renders the er-folio strip).
|
|
7
|
+
*/
|
|
8
|
+
export declare function renderEntryNotFound(entryId: string, reason: string): string;
|
|
9
|
+
//# sourceMappingURL=not-found.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"not-found.d.ts","sourceRoot":"","sources":["../../../src/pages/entry-review/not-found.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAsB3E"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 404 shell for the entry-keyed press-check surface (Phase 34a Layer 2).
|
|
3
|
+
*
|
|
4
|
+
* Carries the folio chrome so the cross-page nav stays consistent with
|
|
5
|
+
* every other surface (folio-cross-page.test.ts asserts every reachable
|
|
6
|
+
* URL renders the er-folio strip).
|
|
7
|
+
*/
|
|
8
|
+
import { html, unsafe } from "../html.js";
|
|
9
|
+
import { layout } from "../layout.js";
|
|
10
|
+
import { renderEditorialFolio } from "../chrome.js";
|
|
11
|
+
export function renderEntryNotFound(entryId, reason) {
|
|
12
|
+
const folio = renderEditorialFolio('longform', `longform · ${entryId}`);
|
|
13
|
+
const body = html `
|
|
14
|
+
<div data-review-ui="entry-review-missing" class="er-review-shell">
|
|
15
|
+
${unsafe(folio.__raw)}
|
|
16
|
+
<main class="er-entry-shell er-entry-shell--missing">
|
|
17
|
+
<h1>Entry not found</h1>
|
|
18
|
+
<p>No sidecar matched <code>${entryId}</code>.</p>
|
|
19
|
+
<p class="er-entry-detail">${reason}</p>
|
|
20
|
+
<p><a href="/dev/editorial-studio">Back to the studio</a></p>
|
|
21
|
+
</main>
|
|
22
|
+
</div>`;
|
|
23
|
+
return layout({
|
|
24
|
+
title: 'Entry not found — dev',
|
|
25
|
+
cssHrefs: [
|
|
26
|
+
'/static/css/editorial-review.css',
|
|
27
|
+
'/static/css/editorial-nav.css',
|
|
28
|
+
'/static/css/entry-review.css',
|
|
29
|
+
],
|
|
30
|
+
bodyHtml: body,
|
|
31
|
+
scriptModules: [],
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=not-found.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"not-found.js","sourceRoot":"","sources":["../../../src/pages/entry-review/not-found.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAEpD,MAAM,UAAU,mBAAmB,CAAC,OAAe,EAAE,MAAc;IACjE,MAAM,KAAK,GAAG,oBAAoB,CAAC,UAAU,EAAE,cAAc,OAAO,EAAE,CAAC,CAAC;IACxE,MAAM,IAAI,GAAG,IAAI,CAAA;;QAEX,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC;;;sCAGW,OAAO;qCACR,MAAM;;;WAGhC,CAAC;IACV,OAAO,MAAM,CAAC;QACZ,KAAK,EAAE,uBAAuB;QAC9B,QAAQ,EAAE;YACR,kCAAkC;YAClC,+BAA+B;YAC/B,8BAA8B;SAC/B;QACD,QAAQ,EAAE,IAAI;QACd,aAAa,EAAE,EAAE;KAClB,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Outline drawer for the entry-keyed press-check surface (Phase 34a — T9).
|
|
3
|
+
*
|
|
4
|
+
* Relocated from `pages/review.ts:renderOutlineDrawer`. Conditional render
|
|
5
|
+
* when the entry's body markdown carries a `## Outline` section (extracted
|
|
6
|
+
* via `splitOutline`). The pull-tab on the left edge mirrors the marginalia
|
|
7
|
+
* tab pattern on the right edge; the drawer is read-only and links to
|
|
8
|
+
* `/deskwork:iterate --kind outline` for editing.
|
|
9
|
+
*/
|
|
10
|
+
import { type RawHtml } from '../html.ts';
|
|
11
|
+
export declare function renderOutlineDrawer(outlineHtml: string): RawHtml;
|
|
12
|
+
//# sourceMappingURL=outline-drawer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"outline-drawer.d.ts","sourceRoot":"","sources":["../../../src/pages/entry-review/outline-drawer.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAgB,KAAK,OAAO,EAAE,MAAM,YAAY,CAAC;AAExD,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAgBhE"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Outline drawer for the entry-keyed press-check surface (Phase 34a — T9).
|
|
3
|
+
*
|
|
4
|
+
* Relocated from `pages/review.ts:renderOutlineDrawer`. Conditional render
|
|
5
|
+
* when the entry's body markdown carries a `## Outline` section (extracted
|
|
6
|
+
* via `splitOutline`). The pull-tab on the left edge mirrors the marginalia
|
|
7
|
+
* tab pattern on the right edge; the drawer is read-only and links to
|
|
8
|
+
* `/deskwork:iterate --kind outline` for editing.
|
|
9
|
+
*/
|
|
10
|
+
import { html, unsafe } from "../html.js";
|
|
11
|
+
export function renderOutlineDrawer(outlineHtml) {
|
|
12
|
+
const hidden = outlineHtml ? '' : ' hidden';
|
|
13
|
+
return unsafe(html `
|
|
14
|
+
<button class="er-outline-tab" data-outline-tab type="button" aria-label="Show outline"${unsafe(hidden)}>
|
|
15
|
+
<span class="er-outline-tab-label">Outline</span>
|
|
16
|
+
</button>
|
|
17
|
+
<aside class="er-outline-drawer" data-outline-drawer aria-label="Outline reference" hidden>
|
|
18
|
+
<header class="er-outline-drawer-head">
|
|
19
|
+
<span class="er-outline-drawer-kicker">Briefing sheet</span>
|
|
20
|
+
<button type="button" class="er-outline-drawer-close" data-outline-close aria-label="Close outline (O or Esc)">×</button>
|
|
21
|
+
</header>
|
|
22
|
+
<div class="er-outline-drawer-body" data-outline-drawer-body>${unsafe(outlineHtml)}</div>
|
|
23
|
+
<footer class="er-outline-drawer-foot">
|
|
24
|
+
<span>Read-only · edit via <code>/deskwork:iterate --kind outline</code></span>
|
|
25
|
+
</footer>
|
|
26
|
+
</aside>`);
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=outline-drawer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"outline-drawer.js","sourceRoot":"","sources":["../../../src/pages/entry-review/outline-drawer.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,EAAgB,MAAM,YAAY,CAAC;AAExD,MAAM,UAAU,mBAAmB,CAAC,WAAmB;IACrD,MAAM,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IAC5C,OAAO,MAAM,CAAC,IAAI,CAAA;6FACyE,MAAM,CAAC,MAAM,CAAC;;;;;;;;qEAQtC,MAAM,CAAC,WAAW,CAAC;;;;aAI3E,CAAC,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Keyboard shortcuts overlay for the entry-keyed press-check surface
|
|
3
|
+
* (Phase 34a — T13 helper).
|
|
4
|
+
*
|
|
5
|
+
* Relocated from `pages/review.ts:renderShortcutsOverlay`. Triggered by
|
|
6
|
+
* `?` (or Shift+/) and the strip's `?` button. Mirrors the destructive-
|
|
7
|
+
* shortcut UX from the legacy surface verbatim — bare-letter double-tap
|
|
8
|
+
* with no Cmd/Ctrl modifier (#108). On the entry-keyed surface, `r r`
|
|
9
|
+
* (reject) is shown for completeness but the underlying button is
|
|
10
|
+
* disabled until reject semantics land — see issue #173.
|
|
11
|
+
*/
|
|
12
|
+
import { type RawHtml } from '../html.ts';
|
|
13
|
+
export declare function renderShortcutsOverlay(): RawHtml;
|
|
14
|
+
//# sourceMappingURL=shortcuts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shortcuts.d.ts","sourceRoot":"","sources":["../../../src/pages/entry-review/shortcuts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAgB,KAAK,OAAO,EAAE,MAAM,YAAY,CAAC;AAExD,wBAAgB,sBAAsB,IAAI,OAAO,CAsBhD"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Keyboard shortcuts overlay for the entry-keyed press-check surface
|
|
3
|
+
* (Phase 34a — T13 helper).
|
|
4
|
+
*
|
|
5
|
+
* Relocated from `pages/review.ts:renderShortcutsOverlay`. Triggered by
|
|
6
|
+
* `?` (or Shift+/) and the strip's `?` button. Mirrors the destructive-
|
|
7
|
+
* shortcut UX from the legacy surface verbatim — bare-letter double-tap
|
|
8
|
+
* with no Cmd/Ctrl modifier (#108). On the entry-keyed surface, `r r`
|
|
9
|
+
* (reject) is shown for completeness but the underlying button is
|
|
10
|
+
* disabled until reject semantics land — see issue #173.
|
|
11
|
+
*/
|
|
12
|
+
import { html, unsafe } from "../html.js";
|
|
13
|
+
export function renderShortcutsOverlay() {
|
|
14
|
+
return unsafe(html `
|
|
15
|
+
<div class="er-shortcuts" data-shortcuts-overlay hidden role="dialog" aria-modal="true" aria-label="Keyboard shortcuts">
|
|
16
|
+
<div class="er-shortcuts-backdrop" data-shortcuts-backdrop></div>
|
|
17
|
+
<div class="er-shortcuts-panel">
|
|
18
|
+
<h2>Keyboard</h2>
|
|
19
|
+
<dl>
|
|
20
|
+
<dt><kbd>e</kbd> / dbl-click</dt><dd>toggle edit mode</dd>
|
|
21
|
+
<dt>select text</dt><dd>leave a margin note</dd>
|
|
22
|
+
<dt><kbd>⌘</kbd><kbd>↵</kbd> / <kbd>ctrl</kbd><kbd>↵</kbd></dt><dd>save margin note (in composer)</dd>
|
|
23
|
+
<dt><kbd>a</kbd> <kbd>a</kbd></dt><dd>approve <em>— press twice within 500ms; first press arms, second fires</em></dd>
|
|
24
|
+
<dt><kbd>i</kbd> <kbd>i</kbd></dt><dd>iterate <em>— press twice within 500ms</em></dd>
|
|
25
|
+
<dt><kbd>r</kbd> <kbd>r</kbd></dt><dd>reject <em>— pending design (#173)</em></dd>
|
|
26
|
+
<dt><kbd>j</kbd> / <kbd>k</kbd></dt><dd>next / previous margin note</dd>
|
|
27
|
+
<dt><kbd>shift</kbd><kbd>F</kbd></dt><dd>focus mode <em>(edit mode only)</em></dd>
|
|
28
|
+
<dt><kbd>shift</kbd><kbd>M</kbd></dt><dd>show / hide margin notes column <em>— or click the chevron in the head when visible, or the pull tab on the right edge when stowed</em></dd>
|
|
29
|
+
<dt><kbd>?</kbd></dt><dd>this panel</dd>
|
|
30
|
+
<dt><kbd>esc</kbd></dt><dd>close / cancel composer</dd>
|
|
31
|
+
</dl>
|
|
32
|
+
<p class="er-shortcuts-footer">Press <kbd>?</kbd> anytime.</p>
|
|
33
|
+
</div>
|
|
34
|
+
</div>`);
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=shortcuts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shortcuts.js","sourceRoot":"","sources":["../../../src/pages/entry-review/shortcuts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,EAAgB,MAAM,YAAY,CAAC;AAExD,MAAM,UAAU,sBAAsB;IACpC,OAAO,MAAM,CAAC,IAAI,CAAA;;;;;;;;;;;;;;;;;;;;WAoBT,CAAC,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Version strip for the entry-keyed press-check surface (Phase 34a — T6).
|
|
3
|
+
*
|
|
4
|
+
* Renders one chip per recorded iteration of this entry. Clicking a chip
|
|
5
|
+
* navigates to `?v=<n>` against the current URL — the renderer then
|
|
6
|
+
* shows the historical markdown captured in the journal at that version.
|
|
7
|
+
*
|
|
8
|
+
* Differs from the legacy workflow-keyed strip:
|
|
9
|
+
* - Source of truth is `listEntryIterations(projectRoot, entryId)`, not
|
|
10
|
+
* `readVersions(workflowId)`.
|
|
11
|
+
* - Iteration "version" numbers are per-stage, so a given entry can
|
|
12
|
+
* legitimately have v1 in Outlining and v1 in Drafting. The chip
|
|
13
|
+
* label includes the stage prefix when more than one stage is
|
|
14
|
+
* represented to avoid an ambiguous "v1 / v1" sequence.
|
|
15
|
+
* - The "current" chip is whichever iteration matches the entry's
|
|
16
|
+
* current stage + iteration count from the sidecar
|
|
17
|
+
* (`entry.iterationByStage[entry.currentStage]`).
|
|
18
|
+
*/
|
|
19
|
+
import type { IterationListing } from '@deskwork/core/iterate/history';
|
|
20
|
+
import type { Entry } from '@deskwork/core/schema/entry';
|
|
21
|
+
import { type RawHtml } from '../html.ts';
|
|
22
|
+
interface VersionStripOptions {
|
|
23
|
+
readonly iterations: readonly IterationListing[];
|
|
24
|
+
readonly entry: Entry;
|
|
25
|
+
/** When set, this (version, stage) pair's chip is highlighted as
|
|
26
|
+
* active (historical view). Stage qualification is required because
|
|
27
|
+
* per-stage iteration counters can collide (e.g. Ideas v1 + Drafting v1). */
|
|
28
|
+
readonly historicalVersion: number | null;
|
|
29
|
+
readonly historicalStage: string | null;
|
|
30
|
+
}
|
|
31
|
+
export declare function renderVersionsStrip(opts: VersionStripOptions): RawHtml;
|
|
32
|
+
export {};
|
|
33
|
+
//# sourceMappingURL=version-strip.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version-strip.d.ts","sourceRoot":"","sources":["../../../src/pages/entry-review/version-strip.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AACzD,OAAO,EAAgB,KAAK,OAAO,EAAE,MAAM,YAAY,CAAC;AAExD,UAAU,mBAAmB;IAC3B,QAAQ,CAAC,UAAU,EAAE,SAAS,gBAAgB,EAAE,CAAC;IACjD,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB;;kFAE8E;IAC9E,QAAQ,CAAC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1C,QAAQ,CAAC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;CACzC;AAsCD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAgCtE"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Version strip for the entry-keyed press-check surface (Phase 34a — T6).
|
|
3
|
+
*
|
|
4
|
+
* Renders one chip per recorded iteration of this entry. Clicking a chip
|
|
5
|
+
* navigates to `?v=<n>` against the current URL — the renderer then
|
|
6
|
+
* shows the historical markdown captured in the journal at that version.
|
|
7
|
+
*
|
|
8
|
+
* Differs from the legacy workflow-keyed strip:
|
|
9
|
+
* - Source of truth is `listEntryIterations(projectRoot, entryId)`, not
|
|
10
|
+
* `readVersions(workflowId)`.
|
|
11
|
+
* - Iteration "version" numbers are per-stage, so a given entry can
|
|
12
|
+
* legitimately have v1 in Outlining and v1 in Drafting. The chip
|
|
13
|
+
* label includes the stage prefix when more than one stage is
|
|
14
|
+
* represented to avoid an ambiguous "v1 / v1" sequence.
|
|
15
|
+
* - The "current" chip is whichever iteration matches the entry's
|
|
16
|
+
* current stage + iteration count from the sidecar
|
|
17
|
+
* (`entry.iterationByStage[entry.currentStage]`).
|
|
18
|
+
*/
|
|
19
|
+
import { html, unsafe } from "../html.js";
|
|
20
|
+
function currentStageVersion(entry) {
|
|
21
|
+
const v = entry.iterationByStage[entry.currentStage];
|
|
22
|
+
return typeof v === 'number' ? v : null;
|
|
23
|
+
}
|
|
24
|
+
function uniqueStages(iterations) {
|
|
25
|
+
const out = new Set();
|
|
26
|
+
for (const it of iterations)
|
|
27
|
+
out.add(it.stage);
|
|
28
|
+
return out;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Determine which iteration the on-disk artifact corresponds to. The
|
|
32
|
+
* preferred signal is `entry.iterationByStage[entry.currentStage]` —
|
|
33
|
+
* the sidecar's per-stage iteration counter. When the current stage
|
|
34
|
+
* has no recorded iterations (typical for Final / Published entries
|
|
35
|
+
* whose history was recorded under Drafting), fall back to the most
|
|
36
|
+
* recent iteration overall — that's the closest match for "what's on
|
|
37
|
+
* disk right now."
|
|
38
|
+
*/
|
|
39
|
+
function activeIteration(iterations, entry) {
|
|
40
|
+
if (iterations.length === 0)
|
|
41
|
+
return null;
|
|
42
|
+
const stageVersion = currentStageVersion(entry);
|
|
43
|
+
if (stageVersion !== null) {
|
|
44
|
+
const exact = iterations.find((it) => it.stage === entry.currentStage && it.versionNumber === stageVersion);
|
|
45
|
+
if (exact !== undefined)
|
|
46
|
+
return exact;
|
|
47
|
+
}
|
|
48
|
+
// Fall back to the latest iteration (iterations are time-ordered).
|
|
49
|
+
return iterations[iterations.length - 1] ?? null;
|
|
50
|
+
}
|
|
51
|
+
export function renderVersionsStrip(opts) {
|
|
52
|
+
const { iterations, entry, historicalVersion, historicalStage } = opts;
|
|
53
|
+
if (iterations.length === 0)
|
|
54
|
+
return unsafe('');
|
|
55
|
+
const stagesSeen = uniqueStages(iterations);
|
|
56
|
+
const showStage = stagesSeen.size > 1;
|
|
57
|
+
const active = activeIteration(iterations, entry);
|
|
58
|
+
const links = iterations.map((it) => {
|
|
59
|
+
// A chip is the active historical chip only when BOTH version
|
|
60
|
+
// number and stage match. Without stage qualification, Ideas v1
|
|
61
|
+
// and Drafting v1 would both light up.
|
|
62
|
+
const isHistorical = historicalVersion !== null &&
|
|
63
|
+
it.versionNumber === historicalVersion &&
|
|
64
|
+
historicalStage !== null &&
|
|
65
|
+
it.stage === historicalStage;
|
|
66
|
+
const isActive = isHistorical ||
|
|
67
|
+
(historicalVersion === null && active !== null &&
|
|
68
|
+
it.stage === active.stage && it.versionNumber === active.versionNumber);
|
|
69
|
+
const label = showStage
|
|
70
|
+
? `${it.stage[0]}·v${it.versionNumber}`
|
|
71
|
+
: `v${it.versionNumber}`;
|
|
72
|
+
// URL carries both ?v= and ?stage= so the loader can disambiguate
|
|
73
|
+
// when the same version number appears under multiple stages.
|
|
74
|
+
const href = `?v=${it.versionNumber}&stage=${encodeURIComponent(it.stage)}`;
|
|
75
|
+
const cls = isActive ? 'active' : '';
|
|
76
|
+
const title = `${it.stage} version ${it.versionNumber} (${it.timestamp})`;
|
|
77
|
+
return html `<a href="${href}" class="${cls}" title="${title}">${label}</a>`;
|
|
78
|
+
}).join('');
|
|
79
|
+
return unsafe(html `<span class="er-strip-versions">${unsafe(links)}</span>`);
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=version-strip.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version-strip.js","sourceRoot":"","sources":["../../../src/pages/entry-review/version-strip.ts"],"names":[],"mappings":"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"}
|