@suzumiyaaoba/mdxr 0.1.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 (236) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +56 -0
  3. package/dist/cli.d.mts +1 -0
  4. package/dist/cli.mjs +2902 -0
  5. package/dist/components.d.mts +791 -0
  6. package/dist/components.mjs +2 -0
  7. package/dist/config-SI9IyFiC.mjs +184 -0
  8. package/dist/doc-context-CEqzMYKv.d.mts +568 -0
  9. package/dist/index.d.mts +20 -0
  10. package/dist/index.mjs +4 -0
  11. package/dist/ui-GKFD0mx5.mjs +15986 -0
  12. package/package.json +131 -0
  13. package/skill/SKILL.md +49 -0
  14. package/skill/references/components/charts.md +172 -0
  15. package/skill/references/components/document.md +98 -0
  16. package/skill/references/components/forms.md +35 -0
  17. package/skill/references/components/investigation.md +198 -0
  18. package/skill/references/components/layout.md +68 -0
  19. package/skill/references/components/output.md +158 -0
  20. package/skill/references/components/planning.md +155 -0
  21. package/skill/references/components/reports.md +252 -0
  22. package/skill/references/components/shadcn.md +19 -0
  23. package/skill/references/components.md +186 -0
  24. package/skill/references/extending.md +48 -0
  25. package/src/ask-sheet.ts +40 -0
  26. package/src/assets/css.ts +392 -0
  27. package/src/assets/scripts.ts +78 -0
  28. package/src/catalog.ts +287 -0
  29. package/src/cli.ts +178 -0
  30. package/src/client/doc-events.ts +1108 -0
  31. package/src/client/entry.ts +27 -0
  32. package/src/client-js.ts +47 -0
  33. package/src/component-map.ts +47 -0
  34. package/src/components/ui/accordion.tsx +77 -0
  35. package/src/components/ui/alert-dialog.tsx +185 -0
  36. package/src/components/ui/alert.tsx +76 -0
  37. package/src/components/ui/aspect-ratio.tsx +22 -0
  38. package/src/components/ui/attachment.tsx +208 -0
  39. package/src/components/ui/avatar.tsx +106 -0
  40. package/src/components/ui/badge.tsx +52 -0
  41. package/src/components/ui/breadcrumb.tsx +121 -0
  42. package/src/components/ui/bubble.tsx +128 -0
  43. package/src/components/ui/button-group.tsx +88 -0
  44. package/src/components/ui/button.tsx +58 -0
  45. package/src/components/ui/calendar.tsx +226 -0
  46. package/src/components/ui/card.tsx +102 -0
  47. package/src/components/ui/carousel.tsx +246 -0
  48. package/src/components/ui/chart.tsx +379 -0
  49. package/src/components/ui/checkbox.tsx +27 -0
  50. package/src/components/ui/collapsible.tsx +19 -0
  51. package/src/components/ui/combobox.tsx +298 -0
  52. package/src/components/ui/command.tsx +193 -0
  53. package/src/components/ui/context-menu.tsx +271 -0
  54. package/src/components/ui/dialog.tsx +159 -0
  55. package/src/components/ui/direction.tsx +4 -0
  56. package/src/components/ui/drawer.tsx +227 -0
  57. package/src/components/ui/dropdown-menu.tsx +269 -0
  58. package/src/components/ui/empty.tsx +104 -0
  59. package/src/components/ui/field.tsx +237 -0
  60. package/src/components/ui/fieldset.tsx +32 -0
  61. package/src/components/ui/frame.tsx +87 -0
  62. package/src/components/ui/hover-card.tsx +50 -0
  63. package/src/components/ui/input-group.tsx +159 -0
  64. package/src/components/ui/input-otp.tsx +83 -0
  65. package/src/components/ui/input.tsx +19 -0
  66. package/src/components/ui/item.tsx +202 -0
  67. package/src/components/ui/kbd.tsx +26 -0
  68. package/src/components/ui/label.tsx +19 -0
  69. package/src/components/ui/marker.tsx +71 -0
  70. package/src/components/ui/menubar.tsx +284 -0
  71. package/src/components/ui/message-scroller.tsx +128 -0
  72. package/src/components/ui/message.tsx +91 -0
  73. package/src/components/ui/meter.tsx +80 -0
  74. package/src/components/ui/native-select.tsx +64 -0
  75. package/src/components/ui/navigation-menu.tsx +170 -0
  76. package/src/components/ui/pagination.tsx +133 -0
  77. package/src/components/ui/popover.tsx +87 -0
  78. package/src/components/ui/progress.tsx +82 -0
  79. package/src/components/ui/questionnaire.tsx +328 -0
  80. package/src/components/ui/radio-group.tsx +35 -0
  81. package/src/components/ui/resizable.tsx +49 -0
  82. package/src/components/ui/scroll-area.tsx +50 -0
  83. package/src/components/ui/select.tsx +201 -0
  84. package/src/components/ui/separator.tsx +22 -0
  85. package/src/components/ui/sheet.tsx +135 -0
  86. package/src/components/ui/sidebar.tsx +730 -0
  87. package/src/components/ui/skeleton.tsx +13 -0
  88. package/src/components/ui/slider.tsx +51 -0
  89. package/src/components/ui/spinner.tsx +16 -0
  90. package/src/components/ui/switch.tsx +31 -0
  91. package/src/components/ui/table.tsx +113 -0
  92. package/src/components/ui/tabs.tsx +82 -0
  93. package/src/components/ui/textarea.tsx +17 -0
  94. package/src/components/ui/toast.tsx +229 -0
  95. package/src/components/ui/toggle-group.tsx +87 -0
  96. package/src/components/ui/toggle.tsx +43 -0
  97. package/src/components/ui/tooltip.tsx +65 -0
  98. package/src/components.ts +78 -0
  99. package/src/config.ts +56 -0
  100. package/src/define.ts +122 -0
  101. package/src/doc-context.ts +20 -0
  102. package/src/editor.ts +94 -0
  103. package/src/format-error.ts +78 -0
  104. package/src/guards.ts +84 -0
  105. package/src/hooks/use-mobile.ts +21 -0
  106. package/src/html.ts +91 -0
  107. package/src/hydrate/export-index.ts +232 -0
  108. package/src/hydrate/import-scan.ts +169 -0
  109. package/src/hydrate/plugins.ts +118 -0
  110. package/src/hydrate/runtime-module.ts +145 -0
  111. package/src/hydrate-runtime.ts +67 -0
  112. package/src/hydrate.ts +147 -0
  113. package/src/index.ts +16 -0
  114. package/src/init.ts +57 -0
  115. package/src/langs.ts +148 -0
  116. package/src/lines.ts +53 -0
  117. package/src/load-user-module.ts +191 -0
  118. package/src/mdx.ts +248 -0
  119. package/src/paths.ts +36 -0
  120. package/src/rehype/shiki.ts +533 -0
  121. package/src/remark/alerts.ts +53 -0
  122. package/src/remark/ast.ts +96 -0
  123. package/src/remark/callouts.ts +25 -0
  124. package/src/remark/code-file.ts +85 -0
  125. package/src/remark/code-meta.ts +21 -0
  126. package/src/remark/directives.ts +170 -0
  127. package/src/remark/file-paths.ts +64 -0
  128. package/src/remark/headings.ts +131 -0
  129. package/src/remark/no-js.ts +40 -0
  130. package/src/render.ts +337 -0
  131. package/src/serve.ts +322 -0
  132. package/src/styles/globals.css +134 -0
  133. package/src/styles/shadcn.css +641 -0
  134. package/src/tailwind.ts +119 -0
  135. package/src/ui/approvals.tsx +76 -0
  136. package/src/ui/ask-question.tsx +386 -0
  137. package/src/ui/ask.tsx +206 -0
  138. package/src/ui/attrs.ts +51 -0
  139. package/src/ui/audit.tsx +139 -0
  140. package/src/ui/bar-chart.tsx +334 -0
  141. package/src/ui/benchmarks.tsx +143 -0
  142. package/src/ui/bits.tsx +537 -0
  143. package/src/ui/board.tsx +173 -0
  144. package/src/ui/bridge.tsx +207 -0
  145. package/src/ui/bumps.tsx +178 -0
  146. package/src/ui/callout.tsx +106 -0
  147. package/src/ui/changes.tsx +89 -0
  148. package/src/ui/chart-bits.tsx +52 -0
  149. package/src/ui/chart.ts +577 -0
  150. package/src/ui/checks.tsx +203 -0
  151. package/src/ui/child-index.tsx +44 -0
  152. package/src/ui/children.ts +43 -0
  153. package/src/ui/chips.tsx +49 -0
  154. package/src/ui/cmd.tsx +27 -0
  155. package/src/ui/columns.tsx +31 -0
  156. package/src/ui/comments.tsx +544 -0
  157. package/src/ui/compare.tsx +67 -0
  158. package/src/ui/decision.tsx +79 -0
  159. package/src/ui/deps.tsx +78 -0
  160. package/src/ui/details.tsx +43 -0
  161. package/src/ui/diff-parse.ts +307 -0
  162. package/src/ui/diff.tsx +458 -0
  163. package/src/ui/diffstat.tsx +58 -0
  164. package/src/ui/due.tsx +65 -0
  165. package/src/ui/effort.tsx +29 -0
  166. package/src/ui/endpoints.tsx +118 -0
  167. package/src/ui/envvars.tsx +96 -0
  168. package/src/ui/figure.tsx +37 -0
  169. package/src/ui/file-icon.ts +1020 -0
  170. package/src/ui/file-link.ts +32 -0
  171. package/src/ui/file-ref.tsx +39 -0
  172. package/src/ui/files.tsx +112 -0
  173. package/src/ui/findings.tsx +85 -0
  174. package/src/ui/flow.tsx +73 -0
  175. package/src/ui/funnel.tsx +121 -0
  176. package/src/ui/gantt.tsx +443 -0
  177. package/src/ui/gauges.tsx +135 -0
  178. package/src/ui/glossary.tsx +29 -0
  179. package/src/ui/graph-layout.ts +149 -0
  180. package/src/ui/graph-specs.tsx +102 -0
  181. package/src/ui/graph.tsx +278 -0
  182. package/src/ui/grid.tsx +119 -0
  183. package/src/ui/hypothesis.tsx +94 -0
  184. package/src/ui/icon.tsx +80 -0
  185. package/src/ui/incident.tsx +130 -0
  186. package/src/ui/index.ts +342 -0
  187. package/src/ui/ins-del.tsx +41 -0
  188. package/src/ui/json.tsx +190 -0
  189. package/src/ui/layout.ts +9 -0
  190. package/src/ui/line-chart.tsx +251 -0
  191. package/src/ui/matrix.tsx +208 -0
  192. package/src/ui/meta.tsx +73 -0
  193. package/src/ui/option.tsx +64 -0
  194. package/src/ui/owner.tsx +40 -0
  195. package/src/ui/packages.tsx +104 -0
  196. package/src/ui/pathway.tsx +96 -0
  197. package/src/ui/phase.tsx +41 -0
  198. package/src/ui/pie-chart.tsx +170 -0
  199. package/src/ui/plan.tsx +77 -0
  200. package/src/ui/pre.tsx +175 -0
  201. package/src/ui/priority.tsx +51 -0
  202. package/src/ui/props.tsx +77 -0
  203. package/src/ui/quadrant.tsx +172 -0
  204. package/src/ui/radar.tsx +200 -0
  205. package/src/ui/ref.tsx +160 -0
  206. package/src/ui/release.tsx +178 -0
  207. package/src/ui/req.tsx +42 -0
  208. package/src/ui/review.tsx +133 -0
  209. package/src/ui/risk.tsx +67 -0
  210. package/src/ui/sankey.tsx +287 -0
  211. package/src/ui/scatter.tsx +237 -0
  212. package/src/ui/schema.tsx +113 -0
  213. package/src/ui/score.tsx +105 -0
  214. package/src/ui/search.tsx +120 -0
  215. package/src/ui/series.tsx +38 -0
  216. package/src/ui/severity.tsx +69 -0
  217. package/src/ui/shadcn.tsx +216 -0
  218. package/src/ui/spark.tsx +86 -0
  219. package/src/ui/stack.tsx +57 -0
  220. package/src/ui/stats.tsx +63 -0
  221. package/src/ui/status-badge.tsx +66 -0
  222. package/src/ui/statuspage.tsx +238 -0
  223. package/src/ui/steps.tsx +74 -0
  224. package/src/ui/summary.tsx +41 -0
  225. package/src/ui/symbol-ref.tsx +73 -0
  226. package/src/ui/terminal.tsx +117 -0
  227. package/src/ui/tests.tsx +218 -0
  228. package/src/ui/timeline.tsx +63 -0
  229. package/src/ui/toc.tsx +56 -0
  230. package/src/ui/tones.ts +187 -0
  231. package/src/ui/trace.tsx +69 -0
  232. package/src/ui/tree.tsx +281 -0
  233. package/src/ui/treemap.tsx +128 -0
  234. package/src/ui/venn.tsx +258 -0
  235. package/src/ui/verdict.tsx +78 -0
  236. package/src/ui/waterfall.tsx +142 -0
@@ -0,0 +1,1020 @@
1
+ import { own } from "../guards.js";
2
+ import { hasIcon } from "./icon.js";
3
+
4
+ /**
5
+ * Maps file paths and directory names to Iconify icons. Uses the bundled
6
+ * `vscode-icons` set (`file-type-*`, `folder-type-*`, `default-*`) so common
7
+ * files get their brand icon. Values in the tables are `file-type-*` keys —
8
+ * or full `prefix:name` iconify names for the rare picks outside the set.
9
+ */
10
+
11
+ const fileType = (key: string): string =>
12
+ key.includes(":") ? key : `vscode-icons:file-type-${key}`;
13
+ const folderType = (key: string): string => `vscode-icons:folder-type-${key}`;
14
+
15
+ const DEFAULT_FILE = "vscode-icons:default-file";
16
+ const DEFAULT_FOLDER = "vscode-icons:default-folder";
17
+
18
+ /** Exact basenames (lowercased) → icon key. Beats patterns and extensions. */
19
+ const FILE_NAMES: Record<string, string> = {
20
+ ".angular-cli.json": "angular",
21
+ ".appveyor.yml": "appveyor",
22
+ ".babelrc": "babel",
23
+ ".bazelignore": "bazel",
24
+ ".bazelrc": "bazel",
25
+ ".bazelversion": "bazel",
26
+ ".browserslistrc": "browserslist",
27
+ ".bunignore": "bun",
28
+ ".clippy.toml": "rust",
29
+ ".codacy.yml": "codacy",
30
+ ".codeclimate.yml": "codeclimate",
31
+ ".codecov.yml": "codecov",
32
+ ".condarc": "conda",
33
+ ".coveragerc": "python",
34
+ ".cursorignore": "cursorrules",
35
+ ".cursorrules": "cursorrules",
36
+ ".deepsource.toml": "deepsource",
37
+ ".devcontainer.json": "devcontainer",
38
+ ".direnvrc": "direnv",
39
+ ".dockerignore": "docker",
40
+ ".drone.yml": "drone",
41
+ ".editorconfig": "editorconfig",
42
+ ".envrc": "direnv",
43
+ ".eslintignore": "eslint",
44
+ ".eslintrc": "eslint",
45
+ ".firebaserc": "firebase",
46
+ ".flake8": "python",
47
+ ".git-blame-ignore-revs": "git",
48
+ ".gitattributes": "git",
49
+ ".gitconfig": "git",
50
+ ".gitignore": "git",
51
+ ".gitkeep": "git",
52
+ ".gitlab-ci.yml": "gitlab",
53
+ ".gitmodules": "git",
54
+ ".htaccess": "apache",
55
+ ".htpasswd": "apache",
56
+ ".huskyrc": "husky",
57
+ ".huskyrc.json": "husky",
58
+ ".ionicrc": "ionic",
59
+ ".justfile": "just",
60
+ ".mailmap": "git",
61
+ ".mise.toml": "mise",
62
+ ".netlifyignore": "netlify",
63
+ ".node-version": "node",
64
+ ".npmignore": "npm",
65
+ ".npmrc": "npm",
66
+ ".nvmrc": "node",
67
+ ".pnp.cjs": "yarn",
68
+ ".pnp.loader.mjs": "yarn",
69
+ ".pnpmfile.cjs": "pnpm",
70
+ ".prettierignore": "prettier",
71
+ ".prettierrc": "prettier",
72
+ ".pylintrc": "python",
73
+ ".python-version": "python",
74
+ ".renovaterc": "renovate",
75
+ ".ruby-version": "ruby",
76
+ ".rustfmt.toml": "rust",
77
+ ".stylelintignore": "stylelint",
78
+ ".stylelintrc": "stylelint",
79
+ ".swcrc": "swc",
80
+ ".terraform.lock.hcl": "terraform",
81
+ ".tool-versions": "mise",
82
+ ".travis.yml": "travis",
83
+ ".vercelignore": "vercel",
84
+ ".vscodeignore": "vscode",
85
+ ".yarnrc": "yarn",
86
+ ".yarnrc.yaml": "yarn",
87
+ ".yarnrc.yml": "yarn",
88
+ "agents.md": "agents",
89
+ "angular-cli.json": "angular",
90
+ "angular.json": "angular",
91
+ "ansible.cfg": "ansible",
92
+ "app.yaml": "gcloud",
93
+ "app.yml": "gcloud",
94
+ "appveyor.yml": "appveyor",
95
+ authorized_keys: "key",
96
+ authors: "text",
97
+ "azure-pipelines.yaml": "azurepipelines",
98
+ "azure-pipelines.yml": "azurepipelines",
99
+ berksfile: "chef",
100
+ "biome.json": "biome",
101
+ "biome.jsonc": "biome",
102
+ "bitbucket-pipelines.yml": "bitbucketpipeline",
103
+ brewfile: "brew",
104
+ browserslist: "browserslist",
105
+ "build.bazel": "bazel",
106
+ "bun.lock": "bun",
107
+ "bun.lockb": "bun",
108
+ "bunfig.toml": "bunfig",
109
+ "cabal.project": "cabal",
110
+ caddyfile: "caddy",
111
+ "cargo.lock": "cargo",
112
+ "cargo.toml": "cargo",
113
+ changelog: "text",
114
+ changes: "text",
115
+ "chart.yaml": "helm",
116
+ cheffile: "chef",
117
+ "circle.yml": "circleci",
118
+ "claude.md": "claude",
119
+ "clippy.toml": "rust",
120
+ "cloudbuild.yaml": "gcloud",
121
+ "cloudbuild.yml": "gcloud",
122
+ "cmakelists.txt": "cmake",
123
+ "codacy.yml": "codacy",
124
+ code_of_conduct: "text",
125
+ "codeclimate.yml": "codeclimate",
126
+ "codecov.yaml": "codecov",
127
+ "codecov.yml": "codecov",
128
+ codeowners: "codeowners",
129
+ "compose.yaml": "docker",
130
+ "compose.yml": "docker",
131
+ "composer.json": "composer",
132
+ "composer.lock": "composer",
133
+ "conda.yaml": "conda",
134
+ "conda.yml": "conda",
135
+ "constraints.txt": "python",
136
+ containerfile: "docker",
137
+ contributing: "text",
138
+ contributors: "text",
139
+ "copilot-instructions.md": "copilot",
140
+ copying: "license",
141
+ "crowdin.yaml": "crowdin",
142
+ "crowdin.yml": "crowdin",
143
+ "database.rules.json": "firebase",
144
+ "default.nix": "nix",
145
+ "deno.json": "deno",
146
+ "deno.jsonc": "deno",
147
+ "deno.lock": "deno",
148
+ "dependabot.yml": "dependabot",
149
+ "devcontainer.json": "devcontainer",
150
+ "devenv.lock": "devenv",
151
+ "devenv.nix": "devenv",
152
+ "devenv.yaml": "devenv",
153
+ direnvrc: "direnv",
154
+ "docker-compose.yaml": "docker",
155
+ "docker-compose.yml": "docker",
156
+ dockerfile: "docker",
157
+ "drone.yml": "drone",
158
+ dune: "dune",
159
+ "dune-project": "dune",
160
+ "dune-workspace": "dune",
161
+ "environment.yaml": "conda",
162
+ "environment.yml": "conda",
163
+ "erlang.mk": "erlang",
164
+ "firebase.json": "firebase",
165
+ "firestore.indexes.json": "firestore",
166
+ "firestore.rules": "firestore",
167
+ "flake.lock": "nix",
168
+ "flake.nix": "nix",
169
+ "fly.toml": "flyio",
170
+ "funding.yml": "funding",
171
+ gemfile: "bundler",
172
+ "gemfile.lock": "bundler",
173
+ "gemini.md": "gemini",
174
+ gnumakefile: "gnu",
175
+ "go.mod": "go-package",
176
+ "go.sum": "go-package",
177
+ "go.work": "go-work",
178
+ "go.work.sum": "go-work",
179
+ "gradle.properties": "gradle",
180
+ gradlew: "gradle",
181
+ "gradlew.bat": "gradle",
182
+ guardfile: "ruby",
183
+ "helmfile.yaml": "helm",
184
+ "helmfile.yml": "helm",
185
+ history: "text",
186
+ "humans.txt": "humanstxt",
187
+ id_dsa: "key",
188
+ id_ecdsa: "key",
189
+ id_ed25519: "key",
190
+ id_rsa: "key",
191
+ "ionic.config.json": "ionic",
192
+ jenkinsfile: "jenkins",
193
+ "jsconfig.json": "jsconfig",
194
+ justfile: "just",
195
+ known_hosts: "key",
196
+ "lefthook.toml": "lefthook",
197
+ "lefthook.yaml": "lefthook",
198
+ "lefthook.yml": "lefthook",
199
+ "lerna.json": "lerna",
200
+ licence: "license",
201
+ license: "license",
202
+ maintainers: "text",
203
+ makefile: "gnu",
204
+ "manifest.json": "manifest",
205
+ "manifest.webmanifest": "manifest",
206
+ "meson.build": "meson",
207
+ "meson_options.txt": "meson",
208
+ "mise.toml": "mise",
209
+ "module.bazel": "bazel",
210
+ "module.bazel.lock": "bazel",
211
+ mvnw: "maven",
212
+ "mvnw.cmd": "maven",
213
+ "netlify.toml": "netlify",
214
+ news: "text",
215
+ "nginx.conf": "nginx",
216
+ notice: "license",
217
+ "now.json": "vercel",
218
+ "npm-shrinkwrap.json": "npm",
219
+ "nx.json": "nx",
220
+ "package-lock.json": "npm",
221
+ "package.json": "npm",
222
+ "package.yaml": "haskell",
223
+ patents: "license",
224
+ "pdm.lock": "python",
225
+ pipfile: "python",
226
+ "pipfile.lock": "python",
227
+ "pnpm-lock.yaml": "pnpm",
228
+ "pnpm-workspace.yaml": "pnpm",
229
+ podfile: "ruby",
230
+ "podfile.lock": "ruby",
231
+ "poetry.lock": "poetry",
232
+ "pom.xml": "maven",
233
+ pylintrc: "python",
234
+ "pyproject.toml": "python",
235
+ rakefile: "rake",
236
+ readme: "text",
237
+ "rebar.config": "erlang",
238
+ "rebar.lock": "erlang",
239
+ "renovate.json": "renovate",
240
+ "requirements.txt": "python",
241
+ "robots.txt": "robots",
242
+ "rust-toolchain": "rust-toolchain",
243
+ "rust-toolchain.toml": "rust-toolchain",
244
+ "rust-toolchain.yaml": "rust-toolchain",
245
+ "rustfmt.toml": "rust",
246
+ security: "text",
247
+ "serverless.yaml": "serverless",
248
+ "serverless.yml": "serverless",
249
+ "setup.cfg": "python",
250
+ "setup.py": "python",
251
+ "shell.nix": "nix",
252
+ "site.webmanifest": "manifest",
253
+ "stack.yaml": "haskell",
254
+ "storage.rules": "firebasestorage",
255
+ support: "text",
256
+ "tauri.conf.json": "tauri",
257
+ todo: "todo",
258
+ todos: "todo",
259
+ "tox.ini": "python",
260
+ "tsconfig.json": "tsconfig",
261
+ "turbo.json": "turbo",
262
+ "uv.lock": "uv",
263
+ vagrantfile: "vagrant",
264
+ "vercel.json": "vercel",
265
+ "web.config": "config",
266
+ "workspace.bazel": "bazel",
267
+ "wrangler.json": "cloudflare",
268
+ "wrangler.jsonc": "cloudflare",
269
+ "wrangler.toml": "cloudflare",
270
+ "yarn.lock": "yarn",
271
+ };
272
+
273
+ /** Basename patterns → icon key. First match wins. */
274
+ const FILE_PATTERNS: readonly (readonly [RegExp, string])[] = [
275
+ [/\.d\.[cm]?ts$/u, "typescriptdef"],
276
+ [/\.blade\.php$/u, "blade"],
277
+ [/\.(?:test|spec)\.tsx?$/u, "testts"],
278
+ [/\.(?:test|spec)\.jsx?$/u, "testjs"],
279
+ [/_test\.go$/u, "go"],
280
+ [/\.(?:test|spec)\.\w+$/u, "test"],
281
+ [/_(?:test|spec)\.\w+$/u, "test"],
282
+ [/^test_.+\.py$/u, "python"],
283
+ [/\.stories?\.[jt]sx?$/u, "storybook"],
284
+ [/^tsconfig(?:\.[\w-]+)*\.json$/u, "tsconfig"],
285
+ [/^jsconfig(?:\.[\w-]+)*\.json$/u, "jsconfig"],
286
+ [/^\.?babelrc(?:\..+)?$/u, "babel"],
287
+ [/^\.?eslintrc(?:\..+)?$/u, "eslint"],
288
+ [/^\.?prettierrc(?:\..+)?$/u, "prettier"],
289
+ [/^\.?stylelintrc(?:\..+)?$/u, "stylelint"],
290
+ [/^\.?commitlintrc(?:\..+)?$/u, "commitlint"],
291
+ [/^\.?oxlintrc(?:\..+)?$/u, "oxc"],
292
+ [/^\.?oxfmtrc(?:\..+)?$/u, "oxc"],
293
+ [/^\.?oxcrc(?:\..+)?$/u, "oxc"],
294
+ [/^\.?cspell(?:rc)?(?:\..+)?$/u, "cspell"],
295
+ [/^\.?markdownlint(?:rc)?(?:\..+)?$/u, "markdownlint"],
296
+ [/^\.?htmlhintrc(?:\..+)?$/u, "htmlhint"],
297
+ [/^\.?jshintrc(?:\..+)?$/u, "jshint"],
298
+ [/^\.?lefthook(?:[-.].+)?$/u, "lefthook"],
299
+ [/^\.?renovate(?:rc)?(?:\..+)?$/u, "renovate"],
300
+ [/^\.?graphqlrc(?:\..+)?$/u, "graphql-config"],
301
+ [/^codegen(?:\..+)?$/u, "graphql-config"],
302
+ [/^\.?gitlab-ci.*\.ya?ml$/u, "gitlab"],
303
+ [/^azure-pipelines.*\.ya?ml$/u, "azurepipelines"],
304
+ [/^\.env(?:\..+)?$/u, "dotenv"],
305
+ [/^dockerfile(?:\..+)?$/u, "docker"],
306
+ [/\.dockerfile$/u, "docker"],
307
+ [/^containerfile(?:\..+)?$/u, "docker"],
308
+ [/^docker-compose(?:\..+)?\.ya?ml$/u, "docker"],
309
+ [/^compose(?:\..+)?\.ya?ml$/u, "docker"],
310
+ [/^requirements[._-]?.*\.txt$/u, "python"],
311
+ [/^licen[cs]e[._-]?(?:\..+)?$/u, "license"],
312
+ [/^sitemap.*\.xml$/u, "sitemap"],
313
+ [/\.vscodeignore$/u, "vscode"],
314
+ [/^wrangler\..+$/u, "cloudflare"],
315
+ [/\.gemspec$/u, "bundler"],
316
+ [/\.jenkinsfile$/u, "jenkins"],
317
+ [/^jenkinsfile\..+$/u, "jenkins"],
318
+ [/\.gradle\.kts$/u, "gradle"],
319
+ [/^gradlew(?:\..+)?$/u, "gradle"],
320
+ [/^tauri\..*\.conf\.json$/u, "tauri"],
321
+ [/^electron-builder(?:\..+)?$/u, "electron"],
322
+ [/^serverless\.(?:ts|js|json)$/u, "serverless"],
323
+ [/^\.mise[./]/u, "mise"],
324
+ ];
325
+
326
+ /** `<tool>.config.<ext>` → icon key (unknown tools fall back to `config`). */
327
+ const CONFIG_TOOLS: Record<string, string> = {
328
+ astro: "astroconfig",
329
+ babel: "babel",
330
+ capacitor: "capacitor",
331
+ commitlint: "commitlint",
332
+ cypress: "cypress",
333
+ drizzle: "drizzle-orm",
334
+ electron: "electron",
335
+ esbuild: "esbuild",
336
+ eslint: "eslint",
337
+ jest: "jest",
338
+ karma: "karma",
339
+ knip: "knip",
340
+ lefthook: "lefthook",
341
+ next: "next",
342
+ nuxt: "nuxt",
343
+ oxc: "oxc",
344
+ oxfmt: "oxc",
345
+ oxlint: "oxc",
346
+ parcel: "parcel",
347
+ playwright: "playwright",
348
+ postcss: "postcss",
349
+ prettier: "prettier",
350
+ rolldown: "rolldown",
351
+ rollup: "rollup",
352
+ storybook: "storybook",
353
+ stylelint: "stylelint",
354
+ svelte: "svelte",
355
+ tailwind: "tailwind",
356
+ tauri: "tauri",
357
+ typedoc: "typedoc",
358
+ vite: "vite",
359
+ vitest: "vitest",
360
+ vue: "vue",
361
+ webpack: "webpack",
362
+ };
363
+
364
+ const CONFIG_RE = /^(?<tool>[a-z0-9][a-z0-9-]*)\.config\.[cm]?[jt]sx?$/u;
365
+
366
+ /** Extensions (lowercase, no dot) → icon key. Also covers bare shiki lang ids. */
367
+ const EXT_ICONS: Record<string, string> = {
368
+ "3gp": "video",
369
+ "7z": "zip",
370
+ a: "binary",
371
+ aab: "binary",
372
+ aac: "audio",
373
+ ada: "ada",
374
+ adb: "ada",
375
+ adoc: "asciidoc",
376
+ ads: "ada",
377
+ ahk: "autohotkey",
378
+ ai: "ai",
379
+ am: "gnu",
380
+ ansible: "ansible",
381
+ apache: "apache",
382
+ apk: "binary",
383
+ appimage: "binary",
384
+ applescript: "applescript",
385
+ asc: "gpg",
386
+ asciidoc: "asciidoc",
387
+ asm: "assembly",
388
+ asp: "asp",
389
+ aspx: "aspx",
390
+ ass: "text",
391
+ astro: "astro",
392
+ au3: "autoit",
393
+ avi: "video",
394
+ avif: "avif",
395
+ avro: "avro",
396
+ awk: "awk",
397
+ azw3: "epub",
398
+ bas: "vb",
399
+ bash: "shell",
400
+ bat: "bat",
401
+ bazel: "bazel",
402
+ bib: "tex",
403
+ bicep: "bicep",
404
+ bin: "binary",
405
+ bmp: "image",
406
+ bru: "bruno",
407
+ bz2: "zip",
408
+ bzl: "bazel",
409
+ c: "c",
410
+ "c#": "csharp",
411
+ "c++": "cpp",
412
+ cab: "zip",
413
+ cabal: "cabal",
414
+ caddy: "caddy",
415
+ capnp: "capnp",
416
+ cbl: "cobol",
417
+ cc: "cpp",
418
+ cer: "cert",
419
+ cfg: "config",
420
+ cjs: "js",
421
+ class: "class",
422
+ clj: "clojure",
423
+ cljc: "clojure",
424
+ cljs: "clojurescript",
425
+ clojure: "clojure",
426
+ cls: "tex",
427
+ cmake: "cmake",
428
+ cmd: "bat",
429
+ cob: "cobol",
430
+ cobol: "cobol",
431
+ com: "binary",
432
+ conf: "config",
433
+ config: "config",
434
+ console: "shell",
435
+ cp: "cpp",
436
+ cpp: "cpp",
437
+ cr: "crystal",
438
+ crt: "cert",
439
+ crystal: "crystal",
440
+ cs: "csharp",
441
+ csharp: "csharp",
442
+ cshtml: "razor",
443
+ csproj: "csproj",
444
+ csr: "cert",
445
+ css: "css",
446
+ csv: "excel",
447
+ csx: "csharp",
448
+ cts: "typescript",
449
+ cur: "image",
450
+ cxx: "cpp",
451
+ dart: "dartlang",
452
+ dat: "binary",
453
+ db: "db",
454
+ db3: "db",
455
+ dbml: "dbml",
456
+ deb: "debian",
457
+ der: "cert",
458
+ diff: "diff",
459
+ dio: "drawio",
460
+ dll: "binary",
461
+ dmg: "binary",
462
+ doc: "word",
463
+ dockerfile: "docker",
464
+ dockerignore: "docker",
465
+ docx: "word",
466
+ dot: "graphviz",
467
+ dpr: "delphi",
468
+ drawio: "drawio",
469
+ dtd: "dtd",
470
+ dylib: "binary",
471
+ ear: "jar",
472
+ edn: "clojure",
473
+ eex: "eex",
474
+ ejs: "ejs",
475
+ elisp: "emacs",
476
+ elixir: "elixir",
477
+ env: "dotenv",
478
+ eot: "font",
479
+ eps: "eps",
480
+ epub: "epub",
481
+ erb: "erb",
482
+ erl: "erlang",
483
+ erlang: "erlang",
484
+ ex: "elixir",
485
+ excalidraw: "excalidraw",
486
+ exe: "binary",
487
+ exs: "elixir",
488
+ f: "fortran",
489
+ "f#": "fsharp",
490
+ f03: "fortran",
491
+ f08: "fortran",
492
+ f90: "fortran",
493
+ f95: "fortran",
494
+ fig: "image",
495
+ fish: "shell",
496
+ flac: "audio",
497
+ flutter: "flutter",
498
+ for: "fortran",
499
+ fortran: "fortran",
500
+ fs: "fsharp",
501
+ fsharp: "fsharp",
502
+ fsi: "fsharp",
503
+ fsproj: "fsproj",
504
+ fsx: "fsharp",
505
+ gif: "image",
506
+ gleam: "gleam",
507
+ go: "go",
508
+ golang: "go",
509
+ gpg: "gpg",
510
+ gql: "graphql",
511
+ gradle: "gradle",
512
+ graphql: "graphql",
513
+ graphqls: "graphql",
514
+ groovy: "groovy",
515
+ gsh: "groovy",
516
+ gv: "graphviz",
517
+ gvy: "groovy",
518
+ gy: "groovy",
519
+ gz: "zip",
520
+ h: "cheader",
521
+ "h++": "cppheader",
522
+ haml: "haml",
523
+ handlebars: "handlebars",
524
+ haskell: "haskell",
525
+ hbs: "handlebars",
526
+ hcl: "terraform",
527
+ heex: "eex",
528
+ heic: "image",
529
+ heif: "image",
530
+ hh: "cppheader",
531
+ hjs: "handlebars",
532
+ hpp: "cppheader",
533
+ hrl: "erlang",
534
+ hs: "haskell",
535
+ htm: "html",
536
+ html: "html",
537
+ http: "http",
538
+ hurl: "hurl",
539
+ hxx: "cppheader",
540
+ icns: "image",
541
+ ico: "favicon",
542
+ img: "binary",
543
+ ini: "ini",
544
+ ipa: "binary",
545
+ ipp: "cppheader",
546
+ ipynb: "jupyter",
547
+ iso: "binary",
548
+ j2: "jinja",
549
+ jade: "pug",
550
+ jar: "jar",
551
+ java: "java",
552
+ javascript: "js",
553
+ jenkinsfile: "jenkins",
554
+ jfif: "image",
555
+ jinja: "jinja",
556
+ jinja2: "jinja",
557
+ jl: "julia",
558
+ jpeg: "image",
559
+ jpg: "image",
560
+ js: "js",
561
+ json: "json",
562
+ json5: "json5",
563
+ jsonc: "json",
564
+ jsonl: "json",
565
+ jsonld: "jsonld",
566
+ jsp: "jsp",
567
+ jspx: "jsp",
568
+ jsx: "reactjs",
569
+ julia: "julia",
570
+ just: "just",
571
+ kdbx: "key",
572
+ key: "key",
573
+ kotlin: "kotlin",
574
+ ksh: "shell",
575
+ kt: "kotlin",
576
+ kts: "kotlin",
577
+ latex: "tex",
578
+ leex: "eex",
579
+ less: "less",
580
+ lhs: "haskell",
581
+ lib: "binary",
582
+ lock: "lucide:lock",
583
+ log: "log",
584
+ lpr: "delphi",
585
+ lua: "lua",
586
+ lz4: "zip",
587
+ m: "objectivec",
588
+ m4a: "audio",
589
+ m4v: "video",
590
+ mak: "gnu",
591
+ makefile: "gnu",
592
+ map: "map",
593
+ markdown: "markdown",
594
+ marko: "marko",
595
+ md: "markdown",
596
+ mdown: "markdown",
597
+ mdx: "mdx",
598
+ mermaid: "mermaid",
599
+ meson: "meson",
600
+ mid: "audio",
601
+ midi: "audio",
602
+ mjml: "mjml",
603
+ mjs: "js",
604
+ mk: "gnu",
605
+ mkd: "markdown",
606
+ mkv: "video",
607
+ ml: "ocaml",
608
+ mli: "ocaml-intf",
609
+ mll: "ocaml",
610
+ mly: "ocaml",
611
+ mm: "objectivec",
612
+ mmd: "mermaid",
613
+ mobi: "epub",
614
+ mojo: "mojo",
615
+ mov: "video",
616
+ mp3: "audio",
617
+ mp4: "video",
618
+ mpeg: "video",
619
+ mpg: "video",
620
+ msi: "binary",
621
+ mts: "typescript",
622
+ mustache: "handlebars",
623
+ mysql: "mysql",
624
+ nasm: "assembly",
625
+ ndjson: "json",
626
+ nginx: "nginx",
627
+ nim: "nim",
628
+ nimble: "nim",
629
+ nims: "nim",
630
+ nix: "nix",
631
+ nu: "nushell",
632
+ numbers: "excel",
633
+ nushell: "nushell",
634
+ o: "binary",
635
+ obj: "binary",
636
+ "objective-c": "objectivec",
637
+ objectivec: "objectivec",
638
+ ocaml: "ocaml",
639
+ odp: "powerpoint",
640
+ ods: "excel",
641
+ odt: "word",
642
+ ogg: "audio",
643
+ opus: "audio",
644
+ org: "org",
645
+ otf: "font",
646
+ p12: "cert",
647
+ pas: "delphi",
648
+ patch: "patch",
649
+ pcss: "postcss",
650
+ pdf: "pdf2",
651
+ pem: "cert",
652
+ perl: "perl",
653
+ pfx: "cert",
654
+ pgp: "gpg",
655
+ pgsql: "postgres",
656
+ php: "php",
657
+ php3: "php",
658
+ php4: "php",
659
+ php5: "php",
660
+ php7: "php",
661
+ phps: "php",
662
+ phtml: "php",
663
+ pkb: "sql",
664
+ pkg: "binary",
665
+ pks: "sql",
666
+ pl: "perl",
667
+ plaintext: "text",
668
+ plantuml: "plantuml",
669
+ plist: "xml",
670
+ plsql: "sql",
671
+ pm: "perl",
672
+ png: "image",
673
+ po: "locale",
674
+ postcss: "postcss",
675
+ pot: "locale",
676
+ powershell: "powershell",
677
+ pp: "delphi",
678
+ ppt: "powerpoint",
679
+ pptx: "powerpoint",
680
+ prisma: "prisma",
681
+ properties: "config",
682
+ props: "config",
683
+ proto: "protobuf",
684
+ protobuf: "protobuf",
685
+ ps1: "powershell",
686
+ psd: "photoshop",
687
+ psd1: "powershell",
688
+ psm1: "powershell",
689
+ pu: "plantuml",
690
+ pub: "key",
691
+ pug: "pug",
692
+ puml: "plantuml",
693
+ py: "python",
694
+ pyc: "python",
695
+ pyi: "python",
696
+ pyo: "python",
697
+ python: "python",
698
+ pyw: "python",
699
+ pyx: "python",
700
+ r: "r",
701
+ rake: "rake",
702
+ rar: "zip",
703
+ raw: "image",
704
+ razor: "razor",
705
+ rb: "ruby",
706
+ reg: "registry",
707
+ rej: "patch",
708
+ rest: "rest",
709
+ rmd: "rmd",
710
+ rpm: "binary",
711
+ rs: "rust",
712
+ rst: "text",
713
+ rtf: "word",
714
+ ruby: "ruby",
715
+ run: "binary",
716
+ rust: "rust",
717
+ s: "assembly",
718
+ s51: "assembly",
719
+ sass: "sass",
720
+ sbt: "sbt",
721
+ sc: "scala",
722
+ scala: "scala",
723
+ scpt: "applescript",
724
+ scss: "scss",
725
+ sh: "shell",
726
+ shell: "shell",
727
+ shellscript: "shell",
728
+ shellsession: "shell",
729
+ sig: "gpg",
730
+ sketch: "sketch",
731
+ sln: "sln",
732
+ slnx: "sln",
733
+ snap: "jest-snapshot",
734
+ so: "binary",
735
+ sol: "solidity",
736
+ solidity: "solidity",
737
+ sql: "sql",
738
+ sqlite: "sqlite",
739
+ sqlite3: "sqlite",
740
+ srt: "text",
741
+ ssa: "text",
742
+ sty: "tex",
743
+ styl: "stylus",
744
+ sv: "verilog",
745
+ svelte: "svelte",
746
+ svg: "svg",
747
+ svh: "verilog",
748
+ swift: "swift",
749
+ t: "perl",
750
+ tar: "zip",
751
+ templ: "templ",
752
+ terraform: "terraform",
753
+ tex: "tex",
754
+ text: "text",
755
+ textile: "textile",
756
+ tf: "terraform",
757
+ tfstate: "terraform",
758
+ tfvars: "terraform",
759
+ tgz: "zip",
760
+ tif: "image",
761
+ tiff: "image",
762
+ tofu: "opentofu",
763
+ toml: "toml",
764
+ ts: "typescript",
765
+ tsbuildinfo: "tsbuildinfo",
766
+ tsv: "excel",
767
+ tsx: "reactts",
768
+ ttf: "font",
769
+ twig: "twig",
770
+ txt: "text",
771
+ typ: "text",
772
+ typescript: "typescript",
773
+ v: "vlang",
774
+ vb: "vb",
775
+ vbproj: "vb",
776
+ verilog: "verilog",
777
+ vh: "verilog",
778
+ vhd: "vhdl",
779
+ vhdl: "vhdl",
780
+ vim: "vim",
781
+ viml: "vim",
782
+ vimrc: "vim",
783
+ vsh: "vlang",
784
+ vtt: "text",
785
+ vue: "vue",
786
+ vv: "vlang",
787
+ vy: "vyper",
788
+ war: "jar",
789
+ wasm: "wasm",
790
+ wat: "wasm",
791
+ wav: "audio",
792
+ webm: "video",
793
+ webmanifest: "manifest",
794
+ webp: "webp",
795
+ wiki: "wikitext",
796
+ wmv: "video",
797
+ woff: "font",
798
+ woff2: "font",
799
+ xcf: "gimp",
800
+ xd: "image",
801
+ xhtml: "html",
802
+ xls: "excel",
803
+ xlsx: "excel",
804
+ xml: "xml",
805
+ xsd: "xml",
806
+ xsl: "xml",
807
+ xslt: "xml",
808
+ xz: "zip",
809
+ yaml: "yaml",
810
+ yml: "yaml",
811
+ zig: "zig",
812
+ zip: "zip",
813
+ zsh: "shell",
814
+ zst: "zip",
815
+ "🔥": "mojo",
816
+ };
817
+
818
+ /** Directory names (lowercased) → `folder-type-*` key — aliases only; exact
819
+ * names resolve via the `folder-type-<name>` probe in `folderIcon`. */
820
+ const DIR_NAMES: Record<string, string> = {
821
+ ".astro": "astro",
822
+ ".aws": "aws",
823
+ ".azure": "azure",
824
+ ".cache": "temp",
825
+ ".cargo": "cargo",
826
+ ".changeset": "changesets",
827
+ ".changesets": "changesets",
828
+ ".circleci": "circleci",
829
+ ".claude": "claude",
830
+ ".composer": "composer",
831
+ ".cursor": "cursor",
832
+ ".dart_tool": "dart",
833
+ ".devcontainer": "devcontainer",
834
+ ".docker": "docker",
835
+ ".expo": "expo",
836
+ ".gcp": "gcp",
837
+ ".gemini": "gemini",
838
+ ".git": "git",
839
+ ".github": "github",
840
+ ".gitlab": "gitlab",
841
+ ".gradle": "gradle",
842
+ ".grok": "grok",
843
+ ".husky": "husky",
844
+ ".idea": "idea",
845
+ ".junie": "junie",
846
+ ".kiro": "kiro",
847
+ ".mvn": "maven",
848
+ ".mypy_cache": "mypy",
849
+ ".netlify": "netlify",
850
+ ".next": "next",
851
+ ".nuget": "nuget",
852
+ ".nuxt": "nuxt",
853
+ ".pytest_cache": "pytest",
854
+ ".storybook": "story",
855
+ ".svelte-kit": "svelte",
856
+ ".tauri": "tauri",
857
+ ".turbo": "turbo",
858
+ ".vercel": "vercel",
859
+ ".vitepress": "vitepress",
860
+ ".vscode": "vscode",
861
+ ".windsurf": "windsurf",
862
+ ".yarn": "yarn",
863
+ ".zed": "zed",
864
+ "@types": "typings",
865
+ __mocks__: "mock",
866
+ __tests__: "test",
867
+ addons: "plugin",
868
+ apis: "api",
869
+ apps: "app",
870
+ assets: "asset",
871
+ auth: "sso",
872
+ bin: "binary",
873
+ bower_components: "bower",
874
+ build: "dist",
875
+ cache: "temp",
876
+ certificates: "certificate",
877
+ certs: "certificate",
878
+ charts: "kubernetes",
879
+ clients: "client",
880
+ cmd: "cli",
881
+ commands: "cli",
882
+ commons: "common",
883
+ components: "component",
884
+ conf: "config",
885
+ configs: "config",
886
+ controllers: "controller",
887
+ darwin: "macos",
888
+ data: "db",
889
+ database: "db",
890
+ databases: "db",
891
+ doc: "docs",
892
+ documentation: "docs",
893
+ dtos: "model",
894
+ elements: "component",
895
+ entities: "model",
896
+ env: "environments",
897
+ envs: "environments",
898
+ extensions: "plugin",
899
+ fixtures: "mock",
900
+ font: "fonts",
901
+ generated: "dist",
902
+ helm: "kubernetes",
903
+ helpers: "helper",
904
+ hooks: "hook",
905
+ i18n: "locale",
906
+ icons: "images",
907
+ image: "images",
908
+ imgs: "images",
909
+ includes: "include",
910
+ interfaces: "interfaces",
911
+ k8s: "kubernetes",
912
+ keys: "certificate",
913
+ l10n: "locale",
914
+ lang: "locale",
915
+ languages: "locale",
916
+ lib: "library",
917
+ libs: "library",
918
+ locales: "locale",
919
+ logs: "log",
920
+ media: "images",
921
+ middlewares: "middleware",
922
+ migrations: "db",
923
+ mocks: "mock",
924
+ models: "model",
925
+ modules: "module",
926
+ mongo: "mongodb",
927
+ node_modules: "node",
928
+ notebook: "notebooks",
929
+ out: "dist",
930
+ output: "dist",
931
+ packages: "package",
932
+ pages: "view",
933
+ pictures: "images",
934
+ pkg: "package",
935
+ plugins: "plugin",
936
+ providers: "services",
937
+ release: "dist",
938
+ router: "route",
939
+ routes: "route",
940
+ schemas: "model",
941
+ screens: "view",
942
+ scripts: "script",
943
+ secrets: "private",
944
+ servers: "server",
945
+ settings: "config",
946
+ spec: "test",
947
+ specs: "test",
948
+ "src-tauri": "tauri",
949
+ ssl: "certificate",
950
+ static: "public",
951
+ stories: "story",
952
+ styles: "style",
953
+ target: "dist",
954
+ templates: "template",
955
+ tests: "test",
956
+ themes: "theme",
957
+ tmp: "temp",
958
+ translations: "locale",
959
+ types: "typescript",
960
+ util: "helper",
961
+ utilities: "helper",
962
+ utils: "helper",
963
+ vendor: "package",
964
+ views: "view",
965
+ widgets: "component",
966
+ wiki: "docs",
967
+ win32: "windows",
968
+ wwwroot: "public",
969
+ };
970
+
971
+ const basename = (path: string): string =>
972
+ (path.split(/[\\/]/u).pop() ?? path).trim().toLowerCase();
973
+
974
+ /** Iconify name for a file path, picked from its name and extension.
975
+ * `own` guards every table lookup: prototype members ("constructor",
976
+ * "toString") are valid file names but not icon keys. */
977
+ export const fileIcon = (path: string): string => {
978
+ const base = basename(path);
979
+ const named = own(FILE_NAMES, base);
980
+ if (named !== undefined) {
981
+ return fileType(named);
982
+ }
983
+ for (const [re, key] of FILE_PATTERNS) {
984
+ if (re.test(base)) {
985
+ return fileType(key);
986
+ }
987
+ }
988
+ const tool = CONFIG_RE.exec(base)?.groups?.tool;
989
+ if (tool !== undefined) {
990
+ return fileType(own(CONFIG_TOOLS, tool) ?? "config");
991
+ }
992
+ const dot = base.lastIndexOf(".");
993
+ // `.gitignore`-style dotfiles carry no extension; an extensionless name is
994
+ // tried as one so bare lang ids ("ts", "python") also resolve.
995
+ let ext = "";
996
+ if (dot === -1) {
997
+ ext = base;
998
+ } else if (dot > 0) {
999
+ ext = base.slice(dot + 1);
1000
+ }
1001
+ if (ext !== "") {
1002
+ const key = own(EXT_ICONS, ext);
1003
+ if (key !== undefined) {
1004
+ return fileType(key);
1005
+ }
1006
+ const probed = fileType(ext);
1007
+ if (hasIcon(probed)) {
1008
+ return probed;
1009
+ }
1010
+ }
1011
+ return DEFAULT_FILE;
1012
+ };
1013
+
1014
+ /** Iconify name for a directory, picked from its name. */
1015
+ export const folderIcon = (name: string): string => {
1016
+ const base = basename(name.replace(/\/+$/u, ""));
1017
+ const key = own(DIR_NAMES, base) ?? base;
1018
+ const probed = folderType(key);
1019
+ return hasIcon(probed) ? probed : DEFAULT_FOLDER;
1020
+ };