@brainfish-ai/devdoc 0.1.21 → 0.1.23
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.
- package/package.json +1 -1
- package/renderer/app/api/collections/route.ts +2 -16
- package/renderer/app/api/docs/route.ts +10 -0
- package/renderer/app/api/schema/route.ts +11 -3
- package/renderer/app/globals.css +88 -0
- package/renderer/components/docs/mdx/index.ts +33 -0
- package/renderer/components/docs/mdx/landing.tsx +684 -0
- package/renderer/components/docs-viewer/content/doc-page.tsx +81 -14
- package/renderer/components/docs-viewer/index.tsx +203 -59
- package/renderer/components/docs-viewer/sidebar/index.tsx +3 -95
- package/renderer/components/docs-viewer/sidebar/sidebar-item.tsx +2 -16
- package/renderer/components/docs-viewer/sidebar/sidebar-section.tsx +2 -16
- package/renderer/lib/api-docs/factories.ts +45 -26
- package/renderer/lib/api-docs/parsers/graphql/parser.ts +1 -1
- package/renderer/lib/api-docs/parsers/openapi/transformer.ts +1 -0
- package/renderer/lib/docs/config/schema.ts +11 -1
- package/renderer/lib/docs/mdx/frontmatter.ts +11 -0
- package/renderer/lib/utils/icons.ts +48 -0
- package/renderer/components/docs-viewer/content/introduction.tsx +0 -21
package/package.json
CHANGED
|
@@ -34,8 +34,8 @@ const BRAINFISH_API_BASE_URL = process.env.BRAINFISH_API_BASE_URL || 'https://ap
|
|
|
34
34
|
const BRAINFISH_CATALOG_ID = process.env.BRAINFISH_CATALOG_ID || 'your_catalog_id_here'
|
|
35
35
|
const BRAINFISH_JWT_TOKEN = process.env.BRAINFISH_JWT_TOKEN || 'your_jwt_token_here'
|
|
36
36
|
|
|
37
|
-
// Debug logging
|
|
38
|
-
if (process.env.
|
|
37
|
+
// Debug logging - only in verbose mode
|
|
38
|
+
if (process.env.DEVDOC_VERBOSE === 'true') {
|
|
39
39
|
console.log('[Collections] Config:', {
|
|
40
40
|
useLocalSpec: USE_LOCAL_SPEC,
|
|
41
41
|
starterPath: STARTER_PATH,
|
|
@@ -219,12 +219,10 @@ function loadGraphQLSchema(schemaPath: string): string | null {
|
|
|
219
219
|
: resolvePath(relativePath)
|
|
220
220
|
|
|
221
221
|
if (!existsSync(fullPath)) {
|
|
222
|
-
console.log('[Collections] GraphQL schema not found at:', fullPath)
|
|
223
222
|
return null
|
|
224
223
|
}
|
|
225
224
|
|
|
226
225
|
const content = readFileSync(fullPath, 'utf-8')
|
|
227
|
-
console.log('[Collections] Loaded GraphQL schema from:', fullPath)
|
|
228
226
|
return content
|
|
229
227
|
} catch (error) {
|
|
230
228
|
console.error('[Collections] Error loading GraphQL schema:', error)
|
|
@@ -243,14 +241,12 @@ function loadLocalSpec(specPath?: string): OpenApiSpec | null {
|
|
|
243
241
|
: resolvePath(relativePath)
|
|
244
242
|
|
|
245
243
|
if (!existsSync(fullPath)) {
|
|
246
|
-
console.log('[Collections] Local spec not found at:', fullPath)
|
|
247
244
|
return null
|
|
248
245
|
}
|
|
249
246
|
|
|
250
247
|
const content = readFileSync(fullPath, 'utf-8')
|
|
251
248
|
const spec = JSON.parse(content) as OpenApiSpec
|
|
252
249
|
|
|
253
|
-
console.log('[Collections] Loaded local spec:', spec.info?.title, 'v' + spec.info?.version, 'from', fullPath)
|
|
254
250
|
return spec
|
|
255
251
|
} catch (error) {
|
|
256
252
|
console.error('[Collections] Error loading local spec:', error)
|
|
@@ -264,7 +260,6 @@ function loadDocsConfig(): DocsConfig | null {
|
|
|
264
260
|
const configPath = resolvePath('docs.json')
|
|
265
261
|
|
|
266
262
|
if (!existsSync(configPath)) {
|
|
267
|
-
console.log('[Collections] docs.json not found at:', configPath)
|
|
268
263
|
return null
|
|
269
264
|
}
|
|
270
265
|
|
|
@@ -282,7 +277,6 @@ function loadThemeConfig(): ThemeConfig | null {
|
|
|
282
277
|
const configPath = resolvePath('theme.json')
|
|
283
278
|
|
|
284
279
|
if (!existsSync(configPath)) {
|
|
285
|
-
console.log('[Collections] theme.json not found at:', configPath)
|
|
286
280
|
return null
|
|
287
281
|
}
|
|
288
282
|
|
|
@@ -577,8 +571,6 @@ async function fetchRemoteSpec(): Promise<OpenApiSpec | null> {
|
|
|
577
571
|
try {
|
|
578
572
|
const url = `${BRAINFISH_API_BASE_URL}/catalogs.openapi-spec`
|
|
579
573
|
|
|
580
|
-
console.log('[Collections] Fetching from:', url)
|
|
581
|
-
|
|
582
574
|
const response = await fetch(url, {
|
|
583
575
|
method: 'POST',
|
|
584
576
|
headers: {
|
|
@@ -612,7 +604,6 @@ async function fetchRemoteSpec(): Promise<OpenApiSpec | null> {
|
|
|
612
604
|
|
|
613
605
|
const fallbackSpec = await CacheUtils.get<OpenApiSpec>(FALLBACK_CACHE_KEY)
|
|
614
606
|
if (fallbackSpec) {
|
|
615
|
-
console.warn('[Collections] Using fallback cache')
|
|
616
607
|
return fallbackSpec
|
|
617
608
|
}
|
|
618
609
|
|
|
@@ -627,7 +618,6 @@ async function getOpenApiSpec(specPath?: string): Promise<OpenApiSpec | null> {
|
|
|
627
618
|
if (localSpec) {
|
|
628
619
|
return localSpec
|
|
629
620
|
}
|
|
630
|
-
console.log('[Collections] Local spec not available, falling back to remote')
|
|
631
621
|
}
|
|
632
622
|
|
|
633
623
|
return fetchRemoteSpec()
|
|
@@ -811,11 +801,9 @@ async function getOrGenerateSummary(collection: BrainfishCollection, specVersion
|
|
|
811
801
|
|
|
812
802
|
const cachedSummary = await CacheUtils.get<string>(versionedCacheKey)
|
|
813
803
|
if (cachedSummary) {
|
|
814
|
-
console.log('[Collections] Using cached API summary for version:', specVersion)
|
|
815
804
|
return cachedSummary
|
|
816
805
|
}
|
|
817
806
|
|
|
818
|
-
console.log('[Collections] Generating new API summary for version:', specVersion)
|
|
819
807
|
const summary = generateAPISummary(collection)
|
|
820
808
|
const formattedSummary = formatAPISummaryForPrompt(summary)
|
|
821
809
|
|
|
@@ -869,8 +857,6 @@ export async function GET(request: Request) {
|
|
|
869
857
|
// Get OpenAPI spec (with optional path for versioned specs)
|
|
870
858
|
const spec = await getOpenApiSpec(specPath)
|
|
871
859
|
|
|
872
|
-
console.log('[Collections] Loaded', docGroups.length, 'doc groups,', navigationTabs.length, 'tabs,', changelogReleases.length, 'changelog releases,', apiVersions.length, 'API versions, selected:', selectedVersion)
|
|
873
|
-
|
|
874
860
|
// Handle no spec available
|
|
875
861
|
if (!spec) {
|
|
876
862
|
return NextResponse.json(
|
|
@@ -101,6 +101,11 @@ export async function GET(request: NextRequest) {
|
|
|
101
101
|
title: frontmatter.title || slug,
|
|
102
102
|
description: frontmatter.description,
|
|
103
103
|
icon: frontmatter.icon,
|
|
104
|
+
// Page mode and layout options
|
|
105
|
+
mode: frontmatter.mode || 'default',
|
|
106
|
+
hideHeader: frontmatter.hideHeader || false,
|
|
107
|
+
fullWidth: frontmatter.fullWidth || false,
|
|
108
|
+
background: frontmatter.background,
|
|
104
109
|
},
|
|
105
110
|
mdxSource,
|
|
106
111
|
rawContent: content, // Include raw content for changelog version extraction
|
|
@@ -171,6 +176,11 @@ async function handleMultiTenantDocs(projectSlug: string, slug: string): Promise
|
|
|
171
176
|
title: frontmatter.title || slug,
|
|
172
177
|
description: frontmatter.description,
|
|
173
178
|
icon: frontmatter.icon,
|
|
179
|
+
// Page mode and layout options
|
|
180
|
+
mode: frontmatter.mode || 'default',
|
|
181
|
+
hideHeader: frontmatter.hideHeader || false,
|
|
182
|
+
fullWidth: frontmatter.fullWidth || false,
|
|
183
|
+
background: frontmatter.background,
|
|
174
184
|
},
|
|
175
185
|
mdxSource,
|
|
176
186
|
rawContent: content,
|
|
@@ -1,15 +1,23 @@
|
|
|
1
1
|
import { NextRequest, NextResponse } from 'next/server'
|
|
2
2
|
import { readFileSync, existsSync } from 'fs'
|
|
3
|
-
import { join } from 'path'
|
|
3
|
+
import { join, isAbsolute } from 'path'
|
|
4
4
|
import { getProjectContent } from '@/lib/storage/blob'
|
|
5
5
|
|
|
6
|
-
//
|
|
6
|
+
// Configuration - match collections route
|
|
7
|
+
const STARTER_PATH = process.env.STARTER_PATH || 'devdoc-docs'
|
|
8
|
+
|
|
9
|
+
// Get the docs directory - respects STARTER_PATH for local development
|
|
7
10
|
function getDocsDir(): string {
|
|
8
11
|
const projectSlug = process.env.BRAINFISH_PROJECT_SLUG
|
|
9
12
|
if (projectSlug) {
|
|
10
13
|
return join(process.cwd(), '.devdoc', projectSlug)
|
|
11
14
|
}
|
|
12
|
-
|
|
15
|
+
|
|
16
|
+
// Use STARTER_PATH (can be absolute or relative)
|
|
17
|
+
if (isAbsolute(STARTER_PATH)) {
|
|
18
|
+
return STARTER_PATH
|
|
19
|
+
}
|
|
20
|
+
return join(process.cwd(), STARTER_PATH)
|
|
13
21
|
}
|
|
14
22
|
|
|
15
23
|
export async function GET(request: NextRequest) {
|
package/renderer/app/globals.css
CHANGED
|
@@ -1100,4 +1100,92 @@ code[data-line-numbers] > [data-line]::before {
|
|
|
1100
1100
|
/* Scroll margin for agent navigation */
|
|
1101
1101
|
[id] {
|
|
1102
1102
|
scroll-margin-top: 80px;
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
/* ============================================
|
|
1106
|
+
Custom Mode Page Styles (Landing Pages)
|
|
1107
|
+
============================================ */
|
|
1108
|
+
|
|
1109
|
+
/* Custom mode pages should fill the entire content area */
|
|
1110
|
+
.docs-page-custom {
|
|
1111
|
+
width: 100%;
|
|
1112
|
+
min-height: 100%;
|
|
1113
|
+
margin: 0;
|
|
1114
|
+
padding: 0;
|
|
1115
|
+
}
|
|
1116
|
+
|
|
1117
|
+
/* Ensure custom content children stretch to fill width */
|
|
1118
|
+
.docs-custom-content {
|
|
1119
|
+
width: 100%;
|
|
1120
|
+
margin: 0;
|
|
1121
|
+
padding: 0;
|
|
1122
|
+
}
|
|
1123
|
+
|
|
1124
|
+
/* All direct children of custom content should be full width */
|
|
1125
|
+
.docs-custom-content > * {
|
|
1126
|
+
width: 100%;
|
|
1127
|
+
margin-left: 0;
|
|
1128
|
+
margin-right: 0;
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1131
|
+
/* Landing page components should not have prose constraints */
|
|
1132
|
+
.docs-custom-content .landing-hero,
|
|
1133
|
+
.docs-custom-content .landing-section {
|
|
1134
|
+
max-width: none;
|
|
1135
|
+
width: 100%;
|
|
1136
|
+
margin-left: 0;
|
|
1137
|
+
margin-right: 0;
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
/* When viewing a custom mode page, the content area should have no background */
|
|
1141
|
+
.docs-content-area:has(.docs-page-custom) {
|
|
1142
|
+
background: transparent !important;
|
|
1143
|
+
padding: 0 !important;
|
|
1144
|
+
}
|
|
1145
|
+
|
|
1146
|
+
/* Ensure the main header doesn't shrink */
|
|
1147
|
+
.docs-main-header {
|
|
1148
|
+
flex-shrink: 0 !important;
|
|
1149
|
+
width: 100% !important;
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
/* Ensure docs-main container maintains width and doesn't collapse */
|
|
1153
|
+
.docs-main {
|
|
1154
|
+
flex: 1 1 0% !important;
|
|
1155
|
+
min-width: 0 !important;
|
|
1156
|
+
width: 100% !important;
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1159
|
+
/* Ensure docs-layout children don't cause layout shifts */
|
|
1160
|
+
.docs-layout {
|
|
1161
|
+
display: flex !important;
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
.docs-layout > .docs-sidebar {
|
|
1165
|
+
flex-shrink: 0 !important;
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1168
|
+
/* Prevent content area from affecting parent layout */
|
|
1169
|
+
.docs-content-area {
|
|
1170
|
+
flex: 1 1 auto !important;
|
|
1171
|
+
min-height: 0 !important;
|
|
1172
|
+
}
|
|
1173
|
+
|
|
1174
|
+
/* Remove any default margins from sections in custom pages */
|
|
1175
|
+
.docs-custom-content section {
|
|
1176
|
+
margin: 0;
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1179
|
+
/* Ensure Hero sections fill entire width */
|
|
1180
|
+
.landing-hero {
|
|
1181
|
+
width: 100%;
|
|
1182
|
+
margin: 0;
|
|
1183
|
+
padding-left: 0;
|
|
1184
|
+
padding-right: 0;
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
/* Section components fill entire width */
|
|
1188
|
+
.landing-section {
|
|
1189
|
+
width: 100%;
|
|
1190
|
+
margin: 0;
|
|
1103
1191
|
}
|
|
@@ -100,6 +100,23 @@ export {
|
|
|
100
100
|
UpdateItem,
|
|
101
101
|
} from './changelog'
|
|
102
102
|
|
|
103
|
+
// Landing Page Components
|
|
104
|
+
export {
|
|
105
|
+
Hero,
|
|
106
|
+
Pre,
|
|
107
|
+
Tagline,
|
|
108
|
+
Headline,
|
|
109
|
+
Description,
|
|
110
|
+
CommandBox,
|
|
111
|
+
Section,
|
|
112
|
+
Center,
|
|
113
|
+
FeatureGrid,
|
|
114
|
+
FeatureItem,
|
|
115
|
+
ButtonLink,
|
|
116
|
+
Spacer,
|
|
117
|
+
Divider,
|
|
118
|
+
} from './landing'
|
|
119
|
+
|
|
103
120
|
// Re-export types
|
|
104
121
|
export type { Frontmatter } from '@/lib/docs/mdx/frontmatter'
|
|
105
122
|
|
|
@@ -123,6 +140,7 @@ import { Badge } from './badge'
|
|
|
123
140
|
import { Mermaid } from './mermaid'
|
|
124
141
|
import { PDF, Audio, Download } from './file-embeds'
|
|
125
142
|
import { ChangelogEntry, ChangelogTitle, ChangelogDescription, ChangelogImage, BreakingChange, MoreUpdates, UpdateItem } from './changelog'
|
|
143
|
+
import { Hero, Pre, Tagline, Headline, Description, CommandBox, Section, Center, FeatureGrid, FeatureItem, ButtonLink, Spacer, Divider } from './landing'
|
|
126
144
|
|
|
127
145
|
export const mdxComponents = {
|
|
128
146
|
// Callouts
|
|
@@ -199,6 +217,21 @@ export const mdxComponents = {
|
|
|
199
217
|
BreakingChange,
|
|
200
218
|
MoreUpdates,
|
|
201
219
|
UpdateItem,
|
|
220
|
+
|
|
221
|
+
// Landing Page
|
|
222
|
+
Hero,
|
|
223
|
+
Pre,
|
|
224
|
+
Tagline,
|
|
225
|
+
Headline,
|
|
226
|
+
Description,
|
|
227
|
+
CommandBox,
|
|
228
|
+
Section,
|
|
229
|
+
Center,
|
|
230
|
+
FeatureGrid,
|
|
231
|
+
FeatureItem,
|
|
232
|
+
ButtonLink,
|
|
233
|
+
Spacer,
|
|
234
|
+
Divider,
|
|
202
235
|
}
|
|
203
236
|
|
|
204
237
|
export default mdxComponents
|