@hardikg/mdview 0.7.1 → 0.9.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.
Files changed (100) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/README.md +76 -9
  3. package/bin/mdview.mjs +986 -258
  4. package/dist/client/assets/abnfDiagram-VCTEODGH-d5-zUW3h.js +1 -0
  5. package/dist/client/assets/{arc-DYMLyL-_.js → arc-DIbSNhHb.js} +1 -1
  6. package/dist/client/assets/architectureDiagram-5GKGNRK7-Cq_KBCV9.js +36 -0
  7. package/dist/client/assets/blockDiagram-NRAW4CY4-CKgrJGzB.js +129 -0
  8. package/dist/client/assets/c4Diagram-UCG6FXSJ-CamsXU_i.js +38 -0
  9. package/dist/client/assets/channel-MJp4QxQY.js +1 -0
  10. package/dist/client/assets/{chunk-QZHKN3VN-Cd7CcXLC.js → chunk-2Q5K7J3B-DHB85OBA.js} +1 -1
  11. package/dist/client/assets/{chunk-FMBD7UC4-BYGwnUQ4.js → chunk-5VM5RSS4-C3v07bfZ.js} +1 -1
  12. package/dist/client/assets/{chunk-ND2GUHAM-TheCoD51.js → chunk-F27PBJKO-bDA5q_T9.js} +1 -1
  13. package/dist/client/assets/chunk-G27WJ6UU-DjS6mkGt.js +231 -0
  14. package/dist/client/assets/{chunk-4BX2VUAB-By-ok8D7.js → chunk-JWPE2WC7-ln94eTAD.js} +1 -1
  15. package/dist/client/assets/{chunk-727SXJPM-Bj1JFNtT.js → chunk-LCL6LL3I-SEXOnCPG.js} +4 -4
  16. package/dist/client/assets/chunk-POPQ4Y6H-Dpgmgmgq.js +1 -0
  17. package/dist/client/assets/chunk-SVP7TREG-C_qgSQCy.js +88 -0
  18. package/dist/client/assets/{chunk-55IACEB6-BDUDnCl9.js → chunk-XXDRQBXY-CguISEfl.js} +1 -1
  19. package/dist/client/assets/classDiagram-DTDB5LWJ-BlbBfPMZ.js +1 -0
  20. package/dist/client/assets/classDiagram-v2-JRS7N3AN-BlbBfPMZ.js +1 -0
  21. package/dist/client/assets/{cose-bilkent-S5V4N54A-Br-CySzr.js → cose-bilkent-JH36ORCC-CjtLn09K.js} +1 -1
  22. package/dist/client/assets/cynefin-OW5HDTMX-BgNmTgCR.js +178 -0
  23. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-BFfuQ7YY.js +62 -0
  24. package/dist/client/assets/cytoscape.esm-BjAbmLdb.js +331 -0
  25. package/dist/client/assets/dagre-3AP2YEHR-BDLHOy1Z.js +4 -0
  26. package/dist/client/assets/diagram-S7CK7UJ4-CfzUQiTU.js +30 -0
  27. package/dist/client/assets/diagram-UQ7AKVKN-Ds3lTKuY.js +41 -0
  28. package/dist/client/assets/{diagram-KO2AKTUF-mwoLS2TK.js → diagram-VSXAHHWV-lwAuvia3.js} +3 -3
  29. package/dist/client/assets/diagram-VX7I27RA-CsU4EPwU.js +24 -0
  30. package/dist/client/assets/{diagram-LMA3HP47-4o7ohGjJ.js → diagram-Z3DM3KII-DFieIgnM.js} +2 -2
  31. package/dist/client/assets/ebnfDiagram-PWID7BFC-BzR_CBzj.js +1 -0
  32. package/dist/client/assets/erDiagram-SSCWMZ5O-joYlyDrM.js +99 -0
  33. package/dist/client/assets/flowDiagram-A5DVABFB-DVyMxsTJ.js +168 -0
  34. package/dist/client/assets/ganttDiagram-EL5Y4UJY-Cf4FwZsI.js +292 -0
  35. package/dist/client/assets/{gitGraphDiagram-PVQCEYII-eN40bRnz.js → gitGraphDiagram-WWUBYQGX-9grceorS.js} +7 -7
  36. package/dist/client/assets/index-7zMmn_PY.js +2 -0
  37. package/dist/client/assets/index-CcKPW3Oc.css +1 -0
  38. package/dist/client/assets/infoDiagram-RXCK75RN-ja-7F4cO.js +2 -0
  39. package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-BDIzsJJZ.js → ishikawaDiagram-5VMMS53U-uRRSMmsi.js} +5 -5
  40. package/dist/client/assets/{journeyDiagram-JHISSGLW-BfWwpj1w.js → journeyDiagram-EYS64GPL-BdD_OYKc.js} +1 -1
  41. package/dist/client/assets/{kanban-definition-UN3LZRKU-Cuij1uoR.js → kanban-definition-3QL26DDD-3rMqnFFk.js} +8 -8
  42. package/dist/client/assets/katex-C5jXJg4s.js +257 -0
  43. package/dist/client/assets/katex.min-BYZTj3zW.css +1 -0
  44. package/dist/client/assets/katex.min-DXaO1tdm.js +1 -0
  45. package/dist/client/assets/layout-3dyJkKek.js +1 -0
  46. package/dist/client/assets/{linear-CZOgGL8m.js → linear-B49R1aTA.js} +1 -1
  47. package/dist/client/assets/mermaid.core-CVM43n3z.js +312 -0
  48. package/dist/client/assets/{mindmap-definition-RKZ34NQL-BbNc5LRE.js → mindmap-definition-FBJOCRG2-B8QesUuH.js} +1 -1
  49. package/dist/client/assets/pegDiagram-XKGWAZYB-BeO8X3By.js +1 -0
  50. package/dist/client/assets/pieDiagram-E7YTZNPT-DD3M93Je.js +39 -0
  51. package/dist/client/assets/{quadrantDiagram-W4KKPZXB-CmJGRE1L.js → quadrantDiagram-AXDQQJYC-LxJ8Qxzg.js} +3 -3
  52. package/dist/client/assets/railroadDiagram-O6MQD6OU-Cc6-wuTB.js +1 -0
  53. package/dist/client/assets/{requirementDiagram-4Y6WPE33-Dp-nBLhC.js → requirementDiagram-EFPCY7ZU-D-vaSng7.js} +5 -5
  54. package/dist/client/assets/sankeyDiagram-P5KCCOFB-C-SrB4wj.js +40 -0
  55. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-BpUTXTa1.js +162 -0
  56. package/dist/client/assets/sizeCapture-X5ZJPWSS-BG1rRkMg.js +1 -0
  57. package/dist/client/assets/stateDiagram-HBIQ2CUA-CAsJ9kP3.js +1 -0
  58. package/dist/client/assets/stateDiagram-v2-4QOOHH4V-ssPfmTD6.js +1 -0
  59. package/dist/client/assets/swimlanes-XN3QIQJK-DH5txxCi.js +1 -0
  60. package/dist/client/assets/swimlanesDiagram-VK2B7HYN-Cqi1auey.js +8 -0
  61. package/dist/client/assets/{timeline-definition-PNZ67QCA-uVQ-oiv8.js → timeline-definition-24CTP7MA-DPSR_k-5.js} +3 -3
  62. package/dist/client/assets/vennDiagram-4TSXK5OY-CRMSJqLq.js +34 -0
  63. package/dist/client/assets/{wardleyDiagram-YWT4CUSO-BQMj40Ao.js → wardleyDiagram-VM6X3IG4-DRCnYQxB.js} +4 -4
  64. package/dist/client/assets/xychartDiagram-S5SC5T6Z-x5N3gqvJ.js +7 -0
  65. package/dist/client/bootstrap.js +13 -2
  66. package/dist/client/index.html +2 -2
  67. package/package.json +3 -3
  68. package/dist/client/assets/architectureDiagram-3BPJPVTR-iXijJkGs.js +0 -36
  69. package/dist/client/assets/blockDiagram-GPEHLZMM-Dmjj2Ajf.js +0 -132
  70. package/dist/client/assets/c4Diagram-AAUBKEIU-kJb6eQJJ.js +0 -10
  71. package/dist/client/assets/channel-DirF0LQF.js +0 -1
  72. package/dist/client/assets/chunk-2J33WTMH-T3vdO-20.js +0 -1
  73. package/dist/client/assets/chunk-AQP2D5EJ-BPZWXvxS.js +0 -231
  74. package/dist/client/assets/classDiagram-4FO5ZUOK-CdoMz3xi.js +0 -1
  75. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-CdoMz3xi.js +0 -1
  76. package/dist/client/assets/cytoscape.esm-D_LviqZs.js +0 -331
  77. package/dist/client/assets/dagre-BM42HDAG-DcIxclFu.js +0 -4
  78. package/dist/client/assets/diagram-2AECGRRQ-C0xPdtMR.js +0 -43
  79. package/dist/client/assets/diagram-5GNKFQAL-B9i7DtoQ.js +0 -10
  80. package/dist/client/assets/diagram-OG6HWLK6-C6rhUBe2.js +0 -24
  81. package/dist/client/assets/erDiagram-TEJ5UH35-smNcu7Lp.js +0 -85
  82. package/dist/client/assets/flowDiagram-I6XJVG4X-CPuYTxJr.js +0 -162
  83. package/dist/client/assets/ganttDiagram-6RSMTGT7-xaV0Djok.js +0 -292
  84. package/dist/client/assets/graph-CAnANduQ.js +0 -1
  85. package/dist/client/assets/index-Cmcberpw.css +0 -1
  86. package/dist/client/assets/index-OFdfWE8x.js +0 -2
  87. package/dist/client/assets/infoDiagram-5YYISTIA-xm1BEpfJ.js +0 -2
  88. package/dist/client/assets/katex-DkKDou_j.js +0 -257
  89. package/dist/client/assets/katex.min-CfVKi3_s.css +0 -1
  90. package/dist/client/assets/katex.min-DBnXG_UH.js +0 -1
  91. package/dist/client/assets/layout-DGIYPm2g.js +0 -1
  92. package/dist/client/assets/mermaid.core-B1i-ZGkv.js +0 -309
  93. package/dist/client/assets/pieDiagram-4H26LBE5-oB2YhWwR.js +0 -30
  94. package/dist/client/assets/sankeyDiagram-5OEKKPKP-DB5dqk7n.js +0 -40
  95. package/dist/client/assets/sequenceDiagram-3UESZ5HK-jmqrpzCx.js +0 -162
  96. package/dist/client/assets/stateDiagram-AJRCARHV-U6m2A9Wk.js +0 -1
  97. package/dist/client/assets/stateDiagram-v2-BHNVJYJU-00c0MW6J.js +0 -1
  98. package/dist/client/assets/vennDiagram-CIIHVFJN-By-tXl41.js +0 -34
  99. package/dist/client/assets/wardley-L42UT6IY-ByB1C5d8.js +0 -173
  100. package/dist/client/assets/xychartDiagram-2RQKCTM6-7czjL7-G.js +0 -7
package/CHANGELOG.md CHANGED
@@ -7,6 +7,66 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.9.0] — 2026-09-14
11
+
12
+ Eight palettes, each with its own ground texture — and code blocks that are
13
+ smaller than they were at five.
14
+
15
+ ### Added
16
+ - **Five new palettes: Everforest, Rosé Pine, Kanagawa, Catppuccin, and Flexoki** — each with a full light and dark variant and its own Shiki theme pair, so code blocks stay inside the palette. Base colours come from each project's own palette file; all six upstream projects are MIT.
17
+ - **Each palette now has its own ground texture.** Previously one texture was defined per light/dark theme, so a warm brown grain (`rgba(120, 70, 30, …)`) was washed over every palette including the cool ones. There are now three patterns, assigned per palette: a dot grain tinted with the palette's own ink on the paper-like palettes (flexoki, paper, solarized), fibre noise on the two lowest-contrast grounds (everforest, kanagawa), and an accent wash — a wide bleed of the palette's accent down from the top edge — on rose-pine and catppuccin. `high-contrast` gets none, because texture over a maximum-contrast ground works against the one thing that palette exists to provide. The noise is an SVG `feTurbulence` data URI, which the existing `img-src 'self' data: blob:` already permits, so the CSP is untouched.
18
+
19
+ Texture is deliberately not a setting. It is part of a palette's identity, and a four-way picker crossed with eight palettes is 32 combinations nobody would author or test.
20
+ - **VS Code extension: two-way cursor sync.** Clicking a heading or an internal link in the preview moves the editor cursor and reveals the line; moving the cursor in the editor scrolls the preview to the nearest heading at or above that line, debounced at 80ms. A suppression window breaks the feedback loop so VS Code's own selection-change event isn't echoed back as a jitter loop. Inbound paths from the webview are canonicalized with `realpath` and rejected unless they stay inside the workspace folder. The extension is still unpublished (`0.1.0`).
21
+ - VS Code extension: `mdview: Open in Browser` command, and the preview now follows the active editor and the VS Code colour theme.
22
+
23
+ ### Changed
24
+ - **Code blocks are rendered for the active palette only, and are far smaller for it.** Every token used to carry one CSS variable per (palette, mode) pair, so adding palettes inflated every document that contained code — 16 variables per token at eight palettes. A token now carries two, `--shiki-light` and `--shiki-dark`. `/api/file` accepts a `palette` query param, checked against the allow-list and falling back to the default rather than failing the request, and the client refetches when you change palette. The light/dark toggle still repaints with no request, since both its variants ship in every response. `test-fixtures/showcase.md` went from 204 KB to 30 KB — smaller than it was before any of the new palettes landed.
25
+ - **Flexoki is the new default palette**, replacing `classic`. It keeps the warm-cream editorial look but is built on a measured 15-step base ramp rather than hand-picked creams, and it is the only palette here designed for reading prose rather than for reading code.
26
+ - The VS Code extension's `auto` palette no longer picks a different palette for light and dark themes. Light versus dark is a separate axis in the renderer — every palette defines both — so `auto` now follows only the high-contrast kinds and otherwise leaves the palette alone.
27
+
28
+ ### Removed
29
+ - **The `classic` and `nord` palettes.** `--palette classic` and `--palette nord` now exit non-zero and list the valid names. A `palette` of either in `.mdview.json` or a stale one in `localStorage` degrades silently to the default, which is the existing behaviour for any unrecognised palette — no migration needed.
30
+ - The VS Code extension drops both from the `mdview.palette` setting enum.
31
+
32
+ ### Security
33
+ - `fastify` 5.8.5 → 5.12.3. Closes a schema-validation bypass via root primitive coercion (GHSA-w2qp-rph6-63g4) and `X-Forwarded-*` spoofing under `trustProxy` hop-count (GHSA-3m5p-2c4r-xxw2). Neither is reachable here — the server defines no root-primitive schemas and never sets `trustProxy` — but the dep ships to users.
34
+ - `js-yaml` 3.15.1 → 3.15.2 (transitively, via `gray-matter`). Closes unbounded CPU use on empty merge sources (GHSA-2883-xcg3-v3hh). This one is reachable: `js-yaml` parses frontmatter out of whatever markdown the user opens.
35
+
36
+ ## [0.8.1] — 2026-08-24
37
+
38
+ ### Fixed
39
+ - Live reload stopped working for any URL that named a file without its root id — a bookmark from before 0.8.0, or the VS Code extension sending a workspace-relative path. Such a request resolves against the primary root and the server answers with the workspace-scoped path, but the page kept comparing watch events against the path it had asked for, so nothing ever matched and the document silently stopped updating on save. The comparison now uses the path the server actually served. The first load always worked, which is why this got past the 0.8.0 checks.
40
+
41
+ ## [0.8.0] — 2026-08-24
42
+
43
+ One background server, many folders. `mdview <path>` no longer holds the terminal.
44
+
45
+ ### Added
46
+ - **`mdview <path>` returns the shell.** It starts one detached background server the first time it's needed; every later `mdview <path>`, in any repo, adds that folder to the same server and opens it. So unrelated folders — `~/work/api/docs` and `~/notes` — can be read side by side in one window at one stable URL. `--foreground` (`-f`) runs a server in the terminal as before.
47
+ - `mdview ls` (open folders, server pid/port, log path), `mdview rm <name|path>…` (stop serving a folder), `mdview stop` (stop the server).
48
+ - Folders persist in `~/.config/mdview/workspace.json` until removed, across restarts and reboots. Capped at 8, because each holds a live recursive watcher. Opening a file or subfolder inside an already-open folder reuses it instead of adding a duplicate.
49
+ - The background server runs until `mdview stop` or a reboot. `MDVIEW_IDLE_TIMEOUT` opts into having it exit after that many minutes with no browser tab connected (it clears its record, and the next `mdview` starts it again) — off by default, since a server that stays put keeps the URL reliable.
50
+ - `--port` and `--palette` now imply `--foreground`: each overrides a setting belonging to a whole server, and the background one is shared. A useful side effect is that every invocation that worked before behaves exactly as it did — only the bare `mdview [path]` form changed.
51
+ - The printed and opened URL is now `http://mdview.localhost:7331/` instead of `http://127.0.0.1:7331/`. `*.localhost` is reserved to loopback by RFC 6761 and resolves with no setup, no `/etc/hosts` entry and no privileges; the server still binds `127.0.0.1` only. If the local resolver doesn't answer the name with a loopback address the CLI falls back to the literal address rather than printing a URL that could leave the machine. `--vscode` keeps `127.0.0.1` unconditionally, because the extension validates that exact prefix.
52
+ - `PORT` is honoured as the default port when `--port` is omitted, so mdview runs unchanged under a local reverse proxy such as [portless](https://github.com/vercel-labs/portless) for a port-free URL. Invalid values are ignored rather than fatal.
53
+
54
+ ### Changed
55
+ - **Paths in URLs are now workspace-scoped**: `?file=docs/api.md` becomes `?file=<rootId>/docs/api.md`, and asset URLs become `/__asset/<rootId>/<path>`. This is what lets one server host several unrelated folders at once. An unprefixed path still resolves against the first root, so existing links and existing bookmarks keep working, as does the VS Code extension.
56
+ - `/api/tree` now returns `{ roots, tree, config }`. With a single root its contents stay at the top level exactly as before; a second root is what introduces a folder node per root. Window-level settings (palette, font, line width) come from the first root; `ignore` stays per-root.
57
+ - Folder search covers every open folder root and labels each hit with its root. The 200-hit cap is a budget for the whole search rather than per root.
58
+ - With more than one folder open the sidebar groups each under its own heading, expanded by default. `⌘P` and folder search span every folder and show which one each result is in. Live reload learns a `workspace` event, so a folder opened or closed elsewhere appears in tabs that are already open without a reload. Closing the last folder shows an empty state rather than an endless skeleton.
59
+
60
+ ### Security
61
+ - There is deliberately **no HTTP endpoint that changes which folders are served**. The CLI writes `workspace.json` and the server watches it, so adding a root requires filesystem access, which a web page does not have — nothing to CSRF, and no shared token to store or leak. `/api/health` is read-only and reports ids, a pid and a start time, never absolute paths.
62
+ - `mdview stop` checks the recorded pid **and** its start time against what the process reports before signalling it, so a recycled pid belonging to an unrelated process is never killed.
63
+ - State files are written `0600` inside a `0700` directory, each through a temp file and one rename so a reader never sees a half-written file. `workspace.json` is validated defensively on read: a hand-edited or truncated file degrades to fewer folders, never to a crash or an unchecked path.
64
+ - Concurrent `mdview` invocations are serialised through a lock file, so two shells can't race into two servers fighting over the port.
65
+ - Every request's `Host` header is now checked against a loopback allow-list (`localhost`, `*.localhost`, the loopback literals) in an `onRequest` hook, and anything else gets a bare `403`. Closes a DNS-rebinding hole: binding `127.0.0.1` never stopped a page the user was already browsing from re-resolving its own domain to loopback and reading every file mdview serves. Verified against a running server — `Host: evil.com` returned `200` before this change.
66
+ - `@fastify/static` 9 → 10 (major). Closes two high-severity advisories in the component that serves the SPA: authorization bypass via non-canonical URL paths (GHSA-8pvw-jcv7-9cmj) and route-guard bypass via path traversal (GHSA-83w8-p2f5-377r). The plugin is registered at a single call site with a `root` + `prefix` only, and v10 changes nothing we use — its diff against v9 is `fastify-plugin` ^5 → ^6 and `content-disposition` ^1 → ^2.
67
+ - Lockfile-only bumps clearing five further high-severity shipped-dep advisories: `brace-expansion` (DoS via unbounded expansion), `fast-uri` (host confusion via backslash authority delimiter), `find-my-way` (HTTP/2 DoS), `js-yaml` (quadratic CPU in `!!omap`), `linkify-it` (quadratic `mailto:` scan). `npm audit --omit=dev` is back to zero.
68
+ - The one remaining advisory is the `low`, dev-only `esbuild` one already deferred in 0.7.1: it is reachable only through `tsup`/`vite`, is absent from shipped deps, and never enters the published tarball. `npm audit fix` still cannot resolve it without a breaking parent bump.
69
+
10
70
  ## [0.7.1] — 2026-07-01
11
71
 
12
72
  ### Security
package/README.md CHANGED
@@ -50,26 +50,93 @@ node bin/mdview.mjs ./docs
50
50
  ### Share with friends without publishing
51
51
 
52
52
  ```bash
53
- npm run build && npm pack # produces mdview-0.6.0.tgz
53
+ npm run build && npm pack # produces hardikg-mdview-<version>.tgz
54
54
  ```
55
55
 
56
56
  Send them the `.tgz` (Slack/Drive/AirDrop). They install with:
57
57
 
58
58
  ```bash
59
- npm install -g ./mdview-0.6.0.tgz
59
+ npm install -g ./hardikg-mdview-<version>.tgz
60
60
  ```
61
61
 
62
62
  ## Usage
63
63
 
64
64
  ```bash
65
- mdview <path> # file or folder
65
+ mdview <path> # open a file or folder; the shell comes straight back
66
66
  mdview # current directory
67
- mdview --port 9000 # custom port (default 7331; auto-fallback unless --port is explicit)
67
+ mdview ls # what's open, and where the server is
68
+ mdview rm <name> # stop serving a folder
69
+ mdview stop # stop the background server
70
+ mdview --foreground # run in this terminal instead (Ctrl-C to stop)
68
71
  mdview --no-open # don't auto-launch the browser
72
+ mdview --port 9000 # one-off server on a specific port (implies --foreground)
73
+ mdview --palette kanagawa # palette for this run (implies --foreground)
69
74
  mdview --help # show usage
70
75
  ```
71
76
 
72
- Closes when you `Ctrl-C` or `kill` the process. Set `MDVIEW_DEBUG=1` for full stack traces on unexpected errors.
77
+ ### One server, many folders
78
+
79
+ `mdview` does not hold your terminal. It starts a single background server the
80
+ first time you need one, and every later `mdview <path>` — in any repo — adds
81
+ that folder to the same server and opens it. So you can read
82
+ `~/work/api/docs` and `~/notes` side by side in one window, with one stable
83
+ URL, whether or not the folders are anywhere near each other.
84
+
85
+ ```console
86
+ $ mdview ~/work/api
87
+ mdview → http://mdview.localhost:7331/?root=api
88
+ added: /Users/you/work/api (api)
89
+ $ cd ~/notes && mdview .
90
+ mdview → http://mdview.localhost:7331/?root=notes
91
+ added: /Users/you/notes (notes)
92
+ $ mdview ls
93
+ ● api ~/work/api (primary)
94
+ ● notes ~/notes
95
+
96
+ server: http://mdview.localhost:7331/ (pid 40113)
97
+ logs: ~/.config/mdview/daemon.log
98
+ ```
99
+
100
+ Folders stay open until you remove them with `mdview rm <name>`, across restarts
101
+ and reboots. Up to 8 at a time — each one holds a live file watcher, so the
102
+ limit is there to keep mdview from quietly watching your whole disk. Opening a
103
+ file or subfolder inside a folder that's already open reuses it rather than
104
+ adding a duplicate.
105
+
106
+ The server keeps running until you `mdview stop` it, or you reboot. If you'd
107
+ rather it stood down on its own, set `MDVIEW_IDLE_TIMEOUT` to a number of
108
+ minutes and it will exit that long after the last browser tab disconnects; the
109
+ next `mdview` starts it again.
110
+
111
+ Its state lives in `~/.config/mdview/` (`daemon.json`, `workspace.json`,
112
+ `daemon.log`) and nowhere else. `workspace.json` is also how the CLI talks to
113
+ the server: `mdview <path>` writes the file and the server picks the change up,
114
+ which is why there is no HTTP endpoint that can change what's being served.
115
+
116
+ The URL is `http://mdview.localhost:7331/` — `*.localhost` always resolves to
117
+ loopback (RFC 6761) with no setup, and the server still listens on `127.0.0.1`
118
+ only. If your resolver doesn't answer the name, mdview falls back to printing
119
+ `http://127.0.0.1:<port>/`. Setting `PORT` changes the default port, so mdview
120
+ works as-is behind a local proxy like
121
+ [portless](https://github.com/vercel-labs/portless) if you want the port gone
122
+ entirely.
123
+
124
+ `--palette` takes `flexoki`, `paper`, `solarized`, `everforest`, `rose-pine`,
125
+ `kanagawa`, `catppuccin`, or `high-contrast`.
126
+ It wins over both `.mdview.json` and the global config, and never writes to
127
+ either. There is also a `--vscode` flag, used by the VS Code extension to run
128
+ mdview as a sidecar; it implies `--no-open` and prints a single JSON ready line
129
+ instead of the human-readable output.
130
+
131
+ `--port` and `--palette` both override a setting that belongs to a whole server,
132
+ and the background one is shared with every other folder you have open — so each
133
+ implies `--foreground`, giving you a server of your own. That also means every
134
+ invocation that worked before still behaves exactly as it did; only the bare
135
+ `mdview [path]` form returns the shell now.
136
+
137
+ `--foreground` closes when you `Ctrl-C` or `kill` it. The background server is
138
+ stopped with `mdview stop`. Set `MDVIEW_DEBUG=1` for full stack traces on
139
+ unexpected errors.
73
140
 
74
141
  ## Keyboard shortcuts
75
142
 
@@ -102,7 +169,7 @@ Click the keyboard icon in the header anytime to see the full list.
102
169
  - 3-pane layout: folder tree, content, outline. Both sidebars collapse to a thin label rail; both have drag handles to resize (widths persist).
103
170
  - Editorial typography (serif body, italic accent H1, paper-grain background, JetBrains Mono in code blocks).
104
171
  - Light & dark theme — follows your OS preference, with a manual override that persists.
105
- - Five built-in palettes: classic / paper / nord / solarized / high-contrast. Pick one from the header palette swatch. Code blocks follow the palette (Nord syntax in Nord, Solarized in Solarized, etc.).
172
+ - Eight built-in palettes: flexoki / paper / solarized / everforest / rose-pine / kanagawa / catppuccin / high-contrast. Pick one from the header palette swatch. Each defines a full light and dark variant and its own ground texture: a dot grain on the paper-like palettes, fibre noise on Everforest and Kanagawa, an accent wash on Rosé Pine and Catppuccin, and none at all on high-contrast. Code blocks follow the palette (Everforest syntax in Everforest, Catppuccin in Catppuccin, etc.).
106
173
  - Reading-progress bar pinned to the bottom of the header.
107
174
  - Doc stats strip below the H1 (reading time, word count, heading count, "Updated N ago").
108
175
  - Focus mode dims everything except the section at the viewport center.
@@ -118,7 +185,7 @@ Click the keyboard icon in the header anytime to see the full list.
118
185
 
119
186
  **Rendering**
120
187
  - CommonMark + GFM (tables, task lists, strikethrough, autolinks).
121
- - Server-side syntax highlighting via Shiki, palette-aware (10 variants per token — one for every palette/theme combination) — zero client highlighter bundle, no re-render on theme/palette swap.
188
+ - Server-side syntax highlighting via Shiki, palette-aware: two variants per token, light and dark, for whichever palette is active. Zero client highlighter bundle, and the light/dark toggle repaints with no request.
122
189
  - Mermaid diagrams, lazy-loaded only when a doc contains a `mermaid` fence.
123
190
  - Math via KaTeX (`$inline$` and `$$block$$`), lazy-loaded only when a doc contains math.
124
191
  - Custom-styled task list checkboxes (filled accent when checked, hollow when unchecked).
@@ -150,7 +217,7 @@ Two layered files, both optional, same schema:
150
217
 
151
218
  ```json
152
219
  {
153
- "palette": "nord",
220
+ "palette": "everforest",
154
221
  "fontFamily": "serif",
155
222
  "lineWidth": "70ch",
156
223
  "defaultCollapsed": { "tree": false, "outline": false },
@@ -186,7 +253,7 @@ Node 20+, TypeScript, Fastify 5, markdown-it 14, Shiki 1, gray-matter, chokidar
186
253
  ## Tests
187
254
 
188
255
  ```bash
189
- npm test # vitest, server + client (289 tests)
256
+ npm test # vitest, server + client
190
257
  npm run typecheck # both tsconfigs
191
258
  npm run build # vite (client) + tsup (server CLI)
192
259
  ```