@v1nvn/md 0.45.0 → 0.45.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/README.md CHANGED
@@ -23,9 +23,9 @@ claude plugin install md@agentic
23
23
  In a terminal, last reply or a named file:
24
24
 
25
25
  ```sh
26
- npx -y @v1nvn/md@0.45.0 # editable — both panes
27
- npx -y @v1nvn/md@0.45.0 --view # read-only — preview pane only
28
- npx -y @v1nvn/md@0.45.0 reply.md
26
+ npx -y @v1nvn/md@0.45.1 # editable — both panes
27
+ npx -y @v1nvn/md@0.45.1 --view # read-only — preview pane only
28
+ npx -y @v1nvn/md@0.45.1 reply.md
29
29
  ```
30
30
 
31
31
  ## Usage
@@ -34,10 +34,10 @@ npx -y @v1nvn/md@0.45.0 reply.md
34
34
  |---|---|
35
35
  | `/md-edit` | the previous assistant reply → viewer, edit pane enabled, one dim status row |
36
36
  | `/md-view` | the same share read-only — preview pane only |
37
- | `npx -y @v1nvn/md@0.45.0` | the same share, printed bare |
38
- | `npx -y @v1nvn/md@0.45.0 --view` | read-only share |
39
- | `npx -y @v1nvn/md@0.45.0 reply.md` | that file instead of the last reply |
40
- | `npx -y @v1nvn/md@0.45.0 -` | Markdown from stdin |
37
+ | `npx -y @v1nvn/md@0.45.1` | the same share, printed bare |
38
+ | `npx -y @v1nvn/md@0.45.1 --view` | read-only share |
39
+ | `npx -y @v1nvn/md@0.45.1 reply.md` | that file instead of the last reply |
40
+ | `npx -y @v1nvn/md@0.45.1 -` | Markdown from stdin |
41
41
 
42
42
  `MD_VIEWER_URL` sets the viewer (default `https://md.v1n.space`); any set
43
43
  `MD_NO_OPEN` value (not just `1`) skips opening the browser.
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@v1nvn/md",
3
- "version": "0.45.0",
3
+ "version": "0.45.1",
4
4
  "description": "Send a Markdown reply to the Markdown-Viewer as a #share= URL — the md-send CLI behind the md plugin.",
5
5
  "type": "module",
6
6
  "bin": {
7
- "md-send": "./src/index.ts"
7
+ "md-send": "./src/index.js"
8
8
  },
9
9
  "scripts": {
10
10
  "test": "yarn run -T vitest run",
@@ -34,6 +34,6 @@
34
34
  "node": ">=23.6"
35
35
  },
36
36
  "dependencies": {
37
- "@v1nvn/agentic-core": "0.45.0"
37
+ "@v1nvn/agentic-core": "0.45.1"
38
38
  }
39
39
  }
package/src/index.js ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env node
2
+ import { lastReply, readMarkdownFile, readStdin, runCli, } from '@v1nvn/agentic-core';
3
+ import { mdSend } from "./share.js";
4
+ const spec = {
5
+ name: 'md-send',
6
+ description: 'Send a Markdown reply to the Markdown-Viewer as a #share= URL',
7
+ argument: {
8
+ flags: '[file]',
9
+ description: 'Markdown file, - for stdin; the last reply when omitted',
10
+ },
11
+ options: [
12
+ {
13
+ flags: '--view',
14
+ description: 'open the viewer read-only, without the edit pane',
15
+ },
16
+ ],
17
+ run: async (options, args) => {
18
+ const arg = args.at(0);
19
+ const markdown = arg === '-'
20
+ ? await readStdin()
21
+ : arg === undefined
22
+ ? lastReply()
23
+ : readMarkdownFile(arg);
24
+ console.log(mdSend(markdown, options.view === true));
25
+ },
26
+ };
27
+ process.exitCode = await runCli(spec, process.argv.slice(2));
package/src/index.ts CHANGED
File without changes
package/src/share.js ADDED
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Send Markdown to the self-hosted Markdown-Viewer as a #share= URL — opens it
3
+ * in the browser and copies the URL.
4
+ *
5
+ * md-send path/to/reply.md # from a file
6
+ * md-send - # from stdin
7
+ * md-send # from the last Claude reply (core.lastReply)
8
+ * md-send --view # open read-only (no edit pane)
9
+ *
10
+ * Env knobs: MD_VIEWER_URL (default: https://md.v1n.space), MD_NO_OPEN (any value skips the browser).
11
+ */
12
+ import { spawnSync } from 'node:child_process';
13
+ import { deflateSync } from 'node:zlib';
14
+ /**
15
+ * Encode Markdown into the Markdown-Viewer share token.
16
+ *
17
+ * Pipeline: UTF-8 bytes → zlib deflate (RFC 1950, pako.deflate-compatible) →
18
+ * base64url. Matches Markdown-Viewer's encodeMarkdownForShare() in script.js
19
+ * byte-for-byte — the decoder (pako.inflate) accepts any valid zlib stream, so
20
+ * compression level is irrelevant.
21
+ */
22
+ export function encodeShare(markdown) {
23
+ return deflateSync(Buffer.from(markdown, 'utf8'))
24
+ .toString('base64')
25
+ .replaceAll('+', '-')
26
+ .replaceAll('/', '_')
27
+ .replace(/=+$/, '');
28
+ }
29
+ export function shareUrl(markdown, view = false) {
30
+ const base = (process.env.MD_VIEWER_URL ?? 'https://md.v1n.space').replace(/\/+$/, '');
31
+ const mode = view ? '' : '&edit=1';
32
+ // Without `edit=1` the viewer opens the snapshot read-only — preview pane
33
+ // only, with edit and split disabled (Markdown-Viewer script.js: loadFromShareHash).
34
+ return `${base}/#share=${encodeShare(markdown)}${mode}`;
35
+ }
36
+ function copyToClipboard(text) {
37
+ try {
38
+ return (spawnSync('pbcopy', { input: text, stdio: ['pipe', 'ignore', 'ignore'] })
39
+ .status === 0);
40
+ }
41
+ catch {
42
+ return false;
43
+ }
44
+ }
45
+ function openUrl(url) {
46
+ try {
47
+ return spawnSync('open', [url], { stdio: 'ignore' }).status === 0;
48
+ }
49
+ catch {
50
+ return false;
51
+ }
52
+ }
53
+ export function statusLine(opened, copied) {
54
+ if (opened && copied) {
55
+ return 'Opened in Markdown-Viewer (link copied).';
56
+ }
57
+ if (opened) {
58
+ return 'Opened in Markdown-Viewer.';
59
+ }
60
+ if (copied) {
61
+ return 'Markdown-Viewer link copied to clipboard.';
62
+ }
63
+ return 'Markdown-Viewer link ready.';
64
+ }
65
+ /** Shares the markdown and returns the status line; the URL itself is never printed. */
66
+ export function mdSend(markdown, view = false) {
67
+ const url = shareUrl(markdown, view);
68
+ const copied = copyToClipboard(url);
69
+ const opened = process.env.MD_NO_OPEN === undefined && openUrl(url);
70
+ return statusLine(opened, copied);
71
+ }