@deskwork/core 0.9.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (188) hide show
  1. package/dist/body-state.d.ts +27 -0
  2. package/dist/body-state.d.ts.map +1 -0
  3. package/dist/body-state.js +62 -0
  4. package/dist/body-state.js.map +1 -0
  5. package/dist/calendar-mutations.d.ts +124 -0
  6. package/dist/calendar-mutations.d.ts.map +1 -0
  7. package/dist/calendar-mutations.js +305 -0
  8. package/dist/calendar-mutations.js.map +1 -0
  9. package/dist/calendar.d.ts +54 -0
  10. package/dist/calendar.d.ts.map +1 -0
  11. package/dist/calendar.js +430 -0
  12. package/dist/calendar.js.map +1 -0
  13. package/dist/cli.d.ts +38 -0
  14. package/dist/cli.d.ts.map +1 -0
  15. package/dist/cli.js +72 -0
  16. package/dist/cli.js.map +1 -0
  17. package/dist/config.d.ts +91 -0
  18. package/dist/config.d.ts.map +1 -0
  19. package/dist/config.js +216 -0
  20. package/dist/config.js.map +1 -0
  21. package/dist/content-index.d.ts +74 -0
  22. package/dist/content-index.d.ts.map +1 -0
  23. package/dist/content-index.js +205 -0
  24. package/dist/content-index.js.map +1 -0
  25. package/dist/content-tree-fs-walk.d.ts +54 -0
  26. package/dist/content-tree-fs-walk.d.ts.map +1 -0
  27. package/dist/content-tree-fs-walk.js +112 -0
  28. package/dist/content-tree-fs-walk.js.map +1 -0
  29. package/dist/content-tree-helpers.d.ts +52 -0
  30. package/dist/content-tree-helpers.d.ts.map +1 -0
  31. package/dist/content-tree-helpers.js +116 -0
  32. package/dist/content-tree-helpers.js.map +1 -0
  33. package/dist/content-tree-types.d.ts +175 -0
  34. package/dist/content-tree-types.d.ts.map +1 -0
  35. package/dist/content-tree-types.js +10 -0
  36. package/dist/content-tree-types.js.map +1 -0
  37. package/dist/content-tree.d.ts +93 -0
  38. package/dist/content-tree.d.ts.map +1 -0
  39. package/dist/content-tree.js +385 -0
  40. package/dist/content-tree.js.map +1 -0
  41. package/dist/doctor/index.d.ts +11 -0
  42. package/dist/doctor/index.d.ts.map +1 -0
  43. package/dist/doctor/index.js +10 -0
  44. package/dist/doctor/index.js.map +1 -0
  45. package/dist/doctor/project-rules.d.ts +59 -0
  46. package/dist/doctor/project-rules.d.ts.map +1 -0
  47. package/dist/doctor/project-rules.js +143 -0
  48. package/dist/doctor/project-rules.js.map +1 -0
  49. package/dist/doctor/rules/calendar-uuid-missing.d.ts +19 -0
  50. package/dist/doctor/rules/calendar-uuid-missing.d.ts.map +1 -0
  51. package/dist/doctor/rules/calendar-uuid-missing.js +176 -0
  52. package/dist/doctor/rules/calendar-uuid-missing.js.map +1 -0
  53. package/dist/doctor/rules/duplicate-id.d.ts +27 -0
  54. package/dist/doctor/rules/duplicate-id.d.ts.map +1 -0
  55. package/dist/doctor/rules/duplicate-id.js +157 -0
  56. package/dist/doctor/rules/duplicate-id.js.map +1 -0
  57. package/dist/doctor/rules/legacy-top-level-id-migration.d.ts +40 -0
  58. package/dist/doctor/rules/legacy-top-level-id-migration.d.ts.map +1 -0
  59. package/dist/doctor/rules/legacy-top-level-id-migration.js +232 -0
  60. package/dist/doctor/rules/legacy-top-level-id-migration.js.map +1 -0
  61. package/dist/doctor/rules/missing-frontmatter-id.d.ts +45 -0
  62. package/dist/doctor/rules/missing-frontmatter-id.d.ts.map +1 -0
  63. package/dist/doctor/rules/missing-frontmatter-id.js +283 -0
  64. package/dist/doctor/rules/missing-frontmatter-id.js.map +1 -0
  65. package/dist/doctor/rules/orphan-frontmatter-id.d.ts +18 -0
  66. package/dist/doctor/rules/orphan-frontmatter-id.d.ts.map +1 -0
  67. package/dist/doctor/rules/orphan-frontmatter-id.js +154 -0
  68. package/dist/doctor/rules/orphan-frontmatter-id.js.map +1 -0
  69. package/dist/doctor/rules/schema-rejected.d.ts +20 -0
  70. package/dist/doctor/rules/schema-rejected.d.ts.map +1 -0
  71. package/dist/doctor/rules/schema-rejected.js +44 -0
  72. package/dist/doctor/rules/schema-rejected.js.map +1 -0
  73. package/dist/doctor/rules/slug-collision.d.ts +18 -0
  74. package/dist/doctor/rules/slug-collision.d.ts.map +1 -0
  75. package/dist/doctor/rules/slug-collision.js +65 -0
  76. package/dist/doctor/rules/slug-collision.js.map +1 -0
  77. package/dist/doctor/rules/workflow-stale.d.ts +20 -0
  78. package/dist/doctor/rules/workflow-stale.d.ts.map +1 -0
  79. package/dist/doctor/rules/workflow-stale.js +136 -0
  80. package/dist/doctor/rules/workflow-stale.js.map +1 -0
  81. package/dist/doctor/runner.d.ts +75 -0
  82. package/dist/doctor/runner.d.ts.map +1 -0
  83. package/dist/doctor/runner.js +289 -0
  84. package/dist/doctor/runner.js.map +1 -0
  85. package/dist/doctor/schema-patch.d.ts +21 -0
  86. package/dist/doctor/schema-patch.d.ts.map +1 -0
  87. package/dist/doctor/schema-patch.js +92 -0
  88. package/dist/doctor/schema-patch.js.map +1 -0
  89. package/dist/doctor/types.d.ts +185 -0
  90. package/dist/doctor/types.d.ts.map +1 -0
  91. package/dist/doctor/types.js +13 -0
  92. package/dist/doctor/types.js.map +1 -0
  93. package/dist/frontmatter.d.ts +103 -0
  94. package/dist/frontmatter.d.ts.map +1 -0
  95. package/dist/frontmatter.js +306 -0
  96. package/dist/frontmatter.js.map +1 -0
  97. package/dist/index.d.ts +27 -0
  98. package/dist/index.d.ts.map +1 -0
  99. package/dist/index.js +27 -0
  100. package/dist/index.js.map +1 -0
  101. package/dist/ingest-derive.d.ts +79 -0
  102. package/dist/ingest-derive.d.ts.map +1 -0
  103. package/dist/ingest-derive.js +299 -0
  104. package/dist/ingest-derive.js.map +1 -0
  105. package/dist/ingest-paths.d.ts +37 -0
  106. package/dist/ingest-paths.d.ts.map +1 -0
  107. package/dist/ingest-paths.js +176 -0
  108. package/dist/ingest-paths.js.map +1 -0
  109. package/dist/ingest.d.ts +162 -0
  110. package/dist/ingest.d.ts.map +1 -0
  111. package/dist/ingest.js +269 -0
  112. package/dist/ingest.js.map +1 -0
  113. package/dist/journal.d.ts +49 -0
  114. package/dist/journal.d.ts.map +1 -0
  115. package/dist/journal.js +113 -0
  116. package/dist/journal.js.map +1 -0
  117. package/dist/outline-split.d.ts +38 -0
  118. package/dist/outline-split.d.ts.map +1 -0
  119. package/dist/outline-split.js +84 -0
  120. package/dist/outline-split.js.map +1 -0
  121. package/dist/overrides.d.ts +83 -0
  122. package/dist/overrides.d.ts.map +1 -0
  123. package/dist/overrides.js +88 -0
  124. package/dist/overrides.js.map +1 -0
  125. package/dist/paths.d.ts +183 -0
  126. package/dist/paths.d.ts.map +1 -0
  127. package/dist/paths.js +266 -0
  128. package/dist/paths.js.map +1 -0
  129. package/dist/remark-image-figure.mjs +77 -0
  130. package/dist/remark-strip-first-h1.mjs +26 -0
  131. package/dist/remark-strip-outline.mjs +44 -0
  132. package/dist/rename-slug.d.ts +49 -0
  133. package/dist/rename-slug.d.ts.map +1 -0
  134. package/dist/rename-slug.js +161 -0
  135. package/dist/rename-slug.js.map +1 -0
  136. package/dist/review/handlers.d.ts +55 -0
  137. package/dist/review/handlers.d.ts.map +1 -0
  138. package/dist/review/handlers.js +307 -0
  139. package/dist/review/handlers.js.map +1 -0
  140. package/dist/review/index.d.ts +14 -0
  141. package/dist/review/index.d.ts.map +1 -0
  142. package/dist/review/index.js +13 -0
  143. package/dist/review/index.js.map +1 -0
  144. package/dist/review/journal-mappers.d.ts +35 -0
  145. package/dist/review/journal-mappers.d.ts.map +1 -0
  146. package/dist/review/journal-mappers.js +48 -0
  147. package/dist/review/journal-mappers.js.map +1 -0
  148. package/dist/review/pipeline.d.ts +79 -0
  149. package/dist/review/pipeline.d.ts.map +1 -0
  150. package/dist/review/pipeline.js +234 -0
  151. package/dist/review/pipeline.js.map +1 -0
  152. package/dist/review/render.d.ts +27 -0
  153. package/dist/review/render.d.ts.map +1 -0
  154. package/dist/review/render.js +42 -0
  155. package/dist/review/render.js.map +1 -0
  156. package/dist/review/report.d.ts +50 -0
  157. package/dist/review/report.d.ts.map +1 -0
  158. package/dist/review/report.js +164 -0
  159. package/dist/review/report.js.map +1 -0
  160. package/dist/review/result.d.ts +12 -0
  161. package/dist/review/result.d.ts.map +1 -0
  162. package/dist/review/result.js +12 -0
  163. package/dist/review/result.js.map +1 -0
  164. package/dist/review/start-handlers.d.ts +62 -0
  165. package/dist/review/start-handlers.d.ts.map +1 -0
  166. package/dist/review/start-handlers.js +223 -0
  167. package/dist/review/start-handlers.js.map +1 -0
  168. package/dist/review/types.d.ts +169 -0
  169. package/dist/review/types.d.ts.map +1 -0
  170. package/dist/review/types.js +26 -0
  171. package/dist/review/types.js.map +1 -0
  172. package/dist/review/workflow-paths.d.ts +68 -0
  173. package/dist/review/workflow-paths.d.ts.map +1 -0
  174. package/dist/review/workflow-paths.js +112 -0
  175. package/dist/review/workflow-paths.js.map +1 -0
  176. package/dist/scaffold.d.ts +67 -0
  177. package/dist/scaffold.d.ts.map +1 -0
  178. package/dist/scaffold.js +122 -0
  179. package/dist/scaffold.js.map +1 -0
  180. package/dist/scrapbook.d.ts +229 -0
  181. package/dist/scrapbook.d.ts.map +1 -0
  182. package/dist/scrapbook.js +500 -0
  183. package/dist/scrapbook.js.map +1 -0
  184. package/dist/types.d.ts +197 -0
  185. package/dist/types.d.ts.map +1 -0
  186. package/dist/types.js +120 -0
  187. package/dist/types.js.map +1 -0
  188. package/package.json +160 -0
@@ -0,0 +1,430 @@
1
+ /**
2
+ * Markdown editorial calendar parser and writer.
3
+ *
4
+ * Each site's calendar is a human-readable markdown file with one table per
5
+ * stage. This module round-trips between that format and the in-memory
6
+ * EditorialCalendar type.
7
+ *
8
+ * ## Markdown format
9
+ *
10
+ * ```markdown
11
+ * # Editorial Calendar
12
+ *
13
+ * ## Ideas
14
+ *
15
+ * | UUID | Slug | Title | Description | Keywords | Source |
16
+ * |------|------|-------|-------------|----------|--------|
17
+ * | abc-123 | my-post | My Post | A post about things | kw1, kw2 | manual |
18
+ *
19
+ * ## Planned
20
+ * ...
21
+ *
22
+ * ## Published
23
+ *
24
+ * | UUID | Slug | Title | Description | Keywords | Source | Published | Issue |
25
+ * |------|------|-------|-------------|----------|--------|-----------|-------|
26
+ * ```
27
+ *
28
+ * Optional columns (Topics, Type, URL) are emitted only when any entry uses
29
+ * them, so a calendar with no cross-posting stays visually simple. Published
30
+ * entries always include Published and Issue columns. The UUID column is
31
+ * always emitted at render time — pre-UUID calendars get backfilled lazily
32
+ * (parser assigns missing UUIDs in-memory; the next write persists them).
33
+ */
34
+ import { readFileSync, writeFileSync } from 'node:fs';
35
+ import { randomUUID } from 'node:crypto';
36
+ import { PLATFORMS, STAGES, effectiveContentType, isContentType, isPausable, isPlatform, isStage, } from "./types.js";
37
+ // ---------------------------------------------------------------------------
38
+ // Parser
39
+ // ---------------------------------------------------------------------------
40
+ function parseRow(line) {
41
+ return line
42
+ .split('|')
43
+ .slice(1, -1)
44
+ .map((cell) => cell.trim());
45
+ }
46
+ function isSeparator(line) {
47
+ return /^\|[\s:-]+\|/.test(line);
48
+ }
49
+ function indexColumns(headerLine) {
50
+ const map = new Map();
51
+ parseRow(headerLine).forEach((name, idx) => {
52
+ map.set(name.trim().toLowerCase(), idx);
53
+ });
54
+ return map;
55
+ }
56
+ function col(cells, cols, name) {
57
+ const idx = cols.get(name);
58
+ if (idx === undefined)
59
+ return undefined;
60
+ const value = cells[idx];
61
+ if (value === undefined)
62
+ return undefined;
63
+ const trimmed = value.trim();
64
+ return trimmed === '' ? undefined : trimmed;
65
+ }
66
+ function parseEntries(lines, stage) {
67
+ const entries = [];
68
+ let i = 0;
69
+ while (i < lines.length && !lines[i].startsWith('|'))
70
+ i++;
71
+ if (i >= lines.length)
72
+ return entries;
73
+ const cols = indexColumns(lines[i]);
74
+ i++;
75
+ if (i < lines.length && isSeparator(lines[i]))
76
+ i++;
77
+ while (i < lines.length && lines[i].startsWith('|')) {
78
+ const cells = parseRow(lines[i]);
79
+ const slug = col(cells, cols, 'slug');
80
+ const title = col(cells, cols, 'title');
81
+ if (slug && title) {
82
+ // UUID column is optional for backward compatibility. Missing IDs
83
+ // get a fresh v4 assigned in-memory; the next writeCalendar
84
+ // persists them, so one save fully migrates a legacy calendar.
85
+ const existingId = col(cells, cols, 'uuid') ?? col(cells, cols, 'id');
86
+ const entry = {
87
+ id: existingId ?? randomUUID(),
88
+ slug,
89
+ title,
90
+ description: col(cells, cols, 'description') ?? '',
91
+ stage,
92
+ targetKeywords: (col(cells, cols, 'keywords') ?? '')
93
+ .split(',')
94
+ .map((k) => k.trim())
95
+ .filter(Boolean),
96
+ source: col(cells, cols, 'source') === 'analytics' ? 'analytics' : 'manual',
97
+ };
98
+ const topics = col(cells, cols, 'topics');
99
+ if (topics) {
100
+ entry.topics = topics.split(',').map((t) => t.trim()).filter(Boolean);
101
+ }
102
+ const typeValue = col(cells, cols, 'type');
103
+ if (typeValue && isContentType(typeValue)) {
104
+ entry.contentType = typeValue;
105
+ }
106
+ const url = col(cells, cols, 'url');
107
+ if (url)
108
+ entry.contentUrl = url;
109
+ // Legacy calendars may carry a `FilePath` column from the prior
110
+ // plan; the parser is column-tolerant and ignores it. Phase 19
111
+ // moves filesystem placement to frontmatter `id:` + the content
112
+ // index, so the column is no longer load-bearing on disk.
113
+ // PausedFrom column round-trips on the Paused section. Other
114
+ // sections that happen to carry the column (legacy hand-edits)
115
+ // ignore the value since `entry.stage !== 'Paused'`.
116
+ const pausedFrom = col(cells, cols, 'pausedfrom');
117
+ if (pausedFrom && isStage(pausedFrom) && isPausable(pausedFrom)) {
118
+ entry.pausedFrom = pausedFrom;
119
+ }
120
+ const published = col(cells, cols, 'published');
121
+ if (published)
122
+ entry.datePublished = published;
123
+ const issue = col(cells, cols, 'issue');
124
+ if (issue) {
125
+ const match = issue.match(/#?(\d+)/);
126
+ if (match)
127
+ entry.issueNumber = parseInt(match[1], 10);
128
+ }
129
+ entries.push(entry);
130
+ }
131
+ i++;
132
+ }
133
+ return entries;
134
+ }
135
+ function parseDistributions(lines) {
136
+ const records = [];
137
+ let i = 0;
138
+ while (i < lines.length && !lines[i].startsWith('|'))
139
+ i++;
140
+ if (i >= lines.length)
141
+ return records;
142
+ const cols = indexColumns(lines[i]);
143
+ i++;
144
+ if (i < lines.length && isSeparator(lines[i]))
145
+ i++;
146
+ while (i < lines.length && lines[i].startsWith('|')) {
147
+ const cells = parseRow(lines[i]);
148
+ const slug = col(cells, cols, 'slug');
149
+ const platformValue = col(cells, cols, 'platform');
150
+ const url = col(cells, cols, 'url');
151
+ const dateShared = col(cells, cols, 'shared');
152
+ // Phase 21a: URL may be empty at creation time (a placeholder
153
+ // distribution record awaiting the operator's posted URL via
154
+ // updateDistributionUrl). Parser accepts empty URL; only slug,
155
+ // platform, and dateShared are required for round-trip.
156
+ if (slug && platformValue && dateShared && isPlatform(platformValue)) {
157
+ // entryId may be missing on legacy rows. Left empty here and
158
+ // backfilled in parseCalendar once entries are parsed and a
159
+ // slug → entry lookup table is available.
160
+ const entryIdCell = col(cells, cols, 'entryid') ?? col(cells, cols, 'uuid');
161
+ const rec = {
162
+ entryId: entryIdCell ?? '',
163
+ slug,
164
+ platform: platformValue,
165
+ url: url ?? '',
166
+ dateShared,
167
+ };
168
+ const channel = col(cells, cols, 'channel');
169
+ if (channel)
170
+ rec.channel = channel;
171
+ const notes = col(cells, cols, 'notes');
172
+ if (notes)
173
+ rec.notes = notes;
174
+ records.push(rec);
175
+ }
176
+ i++;
177
+ }
178
+ return records;
179
+ }
180
+ function parseShortformBlocks(lines) {
181
+ const blocks = [];
182
+ let i = 0;
183
+ while (i < lines.length) {
184
+ const header = lines[i].match(/^### (.+)$/);
185
+ if (!header) {
186
+ i++;
187
+ continue;
188
+ }
189
+ const parts = header[1].split('·').map((s) => s.trim());
190
+ if (parts.length < 2) {
191
+ i++;
192
+ continue;
193
+ }
194
+ const [slug, platform, channel] = parts;
195
+ i++;
196
+ const bodyLines = [];
197
+ while (i < lines.length && !lines[i].startsWith('### ')) {
198
+ bodyLines.push(lines[i]);
199
+ i++;
200
+ }
201
+ const text = bodyLines.join('\n').replace(/^\n+|\n+$/g, '');
202
+ if (text.length > 0) {
203
+ const block = { slug, platform, text };
204
+ if (channel)
205
+ block.channel = channel;
206
+ blocks.push(block);
207
+ }
208
+ }
209
+ return blocks;
210
+ }
211
+ /** Parse the editorial calendar markdown file into an EditorialCalendar. */
212
+ export function parseCalendar(markdown) {
213
+ const entries = [];
214
+ const distributions = [];
215
+ const shortformBlocks = [];
216
+ const lines = markdown.split('\n');
217
+ let currentSection = null;
218
+ let sectionLines = [];
219
+ function flushSection() {
220
+ if (currentSection && sectionLines.length > 0) {
221
+ if (currentSection === 'Distribution') {
222
+ distributions.push(...parseDistributions(sectionLines));
223
+ }
224
+ else if (currentSection === 'Shortform Copy') {
225
+ shortformBlocks.push(...parseShortformBlocks(sectionLines));
226
+ }
227
+ else {
228
+ entries.push(...parseEntries(sectionLines, currentSection));
229
+ }
230
+ }
231
+ sectionLines = [];
232
+ }
233
+ for (const line of lines) {
234
+ const sectionMatch = line.match(/^## (.+)$/);
235
+ if (sectionMatch) {
236
+ flushSection();
237
+ const name = sectionMatch[1].trim();
238
+ if (isStage(name)) {
239
+ currentSection = name;
240
+ }
241
+ else if (name === 'Distribution') {
242
+ currentSection = 'Distribution';
243
+ }
244
+ else if (name === 'Shortform Copy') {
245
+ currentSection = 'Shortform Copy';
246
+ }
247
+ else {
248
+ currentSection = null;
249
+ }
250
+ }
251
+ else if (currentSection) {
252
+ sectionLines.push(line);
253
+ }
254
+ }
255
+ flushSection();
256
+ // Merge shortform blocks onto their matching DistributionRecord by
257
+ // (slug, platform, channel) — normalize channel to avoid case drift.
258
+ for (const b of shortformBlocks) {
259
+ const rec = distributions.find((d) => d.slug === b.slug &&
260
+ d.platform === b.platform &&
261
+ (d.channel ?? '').toLowerCase() === (b.channel ?? '').toLowerCase());
262
+ if (rec)
263
+ rec.shortform = b.text;
264
+ }
265
+ // Backfill missing entryIds on DistributionRecords by slug match
266
+ // against the entries we just parsed. Records whose slug doesn't
267
+ // resolve to a known entry keep an empty entryId — writeCalendar
268
+ // preserves that (the row is still parseable), and a subsequent
269
+ // distribute or migration run will fix it.
270
+ const entryBySlug = new Map(entries.map((e) => [e.slug, e]));
271
+ for (const d of distributions) {
272
+ if (!d.entryId) {
273
+ const match = entryBySlug.get(d.slug);
274
+ if (match && match.id)
275
+ d.entryId = match.id;
276
+ }
277
+ }
278
+ return { entries, distributions };
279
+ }
280
+ /**
281
+ * Read and parse the editorial calendar from an absolute path.
282
+ *
283
+ * A non-existent file is treated as a logically empty calendar — the user
284
+ * hasn't written anything yet. Any other error (e.g. unreadable, malformed)
285
+ * propagates so the operator sees the problem instead of a silently-empty
286
+ * dashboard.
287
+ */
288
+ export function readCalendar(calendarPath) {
289
+ let raw;
290
+ try {
291
+ raw = readFileSync(calendarPath, 'utf-8');
292
+ }
293
+ catch (err) {
294
+ if (err instanceof Error && 'code' in err && err.code === 'ENOENT') {
295
+ return { entries: [], distributions: [] };
296
+ }
297
+ throw err;
298
+ }
299
+ return parseCalendar(raw);
300
+ }
301
+ // ---------------------------------------------------------------------------
302
+ // Writer
303
+ // ---------------------------------------------------------------------------
304
+ function escapeCell(value) {
305
+ return value.replace(/\|/g, '\\|');
306
+ }
307
+ function renderStageTable(entries, stage) {
308
+ const lines = [];
309
+ const hasIssue = entries.some((e) => e.issueNumber !== undefined);
310
+ const hasTopics = entries.some((e) => e.topics !== undefined && e.topics.length > 0);
311
+ const hasType = entries.some((e) => e.contentType !== undefined && e.contentType !== 'blog');
312
+ const hasUrl = entries.some((e) => e.contentUrl !== undefined && e.contentUrl !== '');
313
+ const isPublished = stage === 'Published';
314
+ const isPaused = stage === 'Paused';
315
+ const headers = ['UUID', 'Slug', 'Title', 'Description', 'Keywords'];
316
+ if (hasTopics)
317
+ headers.push('Topics');
318
+ if (hasType)
319
+ headers.push('Type');
320
+ if (hasUrl)
321
+ headers.push('URL');
322
+ headers.push('Source');
323
+ if (isPaused)
324
+ headers.push('PausedFrom');
325
+ if (isPublished)
326
+ headers.push('Published');
327
+ if (hasIssue || isPublished)
328
+ headers.push('Issue');
329
+ lines.push(`| ${headers.join(' | ')} |`);
330
+ lines.push(`|${headers.map(() => '------').join('|')}|`);
331
+ for (const e of entries) {
332
+ // Backfill a UUID at render time if one is missing. Mutates the
333
+ // entry so subsequent reads/writes see a stable id.
334
+ if (!e.id)
335
+ e.id = randomUUID();
336
+ const row = [
337
+ e.id,
338
+ escapeCell(e.slug),
339
+ escapeCell(e.title),
340
+ escapeCell(e.description),
341
+ escapeCell(e.targetKeywords.join(', ')),
342
+ ];
343
+ if (hasTopics)
344
+ row.push(escapeCell((e.topics ?? []).join(', ')));
345
+ if (hasType)
346
+ row.push(effectiveContentType(e));
347
+ if (hasUrl)
348
+ row.push(escapeCell(e.contentUrl ?? ''));
349
+ row.push(e.source);
350
+ if (isPaused)
351
+ row.push(e.pausedFrom ?? '');
352
+ if (isPublished)
353
+ row.push(e.datePublished ?? '');
354
+ if (hasIssue || isPublished)
355
+ row.push(e.issueNumber ? `#${e.issueNumber}` : '');
356
+ lines.push(`| ${row.join(' | ')} |`);
357
+ }
358
+ return lines.join('\n');
359
+ }
360
+ function renderDistributionTable(records) {
361
+ const lines = [];
362
+ const hasChannel = records.some((r) => r.channel !== undefined && r.channel !== '');
363
+ const headers = ['EntryID', 'Slug', 'Platform', 'URL', 'Shared'];
364
+ if (hasChannel)
365
+ headers.push('Channel');
366
+ headers.push('Notes');
367
+ lines.push(`| ${headers.join(' | ')} |`);
368
+ lines.push(`|${headers.map(() => '------').join('|')}|`);
369
+ for (const r of records) {
370
+ const row = [
371
+ r.entryId ?? '',
372
+ escapeCell(r.slug),
373
+ r.platform,
374
+ escapeCell(r.url),
375
+ r.dateShared,
376
+ ];
377
+ if (hasChannel)
378
+ row.push(escapeCell(r.channel ?? ''));
379
+ row.push(escapeCell(r.notes ?? ''));
380
+ lines.push(`| ${row.join(' | ')} |`);
381
+ }
382
+ return lines.join('\n');
383
+ }
384
+ /** Render the full editorial calendar as markdown. */
385
+ export function renderCalendar(calendar) {
386
+ const sections = ['# Editorial Calendar', ''];
387
+ for (const stage of STAGES) {
388
+ const stageEntries = calendar.entries.filter((e) => e.stage === stage);
389
+ sections.push(`## ${stage}`, '');
390
+ if (stageEntries.length > 0) {
391
+ sections.push(renderStageTable(stageEntries, stage));
392
+ }
393
+ else {
394
+ sections.push('*No entries.*');
395
+ }
396
+ sections.push('');
397
+ }
398
+ sections.push('## Distribution', '');
399
+ if (calendar.distributions.length > 0) {
400
+ sections.push(renderDistributionTable(calendar.distributions));
401
+ }
402
+ else {
403
+ sections.push('*No entries.*');
404
+ }
405
+ sections.push('');
406
+ const shortformRecords = calendar.distributions.filter((d) => d.shortform !== undefined && d.shortform !== '');
407
+ if (shortformRecords.length > 0) {
408
+ sections.push('## Shortform Copy', '');
409
+ for (const r of shortformRecords) {
410
+ const headerParts = [r.slug, r.platform];
411
+ if (r.channel)
412
+ headerParts.push(r.channel);
413
+ sections.push(`### ${headerParts.join(' · ')}`, '');
414
+ sections.push((r.shortform ?? '').replace(/\n+$/, ''));
415
+ sections.push('');
416
+ }
417
+ }
418
+ return sections.join('\n');
419
+ }
420
+ /** Write the editorial calendar to an absolute path. */
421
+ export function writeCalendar(calendarPath, calendar) {
422
+ writeFileSync(calendarPath, renderCalendar(calendar), 'utf-8');
423
+ }
424
+ /** Render an empty calendar — used by the install skill to seed a new file. */
425
+ export function renderEmptyCalendar() {
426
+ return renderCalendar({ entries: [], distributions: [] });
427
+ }
428
+ /** Suppress unused-import warnings for re-exported constants available to callers. */
429
+ export { PLATFORMS, STAGES };
430
+ //# sourceMappingURL=calendar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calendar.js","sourceRoot":"","sources":["../src/calendar.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Tiny argv helpers shared by the bin/ scripts.
3
+ *
4
+ * We intentionally avoid pulling in a heavyweight CLI framework — each
5
+ * helper has a small surface, and hand-rolled parsing keeps the scripts
6
+ * transparent. Unknown flags throw so typos surface as an error instead of
7
+ * being silently ignored.
8
+ */
9
+ export interface ParsedArgs {
10
+ /** Positional args in order. */
11
+ positional: string[];
12
+ /** Flags and their string values; repeated flags overwrite. */
13
+ flags: Record<string, string>;
14
+ /** Boolean flags present on the command line (no value). */
15
+ booleans: Set<string>;
16
+ }
17
+ /**
18
+ * Parse argv into positionals, `--flag value` pairs, and boolean flags.
19
+ *
20
+ * @param argv The argv slice to parse (e.g. `process.argv.slice(2)`).
21
+ * @param known Flag names that accept a following value.
22
+ * @param booleanFlags Flag names that are boolean (no value follows).
23
+ *
24
+ * Throws on unknown flags and missing values.
25
+ */
26
+ export declare function parseArgs(argv: string[], known: readonly string[], booleanFlags?: readonly string[]): ParsedArgs;
27
+ /** Resolve a path arg to an absolute path, relative to cwd when not absolute. */
28
+ export declare function absolutize(pathArg: string): string;
29
+ /**
30
+ * Print a fatal error message to stderr and exit non-zero.
31
+ *
32
+ * Use this for user-facing failures (bad args, missing files, schema errors).
33
+ * Developer errors (bugs) should throw and let the stack trace through.
34
+ */
35
+ export declare function fail(message: string, code?: number): never;
36
+ /** Print a JSON result to stdout followed by a newline. */
37
+ export declare function emit(result: unknown): void;
38
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,MAAM,WAAW,UAAU;IACzB,gCAAgC;IAChC,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,+DAA+D;IAC/D,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,4DAA4D;IAC5D,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACvB;AAED;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CACvB,IAAI,EAAE,MAAM,EAAE,EACd,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,YAAY,GAAE,SAAS,MAAM,EAAO,GACnC,UAAU,CAkCZ;AAED,iFAAiF;AACjF,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAElD;AAED;;;;;GAKG;AACH,wBAAgB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,SAAI,GAAG,KAAK,CAGrD;AAED,2DAA2D;AAC3D,wBAAgB,IAAI,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAE1C"}
package/dist/cli.js ADDED
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Tiny argv helpers shared by the bin/ scripts.
3
+ *
4
+ * We intentionally avoid pulling in a heavyweight CLI framework — each
5
+ * helper has a small surface, and hand-rolled parsing keeps the scripts
6
+ * transparent. Unknown flags throw so typos surface as an error instead of
7
+ * being silently ignored.
8
+ */
9
+ import { isAbsolute, resolve } from 'node:path';
10
+ /**
11
+ * Parse argv into positionals, `--flag value` pairs, and boolean flags.
12
+ *
13
+ * @param argv The argv slice to parse (e.g. `process.argv.slice(2)`).
14
+ * @param known Flag names that accept a following value.
15
+ * @param booleanFlags Flag names that are boolean (no value follows).
16
+ *
17
+ * Throws on unknown flags and missing values.
18
+ */
19
+ export function parseArgs(argv, known, booleanFlags = []) {
20
+ const positional = [];
21
+ const flags = {};
22
+ const booleans = new Set();
23
+ const knownSet = new Set(known);
24
+ const boolSet = new Set(booleanFlags);
25
+ for (let i = 0; i < argv.length; i++) {
26
+ const a = argv[i];
27
+ if (!a.startsWith('--')) {
28
+ positional.push(a);
29
+ continue;
30
+ }
31
+ const eq = a.indexOf('=');
32
+ const name = eq >= 0 ? a.slice(2, eq) : a.slice(2);
33
+ if (boolSet.has(name)) {
34
+ booleans.add(name);
35
+ continue;
36
+ }
37
+ if (!knownSet.has(name)) {
38
+ throw new Error(`Unknown flag: --${name}`);
39
+ }
40
+ if (eq >= 0) {
41
+ flags[name] = a.slice(eq + 1);
42
+ }
43
+ else {
44
+ const next = argv[i + 1];
45
+ if (next === undefined || next.startsWith('--')) {
46
+ throw new Error(`Flag --${name} requires a value`);
47
+ }
48
+ flags[name] = next;
49
+ i++;
50
+ }
51
+ }
52
+ return { positional, flags, booleans };
53
+ }
54
+ /** Resolve a path arg to an absolute path, relative to cwd when not absolute. */
55
+ export function absolutize(pathArg) {
56
+ return isAbsolute(pathArg) ? pathArg : resolve(process.cwd(), pathArg);
57
+ }
58
+ /**
59
+ * Print a fatal error message to stderr and exit non-zero.
60
+ *
61
+ * Use this for user-facing failures (bad args, missing files, schema errors).
62
+ * Developer errors (bugs) should throw and let the stack trace through.
63
+ */
64
+ export function fail(message, code = 1) {
65
+ process.stderr.write(`${message}\n`);
66
+ process.exit(code);
67
+ }
68
+ /** Print a JSON result to stdout followed by a newline. */
69
+ export function emit(result) {
70
+ process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
71
+ }
72
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAWhD;;;;;;;;GAQG;AACH,MAAM,UAAU,SAAS,CACvB,IAAc,EACd,KAAwB,EACxB,eAAkC,EAAE;IAEpC,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,MAAM,KAAK,GAA2B,EAAE,CAAC;IACzC,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;IACnC,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;IAChC,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,CAAC;IAEtC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACxB,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACnB,SAAS;QACX,CAAC;QACD,MAAM,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC1B,MAAM,IAAI,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACnD,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACtB,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACnB,SAAS;QACX,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,mBAAmB,IAAI,EAAE,CAAC,CAAC;QAC7C,CAAC;QACD,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;YACZ,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;QAChC,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YACzB,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;gBAChD,MAAM,IAAI,KAAK,CAAC,UAAU,IAAI,mBAAmB,CAAC,CAAC;YACrD,CAAC;YACD,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;YACnB,CAAC,EAAE,CAAC;QACN,CAAC;IACH,CAAC;IACD,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;AACzC,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,UAAU,CAAC,OAAe;IACxC,OAAO,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO,CAAC,CAAC;AACzE,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,IAAI,CAAC,OAAe,EAAE,IAAI,GAAG,CAAC;IAC5C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,OAAO,IAAI,CAAC,CAAC;IACrC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACrB,CAAC;AAED,2DAA2D;AAC3D,MAAM,UAAU,IAAI,CAAC,MAAe;IAClC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;AAC/D,CAAC"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * deskwork plugin configuration.
3
+ *
4
+ * A host project is "installed" by writing a `.deskwork/config.json` at the
5
+ * project root. The config tells the plugin where content lives, where to
6
+ * keep the editorial calendar, and which sites the project hosts.
7
+ *
8
+ * The schema is intentionally minimal — one version, one set of required
9
+ * fields per site, no hidden defaults. `parseConfig` validates an unknown
10
+ * JSON value and returns a typed DeskworkConfig or throws an Error whose
11
+ * message tells the user which field is wrong.
12
+ */
13
+ /** Current config schema version. Bumped only with a migration path. */
14
+ export declare const CONFIG_VERSION = 1;
15
+ /** A single site the host project publishes to. */
16
+ export interface SiteConfig {
17
+ /**
18
+ * Bare public hostname, no protocol (e.g. `audiocontrol.org`). Optional —
19
+ * required only when the collection is rendered as a website. Internal-doc
20
+ * collections, books, or tool monorepos that use deskwork purely for
21
+ * content-lifecycle management omit this field.
22
+ */
23
+ host?: string;
24
+ /** Blog content directory, relative to the project root */
25
+ contentDir: string;
26
+ /** Editorial calendar markdown file, relative to the project root */
27
+ calendarPath: string;
28
+ /** Optional cross-posting channels JSON file, relative to the project root */
29
+ channelsPath?: string;
30
+ /**
31
+ * Value to set on new blog posts' `layout:` frontmatter field. Typically a
32
+ * relative path like `../../layouts/BlogLayout.astro`. Only emitted when
33
+ * set — projects using Astro content collections usually leave this unset
34
+ * (layout resolution happens in the collection config instead).
35
+ */
36
+ blogLayout?: string;
37
+ /**
38
+ * Path template for scaffolded blog files, relative to `contentDir`. Uses
39
+ * `{slug}` as the placeholder. Defaults to `"{slug}/index.md"` (directory-
40
+ * style). Astro content collections typically use `"{slug}.md"` (flat).
41
+ */
42
+ blogFilenameTemplate?: string;
43
+ /**
44
+ * Value to set on the scaffolded post's `state:` frontmatter field. When
45
+ * set, the line `state: <value>` is emitted. Typical value: `"draft"`.
46
+ * Host projects that gate prod builds on `state !== "draft"` use this to
47
+ * keep in-flight posts out of production.
48
+ */
49
+ blogInitialState?: string;
50
+ /**
51
+ * If true, the scaffolder inserts a `## Outline` section (with a placeholder
52
+ * comment) between the H1 and the body placeholder. Default false.
53
+ */
54
+ blogOutlineSection?: boolean;
55
+ /**
56
+ * Path to the site's `_redirects` file (Netlify-style), relative to
57
+ * the project root. The slug-rename helper appends 301 redirects here
58
+ * when an existing post is renamed. Optional — when unset, slug-rename
59
+ * skips the redirect-append step.
60
+ */
61
+ redirectsPath?: string;
62
+ }
63
+ /** Top-level deskwork config. */
64
+ export interface DeskworkConfig {
65
+ version: typeof CONFIG_VERSION;
66
+ /** Sites keyed by slug (matches the directory segment under `src/sites/<slug>/`). */
67
+ sites: Record<string, SiteConfig>;
68
+ /** Which site to target when no `--site` argument is passed. */
69
+ defaultSite: string;
70
+ /** Author name for new blog posts' `author:` frontmatter field (optional). */
71
+ author?: string;
72
+ /**
73
+ * Review journal directory relative to the project root. Defaults to
74
+ * `.deskwork/review-journal`. Host projects migrating from a prior layout
75
+ * can point this at an existing directory (e.g. `journal/editorial`).
76
+ */
77
+ reviewJournalDir?: string;
78
+ }
79
+ /** Return the absolute path to `.deskwork/config.json` under a project root. */
80
+ export declare function configPath(projectRoot: string): string;
81
+ /**
82
+ * Validate and normalize an unknown value as a DeskworkConfig.
83
+ *
84
+ * Throws an Error with a specific message when the value doesn't match the
85
+ * schema. On success, returns a fresh typed object — callers can mutate it
86
+ * without worrying about shared references.
87
+ */
88
+ export declare function parseConfig(value: unknown): DeskworkConfig;
89
+ /** Read and parse the deskwork config for a project root. */
90
+ export declare function readConfig(projectRoot: string): DeskworkConfig;
91
+ //# sourceMappingURL=config.d.ts.map