@shirokuma-library/shirokuma-docs 0.1.0-alpha.5

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.

Potentially problematic release.


This version of @shirokuma-library/shirokuma-docs might be problematic. Click here for more details.

Files changed (753) hide show
  1. package/LICENSE +21 -0
  2. package/README.en.md +308 -0
  3. package/README.md +308 -0
  4. package/THIRD_PARTY_NOTICES.md +18 -0
  5. package/bin/shirokuma-docs +2 -0
  6. package/dist/analyzers/details-test-analysis.d.ts +31 -0
  7. package/dist/analyzers/details-test-analysis.d.ts.map +1 -0
  8. package/dist/analyzers/details-test-analysis.js +172 -0
  9. package/dist/analyzers/details-test-analysis.js.map +1 -0
  10. package/dist/analyzers/feature-map-builder.d.ts +20 -0
  11. package/dist/analyzers/feature-map-builder.d.ts.map +1 -0
  12. package/dist/analyzers/feature-map-builder.js +154 -0
  13. package/dist/analyzers/feature-map-builder.js.map +1 -0
  14. package/dist/analyzers/feature-map-references.d.ts +34 -0
  15. package/dist/analyzers/feature-map-references.d.ts.map +1 -0
  16. package/dist/analyzers/feature-map-references.js +249 -0
  17. package/dist/analyzers/feature-map-references.js.map +1 -0
  18. package/dist/analyzers/reference-analyzer.d.ts +95 -0
  19. package/dist/analyzers/reference-analyzer.d.ts.map +1 -0
  20. package/dist/analyzers/reference-analyzer.js +372 -0
  21. package/dist/analyzers/reference-analyzer.js.map +1 -0
  22. package/dist/commands/adr.d.ts +26 -0
  23. package/dist/commands/adr.d.ts.map +1 -0
  24. package/dist/commands/adr.js +129 -0
  25. package/dist/commands/adr.js.map +1 -0
  26. package/dist/commands/api-tools.d.ts +83 -0
  27. package/dist/commands/api-tools.d.ts.map +1 -0
  28. package/dist/commands/api-tools.js +775 -0
  29. package/dist/commands/api-tools.js.map +1 -0
  30. package/dist/commands/coverage.d.ts +139 -0
  31. package/dist/commands/coverage.d.ts.map +1 -0
  32. package/dist/commands/coverage.js +481 -0
  33. package/dist/commands/coverage.js.map +1 -0
  34. package/dist/commands/deps.d.ts +24 -0
  35. package/dist/commands/deps.d.ts.map +1 -0
  36. package/dist/commands/deps.js +211 -0
  37. package/dist/commands/deps.js.map +1 -0
  38. package/dist/commands/details-context.d.ts +38 -0
  39. package/dist/commands/details-context.d.ts.map +1 -0
  40. package/dist/commands/details-context.js +193 -0
  41. package/dist/commands/details-context.js.map +1 -0
  42. package/dist/commands/details-types.d.ts +315 -0
  43. package/dist/commands/details-types.d.ts.map +1 -0
  44. package/dist/commands/details-types.js +7 -0
  45. package/dist/commands/details-types.js.map +1 -0
  46. package/dist/commands/details.d.ts +24 -0
  47. package/dist/commands/details.d.ts.map +1 -0
  48. package/dist/commands/details.js +299 -0
  49. package/dist/commands/details.js.map +1 -0
  50. package/dist/commands/discussion-templates.d.ts +26 -0
  51. package/dist/commands/discussion-templates.d.ts.map +1 -0
  52. package/dist/commands/discussion-templates.js +270 -0
  53. package/dist/commands/discussion-templates.js.map +1 -0
  54. package/dist/commands/discussions.d.ts +31 -0
  55. package/dist/commands/discussions.d.ts.map +1 -0
  56. package/dist/commands/discussions.js +743 -0
  57. package/dist/commands/discussions.js.map +1 -0
  58. package/dist/commands/feature-map-types.d.ts +294 -0
  59. package/dist/commands/feature-map-types.d.ts.map +1 -0
  60. package/dist/commands/feature-map-types.js +8 -0
  61. package/dist/commands/feature-map-types.js.map +1 -0
  62. package/dist/commands/feature-map.d.ts +30 -0
  63. package/dist/commands/feature-map.d.ts.map +1 -0
  64. package/dist/commands/feature-map.js +137 -0
  65. package/dist/commands/feature-map.js.map +1 -0
  66. package/dist/commands/generate.d.ts +16 -0
  67. package/dist/commands/generate.d.ts.map +1 -0
  68. package/dist/commands/generate.js +88 -0
  69. package/dist/commands/generate.js.map +1 -0
  70. package/dist/commands/gh-discussions.d.ts +31 -0
  71. package/dist/commands/gh-discussions.d.ts.map +1 -0
  72. package/dist/commands/gh-discussions.js +743 -0
  73. package/dist/commands/gh-discussions.js.map +1 -0
  74. package/dist/commands/gh-issues-pr.d.ts +74 -0
  75. package/dist/commands/gh-issues-pr.d.ts.map +1 -0
  76. package/dist/commands/gh-issues-pr.js +417 -0
  77. package/dist/commands/gh-issues-pr.js.map +1 -0
  78. package/dist/commands/gh-issues.d.ts +90 -0
  79. package/dist/commands/gh-issues.d.ts.map +1 -0
  80. package/dist/commands/gh-issues.js +1297 -0
  81. package/dist/commands/gh-issues.js.map +1 -0
  82. package/dist/commands/gh-projects.d.ts +54 -0
  83. package/dist/commands/gh-projects.d.ts.map +1 -0
  84. package/dist/commands/gh-projects.js +966 -0
  85. package/dist/commands/gh-projects.js.map +1 -0
  86. package/dist/commands/gh-repo.d.ts +18 -0
  87. package/dist/commands/gh-repo.d.ts.map +1 -0
  88. package/dist/commands/gh-repo.js +253 -0
  89. package/dist/commands/gh-repo.js.map +1 -0
  90. package/dist/commands/github-data.d.ts +67 -0
  91. package/dist/commands/github-data.d.ts.map +1 -0
  92. package/dist/commands/github-data.js +361 -0
  93. package/dist/commands/github-data.js.map +1 -0
  94. package/dist/commands/i18n.d.ts +102 -0
  95. package/dist/commands/i18n.d.ts.map +1 -0
  96. package/dist/commands/i18n.js +829 -0
  97. package/dist/commands/i18n.js.map +1 -0
  98. package/dist/commands/impact.d.ts +14 -0
  99. package/dist/commands/impact.d.ts.map +1 -0
  100. package/dist/commands/impact.js +263 -0
  101. package/dist/commands/impact.js.map +1 -0
  102. package/dist/commands/init.d.ts +53 -0
  103. package/dist/commands/init.d.ts.map +1 -0
  104. package/dist/commands/init.js +429 -0
  105. package/dist/commands/init.js.map +1 -0
  106. package/dist/commands/issues-pr.d.ts +74 -0
  107. package/dist/commands/issues-pr.d.ts.map +1 -0
  108. package/dist/commands/issues-pr.js +417 -0
  109. package/dist/commands/issues-pr.js.map +1 -0
  110. package/dist/commands/issues.d.ts +76 -0
  111. package/dist/commands/issues.d.ts.map +1 -0
  112. package/dist/commands/issues.js +1285 -0
  113. package/dist/commands/issues.js.map +1 -0
  114. package/dist/commands/link-docs.d.ts +21 -0
  115. package/dist/commands/link-docs.d.ts.map +1 -0
  116. package/dist/commands/link-docs.js +990 -0
  117. package/dist/commands/link-docs.js.map +1 -0
  118. package/dist/commands/lint-annotations.d.ts +28 -0
  119. package/dist/commands/lint-annotations.d.ts.map +1 -0
  120. package/dist/commands/lint-annotations.js +511 -0
  121. package/dist/commands/lint-annotations.js.map +1 -0
  122. package/dist/commands/lint-code.d.ts +26 -0
  123. package/dist/commands/lint-code.d.ts.map +1 -0
  124. package/dist/commands/lint-code.js +428 -0
  125. package/dist/commands/lint-code.js.map +1 -0
  126. package/dist/commands/lint-coverage.d.ts +33 -0
  127. package/dist/commands/lint-coverage.d.ts.map +1 -0
  128. package/dist/commands/lint-coverage.js +379 -0
  129. package/dist/commands/lint-coverage.js.map +1 -0
  130. package/dist/commands/lint-docs.d.ts +23 -0
  131. package/dist/commands/lint-docs.d.ts.map +1 -0
  132. package/dist/commands/lint-docs.js +338 -0
  133. package/dist/commands/lint-docs.js.map +1 -0
  134. package/dist/commands/lint-structure.d.ts +38 -0
  135. package/dist/commands/lint-structure.d.ts.map +1 -0
  136. package/dist/commands/lint-structure.js +350 -0
  137. package/dist/commands/lint-structure.js.map +1 -0
  138. package/dist/commands/lint-tests.d.ts +25 -0
  139. package/dist/commands/lint-tests.d.ts.map +1 -0
  140. package/dist/commands/lint-tests.js +105 -0
  141. package/dist/commands/lint-tests.js.map +1 -0
  142. package/dist/commands/lint-workflow.d.ts +36 -0
  143. package/dist/commands/lint-workflow.d.ts.map +1 -0
  144. package/dist/commands/lint-workflow.js +255 -0
  145. package/dist/commands/lint-workflow.js.map +1 -0
  146. package/dist/commands/overview.d.ts +21 -0
  147. package/dist/commands/overview.d.ts.map +1 -0
  148. package/dist/commands/overview.js +1300 -0
  149. package/dist/commands/overview.js.map +1 -0
  150. package/dist/commands/packages.d.ts +107 -0
  151. package/dist/commands/packages.d.ts.map +1 -0
  152. package/dist/commands/packages.js +308 -0
  153. package/dist/commands/packages.js.map +1 -0
  154. package/dist/commands/portal-nextjs.d.ts +23 -0
  155. package/dist/commands/portal-nextjs.d.ts.map +1 -0
  156. package/dist/commands/portal-nextjs.js +336 -0
  157. package/dist/commands/portal-nextjs.js.map +1 -0
  158. package/dist/commands/portal.d.ts +24 -0
  159. package/dist/commands/portal.d.ts.map +1 -0
  160. package/dist/commands/portal.js +16 -0
  161. package/dist/commands/portal.js.map +1 -0
  162. package/dist/commands/projects.d.ts +54 -0
  163. package/dist/commands/projects.d.ts.map +1 -0
  164. package/dist/commands/projects.js +969 -0
  165. package/dist/commands/projects.js.map +1 -0
  166. package/dist/commands/repo-pairs.d.ts +19 -0
  167. package/dist/commands/repo-pairs.d.ts.map +1 -0
  168. package/dist/commands/repo-pairs.js +529 -0
  169. package/dist/commands/repo-pairs.js.map +1 -0
  170. package/dist/commands/repo.d.ts +18 -0
  171. package/dist/commands/repo.d.ts.map +1 -0
  172. package/dist/commands/repo.js +253 -0
  173. package/dist/commands/repo.js.map +1 -0
  174. package/dist/commands/schema.d.ts +49 -0
  175. package/dist/commands/schema.d.ts.map +1 -0
  176. package/dist/commands/schema.js +830 -0
  177. package/dist/commands/schema.js.map +1 -0
  178. package/dist/commands/screenshots.d.ts +203 -0
  179. package/dist/commands/screenshots.d.ts.map +1 -0
  180. package/dist/commands/screenshots.js +1234 -0
  181. package/dist/commands/screenshots.js.map +1 -0
  182. package/dist/commands/search-index.d.ts +83 -0
  183. package/dist/commands/search-index.d.ts.map +1 -0
  184. package/dist/commands/search-index.js +389 -0
  185. package/dist/commands/search-index.js.map +1 -0
  186. package/dist/commands/session.d.ts +153 -0
  187. package/dist/commands/session.d.ts.map +1 -0
  188. package/dist/commands/session.js +1243 -0
  189. package/dist/commands/session.js.map +1 -0
  190. package/dist/commands/test-cases-types.d.ts +154 -0
  191. package/dist/commands/test-cases-types.d.ts.map +1 -0
  192. package/dist/commands/test-cases-types.js +7 -0
  193. package/dist/commands/test-cases-types.js.map +1 -0
  194. package/dist/commands/test-cases.d.ts +28 -0
  195. package/dist/commands/test-cases.d.ts.map +1 -0
  196. package/dist/commands/test-cases.js +192 -0
  197. package/dist/commands/test-cases.js.map +1 -0
  198. package/dist/commands/typedoc.d.ts +21 -0
  199. package/dist/commands/typedoc.d.ts.map +1 -0
  200. package/dist/commands/typedoc.js +192 -0
  201. package/dist/commands/typedoc.js.map +1 -0
  202. package/dist/commands/update-skills.d.ts +56 -0
  203. package/dist/commands/update-skills.d.ts.map +1 -0
  204. package/dist/commands/update-skills.js +620 -0
  205. package/dist/commands/update-skills.js.map +1 -0
  206. package/dist/generators/details-entity-pages.d.ts +40 -0
  207. package/dist/generators/details-entity-pages.d.ts.map +1 -0
  208. package/dist/generators/details-entity-pages.js +301 -0
  209. package/dist/generators/details-entity-pages.js.map +1 -0
  210. package/dist/generators/details-html.d.ts +23 -0
  211. package/dist/generators/details-html.d.ts.map +1 -0
  212. package/dist/generators/details-html.js +324 -0
  213. package/dist/generators/details-html.js.map +1 -0
  214. package/dist/generators/details-module-page.d.ts +33 -0
  215. package/dist/generators/details-module-page.d.ts.map +1 -0
  216. package/dist/generators/details-module-page.js +408 -0
  217. package/dist/generators/details-module-page.js.map +1 -0
  218. package/dist/generators/details-styles.d.ts +39 -0
  219. package/dist/generators/details-styles.d.ts.map +1 -0
  220. package/dist/generators/details-styles.js +409 -0
  221. package/dist/generators/details-styles.js.map +1 -0
  222. package/dist/generators/feature-map-html.d.ts +66 -0
  223. package/dist/generators/feature-map-html.d.ts.map +1 -0
  224. package/dist/generators/feature-map-html.js +569 -0
  225. package/dist/generators/feature-map-html.js.map +1 -0
  226. package/dist/generators/feature-map-styles.d.ts +39 -0
  227. package/dist/generators/feature-map-styles.d.ts.map +1 -0
  228. package/dist/generators/feature-map-styles.js +449 -0
  229. package/dist/generators/feature-map-styles.js.map +1 -0
  230. package/dist/generators/test-cases-hierarchy.d.ts +21 -0
  231. package/dist/generators/test-cases-hierarchy.d.ts.map +1 -0
  232. package/dist/generators/test-cases-hierarchy.js +336 -0
  233. package/dist/generators/test-cases-hierarchy.js.map +1 -0
  234. package/dist/generators/test-cases-main.d.ts +20 -0
  235. package/dist/generators/test-cases-main.d.ts.map +1 -0
  236. package/dist/generators/test-cases-main.js +439 -0
  237. package/dist/generators/test-cases-main.js.map +1 -0
  238. package/dist/generators/test-cases-styles.d.ts +64 -0
  239. package/dist/generators/test-cases-styles.d.ts.map +1 -0
  240. package/dist/generators/test-cases-styles.js +1277 -0
  241. package/dist/generators/test-cases-styles.js.map +1 -0
  242. package/dist/index.d.ts +13 -0
  243. package/dist/index.d.ts.map +1 -0
  244. package/dist/index.js +517 -0
  245. package/dist/index.js.map +1 -0
  246. package/dist/lint/annotation-lint.d.ts +198 -0
  247. package/dist/lint/annotation-lint.d.ts.map +1 -0
  248. package/dist/lint/annotation-lint.js +510 -0
  249. package/dist/lint/annotation-lint.js.map +1 -0
  250. package/dist/lint/annotation-types.d.ts +161 -0
  251. package/dist/lint/annotation-types.d.ts.map +1 -0
  252. package/dist/lint/annotation-types.js +31 -0
  253. package/dist/lint/annotation-types.js.map +1 -0
  254. package/dist/lint/code-types.d.ts +135 -0
  255. package/dist/lint/code-types.d.ts.map +1 -0
  256. package/dist/lint/code-types.js +25 -0
  257. package/dist/lint/code-types.js.map +1 -0
  258. package/dist/lint/coverage-types.d.ts +128 -0
  259. package/dist/lint/coverage-types.d.ts.map +1 -0
  260. package/dist/lint/coverage-types.js +24 -0
  261. package/dist/lint/coverage-types.js.map +1 -0
  262. package/dist/lint/docs-types.d.ts +214 -0
  263. package/dist/lint/docs-types.d.ts.map +1 -0
  264. package/dist/lint/docs-types.js +18 -0
  265. package/dist/lint/docs-types.js.map +1 -0
  266. package/dist/lint/formatters/index.d.ts +14 -0
  267. package/dist/lint/formatters/index.d.ts.map +1 -0
  268. package/dist/lint/formatters/index.js +28 -0
  269. package/dist/lint/formatters/index.js.map +1 -0
  270. package/dist/lint/formatters/json.d.ts +11 -0
  271. package/dist/lint/formatters/json.d.ts.map +1 -0
  272. package/dist/lint/formatters/json.js +12 -0
  273. package/dist/lint/formatters/json.js.map +1 -0
  274. package/dist/lint/formatters/summary.d.ts +11 -0
  275. package/dist/lint/formatters/summary.d.ts.map +1 -0
  276. package/dist/lint/formatters/summary.js +37 -0
  277. package/dist/lint/formatters/summary.js.map +1 -0
  278. package/dist/lint/formatters/terminal.d.ts +11 -0
  279. package/dist/lint/formatters/terminal.d.ts.map +1 -0
  280. package/dist/lint/formatters/terminal.js +99 -0
  281. package/dist/lint/formatters/terminal.js.map +1 -0
  282. package/dist/lint/index.d.ts +18 -0
  283. package/dist/lint/index.d.ts.map +1 -0
  284. package/dist/lint/index.js +103 -0
  285. package/dist/lint/index.js.map +1 -0
  286. package/dist/lint/rules/annotation-required.d.ts +35 -0
  287. package/dist/lint/rules/annotation-required.d.ts.map +1 -0
  288. package/dist/lint/rules/annotation-required.js +127 -0
  289. package/dist/lint/rules/annotation-required.js.map +1 -0
  290. package/dist/lint/rules/code-rules.d.ts +12 -0
  291. package/dist/lint/rules/code-rules.d.ts.map +1 -0
  292. package/dist/lint/rules/code-rules.js +11 -0
  293. package/dist/lint/rules/code-rules.js.map +1 -0
  294. package/dist/lint/rules/describe-coverage.d.ts +8 -0
  295. package/dist/lint/rules/describe-coverage.d.ts.map +1 -0
  296. package/dist/lint/rules/describe-coverage.js +43 -0
  297. package/dist/lint/rules/describe-coverage.js.map +1 -0
  298. package/dist/lint/rules/duplicate-testdoc.d.ts +8 -0
  299. package/dist/lint/rules/duplicate-testdoc.d.ts.map +1 -0
  300. package/dist/lint/rules/duplicate-testdoc.js +38 -0
  301. package/dist/lint/rules/duplicate-testdoc.js.map +1 -0
  302. package/dist/lint/rules/index.d.ts +29 -0
  303. package/dist/lint/rules/index.d.ts.map +1 -0
  304. package/dist/lint/rules/index.js +55 -0
  305. package/dist/lint/rules/index.js.map +1 -0
  306. package/dist/lint/rules/server-action-structure.d.ts +37 -0
  307. package/dist/lint/rules/server-action-structure.d.ts.map +1 -0
  308. package/dist/lint/rules/server-action-structure.js +151 -0
  309. package/dist/lint/rules/server-action-structure.js.map +1 -0
  310. package/dist/lint/rules/skipped-test-report.d.ts +11 -0
  311. package/dist/lint/rules/skipped-test-report.d.ts.map +1 -0
  312. package/dist/lint/rules/skipped-test-report.js +31 -0
  313. package/dist/lint/rules/skipped-test-report.js.map +1 -0
  314. package/dist/lint/rules/structure-rules.d.ts +67 -0
  315. package/dist/lint/rules/structure-rules.d.ts.map +1 -0
  316. package/dist/lint/rules/structure-rules.js +615 -0
  317. package/dist/lint/rules/structure-rules.js.map +1 -0
  318. package/dist/lint/rules/testdoc-japanese.d.ts +8 -0
  319. package/dist/lint/rules/testdoc-japanese.d.ts.map +1 -0
  320. package/dist/lint/rules/testdoc-japanese.js +31 -0
  321. package/dist/lint/rules/testdoc-japanese.js.map +1 -0
  322. package/dist/lint/rules/testdoc-min-length.d.ts +8 -0
  323. package/dist/lint/rules/testdoc-min-length.d.ts.map +1 -0
  324. package/dist/lint/rules/testdoc-min-length.js +31 -0
  325. package/dist/lint/rules/testdoc-min-length.js.map +1 -0
  326. package/dist/lint/rules/testdoc-required.d.ts +8 -0
  327. package/dist/lint/rules/testdoc-required.d.ts.map +1 -0
  328. package/dist/lint/rules/testdoc-required.js +27 -0
  329. package/dist/lint/rules/testdoc-required.js.map +1 -0
  330. package/dist/lint/rules/workflow-branch-naming.d.ts +20 -0
  331. package/dist/lint/rules/workflow-branch-naming.d.ts.map +1 -0
  332. package/dist/lint/rules/workflow-branch-naming.js +85 -0
  333. package/dist/lint/rules/workflow-branch-naming.js.map +1 -0
  334. package/dist/lint/rules/workflow-commit-format.d.ts +27 -0
  335. package/dist/lint/rules/workflow-commit-format.d.ts.map +1 -0
  336. package/dist/lint/rules/workflow-commit-format.js +92 -0
  337. package/dist/lint/rules/workflow-commit-format.js.map +1 -0
  338. package/dist/lint/rules/workflow-issue-fields.d.ts +24 -0
  339. package/dist/lint/rules/workflow-issue-fields.d.ts.map +1 -0
  340. package/dist/lint/rules/workflow-issue-fields.js +89 -0
  341. package/dist/lint/rules/workflow-issue-fields.js.map +1 -0
  342. package/dist/lint/rules/workflow-main-protection.d.ts +32 -0
  343. package/dist/lint/rules/workflow-main-protection.d.ts.map +1 -0
  344. package/dist/lint/rules/workflow-main-protection.js +114 -0
  345. package/dist/lint/rules/workflow-main-protection.js.map +1 -0
  346. package/dist/lint/structure-types.d.ts +216 -0
  347. package/dist/lint/structure-types.d.ts.map +1 -0
  348. package/dist/lint/structure-types.js +96 -0
  349. package/dist/lint/structure-types.js.map +1 -0
  350. package/dist/lint/types.d.ts +154 -0
  351. package/dist/lint/types.d.ts.map +1 -0
  352. package/dist/lint/types.js +21 -0
  353. package/dist/lint/types.js.map +1 -0
  354. package/dist/lint/workflow-types.d.ts +90 -0
  355. package/dist/lint/workflow-types.d.ts.map +1 -0
  356. package/dist/lint/workflow-types.js +7 -0
  357. package/dist/lint/workflow-types.js.map +1 -0
  358. package/dist/md/analyzer/index.d.ts +46 -0
  359. package/dist/md/analyzer/index.d.ts.map +1 -0
  360. package/dist/md/analyzer/index.js +288 -0
  361. package/dist/md/analyzer/index.js.map +1 -0
  362. package/dist/md/builder/index.d.ts +91 -0
  363. package/dist/md/builder/index.d.ts.map +1 -0
  364. package/dist/md/builder/index.js +446 -0
  365. package/dist/md/builder/index.js.map +1 -0
  366. package/dist/md/cli/analyze.d.ts +11 -0
  367. package/dist/md/cli/analyze.d.ts.map +1 -0
  368. package/dist/md/cli/analyze.js +118 -0
  369. package/dist/md/cli/analyze.js.map +1 -0
  370. package/dist/md/cli/build.d.ts +11 -0
  371. package/dist/md/cli/build.d.ts.map +1 -0
  372. package/dist/md/cli/build.js +74 -0
  373. package/dist/md/cli/build.js.map +1 -0
  374. package/dist/md/cli/extract.d.ts +25 -0
  375. package/dist/md/cli/extract.d.ts.map +1 -0
  376. package/dist/md/cli/extract.js +230 -0
  377. package/dist/md/cli/extract.js.map +1 -0
  378. package/dist/md/cli/index.d.ts +3 -0
  379. package/dist/md/cli/index.d.ts.map +1 -0
  380. package/dist/md/cli/index.js +99 -0
  381. package/dist/md/cli/index.js.map +1 -0
  382. package/dist/md/cli/lint.d.ts +11 -0
  383. package/dist/md/cli/lint.d.ts.map +1 -0
  384. package/dist/md/cli/lint.js +165 -0
  385. package/dist/md/cli/lint.js.map +1 -0
  386. package/dist/md/cli/list.d.ts +16 -0
  387. package/dist/md/cli/list.d.ts.map +1 -0
  388. package/dist/md/cli/list.js +85 -0
  389. package/dist/md/cli/list.js.map +1 -0
  390. package/dist/md/cli/program.d.ts +11 -0
  391. package/dist/md/cli/program.d.ts.map +1 -0
  392. package/dist/md/cli/program.js +104 -0
  393. package/dist/md/cli/program.js.map +1 -0
  394. package/dist/md/cli/validate.d.ts +8 -0
  395. package/dist/md/cli/validate.d.ts.map +1 -0
  396. package/dist/md/cli/validate.js +82 -0
  397. package/dist/md/cli/validate.js.map +1 -0
  398. package/dist/md/constants.d.ts +69 -0
  399. package/dist/md/constants.d.ts.map +1 -0
  400. package/dist/md/constants.js +69 -0
  401. package/dist/md/constants.js.map +1 -0
  402. package/dist/md/extractor/index.d.ts +57 -0
  403. package/dist/md/extractor/index.d.ts.map +1 -0
  404. package/dist/md/extractor/index.js +359 -0
  405. package/dist/md/extractor/index.js.map +1 -0
  406. package/dist/md/index.d.ts +26 -0
  407. package/dist/md/index.d.ts.map +1 -0
  408. package/dist/md/index.js +30 -0
  409. package/dist/md/index.js.map +1 -0
  410. package/dist/md/linter/index.d.ts +20 -0
  411. package/dist/md/linter/index.d.ts.map +1 -0
  412. package/dist/md/linter/index.js +412 -0
  413. package/dist/md/linter/index.js.map +1 -0
  414. package/dist/md/linter/token-optimizer.d.ts +66 -0
  415. package/dist/md/linter/token-optimizer.d.ts.map +1 -0
  416. package/dist/md/linter/token-optimizer.js +292 -0
  417. package/dist/md/linter/token-optimizer.js.map +1 -0
  418. package/dist/md/lister/index.d.ts +42 -0
  419. package/dist/md/lister/index.d.ts.map +1 -0
  420. package/dist/md/lister/index.js +317 -0
  421. package/dist/md/lister/index.js.map +1 -0
  422. package/dist/md/parser/heading-numbers.d.ts +43 -0
  423. package/dist/md/parser/heading-numbers.d.ts.map +1 -0
  424. package/dist/md/parser/heading-numbers.js +97 -0
  425. package/dist/md/parser/heading-numbers.js.map +1 -0
  426. package/dist/md/parser/section-meta.d.ts +50 -0
  427. package/dist/md/parser/section-meta.d.ts.map +1 -0
  428. package/dist/md/parser/section-meta.js +212 -0
  429. package/dist/md/parser/section-meta.js.map +1 -0
  430. package/dist/md/parser/template.d.ts +56 -0
  431. package/dist/md/parser/template.d.ts.map +1 -0
  432. package/dist/md/parser/template.js +122 -0
  433. package/dist/md/parser/template.js.map +1 -0
  434. package/dist/md/plugins/loader.d.ts +15 -0
  435. package/dist/md/plugins/loader.d.ts.map +1 -0
  436. package/dist/md/plugins/loader.js +80 -0
  437. package/dist/md/plugins/loader.js.map +1 -0
  438. package/dist/md/plugins/normalize-headings.d.ts +43 -0
  439. package/dist/md/plugins/normalize-headings.d.ts.map +1 -0
  440. package/dist/md/plugins/normalize-headings.js +51 -0
  441. package/dist/md/plugins/normalize-headings.js.map +1 -0
  442. package/dist/md/plugins/normalize-whitespace.d.ts +46 -0
  443. package/dist/md/plugins/normalize-whitespace.d.ts.map +1 -0
  444. package/dist/md/plugins/normalize-whitespace.js +86 -0
  445. package/dist/md/plugins/normalize-whitespace.js.map +1 -0
  446. package/dist/md/plugins/remove-badges.d.ts +36 -0
  447. package/dist/md/plugins/remove-badges.d.ts.map +1 -0
  448. package/dist/md/plugins/remove-badges.js +59 -0
  449. package/dist/md/plugins/remove-badges.js.map +1 -0
  450. package/dist/md/plugins/remove-comments.d.ts +27 -0
  451. package/dist/md/plugins/remove-comments.d.ts.map +1 -0
  452. package/dist/md/plugins/remove-comments.js +40 -0
  453. package/dist/md/plugins/remove-comments.js.map +1 -0
  454. package/dist/md/plugins/remove-duplicates.d.ts +40 -0
  455. package/dist/md/plugins/remove-duplicates.d.ts.map +1 -0
  456. package/dist/md/plugins/remove-duplicates.js +72 -0
  457. package/dist/md/plugins/remove-duplicates.js.map +1 -0
  458. package/dist/md/plugins/remove-internal-links.d.ts +38 -0
  459. package/dist/md/plugins/remove-internal-links.d.ts.map +1 -0
  460. package/dist/md/plugins/remove-internal-links.js +66 -0
  461. package/dist/md/plugins/remove-internal-links.js.map +1 -0
  462. package/dist/md/plugins/strip-heading-numbers.d.ts +35 -0
  463. package/dist/md/plugins/strip-heading-numbers.d.ts.map +1 -0
  464. package/dist/md/plugins/strip-heading-numbers.js +59 -0
  465. package/dist/md/plugins/strip-heading-numbers.js.map +1 -0
  466. package/dist/md/plugins/strip-section-meta.d.ts +37 -0
  467. package/dist/md/plugins/strip-section-meta.d.ts.map +1 -0
  468. package/dist/md/plugins/strip-section-meta.js +62 -0
  469. package/dist/md/plugins/strip-section-meta.js.map +1 -0
  470. package/dist/md/types/config.d.ts +260 -0
  471. package/dist/md/types/config.d.ts.map +1 -0
  472. package/dist/md/types/config.js +156 -0
  473. package/dist/md/types/config.js.map +1 -0
  474. package/dist/md/types/document.d.ts +37 -0
  475. package/dist/md/types/document.d.ts.map +1 -0
  476. package/dist/md/types/document.js +2 -0
  477. package/dist/md/types/document.js.map +1 -0
  478. package/dist/md/types/validation.d.ts +107 -0
  479. package/dist/md/types/validation.d.ts.map +1 -0
  480. package/dist/md/types/validation.js +2 -0
  481. package/dist/md/types/validation.js.map +1 -0
  482. package/dist/md/utils/code-blocks.d.ts +136 -0
  483. package/dist/md/utils/code-blocks.d.ts.map +1 -0
  484. package/dist/md/utils/code-blocks.js +178 -0
  485. package/dist/md/utils/code-blocks.js.map +1 -0
  486. package/dist/md/utils/config.d.ts +10 -0
  487. package/dist/md/utils/config.d.ts.map +1 -0
  488. package/dist/md/utils/config.js +99 -0
  489. package/dist/md/utils/config.js.map +1 -0
  490. package/dist/md/utils/file-collector.d.ts +78 -0
  491. package/dist/md/utils/file-collector.d.ts.map +1 -0
  492. package/dist/md/utils/file-collector.js +100 -0
  493. package/dist/md/utils/file-collector.js.map +1 -0
  494. package/dist/md/utils/markdown.d.ts +18 -0
  495. package/dist/md/utils/markdown.d.ts.map +1 -0
  496. package/dist/md/utils/markdown.js +93 -0
  497. package/dist/md/utils/markdown.js.map +1 -0
  498. package/dist/md/utils/remark.d.ts +91 -0
  499. package/dist/md/utils/remark.d.ts.map +1 -0
  500. package/dist/md/utils/remark.js +125 -0
  501. package/dist/md/utils/remark.js.map +1 -0
  502. package/dist/md/utils/tokens.d.ts +9 -0
  503. package/dist/md/utils/tokens.d.ts.map +1 -0
  504. package/dist/md/utils/tokens.js +31 -0
  505. package/dist/md/utils/tokens.js.map +1 -0
  506. package/dist/md/validator/index.d.ts +40 -0
  507. package/dist/md/validator/index.d.ts.map +1 -0
  508. package/dist/md/validator/index.js +289 -0
  509. package/dist/md/validator/index.js.map +1 -0
  510. package/dist/parsers/details-jsdoc.d.ts +46 -0
  511. package/dist/parsers/details-jsdoc.d.ts.map +1 -0
  512. package/dist/parsers/details-jsdoc.js +262 -0
  513. package/dist/parsers/details-jsdoc.js.map +1 -0
  514. package/dist/parsers/details-zod.d.ts +22 -0
  515. package/dist/parsers/details-zod.d.ts.map +1 -0
  516. package/dist/parsers/details-zod.js +145 -0
  517. package/dist/parsers/details-zod.js.map +1 -0
  518. package/dist/parsers/drizzle-schema.d.ts +92 -0
  519. package/dist/parsers/drizzle-schema.d.ts.map +1 -0
  520. package/dist/parsers/drizzle-schema.js +376 -0
  521. package/dist/parsers/drizzle-schema.js.map +1 -0
  522. package/dist/parsers/feature-map-tags.d.ts +45 -0
  523. package/dist/parsers/feature-map-tags.d.ts.map +1 -0
  524. package/dist/parsers/feature-map-tags.js +292 -0
  525. package/dist/parsers/feature-map-tags.js.map +1 -0
  526. package/dist/parsers/feature-map-type-extraction.d.ts +62 -0
  527. package/dist/parsers/feature-map-type-extraction.d.ts.map +1 -0
  528. package/dist/parsers/feature-map-type-extraction.js +347 -0
  529. package/dist/parsers/feature-map-type-extraction.js.map +1 -0
  530. package/dist/parsers/feature-map-utils.d.ts +34 -0
  531. package/dist/parsers/feature-map-utils.d.ts.map +1 -0
  532. package/dist/parsers/feature-map-utils.js +101 -0
  533. package/dist/parsers/feature-map-utils.js.map +1 -0
  534. package/dist/parsers/jsdoc-common.d.ts +209 -0
  535. package/dist/parsers/jsdoc-common.d.ts.map +1 -0
  536. package/dist/parsers/jsdoc-common.js +655 -0
  537. package/dist/parsers/jsdoc-common.js.map +1 -0
  538. package/dist/parsers/jsdoc.d.ts +76 -0
  539. package/dist/parsers/jsdoc.d.ts.map +1 -0
  540. package/dist/parsers/jsdoc.js +238 -0
  541. package/dist/parsers/jsdoc.js.map +1 -0
  542. package/dist/parsers/screenshot-annotations.d.ts +96 -0
  543. package/dist/parsers/screenshot-annotations.d.ts.map +1 -0
  544. package/dist/parsers/screenshot-annotations.js +227 -0
  545. package/dist/parsers/screenshot-annotations.js.map +1 -0
  546. package/dist/parsers/test-annotations.d.ts +46 -0
  547. package/dist/parsers/test-annotations.d.ts.map +1 -0
  548. package/dist/parsers/test-annotations.js +393 -0
  549. package/dist/parsers/test-annotations.js.map +1 -0
  550. package/dist/parsers/test-categorization.d.ts +42 -0
  551. package/dist/parsers/test-categorization.d.ts.map +1 -0
  552. package/dist/parsers/test-categorization.js +182 -0
  553. package/dist/parsers/test-categorization.js.map +1 -0
  554. package/dist/parsers/zod-schema.d.ts +105 -0
  555. package/dist/parsers/zod-schema.d.ts.map +1 -0
  556. package/dist/parsers/zod-schema.js +270 -0
  557. package/dist/parsers/zod-schema.js.map +1 -0
  558. package/dist/utils/action-inference.d.ts +23 -0
  559. package/dist/utils/action-inference.d.ts.map +1 -0
  560. package/dist/utils/action-inference.js +36 -0
  561. package/dist/utils/action-inference.js.map +1 -0
  562. package/dist/utils/app-inference.d.ts +31 -0
  563. package/dist/utils/app-inference.d.ts.map +1 -0
  564. package/dist/utils/app-inference.js +41 -0
  565. package/dist/utils/app-inference.js.map +1 -0
  566. package/dist/utils/auto-infer.d.ts +93 -0
  567. package/dist/utils/auto-infer.d.ts.map +1 -0
  568. package/dist/utils/auto-infer.js +184 -0
  569. package/dist/utils/auto-infer.js.map +1 -0
  570. package/dist/utils/config.d.ts +709 -0
  571. package/dist/utils/config.d.ts.map +1 -0
  572. package/dist/utils/config.js +504 -0
  573. package/dist/utils/config.js.map +1 -0
  574. package/dist/utils/file.d.ts +46 -0
  575. package/dist/utils/file.d.ts.map +1 -0
  576. package/dist/utils/file.js +103 -0
  577. package/dist/utils/file.js.map +1 -0
  578. package/dist/utils/formatters.d.ts +111 -0
  579. package/dist/utils/formatters.d.ts.map +1 -0
  580. package/dist/utils/formatters.js +164 -0
  581. package/dist/utils/formatters.js.map +1 -0
  582. package/dist/utils/gh-config.d.ts +99 -0
  583. package/dist/utils/gh-config.d.ts.map +1 -0
  584. package/dist/utils/gh-config.js +247 -0
  585. package/dist/utils/gh-config.js.map +1 -0
  586. package/dist/utils/github.d.ts +98 -0
  587. package/dist/utils/github.d.ts.map +1 -0
  588. package/dist/utils/github.js +295 -0
  589. package/dist/utils/github.js.map +1 -0
  590. package/dist/utils/html.d.ts +107 -0
  591. package/dist/utils/html.d.ts.map +1 -0
  592. package/dist/utils/html.js +376 -0
  593. package/dist/utils/html.js.map +1 -0
  594. package/dist/utils/i18n.d.ts +40 -0
  595. package/dist/utils/i18n.d.ts.map +1 -0
  596. package/dist/utils/i18n.js +148 -0
  597. package/dist/utils/i18n.js.map +1 -0
  598. package/dist/utils/logger.d.ts +20 -0
  599. package/dist/utils/logger.d.ts.map +1 -0
  600. package/dist/utils/logger.js +49 -0
  601. package/dist/utils/logger.js.map +1 -0
  602. package/dist/utils/project-fields.d.ts +71 -0
  603. package/dist/utils/project-fields.d.ts.map +1 -0
  604. package/dist/utils/project-fields.js +318 -0
  605. package/dist/utils/project-fields.js.map +1 -0
  606. package/dist/utils/repo-pairs.d.ts +94 -0
  607. package/dist/utils/repo-pairs.d.ts.map +1 -0
  608. package/dist/utils/repo-pairs.js +196 -0
  609. package/dist/utils/repo-pairs.js.map +1 -0
  610. package/dist/utils/route-inference.d.ts +81 -0
  611. package/dist/utils/route-inference.d.ts.map +1 -0
  612. package/dist/utils/route-inference.js +137 -0
  613. package/dist/utils/route-inference.js.map +1 -0
  614. package/dist/utils/setup-check.d.ts +34 -0
  615. package/dist/utils/setup-check.d.ts.map +1 -0
  616. package/dist/utils/setup-check.js +136 -0
  617. package/dist/utils/setup-check.js.map +1 -0
  618. package/dist/utils/shirokumaignore.d.ts +55 -0
  619. package/dist/utils/shirokumaignore.d.ts.map +1 -0
  620. package/dist/utils/shirokumaignore.js +94 -0
  621. package/dist/utils/shirokumaignore.js.map +1 -0
  622. package/dist/utils/skills-repo.d.ts +353 -0
  623. package/dist/utils/skills-repo.d.ts.map +1 -0
  624. package/dist/utils/skills-repo.js +793 -0
  625. package/dist/utils/skills-repo.js.map +1 -0
  626. package/dist/utils/status-workflow.d.ts +54 -0
  627. package/dist/utils/status-workflow.d.ts.map +1 -0
  628. package/dist/utils/status-workflow.js +103 -0
  629. package/dist/utils/status-workflow.js.map +1 -0
  630. package/dist/validators/frontmatter.d.ts +41 -0
  631. package/dist/validators/frontmatter.d.ts.map +1 -0
  632. package/dist/validators/frontmatter.js +117 -0
  633. package/dist/validators/frontmatter.js.map +1 -0
  634. package/dist/validators/link-checker.d.ts +48 -0
  635. package/dist/validators/link-checker.d.ts.map +1 -0
  636. package/dist/validators/link-checker.js +108 -0
  637. package/dist/validators/link-checker.js.map +1 -0
  638. package/dist/validators/markdown-structure.d.ts +50 -0
  639. package/dist/validators/markdown-structure.d.ts.map +1 -0
  640. package/dist/validators/markdown-structure.js +253 -0
  641. package/dist/validators/markdown-structure.js.map +1 -0
  642. package/i18n/cli/en.json +155 -0
  643. package/i18n/cli/ja.json +155 -0
  644. package/i18n/discussion/en.json +191 -0
  645. package/i18n/discussion/ja.json +191 -0
  646. package/package.json +113 -0
  647. package/portal/app/api-tools/api-tools-client.tsx +411 -0
  648. package/portal/app/api-tools/api-tools-document.tsx +240 -0
  649. package/portal/app/api-tools/page.tsx +56 -0
  650. package/portal/app/api-tools/swagger-view.tsx +114 -0
  651. package/portal/app/apps/[appId]/[type]/[module]/[item]/item-tabs-client.tsx +71 -0
  652. package/portal/app/apps/[appId]/[type]/[module]/[item]/page.tsx +1422 -0
  653. package/portal/app/apps/[appId]/[type]/[module]/page.tsx +373 -0
  654. package/portal/app/apps/[appId]/feature-map/feature-map-app-document.tsx +298 -0
  655. package/portal/app/apps/[appId]/feature-map/page.tsx +224 -0
  656. package/portal/app/apps/[appId]/i18n/page.tsx +139 -0
  657. package/portal/app/apps/[appId]/test-cases/page.tsx +840 -0
  658. package/portal/app/apps/[appId]/tools/[tool]/page.tsx +351 -0
  659. package/portal/app/apps/[appId]/tools/api-tools-client.tsx +429 -0
  660. package/portal/app/apps/[appId]/tools/page.tsx +119 -0
  661. package/portal/app/db-schema/[db]/[table]/page.tsx +235 -0
  662. package/portal/app/db-schema/[db]/diagram/page.tsx +81 -0
  663. package/portal/app/db-schema/[db]/page.tsx +148 -0
  664. package/portal/app/db-schema/db-schema-document.tsx +100 -0
  665. package/portal/app/db-schema/diagram/client.tsx +211 -0
  666. package/portal/app/db-schema/diagram/page.tsx +20 -0
  667. package/portal/app/db-schema/page.tsx +145 -0
  668. package/portal/app/db-schema/table-detail-document.tsx +710 -0
  669. package/portal/app/db-schema/table-detail.tsx +747 -0
  670. package/portal/app/db-schema/table-list-document.tsx +224 -0
  671. package/portal/app/db-schema/table-list.tsx +247 -0
  672. package/portal/app/details/[type]/[module]/[item]/item-tabs-client.tsx +71 -0
  673. package/portal/app/details/[type]/[module]/[item]/page.tsx +1286 -0
  674. package/portal/app/details/[type]/[module]/page.tsx +884 -0
  675. package/portal/app/feature-map/feature-map-client.tsx +681 -0
  676. package/portal/app/feature-map/feature-map-document.tsx +313 -0
  677. package/portal/app/feature-map/page.tsx +438 -0
  678. package/portal/app/globals.css +205 -0
  679. package/portal/app/i18n/[...namespace]/page.tsx +190 -0
  680. package/portal/app/i18n/i18n-client.tsx +369 -0
  681. package/portal/app/i18n/page.tsx +339 -0
  682. package/portal/app/layout.tsx +37 -0
  683. package/portal/app/overview/page.tsx +65 -0
  684. package/portal/app/packages/[packageId]/page.tsx +201 -0
  685. package/portal/app/packages/page.tsx +148 -0
  686. package/portal/app/page.tsx +568 -0
  687. package/portal/app/test-cases/[file]/[line]/page.tsx +455 -0
  688. package/portal/app/test-cases/[file]/[line]/test-detail-document.tsx +335 -0
  689. package/portal/app/test-cases/[file]/page.tsx +323 -0
  690. package/portal/app/test-cases/[file]/test-file-document.tsx +335 -0
  691. package/portal/app/test-cases/page.tsx +546 -0
  692. package/portal/app/test-cases/test-cases-document.tsx +384 -0
  693. package/portal/components/code-block.tsx +57 -0
  694. package/portal/components/document/doc-params-table.tsx +71 -0
  695. package/portal/components/document/doc-section.tsx +133 -0
  696. package/portal/components/document/doc-table.tsx +119 -0
  697. package/portal/components/document/index.ts +9 -0
  698. package/portal/components/drawflow-er-diagram.tsx +607 -0
  699. package/portal/components/interactive-er-diagram.tsx +228 -0
  700. package/portal/components/layout/app-sidebar.tsx +490 -0
  701. package/portal/components/layout/er-sidebar.tsx +116 -0
  702. package/portal/components/layout/global-header.tsx +117 -0
  703. package/portal/components/layout/layout-content.tsx +48 -0
  704. package/portal/components/markdown-content.tsx +120 -0
  705. package/portal/components/mermaid-diagram.tsx +83 -0
  706. package/portal/components/reactflow-er-diagram.tsx +475 -0
  707. package/portal/components/search-dialog.tsx +268 -0
  708. package/portal/components/shared/coverage-score-bar.tsx +144 -0
  709. package/portal/components/swagger/endpoint-accordion.tsx +117 -0
  710. package/portal/components/swagger/index.ts +7 -0
  711. package/portal/components/swagger/method-badge.tsx +55 -0
  712. package/portal/components/swagger/params-table.tsx +78 -0
  713. package/portal/components/tabs-with-hash.tsx +43 -0
  714. package/portal/components/test/index.ts +2 -0
  715. package/portal/components/test/test-bdd-card.tsx +192 -0
  716. package/portal/components/test/test-matrix.tsx +242 -0
  717. package/portal/components/ui/accordion.tsx +66 -0
  718. package/portal/components/ui/badge.tsx +46 -0
  719. package/portal/components/ui/breadcrumb.tsx +109 -0
  720. package/portal/components/ui/button.tsx +62 -0
  721. package/portal/components/ui/card.tsx +92 -0
  722. package/portal/components/ui/collapsible.tsx +33 -0
  723. package/portal/components/ui/dialog.tsx +118 -0
  724. package/portal/components/ui/progress.tsx +28 -0
  725. package/portal/components/ui/scroll-area.tsx +58 -0
  726. package/portal/components/ui/sheet.tsx +139 -0
  727. package/portal/components/ui/table.tsx +116 -0
  728. package/portal/components/ui/tabs.tsx +66 -0
  729. package/portal/components.json +21 -0
  730. package/portal/lib/constants/test-categories.ts +186 -0
  731. package/portal/lib/data-loader.ts +1181 -0
  732. package/portal/lib/db-schema-utils.ts +182 -0
  733. package/portal/lib/format.ts +43 -0
  734. package/portal/lib/hooks/use-hash-tab.ts +144 -0
  735. package/portal/lib/path-utils.ts +25 -0
  736. package/portal/lib/search-index-generator.ts +214 -0
  737. package/portal/lib/search.ts +126 -0
  738. package/portal/lib/sidebar-context.tsx +111 -0
  739. package/portal/lib/types.ts +740 -0
  740. package/portal/lib/utils.ts +6 -0
  741. package/portal/next.config.ts +21 -0
  742. package/portal/package.json +45 -0
  743. package/portal/postcss.config.mjs +8 -0
  744. package/portal/tsconfig.json +41 -0
  745. package/portal/types/drawflow.d.ts +80 -0
  746. package/templates/README.md +73 -0
  747. package/templates/coverage.html +367 -0
  748. package/templates/dark-theme.css +443 -0
  749. package/templates/discussion/adr.yml.hbs +65 -0
  750. package/templates/discussion/handovers.yml.hbs +57 -0
  751. package/templates/discussion/knowledge.yml.hbs +60 -0
  752. package/templates/discussion/reports.yml.hbs +68 -0
  753. package/templates/discussion/research.yml.hbs +61 -0
@@ -0,0 +1,1422 @@
1
+ import { notFound } from "next/navigation";
2
+ import Link from "next/link";
3
+ import {
4
+ Monitor,
5
+ Component,
6
+ Zap,
7
+ Database,
8
+ Package,
9
+ ArrowLeft,
10
+ FileCode,
11
+ TestTube2,
12
+ ChevronDown,
13
+ ChevronRight,
14
+ AlertTriangle,
15
+ CheckCircle2,
16
+ Info,
17
+ Shield,
18
+ Globe,
19
+ Users,
20
+ Lock,
21
+ Clock,
22
+ ExternalLink,
23
+ Route,
24
+ Layers,
25
+ Languages,
26
+ Workflow,
27
+ Tag,
28
+ AppWindow,
29
+ Camera,
30
+ ImageOff,
31
+ } from "lucide-react";
32
+ import { ItemTabsClient } from "./item-tabs-client";
33
+ import {
34
+ Card,
35
+ CardContent,
36
+ CardDescription,
37
+ CardHeader,
38
+ CardTitle,
39
+ } from "@/components/ui/card";
40
+ import { Badge } from "@/components/ui/badge";
41
+ import {
42
+ Table,
43
+ TableBody,
44
+ TableCell,
45
+ TableHead,
46
+ TableHeader,
47
+ TableRow,
48
+ } from "@/components/ui/table";
49
+ import {
50
+ Collapsible,
51
+ CollapsibleContent,
52
+ CollapsibleTrigger,
53
+ } from "@/components/ui/collapsible";
54
+ import { loadFeatureMap, loadDetails, loadApplications, getScreenshotForScreen, type ScreenshotEntry } from "@/lib/data-loader";
55
+ import { encodeFilePath } from "@/lib/path-utils";
56
+ import { CodeBlock } from "@/components/code-block";
57
+ import { CATEGORY_LABELS } from "@/lib/constants/test-categories";
58
+ import type {
59
+ FeatureMapData,
60
+ ScreenItem,
61
+ ComponentItem,
62
+ ActionItem,
63
+ ModuleItem,
64
+ TableItem,
65
+ DetailItem,
66
+ AuthLevel,
67
+ ZodParameterInfo,
68
+ ErrorCodeInfo,
69
+ } from "@/lib/types";
70
+
71
+ // Only pre-generated paths will work (required for output: export)
72
+ export const dynamicParams = false;
73
+
74
+ type LayerType = "screens" | "components" | "actions" | "modules" | "tables";
75
+ type LayerTypeSingular = "screen" | "component" | "action" | "module" | "table";
76
+
77
+ interface LayerConfig {
78
+ key: LayerType;
79
+ singular: LayerTypeSingular;
80
+ label: string;
81
+ icon: typeof Monitor;
82
+ color: string;
83
+ bgColor: string;
84
+ }
85
+
86
+ const layerConfigs: Record<LayerType, LayerConfig> = {
87
+ screens: {
88
+ key: "screens",
89
+ singular: "screen",
90
+ label: "Screens",
91
+ icon: Monitor,
92
+ color: "text-accent-blue",
93
+ bgColor: "bg-accent-blue/10",
94
+ },
95
+ components: {
96
+ key: "components",
97
+ singular: "component",
98
+ label: "Components",
99
+ icon: Component,
100
+ color: "text-accent-green",
101
+ bgColor: "bg-accent-green/10",
102
+ },
103
+ actions: {
104
+ key: "actions",
105
+ singular: "action",
106
+ label: "Actions",
107
+ icon: Zap,
108
+ color: "text-accent-yellow",
109
+ bgColor: "bg-accent-yellow/10",
110
+ },
111
+ modules: {
112
+ key: "modules",
113
+ singular: "module",
114
+ label: "Modules",
115
+ icon: Package,
116
+ color: "text-accent-orange",
117
+ bgColor: "bg-accent-orange/10",
118
+ },
119
+ tables: {
120
+ key: "tables",
121
+ singular: "table",
122
+ label: "Tables",
123
+ icon: Database,
124
+ color: "text-accent-purple",
125
+ bgColor: "bg-accent-purple/10",
126
+ },
127
+ };
128
+
129
+ export async function generateStaticParams(): Promise<
130
+ { appId: string; type: string; module: string; item: string }[]
131
+ > {
132
+ const [data, applications] = await Promise.all([
133
+ loadFeatureMap(),
134
+ loadApplications(),
135
+ ]);
136
+
137
+ if (!data || !applications?.apps) return [];
138
+
139
+ const params: { appId: string; type: string; module: string; item: string }[] = [];
140
+ const layers: LayerType[] = ["screens", "components", "actions", "modules", "tables"];
141
+
142
+ // For each app
143
+ for (const app of applications.apps) {
144
+ // Skip API type apps - they don't have feature map items
145
+ if (app.type === "api") continue;
146
+
147
+ const appNameForFilter = app.name.replace(" アプリ", "");
148
+
149
+ // Add items from feature modules
150
+ for (const [moduleName, group] of Object.entries(data.features)) {
151
+ for (const layer of layers) {
152
+ const items = group[layer] || [];
153
+ for (const item of items) {
154
+ if (item.app === appNameForFilter) {
155
+ params.push({
156
+ appId: app.id,
157
+ type: layer,
158
+ module: moduleName,
159
+ item: item.name,
160
+ });
161
+ }
162
+ }
163
+ }
164
+ }
165
+
166
+ // Add uncategorized items
167
+ for (const layer of layers) {
168
+ const items = data.uncategorized[layer] || [];
169
+ for (const item of items) {
170
+ if (item.app === appNameForFilter) {
171
+ params.push({
172
+ appId: app.id,
173
+ type: layer,
174
+ module: "Uncategorized",
175
+ item: item.name,
176
+ });
177
+ }
178
+ }
179
+ }
180
+ }
181
+
182
+ return params;
183
+ }
184
+
185
+ // Test category labels - using shared constant
186
+ const categoryLabels = CATEGORY_LABELS;
187
+
188
+ // Auth Level Badge Component
189
+ const authLevelConfig: Record<AuthLevel, { label: string; icon: typeof Shield; color: string }> = {
190
+ none: { label: "Public", icon: Globe, color: "text-green-600 bg-green-500/10 border-green-500/30" },
191
+ authenticated: { label: "Auth Required", icon: Lock, color: "text-blue-600 bg-blue-500/10 border-blue-500/30" },
192
+ member: { label: "Member Only", icon: Users, color: "text-purple-600 bg-purple-500/10 border-purple-500/30" },
193
+ admin: { label: "Admin Only", icon: Shield, color: "text-red-600 bg-red-500/10 border-red-500/30" },
194
+ };
195
+
196
+ function AuthLevelBadge({ level }: { level: AuthLevel }) {
197
+ const config = authLevelConfig[level];
198
+ const Icon = config.icon;
199
+ return (
200
+ <Badge variant="outline" className={`${config.color} text-xs`}>
201
+ <Icon className="mr-1 h-3 w-3" />
202
+ {config.label}
203
+ </Badge>
204
+ );
205
+ }
206
+
207
+ // Coverage Score Bar Component
208
+ function CoverageScoreBar({ score }: { score: number }) {
209
+ const getScoreColor = (score: number) => {
210
+ if (score >= 70) return "bg-green-500";
211
+ if (score >= 40) return "bg-yellow-500";
212
+ return "bg-red-500";
213
+ };
214
+
215
+ return (
216
+ <div className="space-y-1">
217
+ <div className="flex items-center justify-between text-sm">
218
+ <span className="text-muted-foreground">カバレッジスコア</span>
219
+ <span className="font-medium">{score}%</span>
220
+ </div>
221
+ <div className="h-2 w-full overflow-hidden rounded-full bg-muted">
222
+ <div
223
+ className={`h-full transition-all ${getScoreColor(score)}`}
224
+ style={{ width: `${Math.min(score, 100)}%` }}
225
+ />
226
+ </div>
227
+ </div>
228
+ );
229
+ }
230
+
231
+ // Enhanced Parameters Table (from Zod schema)
232
+ function EnhancedParametersTable({ parameters }: { parameters: ZodParameterInfo[] }) {
233
+ if (!parameters || parameters.length === 0) return null;
234
+
235
+ return (
236
+ <div>
237
+ <h4 className="mb-2 text-sm font-semibold text-muted-foreground">入力パラメータ (Zodスキーマ)</h4>
238
+ <Table>
239
+ <TableHeader>
240
+ <TableRow>
241
+ <TableHead className="w-[120px]">名前</TableHead>
242
+ <TableHead className="w-[100px]">型</TableHead>
243
+ <TableHead className="w-[60px]">必須</TableHead>
244
+ <TableHead className="w-[150px]">制約</TableHead>
245
+ <TableHead className="w-[100px]">デフォルト</TableHead>
246
+ <TableHead>説明</TableHead>
247
+ </TableRow>
248
+ </TableHeader>
249
+ <TableBody>
250
+ {parameters.map((param, idx) => {
251
+ const constraints: string[] = [];
252
+ if (param.format) constraints.push(param.format);
253
+ if (param.minLength !== undefined) constraints.push(`min: ${param.minLength}`);
254
+ if (param.maxLength !== undefined) constraints.push(`max: ${param.maxLength}`);
255
+ if (param.min !== undefined) constraints.push(`≥ ${param.min}`);
256
+ if (param.max !== undefined) constraints.push(`≤ ${param.max}`);
257
+ if (param.enumValues) constraints.push(param.enumValues.join(" | "));
258
+
259
+ return (
260
+ <TableRow key={idx}>
261
+ <TableCell className="font-mono text-sm">{param.name}</TableCell>
262
+ <TableCell className="font-mono text-xs text-muted-foreground">{param.type}</TableCell>
263
+ <TableCell>
264
+ {param.required ? (
265
+ <CheckCircle2 className="h-4 w-4 text-green-500" />
266
+ ) : (
267
+ <span className="text-muted-foreground">-</span>
268
+ )}
269
+ </TableCell>
270
+ <TableCell className="text-xs text-muted-foreground">
271
+ {constraints.length > 0 ? constraints.join(", ") : "-"}
272
+ </TableCell>
273
+ <TableCell className="font-mono text-xs">
274
+ {param.default !== undefined ? JSON.stringify(param.default) : "-"}
275
+ </TableCell>
276
+ <TableCell className="text-sm">{param.description || "-"}</TableCell>
277
+ </TableRow>
278
+ );
279
+ })}
280
+ </TableBody>
281
+ </Table>
282
+ </div>
283
+ );
284
+ }
285
+
286
+ // Error Codes Section
287
+ function ErrorCodesSection({ errorCodes }: { errorCodes: ErrorCodeInfo[] }) {
288
+ if (!errorCodes || errorCodes.length === 0) return null;
289
+
290
+ return (
291
+ <div>
292
+ <h4 className="mb-2 text-sm font-semibold text-muted-foreground">エラーコード</h4>
293
+ <Table>
294
+ <TableHeader>
295
+ <TableRow>
296
+ <TableHead className="w-[150px]">コード</TableHead>
297
+ <TableHead className="w-[80px]">ステータス</TableHead>
298
+ <TableHead>説明</TableHead>
299
+ </TableRow>
300
+ </TableHeader>
301
+ <TableBody>
302
+ {errorCodes.map((error, idx) => (
303
+ <TableRow key={idx}>
304
+ <TableCell className="font-mono text-sm text-red-600">{error.code}</TableCell>
305
+ <TableCell>
306
+ {error.status && (
307
+ <Badge variant="outline" className="text-xs">
308
+ {error.status}
309
+ </Badge>
310
+ )}
311
+ </TableCell>
312
+ <TableCell className="text-sm">{error.description}</TableCell>
313
+ </TableRow>
314
+ ))}
315
+ </TableBody>
316
+ </Table>
317
+ </div>
318
+ );
319
+ }
320
+
321
+ // Tag configuration for enhanced display
322
+ interface TagConfig {
323
+ icon: typeof Route;
324
+ color: string;
325
+ bgColor: string;
326
+ label: string;
327
+ }
328
+
329
+ const tagConfigs: Record<string, TagConfig> = {
330
+ route: {
331
+ icon: Route,
332
+ color: "text-blue-600",
333
+ bgColor: "bg-blue-500/10 border-blue-500/30",
334
+ label: "Route",
335
+ },
336
+ layer: {
337
+ icon: Layers,
338
+ color: "text-purple-600",
339
+ bgColor: "bg-purple-500/10 border-purple-500/30",
340
+ label: "Layer",
341
+ },
342
+ accessControl: {
343
+ icon: Shield,
344
+ color: "text-red-600",
345
+ bgColor: "bg-red-500/10 border-red-500/30",
346
+ label: "Access",
347
+ },
348
+ i18nNamespaces: {
349
+ icon: Languages,
350
+ color: "text-green-600",
351
+ bgColor: "bg-green-500/10 border-green-500/30",
352
+ label: "i18n",
353
+ },
354
+ dataFlow: {
355
+ icon: Workflow,
356
+ color: "text-amber-600",
357
+ bgColor: "bg-amber-500/10 border-amber-500/30",
358
+ label: "Data Flow",
359
+ },
360
+ feature: {
361
+ icon: Tag,
362
+ color: "text-cyan-600",
363
+ bgColor: "bg-cyan-500/10 border-cyan-500/30",
364
+ label: "Feature",
365
+ },
366
+ category: {
367
+ icon: Tag,
368
+ color: "text-gray-600",
369
+ bgColor: "bg-gray-500/10 border-gray-500/30",
370
+ label: "Category",
371
+ },
372
+ };
373
+
374
+ // Hidden tags (internal use, not displayed prominently)
375
+ const hiddenTags = ["screen", "component", "action", "table", "screenshot", "screenshotWaitFor"];
376
+
377
+ // Type for item lookup function - now includes appId and returns app info for cross-app linking
378
+ type ItemLookupResult = { module: string; app?: string } | null;
379
+ type ItemLookupFn = (type: "components" | "actions" | "screens" | "tables", name: string, targetApp?: string) => ItemLookupResult;
380
+
381
+ // Build a lookup map from item name to module name using feature map
382
+ // For app-specific context, we also track the app each item belongs to
383
+ function buildItemModuleLookup(featureMap: FeatureMapData): ItemLookupFn {
384
+ // Maps: { "components": { "ProjectHeader": { module: "ProjectManagement", app: "Web" } }, ... }
385
+ const lookupMaps: Record<string, Map<string, { module: string; app?: string }>> = {
386
+ screens: new Map(),
387
+ components: new Map(),
388
+ actions: new Map(),
389
+ tables: new Map(),
390
+ };
391
+
392
+ // Process all feature groups
393
+ for (const [moduleName, group] of Object.entries(featureMap.features)) {
394
+ for (const screen of group.screens || []) {
395
+ lookupMaps.screens.set(screen.name, { module: moduleName, app: screen.app });
396
+ }
397
+ for (const component of group.components || []) {
398
+ lookupMaps.components.set(component.name, { module: moduleName, app: component.app });
399
+ }
400
+ for (const action of group.actions || []) {
401
+ lookupMaps.actions.set(action.name, { module: moduleName, app: action.app });
402
+ }
403
+ for (const table of group.tables || []) {
404
+ lookupMaps.tables.set(table.name, { module: moduleName, app: table.app });
405
+ }
406
+ }
407
+
408
+ // Process uncategorized
409
+ const uncategorized = featureMap.uncategorized;
410
+ for (const screen of uncategorized.screens || []) {
411
+ lookupMaps.screens.set(screen.name, { module: "Uncategorized", app: screen.app });
412
+ }
413
+ for (const component of uncategorized.components || []) {
414
+ lookupMaps.components.set(component.name, { module: "Uncategorized", app: component.app });
415
+ }
416
+ for (const action of uncategorized.actions || []) {
417
+ lookupMaps.actions.set(action.name, { module: "Uncategorized", app: action.app });
418
+ }
419
+ for (const table of uncategorized.tables || []) {
420
+ lookupMaps.tables.set(table.name, { module: "Uncategorized", app: table.app });
421
+ }
422
+
423
+ // Return the full entry with app info for cross-app linking
424
+ // targetApp parameter is kept for backward compatibility but not used for filtering
425
+ return (type, name, _targetApp) => {
426
+ const entry = lookupMaps[type]?.get(name);
427
+ if (!entry) return null;
428
+ return entry; // { module: string; app?: string }
429
+ };
430
+ }
431
+
432
+ // Enhanced Tags Section Component
433
+ function EnhancedTagsSection({
434
+ tags,
435
+ moduleName,
436
+ appId,
437
+ appName,
438
+ lookupModule
439
+ }: {
440
+ tags: Array<{ name: string; value: string }>;
441
+ moduleName: string;
442
+ appId: string;
443
+ appName: string;
444
+ lookupModule?: ItemLookupFn;
445
+ }) {
446
+ // Separate tags into categories
447
+ const keyTags = tags.filter(t => ["route", "layer", "accessControl", "feature", "category"].includes(t.name));
448
+ const dependencyTags = tags.filter(t => ["usedComponents", "usedActions"].includes(t.name));
449
+ const dataFlowTag = tags.find(t => t.name === "dataFlow");
450
+ const i18nTag = tags.find(t => t.name === "i18nNamespaces");
451
+ const otherTags = tags.filter(t =>
452
+ !["route", "layer", "accessControl", "feature", "category", "usedComponents", "usedActions", "dataFlow", "i18nNamespaces", ...hiddenTags].includes(t.name)
453
+ );
454
+
455
+ return (
456
+ <div className="space-y-4">
457
+ <h4 className="text-sm font-semibold text-muted-foreground">タグ情報</h4>
458
+
459
+ {/* Key Tags + i18n as Table */}
460
+ {(keyTags.length > 0 || (i18nTag && i18nTag.value)) && (
461
+ <Table>
462
+ <TableBody>
463
+ {keyTags.map((tag, idx) => {
464
+ const config = tagConfigs[tag.name];
465
+ if (!config || !tag.value) return null;
466
+ const Icon = config.icon;
467
+ return (
468
+ <TableRow key={idx} className="border-b-0">
469
+ <TableCell className="py-2 pl-0 w-[140px]">
470
+ <div className={`flex items-center gap-2 ${config.color}`}>
471
+ <Icon className="h-4 w-4" />
472
+ <span className="font-medium text-sm">{config.label}</span>
473
+ </div>
474
+ </TableCell>
475
+ <TableCell className="py-2 text-sm">
476
+ {tag.value}
477
+ </TableCell>
478
+ </TableRow>
479
+ );
480
+ })}
481
+ {/* i18n Namespaces row */}
482
+ {i18nTag && i18nTag.value && (
483
+ <TableRow className="border-b-0">
484
+ <TableCell className="py-2 pl-0 w-[140px]">
485
+ <div className="flex items-center gap-2 text-green-600">
486
+ <Languages className="h-4 w-4" />
487
+ <span className="font-medium text-sm">i18n</span>
488
+ </div>
489
+ </TableCell>
490
+ <TableCell className="py-2 text-sm">
491
+ <div className="flex flex-wrap gap-1">
492
+ {i18nTag.value.split(",").map((ns, i) => {
493
+ const namespace = ns.trim();
494
+ if (!namespace) return null;
495
+ return (
496
+ <Link key={i} href={`/i18n/${encodeURIComponent(namespace)}`}>
497
+ <Badge
498
+ variant="outline"
499
+ className="text-xs hover:bg-green-100 cursor-pointer transition-colors border-green-300"
500
+ >
501
+ {namespace}
502
+ </Badge>
503
+ </Link>
504
+ );
505
+ })}
506
+ </div>
507
+ </TableCell>
508
+ </TableRow>
509
+ )}
510
+ </TableBody>
511
+ </Table>
512
+ )}
513
+
514
+ {/* Dependencies (usedComponents, usedActions) */}
515
+ {dependencyTags.length > 0 && (
516
+ <div className="space-y-2">
517
+ {dependencyTags.map((tag, idx) => {
518
+ const items = tag.value?.split(",").map(s => s.trim()).filter(Boolean) || [];
519
+ if (items.length === 0) return null;
520
+
521
+ const isComponents = tag.name === "usedComponents";
522
+ const Icon = isComponents ? Component : Zap;
523
+ const color = isComponents ? "text-accent-green" : "text-accent-yellow";
524
+ const label = isComponents ? "使用コンポーネント" : "使用アクション";
525
+ const linkType = isComponents ? "components" : "actions";
526
+
527
+ return (
528
+ <div key={idx} className="rounded-md border p-3 bg-muted/30">
529
+ <div className="flex items-start gap-2">
530
+ <Icon className={`h-4 w-4 mt-0.5 ${color}`} />
531
+ <div>
532
+ <span className="text-sm font-medium">{label}</span>
533
+ <div className="flex flex-wrap gap-1 mt-1">
534
+ {items.map((item, i) => {
535
+ // Look up the correct module for this item
536
+ const result = lookupModule?.(linkType, item);
537
+
538
+ if (result) {
539
+ // Determine if this is a cross-app link
540
+ const isCrossApp = result.app && result.app !== appName;
541
+ const targetAppId = result.app ? result.app.toLowerCase() : appId;
542
+
543
+ return (
544
+ <Link
545
+ key={i}
546
+ href={`/apps/${targetAppId}/${linkType}/${encodeURIComponent(result.module)}/${encodeURIComponent(item)}`}
547
+ >
548
+ <Badge
549
+ variant="outline"
550
+ className={`text-xs hover:bg-muted cursor-pointer transition-colors ${isCrossApp ? "border-dashed" : ""}`}
551
+ >
552
+ {item}
553
+ {isCrossApp && <ExternalLink className="ml-1 h-2 w-2 inline" />}
554
+ </Badge>
555
+ </Link>
556
+ );
557
+ }
558
+ // Item not found - show plain badge without link
559
+ return (
560
+ <Badge
561
+ key={i}
562
+ variant="outline"
563
+ className="text-xs text-muted-foreground"
564
+ >
565
+ {item}
566
+ </Badge>
567
+ );
568
+ })}
569
+ </div>
570
+ </div>
571
+ </div>
572
+ </div>
573
+ );
574
+ })}
575
+ </div>
576
+ )}
577
+
578
+ {/* Data Flow as numbered list */}
579
+ {dataFlowTag && dataFlowTag.value && (
580
+ <div className="rounded-md border p-3 bg-amber-500/5 border-amber-500/20">
581
+ <div className="flex items-start gap-2">
582
+ <Workflow className="h-4 w-4 mt-0.5 text-amber-600" />
583
+ <div>
584
+ <span className="text-sm font-medium text-amber-700">データフロー</span>
585
+ <ol className="mt-2 space-y-1 text-sm list-decimal list-inside text-muted-foreground">
586
+ {dataFlowTag.value
587
+ .split(/\d+\.\s*/)
588
+ .filter(Boolean)
589
+ .map((step, idx) => (
590
+ <li key={idx}>{step.trim()}</li>
591
+ ))}
592
+ </ol>
593
+ </div>
594
+ </div>
595
+ </div>
596
+ )}
597
+
598
+ {/* Other Tags in collapsible */}
599
+ {otherTags.length > 0 && (
600
+ <Collapsible>
601
+ <CollapsibleTrigger className="flex items-center gap-2 text-sm text-muted-foreground hover:text-foreground">
602
+ <ChevronRight className="h-4 w-4 transition-transform [[data-state=open]_&]:rotate-90" />
603
+ <span>その他のタグ ({otherTags.length})</span>
604
+ </CollapsibleTrigger>
605
+ <CollapsibleContent className="mt-2">
606
+ <Table>
607
+ <TableHeader>
608
+ <TableRow>
609
+ <TableHead className="w-[180px]">タグ名</TableHead>
610
+ <TableHead>値</TableHead>
611
+ </TableRow>
612
+ </TableHeader>
613
+ <TableBody>
614
+ {otherTags.map((tag, idx) => (
615
+ <TableRow key={idx}>
616
+ <TableCell className="font-mono text-sm">@{tag.name}</TableCell>
617
+ <TableCell className="text-sm">{tag.value || "-"}</TableCell>
618
+ </TableRow>
619
+ ))}
620
+ </TableBody>
621
+ </Table>
622
+ </CollapsibleContent>
623
+ </Collapsible>
624
+ )}
625
+ </div>
626
+ );
627
+ }
628
+
629
+ /**
630
+ * Parse markdown code fence and extract language and code
631
+ * @example ```tsx\nconst x = 1;\n``` -> { language: "tsx", code: "const x = 1;" }
632
+ */
633
+ function parseMarkdownCodeFence(text: string): { language: string; code: string } {
634
+ // Match ```language\ncode\n```
635
+ const fenceMatch = text.match(/^```(\w+)?\s*\n?([\s\S]*?)\n?```\s*$/);
636
+ if (fenceMatch) {
637
+ return {
638
+ language: fenceMatch[1] || "typescript",
639
+ code: fenceMatch[2].trim(),
640
+ };
641
+ }
642
+ // No code fence, return as-is
643
+ return { language: "typescript", code: text.trim() };
644
+ }
645
+
646
+ // JSDoc Section Component
647
+ function JSDocSection({
648
+ detail,
649
+ appId,
650
+ appName,
651
+ lookupModule
652
+ }: {
653
+ detail: DetailItem;
654
+ appId: string;
655
+ appName: string;
656
+ lookupModule?: ItemLookupFn;
657
+ }) {
658
+ const { jsDoc } = detail;
659
+ // Fallback to detail.description if jsDoc.description is empty
660
+ const descriptionText = jsDoc.description || detail.description;
661
+
662
+ return (
663
+ <div className="space-y-6">
664
+ {/* Description */}
665
+ {descriptionText && (
666
+ <div>
667
+ <h4 className="mb-2 text-sm font-semibold text-muted-foreground">概要</h4>
668
+ <p className="whitespace-pre-wrap text-sm">{descriptionText}</p>
669
+ </div>
670
+ )}
671
+
672
+ {/* Parameters (JSDoc) - only show if no Zod schema */}
673
+ {!detail.inputSchema && jsDoc.params && jsDoc.params.length > 0 && (
674
+ <div>
675
+ <h4 className="mb-2 text-sm font-semibold text-muted-foreground">パラメータ</h4>
676
+ <Table>
677
+ <TableHeader>
678
+ <TableRow>
679
+ <TableHead className="w-[150px]">名前</TableHead>
680
+ <TableHead className="w-[200px]">型</TableHead>
681
+ <TableHead>説明</TableHead>
682
+ </TableRow>
683
+ </TableHeader>
684
+ <TableBody>
685
+ {jsDoc.params.map((param, idx) => (
686
+ <TableRow key={idx}>
687
+ <TableCell className="font-mono text-sm">{param.name}</TableCell>
688
+ <TableCell className="font-mono text-xs text-muted-foreground">
689
+ {param.type || "-"}
690
+ </TableCell>
691
+ <TableCell className="text-sm">{param.description || "-"}</TableCell>
692
+ </TableRow>
693
+ ))}
694
+ </TableBody>
695
+ </Table>
696
+ </div>
697
+ )}
698
+
699
+ {/* Returns - only show if no outputSchema */}
700
+ {!detail.outputSchema && jsDoc.returns && (
701
+ <div>
702
+ <h4 className="mb-2 text-sm font-semibold text-muted-foreground">戻り値</h4>
703
+ <p className="text-sm">{jsDoc.returns}</p>
704
+ </div>
705
+ )}
706
+
707
+ {/* Throws */}
708
+ {jsDoc.throws && jsDoc.throws.length > 0 && (
709
+ <div>
710
+ <h4 className="mb-2 text-sm font-semibold text-muted-foreground">例外</h4>
711
+ <ul className="list-inside list-disc space-y-1 text-sm">
712
+ {jsDoc.throws.map((t, idx) => (
713
+ <li key={idx}>{t}</li>
714
+ ))}
715
+ </ul>
716
+ </div>
717
+ )}
718
+
719
+ {/* Examples - Parse markdown code fences and use CodeBlock */}
720
+ {jsDoc.examples && jsDoc.examples.length > 0 && (
721
+ <div>
722
+ <h4 className="mb-2 text-sm font-semibold text-muted-foreground">使用例</h4>
723
+ <div className="space-y-3">
724
+ {jsDoc.examples.map((example, idx) => {
725
+ const { language, code } = parseMarkdownCodeFence(example);
726
+ return (
727
+ <CodeBlock key={idx} code={code} language={language} />
728
+ );
729
+ })}
730
+ </div>
731
+ </div>
732
+ )}
733
+
734
+ {/* Enhanced Tags Section */}
735
+ {jsDoc.tags && jsDoc.tags.length > 0 && (
736
+ <EnhancedTagsSection
737
+ tags={jsDoc.tags}
738
+ moduleName={detail.moduleName}
739
+ appId={appId}
740
+ appName={appName}
741
+ lookupModule={lookupModule}
742
+ />
743
+ )}
744
+ </div>
745
+ );
746
+ }
747
+
748
+ // Source Code Section
749
+ function SourceCodeSection({ sourceCode }: { sourceCode: string }) {
750
+ return (
751
+ <div className="space-y-4">
752
+ <h4 className="text-sm font-semibold text-muted-foreground">ソースコード</h4>
753
+ <div className="max-h-[600px] overflow-auto">
754
+ <CodeBlock code={sourceCode} language="typescript" />
755
+ </div>
756
+ </div>
757
+ );
758
+ }
759
+
760
+ // BDD Section Component for individual test
761
+ function BddDisplay({ bdd }: { bdd: { given?: string; when?: string; then?: string; and?: string[] } }) {
762
+ const bddColors = {
763
+ given: "border-l-blue-500 bg-blue-50 dark:bg-blue-950/30",
764
+ when: "border-l-amber-500 bg-amber-50 dark:bg-amber-950/30",
765
+ then: "border-l-green-500 bg-green-50 dark:bg-green-950/30",
766
+ and: "border-l-gray-400 bg-gray-50 dark:bg-gray-950/30",
767
+ };
768
+ const labelColors = {
769
+ given: "text-blue-600 dark:text-blue-400",
770
+ when: "text-amber-600 dark:text-amber-400",
771
+ then: "text-green-600 dark:text-green-400",
772
+ and: "text-gray-600 dark:text-gray-400",
773
+ };
774
+
775
+ return (
776
+ <div className="space-y-1 mt-2">
777
+ {bdd.given && (
778
+ <div className={`border-l-4 ${bddColors.given} rounded-r px-2 py-1`}>
779
+ <span className={`text-xs font-bold uppercase ${labelColors.given}`}>Given</span>
780
+ <p className="text-xs">{bdd.given}</p>
781
+ </div>
782
+ )}
783
+ {bdd.when && (
784
+ <div className={`border-l-4 ${bddColors.when} rounded-r px-2 py-1`}>
785
+ <span className={`text-xs font-bold uppercase ${labelColors.when}`}>When</span>
786
+ <p className="text-xs">{bdd.when}</p>
787
+ </div>
788
+ )}
789
+ {bdd.then && (
790
+ <div className={`border-l-4 ${bddColors.then} rounded-r px-2 py-1`}>
791
+ <span className={`text-xs font-bold uppercase ${labelColors.then}`}>Then</span>
792
+ <p className="text-xs">{bdd.then}</p>
793
+ </div>
794
+ )}
795
+ {bdd.and?.map((andItem, idx) => (
796
+ <div key={idx} className={`border-l-4 ${bddColors.and} rounded-r px-2 py-1`}>
797
+ <span className={`text-xs font-bold uppercase ${labelColors.and}`}>And</span>
798
+ <p className="text-xs">{andItem}</p>
799
+ </div>
800
+ ))}
801
+ </div>
802
+ );
803
+ }
804
+
805
+ // Test Coverage Section
806
+ function TestCoverageSection({ detail }: { detail: DetailItem }) {
807
+ const { testCoverage } = detail;
808
+
809
+ if (!testCoverage || !testCoverage.hasTest) {
810
+ return (
811
+ <div className="space-y-4">
812
+ <div className="rounded-lg border border-yellow-500/30 bg-yellow-500/10 p-4">
813
+ <div className="flex items-center gap-2">
814
+ <AlertTriangle className="h-5 w-5 text-yellow-500" />
815
+ <span className="font-medium text-yellow-600">テストがありません</span>
816
+ </div>
817
+ {testCoverage?.recommendations && testCoverage.recommendations.length > 0 && (
818
+ <ul className="mt-2 list-inside list-disc text-sm text-muted-foreground">
819
+ {testCoverage.recommendations.map((rec, idx) => (
820
+ <li key={idx}>{rec}</li>
821
+ ))}
822
+ </ul>
823
+ )}
824
+ </div>
825
+ </div>
826
+ );
827
+ }
828
+
829
+ return (
830
+ <div className="space-y-6">
831
+ <CoverageScoreBar score={testCoverage.coverageScore || 0} />
832
+
833
+ <div className="grid gap-4 sm:grid-cols-2">
834
+ <div className="rounded-lg border p-4">
835
+ <div className="text-2xl font-bold">{testCoverage.totalTests || 0}</div>
836
+ <div className="text-sm text-muted-foreground">総テスト数</div>
837
+ </div>
838
+ <div className="rounded-lg border p-4">
839
+ <div className="text-2xl font-bold">{Object.keys(testCoverage.byCategory || {}).length}</div>
840
+ <div className="text-sm text-muted-foreground">カテゴリ数</div>
841
+ </div>
842
+ </div>
843
+
844
+ {/* Tests by Category with BDD display */}
845
+ <div className="space-y-4">
846
+ <h4 className="text-sm font-semibold text-muted-foreground">カテゴリ別テスト</h4>
847
+ {Object.entries(testCoverage.byCategory || {}).map(([category, tests]) => {
848
+ const catConfig = categoryLabels[category] || categoryLabels["other"];
849
+
850
+ return (
851
+ <Collapsible key={category} defaultOpen={tests.length <= 5}>
852
+ <CollapsibleTrigger className="flex w-full items-center justify-between rounded-lg border p-3 hover:bg-muted/50">
853
+ <div className="flex items-center gap-2">
854
+ <div className={`h-2 w-2 rounded-full ${catConfig.color}`} />
855
+ <span className="font-medium">{catConfig.label}</span>
856
+ <Badge variant="secondary" className="text-xs">
857
+ {tests.length}
858
+ </Badge>
859
+ </div>
860
+ <ChevronRight className="h-4 w-4 transition-transform [[data-state=open]_&]:rotate-90" />
861
+ </CollapsibleTrigger>
862
+ <CollapsibleContent className="mt-2 space-y-3 pl-4">
863
+ {tests.map((test, idx) => (
864
+ <Link
865
+ key={idx}
866
+ href={`/test-cases/${encodeFilePath(test.file)}/${test.line}`}
867
+ className="block rounded-lg border p-3 hover:bg-muted/30 transition-colors group"
868
+ >
869
+ <div className="flex items-start gap-2">
870
+ <TestTube2 className="mt-0.5 h-4 w-4 text-muted-foreground flex-shrink-0" />
871
+ <div className="flex-1 min-w-0">
872
+ <p className="font-medium text-sm group-hover:text-primary transition-colors">{test.name}</p>
873
+ {test.summary && (
874
+ <p className="text-xs text-muted-foreground mt-1">{test.summary}</p>
875
+ )}
876
+ {test.purpose && (
877
+ <p className="text-xs text-muted-foreground mt-1">
878
+ <span className="font-medium">目的:</span> {test.purpose}
879
+ </p>
880
+ )}
881
+ {test.expected && (
882
+ <p className="text-xs text-muted-foreground mt-1">
883
+ <span className="font-medium">期待結果:</span> {test.expected}
884
+ </p>
885
+ )}
886
+ {/* BDD Display */}
887
+ {test.bdd && (test.bdd.given || test.bdd.when || test.bdd.then) && (
888
+ <BddDisplay bdd={test.bdd} />
889
+ )}
890
+ {/* File Link */}
891
+ <div className="mt-2 flex items-center gap-2 text-xs text-muted-foreground">
892
+ <FileCode className="h-3 w-3" />
893
+ <span className="truncate">{test.file}:{test.line}</span>
894
+ </div>
895
+ </div>
896
+ </div>
897
+ </Link>
898
+ ))}
899
+ </CollapsibleContent>
900
+ </Collapsible>
901
+ );
902
+ })}
903
+ </div>
904
+
905
+ {/* Recommendations */}
906
+ {testCoverage.recommendations && testCoverage.recommendations.length > 0 && (
907
+ <div className="rounded-lg border border-yellow-500/30 bg-yellow-500/10 p-4">
908
+ <h4 className="mb-2 flex items-center gap-2 font-medium text-yellow-600">
909
+ <Info className="h-4 w-4" />
910
+ 推奨事項
911
+ </h4>
912
+ <ul className="list-inside list-disc space-y-1 text-sm text-muted-foreground">
913
+ {testCoverage.recommendations.map((rec, idx) => (
914
+ <li key={idx}>{rec}</li>
915
+ ))}
916
+ </ul>
917
+ </div>
918
+ )}
919
+ </div>
920
+ );
921
+ }
922
+
923
+ // Related Items Section - app-specific version
924
+ function RelatedItemsSection({
925
+ detail,
926
+ config,
927
+ appId,
928
+ appName,
929
+ lookupModule
930
+ }: {
931
+ detail: DetailItem;
932
+ config: LayerConfig;
933
+ appId: string;
934
+ appName: string;
935
+ lookupModule?: ItemLookupFn;
936
+ }) {
937
+ const { related } = detail;
938
+
939
+ const hasRelated =
940
+ (related.usedInScreens?.length || 0) +
941
+ (related.usedInComponents?.length || 0) +
942
+ (related.usedInActions?.length || 0) +
943
+ (related.dbTables?.length || 0) > 0;
944
+
945
+ if (!hasRelated) {
946
+ return (
947
+ <div className="text-center text-muted-foreground">
948
+ 関連アイテムはありません
949
+ </div>
950
+ );
951
+ }
952
+
953
+ return (
954
+ <div className="space-y-6">
955
+ {/* Used in Screens */}
956
+ {related.usedInScreens && related.usedInScreens.length > 0 && (
957
+ <div>
958
+ <h4 className="mb-2 flex items-center gap-2 text-sm font-semibold text-muted-foreground">
959
+ <Monitor className="h-4 w-4 text-accent-blue" />
960
+ 使用している画面
961
+ </h4>
962
+ <div className="flex flex-wrap gap-2">
963
+ {related.usedInScreens.map((screen, idx) => {
964
+ const result = lookupModule?.("screens", screen);
965
+ if (result) {
966
+ const isCrossApp = result.app && result.app !== appName;
967
+ const targetAppId = result.app ? result.app.toLowerCase() : appId;
968
+ return (
969
+ <Link
970
+ key={idx}
971
+ href={`/apps/${targetAppId}/screens/${encodeURIComponent(result.module)}/${encodeURIComponent(screen)}`}
972
+ >
973
+ <Badge variant="outline" className={`text-xs hover:bg-muted cursor-pointer transition-colors ${isCrossApp ? "border-dashed" : ""}`}>
974
+ {screen}
975
+ {isCrossApp && <ExternalLink className="ml-1 h-2 w-2 inline" />}
976
+ </Badge>
977
+ </Link>
978
+ );
979
+ }
980
+ return (
981
+ <Badge key={idx} variant="outline" className="text-xs text-muted-foreground">
982
+ {screen}
983
+ </Badge>
984
+ );
985
+ })}
986
+ </div>
987
+ </div>
988
+ )}
989
+
990
+ {/* Used in Components */}
991
+ {related.usedInComponents && related.usedInComponents.length > 0 && (
992
+ <div>
993
+ <h4 className="mb-2 flex items-center gap-2 text-sm font-semibold text-muted-foreground">
994
+ <Component className="h-4 w-4 text-accent-green" />
995
+ 使用しているコンポーネント
996
+ </h4>
997
+ <div className="flex flex-wrap gap-2">
998
+ {related.usedInComponents.map((comp, idx) => {
999
+ const result = lookupModule?.("components", comp);
1000
+ if (result) {
1001
+ const isCrossApp = result.app && result.app !== appName;
1002
+ const targetAppId = result.app ? result.app.toLowerCase() : appId;
1003
+ return (
1004
+ <Link
1005
+ key={idx}
1006
+ href={`/apps/${targetAppId}/components/${encodeURIComponent(result.module)}/${encodeURIComponent(comp)}`}
1007
+ >
1008
+ <Badge variant="outline" className={`text-xs hover:bg-muted cursor-pointer transition-colors ${isCrossApp ? "border-dashed" : ""}`}>
1009
+ {comp}
1010
+ {isCrossApp && <ExternalLink className="ml-1 h-2 w-2 inline" />}
1011
+ </Badge>
1012
+ </Link>
1013
+ );
1014
+ }
1015
+ return (
1016
+ <Badge key={idx} variant="outline" className="text-xs text-muted-foreground">
1017
+ {comp}
1018
+ </Badge>
1019
+ );
1020
+ })}
1021
+ </div>
1022
+ </div>
1023
+ )}
1024
+
1025
+ {/* Used in Actions */}
1026
+ {related.usedInActions && related.usedInActions.length > 0 && (
1027
+ <div>
1028
+ <h4 className="mb-2 flex items-center gap-2 text-sm font-semibold text-muted-foreground">
1029
+ <Zap className="h-4 w-4 text-accent-yellow" />
1030
+ 使用しているアクション
1031
+ </h4>
1032
+ <div className="flex flex-wrap gap-2">
1033
+ {related.usedInActions.map((action, idx) => {
1034
+ const result = lookupModule?.("actions", action);
1035
+ if (result) {
1036
+ const isCrossApp = result.app && result.app !== appName;
1037
+ const targetAppId = result.app ? result.app.toLowerCase() : appId;
1038
+ return (
1039
+ <Link
1040
+ key={idx}
1041
+ href={`/apps/${targetAppId}/actions/${encodeURIComponent(result.module)}/${encodeURIComponent(action)}`}
1042
+ >
1043
+ <Badge variant="outline" className={`text-xs hover:bg-muted cursor-pointer transition-colors ${isCrossApp ? "border-dashed" : ""}`}>
1044
+ {action}
1045
+ {isCrossApp && <ExternalLink className="ml-1 h-2 w-2 inline" />}
1046
+ </Badge>
1047
+ </Link>
1048
+ );
1049
+ }
1050
+ return (
1051
+ <Badge key={idx} variant="outline" className="text-xs text-muted-foreground">
1052
+ {action}
1053
+ </Badge>
1054
+ );
1055
+ })}
1056
+ </div>
1057
+ </div>
1058
+ )}
1059
+
1060
+ {/* Uses DB Tables - link to db-schema page */}
1061
+ {related.dbTables && related.dbTables.length > 0 && (
1062
+ <div>
1063
+ <h4 className="mb-2 flex items-center gap-2 text-sm font-semibold text-muted-foreground">
1064
+ <Database className="h-4 w-4 text-accent-purple" />
1065
+ 使用しているテーブル
1066
+ </h4>
1067
+ <div className="flex flex-wrap gap-2">
1068
+ {related.dbTables.map((table, idx) => (
1069
+ <Link
1070
+ key={idx}
1071
+ href={`/db-schema/${encodeURIComponent(table)}`}
1072
+ >
1073
+ <Badge variant="outline" className="text-xs hover:bg-muted cursor-pointer transition-colors">
1074
+ {table}
1075
+ </Badge>
1076
+ </Link>
1077
+ ))}
1078
+ </div>
1079
+ </div>
1080
+ )}
1081
+ </div>
1082
+ );
1083
+ }
1084
+
1085
+ function getModuleItems(
1086
+ data: FeatureMapData,
1087
+ module: string,
1088
+ type: LayerType,
1089
+ appName: string
1090
+ ): (ScreenItem | ComponentItem | ActionItem | ModuleItem | TableItem)[] {
1091
+ const items = module === "Uncategorized"
1092
+ ? data.uncategorized[type] || []
1093
+ : data.features[module]?.[type] || [];
1094
+
1095
+ // Filter by app
1096
+ return items.filter((item) => item.app === appName);
1097
+ }
1098
+
1099
+ export default async function AppItemDetailPage({
1100
+ params,
1101
+ }: {
1102
+ params: Promise<{ appId: string; type: string; module: string; item: string }>;
1103
+ }) {
1104
+ const { appId, type, module, item } = await params;
1105
+ const decodedModule = decodeURIComponent(module);
1106
+ const decodedItem = decodeURIComponent(item);
1107
+
1108
+ const [featureMapData, detailsData, applications] = await Promise.all([
1109
+ loadFeatureMap(),
1110
+ loadDetails(),
1111
+ loadApplications(),
1112
+ ]);
1113
+
1114
+ // Load screenshot for screens only
1115
+ let screenshot: ScreenshotEntry | null = null;
1116
+ let screenshotAppId: string | null = null;
1117
+ if (type === "screens") {
1118
+ const result = await getScreenshotForScreen(decodedItem, appId);
1119
+ if (result) {
1120
+ screenshot = result.entry;
1121
+ screenshotAppId = result.appId;
1122
+ }
1123
+ }
1124
+
1125
+ // Find the app configuration
1126
+ const app = applications?.apps?.find((a) => a.id === appId);
1127
+ if (!app) {
1128
+ notFound();
1129
+ }
1130
+
1131
+ const appNameForFilter = app.name.replace(" アプリ", "");
1132
+
1133
+ if (!featureMapData) {
1134
+ notFound();
1135
+ }
1136
+
1137
+ // Build lookup function for cross-module linking
1138
+ const lookupModule = buildItemModuleLookup(featureMapData);
1139
+
1140
+ const layerType = type as LayerType;
1141
+ if (!layerConfigs[layerType]) {
1142
+ notFound();
1143
+ }
1144
+
1145
+ const config = layerConfigs[layerType];
1146
+ const Icon = config.icon;
1147
+
1148
+ // Get all items in this module filtered by app
1149
+ const items = getModuleItems(featureMapData, decodedModule, layerType, appNameForFilter);
1150
+ const foundItem = items.find((i) => i.name === decodedItem);
1151
+
1152
+ if (!foundItem) {
1153
+ notFound();
1154
+ }
1155
+
1156
+ // Get detail from details.json
1157
+ const getDetailForItem = (itemName: string): DetailItem | null => {
1158
+ if (!detailsData) return null;
1159
+
1160
+ // First try exact key match (type/module/name)
1161
+ const exactKey = `${config.singular}/${decodedModule}/${itemName}`;
1162
+ if (detailsData.details[exactKey]) {
1163
+ return detailsData.details[exactKey];
1164
+ }
1165
+
1166
+ // Search by item name across all modules
1167
+ const prefix = `${config.singular}/`;
1168
+ const suffix = `/${itemName}`;
1169
+
1170
+ for (const [key, detail] of Object.entries(detailsData.details)) {
1171
+ if (key.startsWith(prefix) && key.endsWith(suffix)) {
1172
+ return detail;
1173
+ }
1174
+ }
1175
+
1176
+ return null;
1177
+ };
1178
+
1179
+ const detail = getDetailForItem(decodedItem);
1180
+
1181
+ return (
1182
+ <div className="space-y-8">
1183
+ {/* Breadcrumb */}
1184
+ <div className="flex items-center gap-2 text-sm">
1185
+ <Link
1186
+ href={`/apps/${appId}/feature-map`}
1187
+ className="flex items-center gap-1 text-muted-foreground hover:text-primary"
1188
+ >
1189
+ <ArrowLeft className="h-4 w-4" />
1190
+ {app.name} Feature Map
1191
+ </Link>
1192
+ <span className="text-muted-foreground">/</span>
1193
+ <span className="text-muted-foreground">{config.label}</span>
1194
+ <span className="text-muted-foreground">/</span>
1195
+ <Link
1196
+ href={`/apps/${appId}/${type}/${module}`}
1197
+ className="text-muted-foreground hover:text-primary"
1198
+ >
1199
+ {decodedModule}
1200
+ </Link>
1201
+ <span className="text-muted-foreground">/</span>
1202
+ <span className="font-medium">{decodedItem}</span>
1203
+ </div>
1204
+
1205
+ {/* Header */}
1206
+ <header className="flex items-start gap-4">
1207
+ <div className={`rounded-lg p-3 ${config.bgColor}`}>
1208
+ <Icon className={`h-8 w-8 ${config.color}`} />
1209
+ </div>
1210
+ <div className="flex-1">
1211
+ <h1 className="text-3xl font-bold tracking-tight">{decodedItem}</h1>
1212
+ <div className="mt-3 flex flex-wrap items-center gap-2">
1213
+ {/* Auth Level Badge */}
1214
+ {detail?.authLevel && <AuthLevelBadge level={detail.authLevel} />}
1215
+
1216
+ {/* Rate Limit Badge */}
1217
+ {detail?.rateLimit && (
1218
+ <Badge variant="outline" className="text-xs text-orange-600 bg-orange-500/10 border-orange-500/30">
1219
+ <Clock className="mr-1 h-3 w-3" />
1220
+ {detail.rateLimit}
1221
+ </Badge>
1222
+ )}
1223
+
1224
+ {/* CSRF Badge */}
1225
+ {detail?.csrfProtection && (
1226
+ <Badge variant="outline" className="text-xs text-cyan-600 bg-cyan-500/10 border-cyan-500/30">
1227
+ <Shield className="mr-1 h-3 w-3" />
1228
+ CSRF Protected
1229
+ </Badge>
1230
+ )}
1231
+
1232
+ {/* Test Coverage Badges */}
1233
+ {detail?.testCoverage && (
1234
+ <>
1235
+ <Badge
1236
+ variant={detail.testCoverage.coverageScore >= 70 ? "default" : "secondary"}
1237
+ >
1238
+ {detail.testCoverage.totalTests} tests
1239
+ </Badge>
1240
+ <Badge
1241
+ variant="outline"
1242
+ className={
1243
+ detail.testCoverage.coverageScore >= 70
1244
+ ? "border-green-500 text-green-600"
1245
+ : detail.testCoverage.coverageScore >= 40
1246
+ ? "border-yellow-500 text-yellow-600"
1247
+ : "border-red-500 text-red-600"
1248
+ }
1249
+ >
1250
+ {detail.testCoverage.coverageScore}%
1251
+ </Badge>
1252
+ </>
1253
+ )}
1254
+
1255
+ {/* App Badge */}
1256
+ <Badge
1257
+ variant="outline"
1258
+ className={`text-xs ${
1259
+ appNameForFilter === "Admin"
1260
+ ? "bg-blue-500/10 text-blue-600 border-blue-500/30"
1261
+ : appNameForFilter === "Public"
1262
+ ? "bg-green-500/10 text-green-600 border-green-500/30"
1263
+ : appNameForFilter === "Web"
1264
+ ? "bg-purple-500/10 text-purple-600 border-purple-500/30"
1265
+ : "bg-gray-500/10 text-gray-600 border-gray-500/30"
1266
+ }`}
1267
+ >
1268
+ <AppWindow className="mr-1 h-3 w-3" />
1269
+ {appNameForFilter}
1270
+ </Badge>
1271
+
1272
+ {/* Module Badge */}
1273
+ <Badge variant="outline" className="text-xs">
1274
+ {decodedModule}
1275
+ </Badge>
1276
+ </div>
1277
+ </div>
1278
+ </header>
1279
+
1280
+ {/* Main Content */}
1281
+ {detail ? (
1282
+ <ItemTabsClient
1283
+ overviewContent={
1284
+ <Card>
1285
+ <CardContent className="pt-6 space-y-8">
1286
+ {/* Screenshot (Screens only) */}
1287
+ {layerType === "screens" && (
1288
+ <div className="space-y-2">
1289
+ <div className="flex items-center gap-2 text-sm font-medium text-muted-foreground">
1290
+ <Camera className="h-4 w-4" />
1291
+ スクリーンショット
1292
+ </div>
1293
+ {screenshot && screenshotAppId ? (
1294
+ <div className="relative overflow-hidden rounded-lg border bg-muted/30">
1295
+ <img
1296
+ src={screenshotAppId === "default"
1297
+ ? `/screenshots/${screenshot.fileName}`
1298
+ : `/screenshots/${screenshotAppId}/${screenshot.fileName}`
1299
+ }
1300
+ alt={`Screenshot of ${screenshot.name}`}
1301
+ className="w-full h-auto"
1302
+ loading="lazy"
1303
+ />
1304
+ {screenshot.account && (
1305
+ <div className="absolute bottom-2 right-2">
1306
+ <Badge variant="outline" className="text-xs bg-background/80">
1307
+ {screenshot.account}
1308
+ </Badge>
1309
+ </div>
1310
+ )}
1311
+ </div>
1312
+ ) : (
1313
+ <div className="flex items-center justify-center h-32 rounded-lg border border-dashed bg-muted/20 text-muted-foreground">
1314
+ <div className="text-center">
1315
+ <ImageOff className="h-8 w-8 mx-auto mb-2 opacity-50" />
1316
+ <p className="text-sm">スクリーンショット未生成</p>
1317
+ <p className="text-xs mt-1">
1318
+ <code>shirokuma-docs screenshots --run</code> で生成
1319
+ </p>
1320
+ </div>
1321
+ </div>
1322
+ )}
1323
+ </div>
1324
+ )}
1325
+
1326
+ {/* File Path */}
1327
+ <div className="flex items-center gap-2 text-sm text-muted-foreground">
1328
+ <FileCode className="h-4 w-4" />
1329
+ <code className="truncate">{detail.filePath}</code>
1330
+ </div>
1331
+
1332
+ {/* Enhanced Parameters Table (from Zod schema) */}
1333
+ {detail.inputSchema?.parameters && (
1334
+ <EnhancedParametersTable parameters={detail.inputSchema.parameters} />
1335
+ )}
1336
+
1337
+ {/* Output Schema */}
1338
+ {detail.outputSchema && (
1339
+ <div>
1340
+ <h4 className="mb-2 text-sm font-semibold text-muted-foreground">戻り値</h4>
1341
+ <div className="rounded-md bg-muted p-3">
1342
+ <code className="text-sm">{detail.outputSchema.type}</code>
1343
+ {detail.outputSchema.successType && (
1344
+ <p className="mt-1 text-xs text-muted-foreground">
1345
+ 成功時: <code>{detail.outputSchema.successType}</code>
1346
+ </p>
1347
+ )}
1348
+ {detail.outputSchema.errorType && (
1349
+ <p className="mt-1 text-xs text-muted-foreground">
1350
+ エラー時: <code>{detail.outputSchema.errorType}</code>
1351
+ </p>
1352
+ )}
1353
+ </div>
1354
+ </div>
1355
+ )}
1356
+
1357
+ {/* Error Codes */}
1358
+ {detail.errorCodes && detail.errorCodes.length > 0 && (
1359
+ <ErrorCodesSection errorCodes={detail.errorCodes} />
1360
+ )}
1361
+
1362
+ {/* JSDoc Section */}
1363
+ <JSDocSection
1364
+ detail={detail}
1365
+ appId={appId}
1366
+ appName={appNameForFilter}
1367
+ lookupModule={lookupModule}
1368
+ />
1369
+ </CardContent>
1370
+ </Card>
1371
+ }
1372
+ codeContent={
1373
+ <Card>
1374
+ <CardContent className="pt-6">
1375
+ <SourceCodeSection sourceCode={detail.sourceCode} />
1376
+ </CardContent>
1377
+ </Card>
1378
+ }
1379
+ testsContent={
1380
+ <Card>
1381
+ <CardContent className="pt-6">
1382
+ <TestCoverageSection detail={detail} />
1383
+ </CardContent>
1384
+ </Card>
1385
+ }
1386
+ relatedContent={
1387
+ <Card>
1388
+ <CardContent className="pt-6">
1389
+ <RelatedItemsSection
1390
+ detail={detail}
1391
+ config={config}
1392
+ appId={appId}
1393
+ appName={appNameForFilter}
1394
+ lookupModule={lookupModule}
1395
+ />
1396
+ </CardContent>
1397
+ </Card>
1398
+ }
1399
+ />
1400
+ ) : (
1401
+ <Card>
1402
+ <CardContent className="pt-6">
1403
+ <div className="text-center text-muted-foreground">
1404
+ 詳細情報はありません
1405
+ </div>
1406
+ </CardContent>
1407
+ </Card>
1408
+ )}
1409
+
1410
+ {/* Navigation */}
1411
+ <div className="flex justify-between pt-4 border-t">
1412
+ <Link
1413
+ href={`/apps/${appId}/${type}/${module}`}
1414
+ className="flex items-center gap-2 text-sm text-muted-foreground hover:text-primary"
1415
+ >
1416
+ <ArrowLeft className="h-4 w-4" />
1417
+ {decodedModule} の一覧に戻る
1418
+ </Link>
1419
+ </div>
1420
+ </div>
1421
+ );
1422
+ }