bikeshed-now 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -30,6 +30,10 @@ bikeshed comments storage-migration
30
30
  # Fix that sentence, publish the revision, and say what you changed.
31
31
  bikeshed update storage-migration proposal.md
32
32
  bikeshed reply storage-migration <thread> "Rewritten to describe the dual-write period."
33
+
34
+ # Given "Can suggest" rather than "Can edit"? Propose the change instead, for a
35
+ # person to accept or reject.
36
+ bikeshed suggest storage-migration "a single weekend" --with "two weekends"
33
37
  ```
34
38
 
35
39
  Publishing identical bytes is a no-op: the bundle is hashed, and a matching hash
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bikeshed-now",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "description": "Publish and revise documents on a Bikeshed deployment from the terminal.",
package/src/client.mjs CHANGED
@@ -4,7 +4,7 @@
4
4
  import { readFileSync } from "node:fs";
5
5
  import { basename } from "node:path";
6
6
 
7
- export const CLIENT_NAME = "bikeshed-cli/0.5.0";
7
+ export const CLIENT_NAME = "bikeshed-cli/0.6.0";
8
8
 
9
9
  /**
10
10
  * Three surfaces, and the split is deliberate rather than untidy.
package/src/index.mjs CHANGED
@@ -44,6 +44,10 @@ const USAGE = `bikeshed — publish and revise documents
44
44
  bikeshed get <id> print a document's source
45
45
  bikeshed comments <id> unresolved feedback, with its anchored text
46
46
  bikeshed reply <id> <thread> <text> reply in a thread
47
+ bikeshed suggest <id> <text> --with <new text>
48
+ propose new text for a passage, for a
49
+ person to accept or reject (--delete to
50
+ propose removing it)
47
51
  bikeshed open <id> open it in a browser
48
52
 
49
53
  Where a command takes <id> it also takes the link you were sent. An unlisted
@@ -82,6 +86,11 @@ Options
82
86
  --limit <n> with list: rows per page (default 20, max 50)
83
87
  --cursor <id> with list: the page after the one that printed it
84
88
  --all with list: every page; with comments: resolved too
89
+ --with <text> with suggest: what the passage should say instead
90
+ --delete with suggest: propose deleting the passage
91
+ --note <text> with suggest: why, for whoever decides
92
+ --prefix <text> with suggest: words just before a passage that repeats
93
+ --suffix <text> with suggest: words just after it
85
94
  --watch with publish/update: republish on every save
86
95
  --origin <url> the deployment (default: the one you logged in to)
87
96
  --token <token> override the stored token
@@ -303,6 +312,12 @@ async function comments(flags, [ref]) {
303
312
  // which passage to change without opening the document.
304
313
  console.log(`\n── ${thread.threadId}${thread.section ? ` (${thread.section})` : ""}`);
305
314
  if (thread.quote) console.log(` “${thread.quote}”`);
315
+ // A suggested edit says what the passage would become, and whether a
316
+ // person has decided it yet (SPEC §22).
317
+ if (thread.suggestion) {
318
+ const change = thread.suggestion.replacement === "" ? "(delete it)" : `“${thread.suggestion.replacement}”`;
319
+ console.log(` → ${change} [${thread.suggestion.state}]`);
320
+ }
306
321
  for (const comment of thread.comments) {
307
322
  const via = comment.via && comment.via !== "web" ? ` [via ${comment.via}]` : "";
308
323
  console.log(` ${comment.author}${via}: ${comment.body}`);
@@ -324,6 +339,34 @@ async function reply(flags, [ref, threadId, ...rest]) {
324
339
  out(flags.json, result, () => console.log(`replied in ${threadId}`));
325
340
  }
326
341
 
342
+ /**
343
+ * Propose new text for one passage of a document's current version. The
344
+ * passage is quoted as a reader sees it, which is how `comments` prints it, so
345
+ * a quote can go straight from one command to the other.
346
+ */
347
+ async function suggest(flags, [ref, ...rest]) {
348
+ const exact = rest.join(" ");
349
+ const usage = "usage: bikeshed suggest <id> <text> (--with <new text> | --delete) [--note <why>]";
350
+ if (!ref || !exact) fail(usage);
351
+ const replacing = typeof flags.with === "string";
352
+ if (replacing === Boolean(flags.delete)) fail(usage);
353
+ // An empty --with is what an unset shell variable sends; deleting a passage
354
+ // has to be asked for by name.
355
+ if (replacing && flags.with === "") fail("an empty --with would delete the passage; say --delete if you mean that");
356
+ const { origin, token } = resolveAuth(flags);
357
+ const result = await callTool(origin, token, "suggest_edit", {
358
+ ...docArgs(ref),
359
+ exact,
360
+ replacement: replacing ? flags.with : "",
361
+ ...(typeof flags.note === "string" ? { note: flags.note } : {}),
362
+ ...(typeof flags.prefix === "string" ? { prefix: flags.prefix } : {}),
363
+ ...(typeof flags.suffix === "string" ? { suffix: flags.suffix } : {}),
364
+ });
365
+ out(flags.json, result, () =>
366
+ console.log(`suggested in ${result.threadId}; a person who can approve will accept or reject it`),
367
+ );
368
+ }
369
+
327
370
  async function folders(flags) {
328
371
  const { origin, token } = resolveAuth(flags);
329
372
  const result = await callTool(origin, token, "list_folders", {});
@@ -528,6 +571,7 @@ const COMMANDS = {
528
571
  get,
529
572
  comments,
530
573
  reply,
574
+ suggest,
531
575
  open,
532
576
  folders,
533
577
  mkdir,
@@ -557,6 +601,11 @@ async function main() {
557
601
  token: { type: "string" },
558
602
  limit: { type: "string" },
559
603
  cursor: { type: "string" },
604
+ with: { type: "string" },
605
+ delete: { type: "boolean", default: false },
606
+ note: { type: "string" },
607
+ prefix: { type: "string" },
608
+ suffix: { type: "string" },
560
609
  },
561
610
  });
562
611