@peaske7/readit 0.2.0 → 0.2.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.
Files changed (173) hide show
  1. package/.claude/CLAUDE.md +118 -76
  2. package/.claude/commands/review.md +1 -1
  3. package/.claude/roadmap.md +32 -9
  4. package/.claude/user-stories.md +100 -15
  5. package/AGENTS.md +30 -26
  6. package/Makefile +32 -0
  7. package/README.md +90 -2
  8. package/biome.json +18 -8
  9. package/bun.lock +426 -568
  10. package/bunfig.toml +2 -0
  11. package/docs/perf-baseline.md +56 -1
  12. package/docs/superpowers/specs/2026-03-27-go-server-rewrite-design.md +284 -0
  13. package/e2e/comments.spec.ts +14 -58
  14. package/e2e/document-load.spec.ts +1 -23
  15. package/e2e/export.spec.ts +4 -4
  16. package/e2e/perf/add-comment.spec.ts +9 -11
  17. package/e2e/perf/fixtures/generate.ts +1 -5
  18. package/e2e/perf/screenshot-final.png +0 -0
  19. package/e2e/perf/utils/metrics.ts +73 -9
  20. package/e2e/persistence-file.spec.ts +41 -26
  21. package/e2e/utils/selection.ts +17 -73
  22. package/go/cmd/readit/main.go +416 -0
  23. package/go/go.mod +20 -0
  24. package/go/go.sum +41 -0
  25. package/go/internal/server/anchor.go +302 -0
  26. package/go/internal/server/anchor_test.go +111 -0
  27. package/go/internal/server/comments.go +390 -0
  28. package/go/internal/server/documents.go +113 -0
  29. package/go/internal/server/embed.go +17 -0
  30. package/go/internal/server/headings.go +33 -0
  31. package/go/internal/server/headings_test.go +75 -0
  32. package/go/internal/server/htmltext.go +123 -0
  33. package/go/internal/server/markdown.go +157 -0
  34. package/go/internal/server/markdown_bench_test.go +42 -0
  35. package/go/internal/server/markdown_test.go +79 -0
  36. package/go/internal/server/server.go +453 -0
  37. package/go/internal/server/server_bench_test.go +122 -0
  38. package/go/internal/server/settings.go +110 -0
  39. package/go/internal/server/sse.go +140 -0
  40. package/go/internal/server/storage.go +275 -0
  41. package/go/internal/server/storage_test.go +118 -0
  42. package/go/internal/server/template.go +66 -0
  43. package/go/internal/server/types.go +101 -0
  44. package/go/internal/server/watcher.go +74 -0
  45. package/index.html +4 -14
  46. package/nvim-readit/lua/readit/health.lua +64 -0
  47. package/nvim-readit/lua/readit/init.lua +463 -0
  48. package/nvim-readit/plugin/readit.lua +19 -0
  49. package/package.json +20 -28
  50. package/shell/_readit +158 -0
  51. package/shell/readit.zsh +87 -0
  52. package/src/App.svelte +881 -0
  53. package/src/cli.ts +183 -21
  54. package/src/components/ActionsMenu.svelte +95 -0
  55. package/src/components/CommentBadge.svelte +67 -0
  56. package/src/components/CommentErrorBanner.svelte +33 -0
  57. package/src/components/CommentInput.svelte +75 -0
  58. package/src/components/CommentListItem.svelte +95 -0
  59. package/src/components/CommentManager.svelte +129 -0
  60. package/src/components/CommentNav.svelte +109 -0
  61. package/src/components/DocumentViewer.svelte +218 -0
  62. package/src/components/FloatingComment.svelte +107 -0
  63. package/src/components/Header.svelte +76 -0
  64. package/src/components/InlineEditor.svelte +72 -0
  65. package/src/components/MarginNote.svelte +167 -0
  66. package/src/components/MarginNotesContainer.svelte +33 -0
  67. package/src/components/RawModal.svelte +126 -0
  68. package/src/components/ReanchorConfirm.svelte +30 -0
  69. package/src/components/SettingsModal.svelte +220 -0
  70. package/src/components/ShortcutCapture.svelte +82 -0
  71. package/src/components/ShortcutList.svelte +145 -0
  72. package/src/components/TabBar.svelte +52 -0
  73. package/src/components/TableOfContents.svelte +125 -0
  74. package/src/components/ui/ActionLink.svelte +40 -0
  75. package/src/components/ui/{Button.tsx → Button.svelte} +19 -20
  76. package/src/components/ui/Dialog.svelte +97 -0
  77. package/src/components/ui/DropdownMenu.svelte +85 -0
  78. package/src/components/ui/DropdownMenuItem.svelte +38 -0
  79. package/src/components/ui/DropdownMenuSeparator.svelte +11 -0
  80. package/src/components/ui/{Text.tsx → Text.svelte} +18 -23
  81. package/src/env.d.ts +6 -0
  82. package/src/index.css +36 -166
  83. package/src/lib/__fixtures__/bench-data.ts +0 -13
  84. package/src/lib/anchor.bench.ts +1 -12
  85. package/src/lib/anchor.test.ts +0 -8
  86. package/src/lib/anchor.ts +0 -4
  87. package/src/lib/comment-storage.bench.ts +49 -0
  88. package/src/lib/comment-storage.test.ts +41 -33
  89. package/src/lib/comment-storage.ts +21 -18
  90. package/src/lib/export.bench.ts +21 -0
  91. package/src/lib/export.ts +0 -1
  92. package/src/{hooks/useHeadings.test.ts → lib/headings.test.ts} +10 -24
  93. package/src/{hooks/useHeadings.ts → lib/headings.ts} +11 -13
  94. package/src/lib/highlight/core.test.ts +0 -5
  95. package/src/lib/highlight/dom.ts +52 -216
  96. package/src/lib/highlight/highlight-registry.ts +221 -0
  97. package/src/lib/highlight/highlight.bench.ts +92 -0
  98. package/src/lib/highlight/highlighter.ts +112 -132
  99. package/src/lib/highlight/resolver.ts +5 -79
  100. package/src/lib/highlight/types.ts +0 -5
  101. package/src/lib/html-text.test.ts +162 -0
  102. package/src/lib/html-text.ts +161 -0
  103. package/src/lib/i18n/en.ts +26 -0
  104. package/src/lib/i18n/ja.ts +26 -0
  105. package/src/lib/i18n/types.ts +25 -0
  106. package/src/lib/margin-layout.bench.ts +61 -0
  107. package/src/lib/margin-layout.ts +0 -7
  108. package/src/lib/markdown-renderer.test.ts +154 -0
  109. package/src/lib/markdown-renderer.ts +177 -0
  110. package/src/lib/mermaid-config.ts +38 -0
  111. package/src/lib/mermaid-renderer.ts +162 -0
  112. package/src/lib/mermaid-worker.ts +60 -0
  113. package/src/lib/positions.ts +31 -24
  114. package/src/lib/shortcut-registry.ts +244 -0
  115. package/src/lib/utils.ts +0 -29
  116. package/src/main.ts +16 -0
  117. package/src/schema.ts +16 -5
  118. package/src/server.ts +355 -91
  119. package/src/stores/app.svelte.ts +231 -0
  120. package/src/stores/locale.svelte.ts +46 -0
  121. package/src/stores/settings.svelte.ts +90 -0
  122. package/src/stores/shortcuts.svelte.ts +104 -0
  123. package/src/stores/ui.svelte.ts +12 -0
  124. package/src/template.ts +104 -0
  125. package/src/test-setup.ts +47 -0
  126. package/svelte.config.js +5 -0
  127. package/tsconfig.json +2 -2
  128. package/vite.config.ts +23 -3
  129. package/vscode-readit/.mcp.json +7 -0
  130. package/vscode-readit/.vscodeignore +7 -0
  131. package/vscode-readit/bun.lock +78 -0
  132. package/vscode-readit/icon.svg +10 -0
  133. package/vscode-readit/package.json +110 -0
  134. package/vscode-readit/src/extension.ts +117 -0
  135. package/vscode-readit/src/server-manager.ts +272 -0
  136. package/vscode-readit/src/webview-provider.ts +204 -0
  137. package/vscode-readit/tsconfig.json +20 -0
  138. package/e2e/fixtures/sample.html +0 -13
  139. package/src/App.tsx +0 -368
  140. package/src/components/ActionsMenu.tsx +0 -91
  141. package/src/components/DocumentViewer/CodeBlock.tsx +0 -160
  142. package/src/components/DocumentViewer/DocumentViewer.tsx +0 -230
  143. package/src/components/DocumentViewer/MermaidDiagram.tsx +0 -136
  144. package/src/components/Header.tsx +0 -54
  145. package/src/components/InlineEditor.tsx +0 -74
  146. package/src/components/MarginNote.tsx +0 -185
  147. package/src/components/MarginNotes.tsx +0 -23
  148. package/src/components/RawModal.tsx +0 -144
  149. package/src/components/ReanchorConfirm.tsx +0 -36
  150. package/src/components/SettingsModal.tsx +0 -232
  151. package/src/components/TabBar.tsx +0 -60
  152. package/src/components/TableOfContents.tsx +0 -108
  153. package/src/components/comments/CommentBadge.tsx +0 -49
  154. package/src/components/comments/CommentInput.tsx +0 -86
  155. package/src/components/comments/CommentListItem.tsx +0 -90
  156. package/src/components/comments/CommentManager.tsx +0 -129
  157. package/src/components/comments/CommentNav.tsx +0 -109
  158. package/src/components/ui/ActionLink.tsx +0 -28
  159. package/src/components/ui/Dialog.tsx +0 -116
  160. package/src/components/ui/DropdownMenu.tsx +0 -158
  161. package/src/contexts/CommentContext.tsx +0 -198
  162. package/src/contexts/LocaleContext.tsx +0 -76
  163. package/src/contexts/PositionsContext.tsx +0 -16
  164. package/src/contexts/SettingsContext.tsx +0 -133
  165. package/src/hooks/useClickOutside.ts +0 -31
  166. package/src/hooks/useCommentNavigation.ts +0 -107
  167. package/src/hooks/useComments.ts +0 -311
  168. package/src/hooks/useDocument.ts +0 -157
  169. package/src/hooks/useScrollSpy.ts +0 -77
  170. package/src/hooks/useTextSelection.ts +0 -86
  171. package/src/lib/highlight/worker.ts +0 -45
  172. package/src/main.tsx +0 -13
  173. package/src/store.ts +0 -222
@@ -0,0 +1,416 @@
1
+ package main
2
+
3
+ import (
4
+ "bytes"
5
+ "encoding/json"
6
+ "flag"
7
+ "fmt"
8
+ "log"
9
+ "net/http"
10
+ "os"
11
+ "os/exec"
12
+ "os/signal"
13
+ "path/filepath"
14
+ "strings"
15
+ "syscall"
16
+ "time"
17
+
18
+ "github.com/peaske7/readit/go/internal/server"
19
+ "github.com/pkg/browser"
20
+ )
21
+
22
+ const version = "0.3.0"
23
+
24
+ type serverInfo struct {
25
+ Port int `json:"port"`
26
+ PID int `json:"pid"`
27
+ Host string `json:"host,omitempty"`
28
+ }
29
+
30
+ func main() {
31
+ if len(os.Args) < 2 {
32
+ fmt.Println("Usage: readit <file.md> [flags]")
33
+ fmt.Println(" readit list")
34
+ fmt.Println(" readit show <file.md>")
35
+ fmt.Println(" readit open <file.md>")
36
+ os.Exit(1)
37
+ }
38
+
39
+ switch os.Args[1] {
40
+ case "list":
41
+ cmdList()
42
+ case "show":
43
+ cmdShow()
44
+ case "open":
45
+ cmdOpen()
46
+ case "version", "--version", "-v":
47
+ fmt.Println("readit", version)
48
+ case "help", "--help", "-h":
49
+ printHelp()
50
+ default:
51
+ cmdServe()
52
+ }
53
+ }
54
+
55
+ func cmdServe() {
56
+ fs := flag.NewFlagSet("serve", flag.ExitOnError)
57
+ port := fs.Int("port", 0, "port to listen on (default: random)")
58
+ host := fs.String("host", "127.0.0.1", "host to bind to")
59
+ noOpen := fs.Bool("no-open", false, "don't open browser")
60
+ clean := fs.Bool("clean", false, "clear existing comments")
61
+ assetsDir := fs.String("assets-dir", "", "serve assets from directory instead of embedded")
62
+ dev := fs.Bool("dev", false, "development mode (proxy to Vite)")
63
+
64
+ // Separate file args from flag args. Flags that take values
65
+ // (--port 3000, --host 0.0.0.0, --assets-dir ./dist) consume the next arg.
66
+ valueFlags := map[string]bool{
67
+ "-port": true, "--port": true,
68
+ "-host": true, "--host": true,
69
+ "-assets-dir": true, "--assets-dir": true,
70
+ }
71
+
72
+ var fileArgs []string
73
+ var flagArgs []string
74
+ args := os.Args[1:]
75
+ for i := 0; i < len(args); i++ {
76
+ arg := args[i]
77
+ if strings.HasPrefix(arg, "-") {
78
+ flagArgs = append(flagArgs, arg)
79
+ // If this flag takes a value, consume the next arg too
80
+ if valueFlags[arg] && i+1 < len(args) {
81
+ i++
82
+ flagArgs = append(flagArgs, args[i])
83
+ }
84
+ } else {
85
+ fileArgs = append(fileArgs, arg)
86
+ }
87
+ }
88
+ _ = fs.Parse(flagArgs)
89
+
90
+ if len(fileArgs) == 0 {
91
+ fmt.Fprintln(os.Stderr, "Error: at least one file is required")
92
+ os.Exit(1)
93
+ }
94
+
95
+ files, err := resolveFiles(fileArgs)
96
+ if err != nil {
97
+ fmt.Fprintf(os.Stderr, "Error: %v\n", err)
98
+ os.Exit(1)
99
+ }
100
+
101
+ if *port == 0 {
102
+ *port = 4567
103
+ }
104
+
105
+ // Dev mode: spawn Vite
106
+ var viteCmd *exec.Cmd
107
+ if *dev {
108
+ viteCmd = spawnVite()
109
+ }
110
+
111
+ // Setup signal channel before server so the SSE shutdown callback can use it
112
+ sig := make(chan os.Signal, 1)
113
+ signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM)
114
+
115
+ srv, err := server.NewServer(server.Options{
116
+ Files: files,
117
+ Port: *port,
118
+ Host: *host,
119
+ Clean: *clean,
120
+ AssetsDir: *assetsDir,
121
+ Dev: *dev,
122
+ OnShutdown: func() {
123
+ log.Println("All clients disconnected, shutting down")
124
+ sig <- syscall.SIGTERM
125
+ },
126
+ })
127
+ if err != nil {
128
+ log.Fatal(err)
129
+ }
130
+
131
+ actualPort, err := srv.Start(*host, *port)
132
+ if err != nil {
133
+ log.Fatal(err)
134
+ }
135
+
136
+ writeServerInfo(actualPort, *host)
137
+
138
+ url := fmt.Sprintf("http://%s:%d", *host, actualPort)
139
+ fmt.Printf("readit v%s serving at %s\n", version, url)
140
+
141
+ if !*noOpen {
142
+ _ = browser.OpenURL(url)
143
+ }
144
+
145
+ // Wait for interrupt or SSE-triggered shutdown
146
+ <-sig
147
+
148
+ fmt.Println("\nShutting down...")
149
+ srv.Stop()
150
+ if viteCmd != nil && viteCmd.Process != nil {
151
+ _ = viteCmd.Process.Kill()
152
+ }
153
+ removeServerInfo()
154
+ }
155
+
156
+ func cmdList() {
157
+ home, _ := os.UserHomeDir()
158
+ commentsDir := filepath.Join(home, ".readit", "comments")
159
+
160
+ _ = filepath.Walk(commentsDir, func(path string, info os.FileInfo, err error) error {
161
+ if err != nil || info.IsDir() {
162
+ return nil
163
+ }
164
+ if !strings.HasSuffix(path, ".comments.md") {
165
+ return nil
166
+ }
167
+
168
+ data, err := os.ReadFile(path)
169
+ if err != nil {
170
+ return nil
171
+ }
172
+
173
+ cf, err := server.ParseCommentFile(data)
174
+ if err != nil {
175
+ return nil
176
+ }
177
+
178
+ fmt.Printf("%s (%d comments)\n", cf.Source, len(cf.Comments))
179
+ return nil
180
+ })
181
+ }
182
+
183
+ func cmdShow() {
184
+ if len(os.Args) < 3 {
185
+ fmt.Fprintln(os.Stderr, "Usage: readit show <file.md>")
186
+ os.Exit(1)
187
+ }
188
+
189
+ filePath, err := filepath.Abs(os.Args[2])
190
+ if err != nil {
191
+ fmt.Fprintf(os.Stderr, "Error: %v\n", err)
192
+ os.Exit(1)
193
+ }
194
+
195
+ commentPath, err := server.CommentPath(filePath)
196
+ if err != nil {
197
+ fmt.Fprintf(os.Stderr, "Error: %v\n", err)
198
+ os.Exit(1)
199
+ }
200
+ data, err := os.ReadFile(commentPath)
201
+ if err != nil {
202
+ fmt.Println("No comments found for", filePath)
203
+ return
204
+ }
205
+
206
+ cf, err := server.ParseCommentFile(data)
207
+ if err != nil {
208
+ fmt.Fprintf(os.Stderr, "Error: %v\n", err)
209
+ os.Exit(1)
210
+ }
211
+
212
+ for i, c := range cf.Comments {
213
+ text := c.SelectedText
214
+ if len(text) > 80 {
215
+ text = text[:80] + "…"
216
+ }
217
+ fmt.Printf("[%d] %s\n", i+1, c.LineHint)
218
+ fmt.Printf(" > %s\n", strings.ReplaceAll(text, "\n", "\n > "))
219
+ fmt.Printf(" %s\n", c.Comment)
220
+ fmt.Printf(" (%s)\n\n", c.CreatedAt)
221
+ }
222
+ }
223
+
224
+ func cmdOpen() {
225
+ if len(os.Args) < 3 {
226
+ fmt.Fprintln(os.Stderr, "Usage: readit open <file.md>")
227
+ os.Exit(1)
228
+ }
229
+
230
+ files, err := resolveFiles(os.Args[2:])
231
+ if err != nil {
232
+ fmt.Fprintf(os.Stderr, "Error: %v\n", err)
233
+ os.Exit(1)
234
+ }
235
+
236
+ // Try to discover a running server
237
+ info, err := discoverServer()
238
+ if err == nil && info != nil {
239
+ // Attach to existing server
240
+ for _, f := range files {
241
+ attachFile(info, f.FilePath)
242
+ }
243
+ url := fmt.Sprintf("http://%s:%d", info.resolvedHost(), info.Port)
244
+ _ = browser.OpenURL(url)
245
+ return
246
+ }
247
+
248
+ // No running server — start one
249
+ os.Args = append([]string{os.Args[0]}, os.Args[2:]...)
250
+ cmdServe()
251
+ }
252
+
253
+ func resolveFiles(args []string) ([]server.FileEntry, error) {
254
+ seen := make(map[string]bool)
255
+ var files []server.FileEntry
256
+
257
+ for _, arg := range args {
258
+ absPath, err := filepath.Abs(arg)
259
+ if err != nil {
260
+ return nil, fmt.Errorf("invalid path %s: %w", arg, err)
261
+ }
262
+
263
+ absPath, err = filepath.EvalSymlinks(absPath)
264
+ if err != nil {
265
+ return nil, fmt.Errorf("file not found: %s", arg)
266
+ }
267
+
268
+ info, err := os.Stat(absPath)
269
+ if err != nil {
270
+ return nil, fmt.Errorf("file not found: %s", arg)
271
+ }
272
+
273
+ if info.IsDir() {
274
+ // Scan directory for markdown files
275
+ _ = filepath.Walk(absPath, func(path string, fi os.FileInfo, err error) error {
276
+ if err != nil || fi.IsDir() {
277
+ if fi != nil && fi.IsDir() && strings.HasPrefix(fi.Name(), ".") {
278
+ return filepath.SkipDir
279
+ }
280
+ if fi != nil && fi.IsDir() && fi.Name() == "node_modules" {
281
+ return filepath.SkipDir
282
+ }
283
+ return nil
284
+ }
285
+ ext := strings.ToLower(filepath.Ext(path))
286
+ if ext == ".md" || ext == ".markdown" {
287
+ if !seen[path] {
288
+ seen[path] = true
289
+ files = append(files, server.FileEntry{FilePath: path})
290
+ }
291
+ }
292
+ return nil
293
+ })
294
+ } else {
295
+ ext := strings.ToLower(filepath.Ext(absPath))
296
+ if ext != ".md" && ext != ".markdown" {
297
+ return nil, fmt.Errorf("unsupported file type: %s (only .md and .markdown)", arg)
298
+ }
299
+ if !seen[absPath] {
300
+ seen[absPath] = true
301
+ files = append(files, server.FileEntry{FilePath: absPath})
302
+ }
303
+ }
304
+ }
305
+
306
+ if len(files) == 0 {
307
+ return nil, fmt.Errorf("no markdown files found")
308
+ }
309
+
310
+ return files, nil
311
+ }
312
+
313
+ func serverInfoPath() string {
314
+ home, _ := os.UserHomeDir()
315
+ return filepath.Join(home, ".readit", "server.json")
316
+ }
317
+
318
+ func writeServerInfo(port int, host string) {
319
+ info := serverInfo{Port: port, PID: os.Getpid(), Host: host}
320
+ data, _ := json.Marshal(info)
321
+ path := serverInfoPath()
322
+ _ = os.MkdirAll(filepath.Dir(path), 0755)
323
+ _ = os.WriteFile(path, data, 0644)
324
+ }
325
+
326
+ func removeServerInfo() {
327
+ _ = os.Remove(serverInfoPath())
328
+ }
329
+
330
+ func (si *serverInfo) resolvedHost() string {
331
+ if si.Host != "" {
332
+ return si.Host
333
+ }
334
+ return "127.0.0.1"
335
+ }
336
+
337
+ func discoverServer() (*serverInfo, error) {
338
+ data, err := os.ReadFile(serverInfoPath())
339
+ if err != nil {
340
+ return nil, err
341
+ }
342
+
343
+ var info serverInfo
344
+ if err := json.Unmarshal(data, &info); err != nil {
345
+ return nil, err
346
+ }
347
+
348
+ // Check if process is alive
349
+ proc, err := os.FindProcess(info.PID)
350
+ if err != nil {
351
+ return nil, err
352
+ }
353
+ if err := proc.Signal(syscall.Signal(0)); err != nil {
354
+ return nil, fmt.Errorf("process not alive")
355
+ }
356
+
357
+ // Health check
358
+ client := &http.Client{Timeout: 2 * time.Second}
359
+ resp, err := client.Get(fmt.Sprintf("http://%s:%d/api/health", info.resolvedHost(), info.Port))
360
+ if err != nil {
361
+ return nil, err
362
+ }
363
+ _ = resp.Body.Close()
364
+ if resp.StatusCode != http.StatusOK {
365
+ return nil, fmt.Errorf("health check failed")
366
+ }
367
+
368
+ return &info, nil
369
+ }
370
+
371
+ func attachFile(info *serverInfo, filePath string) {
372
+ body, _ := json.Marshal(map[string]string{"path": filePath})
373
+ resp, err := http.Post(
374
+ fmt.Sprintf("http://%s:%d/api/documents", info.resolvedHost(), info.Port),
375
+ "application/json",
376
+ bytes.NewReader(body),
377
+ )
378
+ if err != nil {
379
+ log.Printf("Warning: failed to attach %s: %v", filePath, err)
380
+ return
381
+ }
382
+ _ = resp.Body.Close()
383
+ }
384
+
385
+ func spawnVite() *exec.Cmd {
386
+ cmd := exec.Command("bunx", "vite", "--port", "24678")
387
+ cmd.Stdout = os.Stdout
388
+ cmd.Stderr = os.Stderr
389
+ if err := cmd.Start(); err != nil {
390
+ log.Printf("Warning: failed to start Vite: %v", err)
391
+ return nil
392
+ }
393
+ // Give Vite a moment to start
394
+ time.Sleep(500 * time.Millisecond)
395
+ return cmd
396
+ }
397
+
398
+ func printHelp() {
399
+ fmt.Printf(`readit v%s — Review Markdown documents with inline comments
400
+
401
+ Usage:
402
+ readit <file.md> [flags] Start server and open browser
403
+ readit list List files with comments
404
+ readit show <file.md> Show comments for a file
405
+ readit open <file.md> Add file to running server
406
+
407
+ Flags:
408
+ --port <n> Port to listen on (default: 4567)
409
+ --host <addr> Host to bind to (default: 127.0.0.1)
410
+ --no-open Don't auto-open browser
411
+ --clean Clear existing comments
412
+ --assets-dir <d> Serve assets from directory
413
+ --dev Development mode (spawn Vite)
414
+
415
+ `, version)
416
+ }
package/go/go.mod ADDED
@@ -0,0 +1,20 @@
1
+ module github.com/peaske7/readit/go
2
+
3
+ go 1.24
4
+
5
+ require (
6
+ github.com/alecthomas/chroma/v2 v2.23.1
7
+ github.com/fsnotify/fsnotify v1.9.0
8
+ github.com/microcosm-cc/bluemonday v1.0.27
9
+ github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c
10
+ github.com/yuin/goldmark v1.8.2
11
+ github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc
12
+ )
13
+
14
+ require (
15
+ github.com/aymerick/douceur v0.2.0 // indirect
16
+ github.com/dlclark/regexp2 v1.11.5 // indirect
17
+ github.com/gorilla/css v1.0.1 // indirect
18
+ golang.org/x/net v0.26.0 // indirect
19
+ golang.org/x/sys v0.21.0 // indirect
20
+ )
package/go/go.sum ADDED
@@ -0,0 +1,41 @@
1
+ github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0=
2
+ github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
3
+ github.com/alecthomas/chroma/v2 v2.2.0/go.mod h1:vf4zrexSH54oEjJ7EdB65tGNHmH3pGZmVkgTP5RHvAs=
4
+ github.com/alecthomas/chroma/v2 v2.23.1 h1:nv2AVZdTyClGbVQkIzlDm/rnhk1E9bU9nXwmZ/Vk/iY=
5
+ github.com/alecthomas/chroma/v2 v2.23.1/go.mod h1:NqVhfBR0lte5Ouh3DcthuUCTUpDC9cxBOfyMbMQPs3o=
6
+ github.com/alecthomas/repr v0.0.0-20220113201626-b1b626ac65ae/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8=
7
+ github.com/alecthomas/repr v0.5.2 h1:SU73FTI9D1P5UNtvseffFSGmdNci/O6RsqzeXJtP0Qs=
8
+ github.com/alecthomas/repr v0.5.2/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
9
+ github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
10
+ github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
11
+ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
12
+ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
13
+ github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
14
+ github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
15
+ github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ=
16
+ github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
17
+ github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
18
+ github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
19
+ github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8=
20
+ github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0=
21
+ github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
22
+ github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
23
+ github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk=
24
+ github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA=
25
+ github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
26
+ github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
27
+ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
28
+ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
29
+ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
30
+ github.com/yuin/goldmark v1.4.15/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
31
+ github.com/yuin/goldmark v1.8.2 h1:kEGpgqJXdgbkhcOgBxkC0X0PmoPG1ZyoZ117rDVp4zE=
32
+ github.com/yuin/goldmark v1.8.2/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
33
+ github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc h1:+IAOyRda+RLrxa1WC7umKOZRsGq4QrFFMYApOeHzQwQ=
34
+ github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc/go.mod h1:ovIvrum6DQJA4QsJSovrkC4saKHQVs7TvcaeO8AIl5I=
35
+ golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
36
+ golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
37
+ golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
38
+ golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
39
+ golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
40
+ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
41
+ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=