codesynapt 0.0.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 (61) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/LICENSE +686 -0
  3. package/LICENSES.md +141 -0
  4. package/README.md +331 -0
  5. package/electron/main.cjs +2849 -0
  6. package/electron/plugin-loader.cjs +184 -0
  7. package/electron/preload.cjs +108 -0
  8. package/package.json +216 -0
  9. package/packages/core/bin/codesynapt-mcp.cjs +611 -0
  10. package/packages/core/bin/codesynapt.cjs +1933 -0
  11. package/packages/core/legacy.js +300 -0
  12. package/packages/core/lib/control-server.cjs +1539 -0
  13. package/packages/core/lib/embedding.cjs +89 -0
  14. package/packages/core/lib/logger.cjs +63 -0
  15. package/packages/core/lib/search-cache.cjs +140 -0
  16. package/packages/core/lib/search-worker.cjs +255 -0
  17. package/packages/core/lib/search.cjs +211 -0
  18. package/packages/core/lib/symbol-graph.cjs +402 -0
  19. package/packages/core/lib/symbol-parser-js.cjs +542 -0
  20. package/packages/core/lib/symbol-parser-misc.cjs +394 -0
  21. package/packages/core/lib/symbol-parser-py.cjs +215 -0
  22. package/packages/core/lib/symbol-parser-treesitter.cjs +658 -0
  23. package/packages/core/lib/symbol-parser-tsc.cjs +332 -0
  24. package/packages/core/monorepo.js +310 -0
  25. package/packages/core/parser.js +2234 -0
  26. package/packages/core/scanner.js +623 -0
  27. package/plugin-api/LICENSE +21 -0
  28. package/plugin-api/README.md +114 -0
  29. package/plugin-api/docs/01-getting-started.md +197 -0
  30. package/plugin-api/docs/02-concepts.md +269 -0
  31. package/plugin-api/docs/api-reference.md +463 -0
  32. package/plugin-api/docs/troubleshooting.md +332 -0
  33. package/plugin-api/docs/types/exporter.md +377 -0
  34. package/plugin-api/docs/types/theme.md +312 -0
  35. package/plugin-api/examples/hello-world-plugin/README.md +70 -0
  36. package/plugin-api/examples/hello-world-plugin/main.js +36 -0
  37. package/plugin-api/examples/hello-world-plugin/manifest.json +12 -0
  38. package/plugin-api/examples/mermaid-exporter/README.md +125 -0
  39. package/plugin-api/examples/mermaid-exporter/main.js +58 -0
  40. package/plugin-api/examples/mermaid-exporter/manifest.json +12 -0
  41. package/plugin-api/examples/rust-parser/README.md +71 -0
  42. package/plugin-api/examples/rust-parser/main.js +123 -0
  43. package/plugin-api/examples/rust-parser/manifest.json +12 -0
  44. package/plugin-api/examples/sunset-theme/README.md +95 -0
  45. package/plugin-api/examples/sunset-theme/manifest.json +12 -0
  46. package/plugin-api/examples/sunset-theme/theme.css +31 -0
  47. package/plugin-api/package.json +20 -0
  48. package/plugin-api/types.d.ts +395 -0
  49. package/public/app.js +6837 -0
  50. package/public/backend.js +285 -0
  51. package/public/index.html +647 -0
  52. package/public/plugin-host.js +321 -0
  53. package/public/style.css +4359 -0
  54. package/public/vendor/three.module.js +53044 -0
  55. package/scripts/competitor-watch.mjs +144 -0
  56. package/scripts/copy-vendor.js +21 -0
  57. package/scripts/download-bundled-node.cjs +53 -0
  58. package/scripts/fuses-after-pack.cjs +34 -0
  59. package/scripts/license-check.js +119 -0
  60. package/scripts/perf-test.js +200 -0
  61. package/server.js +132 -0
@@ -0,0 +1,312 @@
1
+ # Theme plugin
2
+
3
+ A theme plugin is the simplest plugin type — just CSS. You override
4
+ the app's CSS variables under a `body[data-theme="your-id"]` selector,
5
+ and filegraph3d picks it up automatically.
6
+
7
+ - [Minimal example](#minimal-example)
8
+ - [Every variable you can override](#every-variable-you-can-override)
9
+ - [Palette construction](#palette-construction)
10
+ - [Decorations: corner brackets and accents](#decorations-corner-brackets-and-accents)
11
+ - [Dark vs light themes](#dark-vs-light-themes)
12
+ - [Studying built-in themes](#studying-built-in-themes)
13
+ - [Common mistakes](#common-mistakes)
14
+
15
+ ## Minimal example
16
+
17
+ ```
18
+ plugins/my-theme/
19
+ ├── manifest.json
20
+ └── theme.css
21
+ ```
22
+
23
+ **`manifest.json`:**
24
+
25
+ ```json
26
+ {
27
+ "id": "my-theme",
28
+ "name": "My Theme",
29
+ "version": "1.0.0",
30
+ "type": "theme",
31
+ "main": "theme.css",
32
+ "minAppVersion": "0.10.0",
33
+ "license": "MIT"
34
+ }
35
+ ```
36
+
37
+ **`theme.css`:**
38
+
39
+ ```css
40
+ body[data-theme="my-theme"] {
41
+ --bg: #1A1A1A;
42
+ --fg: #F0F0F0;
43
+ --accent: #FF8800;
44
+ }
45
+ ```
46
+
47
+ That's a working theme. It won't look great because you've only set 3
48
+ of ~30 variables, but it'll load. Read on for the rest.
49
+
50
+ ## Every variable you can override
51
+
52
+ filegraph3d's UI is parameterized by ~30 CSS custom properties. The
53
+ full list:
54
+
55
+ ### Backgrounds
56
+
57
+ | Variable | Used by | Notes |
58
+ |---|---|---|
59
+ | `--bg` | Body background | The main canvas background. Pure color, no alpha. |
60
+ | `--bg-deep` | Very deep accents | Slightly darker than `--bg`. |
61
+ | `--bg-elev` | Raised elements | Tooltips, dropdowns. Use `rgba(...)` for translucency. |
62
+ | `--bg-glass` | All floating panels | The "frosted glass" panel background. Should be `rgba()` with ~0.85 alpha. |
63
+ | `--bg-solid` | Where solid is required | Settings panel sections, etc. |
64
+
65
+ ### Borders
66
+
67
+ | Variable | Used by | Notes |
68
+ |---|---|---|
69
+ | `--border` | Default panel borders | Should be visible but not loud. |
70
+ | `--border-hot` | Active / focused borders | Brighter version of `--border`. |
71
+ | `--border-edge` | Subtle dividers, separators | Nearly invisible (alpha ~0.05). |
72
+
73
+ ### Foregrounds
74
+
75
+ | Variable | Used by | Notes |
76
+ |---|---|---|
77
+ | `--fg` | Primary text | Should pass contrast against `--bg`. |
78
+ | `--fg-dim` | Secondary text | Labels, less important info. |
79
+ | `--fg-mute` | Tertiary text | Captions, kicker text. |
80
+ | `--fg-faint` | Quaternary text | Disabled, divider labels. |
81
+
82
+ ### Accents (semantic colors)
83
+
84
+ | Variable | Semantic role | Where |
85
+ |---|---|---|
86
+ | `--accent` | Default information / focus | Buttons, highlights, brand dot, search focus border |
87
+ | `--accent-warm` | Active set / starred | Star buttons, pipelines panel, active markings |
88
+ | `--accent-pink` | Warning / danger | Delete buttons, error states |
89
+ | `--accent-cool` | Secondary focus | Focus ripples (less common) |
90
+ | `--danger` | Errors | Validation failures, destructive confirmation |
91
+
92
+ ### Typography
93
+
94
+ | Variable | Used by |
95
+ |---|---|
96
+ | `--font-mono` | Monospace text (code, data, default body) |
97
+ | `--font-display` | Display text (logo, headers) |
98
+
99
+ The defaults expect `'JetBrains Mono'` to be available, with fallbacks
100
+ to `'SF Mono'`, `ui-monospace`, `Menlo`. You can change to any font
101
+ stack you like; the user must have it installed.
102
+
103
+ ### Layout
104
+
105
+ | Variable | Used by |
106
+ |---|---|
107
+ | `--radius` | Border-radius for panels, buttons | `0` = brutalist, `4-6px` = friendly, `12px+` = bubbly |
108
+ | `--space-1` through `--space-6` | 4px grid spacing | Rarely needs override |
109
+
110
+ ### Motion & decoration flags
111
+
112
+ | Variable | What it controls |
113
+ |---|---|
114
+ | `--decoration` | `1` to show corner brackets on panels, `0` to hide |
115
+ | `--grain` | Opacity of background noise overlay (`0` to `0.05`) |
116
+ | `--motion-scale` | Multiplier for ambient animations (`0` = none, `1` = default, `1.5` = more) |
117
+
118
+ ### Easing
119
+
120
+ | Variable | Used by |
121
+ |---|---|
122
+ | `--ease-out` | Smooth ease-out for hover transitions |
123
+ | `--ease-snap` | Snappy ease for selection changes |
124
+
125
+ ## Palette construction
126
+
127
+ A good theme needs **5 colors** at minimum:
128
+
129
+ 1. **Background** (`--bg`)
130
+ 2. **Foreground** (`--fg`)
131
+ 3. **Three accents** (`--accent`, `--accent-warm`, `--accent-pink`)
132
+
133
+ ### Step-by-step
134
+
135
+ **1. Pick a background.** This sets the mood:
136
+ - Near-black (`#0A0A0A`) — neutral terminal feel
137
+ - Tinted dark (`#1A1B26` Tokyo Night, `#2A1810` warm) — character
138
+ - True white (`#FAFAFA`) — light mode
139
+
140
+ **2. Pick a foreground that contrasts.**
141
+ - For dark bg: `#E0E0E0` to `#F5F5F5`
142
+ - For light bg: `#1A1A1A` to `#333333`
143
+ - Aim for **WCAG AA** contrast (4.5:1 minimum for normal text).
144
+
145
+ **3. Pick `--accent`.** This is the main signal color. Used everywhere
146
+ you want to draw the eye. Choose something that:
147
+ - Stands out against `--bg`
148
+ - Doesn't fight `--fg` (don't pick a similar hue)
149
+
150
+ **4. Pick `--accent-warm` and `--accent-pink`.** These are semantic:
151
+ - `--accent-warm` = active set, starred (golds, oranges work great)
152
+ - `--accent-pink` = danger, deletion (reds, hot pinks)
153
+
154
+ The three accents should be **distinguishable at a glance**. If they're
155
+ all bluish, users can't tell what each one means.
156
+
157
+ **5. Generate the supporting colors.**
158
+
159
+ Common pattern (in HSL):
160
+ ```
161
+ --fg: hsl(H, S, 95%)
162
+ --fg-dim: hsl(H, S*0.8, 75%)
163
+ --fg-mute: hsl(H, S*0.5, 50%)
164
+ --fg-faint: hsl(H, S*0.3, 35%)
165
+ ```
166
+
167
+ Where `H, S` are the hue/saturation of the base foreground.
168
+
169
+ For borders, use the accent color at low alpha:
170
+ ```
171
+ --border: rgba(R, G, B, 0.16) /* visible */
172
+ --border-hot: rgba(R, G, B, 0.55) /* active */
173
+ --border-edge: rgba(R, G, B, 0.06) /* nearly invisible */
174
+ ```
175
+
176
+ Where `R, G, B` is your accent color's RGB.
177
+
178
+ ## Decorations: corner brackets and accents
179
+
180
+ filegraph3d's built-in themes have **corner brackets** on panels —
181
+ small `┌` `┐` `└` `┘` marks that frame each panel. These are part of
182
+ the "Observatory" aesthetic.
183
+
184
+ You control them with `--decoration`:
185
+
186
+ ```css
187
+ body[data-theme="my-clean-theme"] {
188
+ --decoration: 0; /* hide all corner brackets */
189
+ }
190
+ ```
191
+
192
+ ```css
193
+ body[data-theme="my-bold-theme"] {
194
+ --decoration: 1; /* show corner brackets (default) */
195
+ }
196
+ ```
197
+
198
+ When `--decoration: 0`:
199
+ - Corner brackets disappear
200
+ - ASCII dividers in welcome screen hide
201
+ - `[ ]` brackets around the brand label hide
202
+
203
+ This single switch controls roughly two dozen decorative elements.
204
+
205
+ ## Dark vs light themes
206
+
207
+ Light themes need a few extra tweaks. Set everything as usual, then:
208
+
209
+ ```css
210
+ body[data-theme="my-light-theme"] {
211
+ --bg: #FAFAFA;
212
+ --fg: #1A1A1A;
213
+ --accent: #0066CC;
214
+ --accent-warm: #B87000;
215
+ --accent-pink: #CC2233;
216
+
217
+ /* Soften the grain overlay (it looks bad on white) */
218
+ --grain: 0;
219
+
220
+ /* Borders need to be dark on light bg */
221
+ --border: rgba(0, 0, 0, 0.08);
222
+ --border-hot: rgba(0, 0, 0, 0.3);
223
+ --border-edge: rgba(0, 0, 0, 0.04);
224
+ }
225
+
226
+ /* Hide the grain overlay specifically for this theme */
227
+ body[data-theme="my-light-theme"]::before {
228
+ opacity: 0 !important;
229
+ }
230
+ ```
231
+
232
+ The grain overlay is set on `body::before` and uses
233
+ `mix-blend-mode: overlay`, which looks fine on dark but adds ugly
234
+ specks on light. Force it off.
235
+
236
+ ## Studying built-in themes
237
+
238
+ The seven built-in themes are great references. They live in the
239
+ app's `public/style.css`. Each is implemented as a `body[data-theme="..."]`
240
+ block:
241
+
242
+ - `observatory` — the default, brutalist + corner brackets
243
+ - `minimal` — Obsidian-style, soft and quiet
244
+ - `terminal` — Linear-style, monochrome
245
+ - `maximal` — bold gradients
246
+ - `carbon` — CRT phosphor green
247
+ - `mono` — Tokyo Night warmth
248
+ - `daylight` — light mode
249
+
250
+ Open `style.css` and grep for `body[data-theme=` to find each one.
251
+ Copy the parts you like.
252
+
253
+ ## Common mistakes
254
+
255
+ ### "My theme doesn't show up"
256
+
257
+ - Did you **fully quit** the app (Cmd/Ctrl+Q) and reopen? Themes are
258
+ injected at startup.
259
+ - Is `manifest.json` valid JSON? Try `jsonlint.com`.
260
+ - Is the folder name and `manifest.id` matching? They don't have to be
261
+ identical, but the `id` determines what selector you need (it's
262
+ `body[data-theme="<id>"]`, not the folder name).
263
+
264
+ ### "Colors look right but layout is weird"
265
+
266
+ You probably forgot `--decoration` or `--radius`. Set them explicitly
267
+ even if you want defaults — relying on inheritance gives unpredictable
268
+ results when users switch from another theme.
269
+
270
+ ### "It looks fine in my theme but broken in others"
271
+
272
+ Don't define your CSS variables outside the `body[data-theme="..."]`
273
+ selector. If you do, they leak into other themes. Bad:
274
+
275
+ ```css
276
+ /* ❌ leaks to all themes */
277
+ :root {
278
+ --accent: #FF0000;
279
+ }
280
+ ```
281
+
282
+ Good:
283
+
284
+ ```css
285
+ /* ✅ scoped to this theme only */
286
+ body[data-theme="my-theme"] {
287
+ --accent: #FF0000;
288
+ }
289
+ ```
290
+
291
+ ### "Light mode text is unreadable"
292
+
293
+ Check your contrast ratios. On light backgrounds:
294
+ - `--fg` should be very dark (`#1A1A1A` to `#333`)
295
+ - `--fg-mute` should still be readable (`#666` minimum)
296
+
297
+ Use a contrast checker like `webaim.org/resources/contrastchecker/`.
298
+
299
+ ### "My theme breaks the file tree colors"
300
+
301
+ The colored squares next to filenames come from the **app's** file-type
302
+ palette, not your theme. They're hardcoded by extension (`.js` = yellow,
303
+ `.tsx` = blue, etc). If you want a different file-type palette, that's
304
+ a different feature — currently not user-overridable.
305
+
306
+ ## Next steps
307
+
308
+ - Try the [sunset-theme example](../../examples/sunset-theme/) — a
309
+ warm coral-orange theme you can copy and modify.
310
+ - Read the [exporter guide](./exporter.md) for your next plugin type.
311
+ - Or jump to the [API reference](../api-reference.md) for the full
312
+ surface.
@@ -0,0 +1,70 @@
1
+ # hello-world-plugin
2
+
3
+ A minimal action plugin that demonstrates:
4
+
5
+ - Registering a context-menu item
6
+ - Subscribing to selection events
7
+ - Showing toast notifications
8
+ - Using `ctx.log` for debugging
9
+
10
+ ## What it does
11
+
12
+ When installed:
13
+
14
+ 1. **Right-click any node** in the graph — a "Hello from plugin" item
15
+ appears in the menu. Click it to see a toast.
16
+
17
+ 2. **Click any node** — a toast pops up with that node's basic stats
18
+ (incoming/outgoing edge counts).
19
+
20
+ ## Install
21
+
22
+ Copy this folder into your filegraph3d plugins directory:
23
+
24
+ ```
25
+ macOS: ~/Library/Application Support/FileGraph 3D/plugins/
26
+ Windows: %APPDATA%\FileGraph 3D\plugins\
27
+ Linux: ~/.config/FileGraph 3D/plugins/
28
+ ```
29
+
30
+ Quit and reopen filegraph3d. Open any folder. Click or right-click
31
+ nodes.
32
+
33
+ ## Files
34
+
35
+ - **`manifest.json`** — declares the plugin as type `action` with no
36
+ required permissions (read-graph is implicit, and the toast/log
37
+ helpers don't need permissions).
38
+
39
+ - **`main.js`** — the entry point. Subscribes to events, registers a
40
+ context-menu item, and stores its unsubscribe function so
41
+ `deactivate()` can clean up.
42
+
43
+ ## What to look at
44
+
45
+ - The `default export` shape — every code plugin has an object with
46
+ at least an `activate(ctx)` function.
47
+
48
+ - `ctx.events.on(...)` returns an unsubscribe function. The plugin
49
+ stores it as `this._unsub` and calls it from `deactivate()`.
50
+
51
+ - `ctx.ui.registerContextMenuItem(...)` doesn't return a useful handle
52
+ for the plugin to track because the plugin host handles cleanup
53
+ automatically when the plugin unloads.
54
+
55
+ - `ctx.toast(...)` automatically prefixes messages with `[hello-world]`
56
+ so the user knows where they came from.
57
+
58
+ ## What to try next
59
+
60
+ Modify `main.js` to:
61
+
62
+ - Show different info in the toast (e.g. file extension, size in KB)
63
+ - Filter the context menu to only appear on `.js` files (use the
64
+ `enabled` callback)
65
+ - Subscribe to a different event (`focus:changed`, `snapshot:applied`)
66
+ - Persist a counter in `ctx.storage` ("you've clicked X files")
67
+
68
+ ## License
69
+
70
+ MIT.
@@ -0,0 +1,36 @@
1
+ // Minimal plugin example.
2
+ // Listens for node selections and shows a toast with stats.
3
+
4
+ export default {
5
+ activate(ctx) {
6
+ ctx.log('Hello World plugin loaded')
7
+
8
+ // Subscribe to selection events
9
+ const unsub = ctx.events.on('selection:changed', (id) => {
10
+ if (!id) return
11
+ const node = ctx.graph.getNode(id)
12
+ if (!node) return
13
+
14
+ const outCount = ctx.graph.outgoing(id).length
15
+ const inCount = ctx.graph.incoming(id).length
16
+
17
+ ctx.toast(`${id} — ${outCount} out, ${inCount} in`)
18
+ })
19
+
20
+ // Register a context-menu item
21
+ ctx.ui.registerContextMenuItem({
22
+ label: 'Hello from plugin',
23
+ icon: '👋',
24
+ action: (nodeId) => {
25
+ ctx.toast(`You picked: ${nodeId}`)
26
+ }
27
+ })
28
+
29
+ // Cleanup function — called when plugin is disabled
30
+ this._unsub = unsub
31
+ },
32
+
33
+ deactivate() {
34
+ if (this._unsub) this._unsub()
35
+ }
36
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "id": "hello-world",
3
+ "name": "Hello World",
4
+ "version": "1.0.0",
5
+ "author": "filegraph3d",
6
+ "description": "Minimal plugin scaffold — shows a toast on every selection",
7
+ "type": "action",
8
+ "main": "main.js",
9
+ "minAppVersion": "0.10.0",
10
+ "license": "MIT",
11
+ "permissions": []
12
+ }
@@ -0,0 +1,125 @@
1
+ # mermaid-exporter
2
+
3
+ Exports the current graph as a [Mermaid](https://mermaid.js.org/)
4
+ diagram (`.mmd`). Mermaid renders natively in GitHub Markdown, Notion,
5
+ Obsidian, GitLab, and many other tools.
6
+
7
+ ## What it does
8
+
9
+ Adds **"Mermaid Diagram"** as a new option in the export menu.
10
+
11
+ Clicking it generates a file like:
12
+
13
+ ```mermaid
14
+ graph LR
15
+ index_js["index.js"]
16
+ utils_js["utils.js"]
17
+ parser_js["parser.js"]
18
+ index_js --> utils_js
19
+ index_js --> parser_js
20
+ parser_js --> utils_js
21
+ ```
22
+
23
+ You can paste this directly into a GitHub README inside a
24
+ ```` ```mermaid ```` code block, and it'll render as a diagram.
25
+
26
+ ## Install
27
+
28
+ Copy this folder into your filegraph3d plugins directory:
29
+
30
+ ```
31
+ macOS: ~/Library/Application Support/FileGraph 3D/plugins/
32
+ Windows: %APPDATA%\FileGraph 3D\plugins\
33
+ Linux: ~/.config/FileGraph 3D/plugins/
34
+ ```
35
+
36
+ Quit and reopen filegraph3d. Open a folder. Open **Settings → Export**
37
+ — you'll see "Mermaid Diagram" listed.
38
+
39
+ ## Files
40
+
41
+ - **`manifest.json`** — declares the plugin as type `exporter` with
42
+ the `export` permission.
43
+
44
+ - **`main.js`** — registers the exporter. The `generate` function
45
+ receives the graph and returns a Mermaid-format string.
46
+
47
+ ## How it handles ids
48
+
49
+ Mermaid identifiers must be alphanumeric. The plugin maps every file
50
+ path to a safe alias by:
51
+
52
+ 1. Taking the basename: `src/foo/bar.js` → `bar.js`
53
+ 2. Replacing non-alphanumeric chars with `_`: `bar.js` → `bar_js`
54
+ 3. Disambiguating duplicates: if two files have the same basename,
55
+ the second becomes `bar_js2`, the third `bar_js3`, etc.
56
+
57
+ The original path is preserved as the **label** so it's still readable
58
+ in the rendered diagram.
59
+
60
+ ## Limitations
61
+
62
+ Mermaid struggles with very large graphs. Performance gets sluggish
63
+ past ~500 nodes; rendering may fail past ~2000.
64
+
65
+ For large codebases:
66
+
67
+ 1. Use filegraph3d's **active set** feature to mark just the files
68
+ you care about, then export.
69
+
70
+ 2. Or use the [GraphViz DOT exporter pattern](../../docs/types/exporter.md#example-graphviz-dot)
71
+ — GraphViz handles 10k+ nodes well.
72
+
73
+ ## What to change
74
+
75
+ If you want to customize the output:
76
+
77
+ ### Different layout direction
78
+
79
+ ```js
80
+ // Top-to-bottom instead of left-to-right:
81
+ const lines = ['graph TB']
82
+ ```
83
+
84
+ Options: `TB` (top→bottom), `BT`, `LR` (left→right), `RL`.
85
+
86
+ ### Group by folder
87
+
88
+ ```js
89
+ const lines = ['graph LR']
90
+ const folders = new Map()
91
+ for (const node of graph.nodes) {
92
+ const dir = node.id.split('/').slice(0, -1).join('/') || 'root'
93
+ if (!folders.has(dir)) folders.set(dir, [])
94
+ folders.get(dir).push(node)
95
+ }
96
+ for (const [dir, nodes] of folders) {
97
+ lines.push(` subgraph "${dir}"`)
98
+ for (const node of nodes) {
99
+ lines.push(` ${alias(node.id)}["${basename(node.id)}"]`)
100
+ }
101
+ lines.push(' end')
102
+ }
103
+ // ... edges
104
+ ```
105
+
106
+ ### Style by extension
107
+
108
+ ```js
109
+ // After declaring nodes:
110
+ lines.push(' classDef js fill:#F7DF1E,stroke:#000')
111
+ lines.push(' classDef ts fill:#3178C6,stroke:#000')
112
+ for (const node of graph.nodes) {
113
+ lines.push(` class ${alias(node.id)} ${node.ext}`)
114
+ }
115
+ ```
116
+
117
+ ## License
118
+
119
+ MIT.
120
+
121
+ ## More
122
+
123
+ See [../../docs/types/exporter.md](../../docs/types/exporter.md) for
124
+ the full exporter guide, including more output formats (GraphViz,
125
+ custom JSON) and patterns for handling the active set.
@@ -0,0 +1,58 @@
1
+ // Exports the current graph as a Mermaid diagram.
2
+ // Output renders inside GitHub Markdown, Notion, Obsidian, etc.
3
+
4
+ export default {
5
+ activate(ctx) {
6
+ ctx.exporters.register({
7
+ name: 'Mermaid Diagram',
8
+ extension: 'mmd',
9
+ mimeType: 'text/plain',
10
+ generate(graph) {
11
+ const lines = ['graph LR']
12
+
13
+ // Build a short alias for each node so the diagram stays readable
14
+ // when file paths are long
15
+ const aliases = new Map()
16
+ for (const node of graph.nodes) {
17
+ const short = node.id.split('/').pop() || node.id
18
+ let alias = sanitize(short)
19
+ // Disambiguate if two files share a basename
20
+ let n = 2
21
+ const taken = new Set(aliases.values())
22
+ while (taken.has(alias)) {
23
+ alias = sanitize(short) + n
24
+ n++
25
+ }
26
+ aliases.set(node.id, alias)
27
+ }
28
+
29
+ // Declare nodes with their display names
30
+ for (const node of graph.nodes) {
31
+ const alias = aliases.get(node.id)
32
+ const label = node.id.split('/').pop() || node.id
33
+ lines.push(` ${alias}["${escapeLabel(label)}"]`)
34
+ }
35
+
36
+ // Then edges
37
+ for (const e of graph.edges) {
38
+ const sa = aliases.get(e.s)
39
+ const ta = aliases.get(e.t)
40
+ if (sa && ta) lines.push(` ${sa} --> ${ta}`)
41
+ }
42
+
43
+ return lines.join('\n')
44
+ }
45
+ })
46
+
47
+ ctx.log('Mermaid exporter ready — use Export → Mermaid Diagram')
48
+ }
49
+ }
50
+
51
+ // Mermaid requires alphanumeric node ids — strip everything else
52
+ function sanitize(s) {
53
+ return s.replace(/[^a-zA-Z0-9_]/g, '_').replace(/^(\d)/, '_$1')
54
+ }
55
+
56
+ function escapeLabel(s) {
57
+ return s.replace(/"/g, '\\"')
58
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "id": "mermaid-exporter",
3
+ "name": "Mermaid Exporter",
4
+ "version": "1.0.0",
5
+ "author": "filegraph3d",
6
+ "description": "Export the graph as a Mermaid diagram (.mmd) for use in Markdown",
7
+ "type": "exporter",
8
+ "main": "main.js",
9
+ "minAppVersion": "0.10.0",
10
+ "license": "MIT",
11
+ "permissions": []
12
+ }
@@ -0,0 +1,71 @@
1
+ # rust-parser
2
+
3
+ A filegraph3d plugin that adds support for **Rust** (`.rs`) files.
4
+
5
+ ## What it does
6
+
7
+ Without this plugin, filegraph3d ignores `.rs` files — they appear as
8
+ isolated nodes with no edges, because the app doesn't know how to
9
+ read Rust's import syntax.
10
+
11
+ With this plugin installed, filegraph3d parses:
12
+
13
+ - `use path::to::thing;` — including `pub use`
14
+ - `mod foo;` — local module declarations
15
+ - `extern crate foo;` — legacy crate imports
16
+
17
+ Comments are stripped first so commented-out imports don't produce
18
+ false edges.
19
+
20
+ ## Install
21
+
22
+ ```sh
23
+ # Copy this folder into your filegraph3d plugins directory:
24
+ # macOS: ~/Library/Application Support/FileGraph 3D/plugins/
25
+ # Windows: %APPDATA%\FileGraph 3D\plugins\
26
+ # Linux: ~/.config/FileGraph 3D/plugins/
27
+
28
+ cp -r rust-parser ~/Library/Application\ Support/FileGraph\ 3D/plugins/
29
+ ```
30
+
31
+ Then quit and reopen filegraph3d.
32
+
33
+ Open a Rust project (or any folder containing `.rs` files). You'll
34
+ see them connected by import edges in the graph.
35
+
36
+ ## Limitations
37
+
38
+ This is a regex-based parser. It handles 95% of real-world Rust code
39
+ but has known blind spots:
40
+
41
+ | Case | Handling |
42
+ |---|---|
43
+ | `use foo::bar;` | ✅ Captures `foo` (the leading path segment) |
44
+ | `use foo::{bar, baz};` | ✅ Captures `foo` once |
45
+ | `use foo as f;` | ✅ Captures `foo` |
46
+ | `use foo::*;` | ✅ Captures `foo` |
47
+ | `pub use foo::bar;` | ✅ Captures `foo` |
48
+ | Macro-generated `use` | ❌ Not seen (macros not expanded) |
49
+ | `use` inside `mod { ... }` blocks | ⚠️ Captured but path may be wrong |
50
+ | `#[cfg(...)] use foo;` | ✅ Captures (cfg-gated imports counted) |
51
+
52
+ If you need precise Rust parsing (workspace resolution, real path
53
+ resolution, cfg evaluation), this isn't the right tool — use
54
+ [cargo-modules](https://github.com/regexident/cargo-modules) and
55
+ export its graph.
56
+
57
+ ## How resolution works
58
+
59
+ The parser returns import paths like `"std::collections"`. filegraph3d
60
+ then tries to match these against actual files in your project. The
61
+ matching is path-prefix based, so:
62
+
63
+ - `use crate::foo::bar` → matches `src/foo/bar.rs` or `src/foo/bar/mod.rs`
64
+ - `use std::collections` → no match (external crate, no source in your project)
65
+
66
+ External crates appear as imports with no resolved target — they're
67
+ visible in the inspector but don't create edges.
68
+
69
+ ## License
70
+
71
+ MIT. Copy, modify, redistribute freely.