specra 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.MD +21 -0
- package/README.md +157 -0
- package/dist/app/api/mdx-watch/route.d.mts +12 -0
- package/dist/app/api/mdx-watch/route.d.ts +12 -0
- package/dist/app/api/mdx-watch/route.js +98 -0
- package/dist/app/api/mdx-watch/route.js.map +1 -0
- package/dist/app/api/mdx-watch/route.mjs +71 -0
- package/dist/app/api/mdx-watch/route.mjs.map +1 -0
- package/dist/app/docs-page.d.mts +32 -0
- package/dist/app/docs-page.d.ts +32 -0
- package/dist/app/docs-page.js +4072 -0
- package/dist/app/docs-page.js.map +1 -0
- package/dist/app/docs-page.mjs +14 -0
- package/dist/app/docs-page.mjs.map +1 -0
- package/dist/app/layout.css +297 -0
- package/dist/app/layout.css.map +1 -0
- package/dist/app/layout.d.mts +19 -0
- package/dist/app/layout.d.ts +19 -0
- package/dist/app/layout.js +112 -0
- package/dist/app/layout.js.map +1 -0
- package/dist/app/layout.mjs +13 -0
- package/dist/app/layout.mjs.map +1 -0
- package/dist/chunk-DR4EPLMT.mjs +1013 -0
- package/dist/chunk-DR4EPLMT.mjs.map +1 -0
- package/dist/chunk-INL2EC72.mjs +170 -0
- package/dist/chunk-INL2EC72.mjs.map +1 -0
- package/dist/chunk-IZFGEAD6.mjs +61 -0
- package/dist/chunk-IZFGEAD6.mjs.map +1 -0
- package/dist/chunk-KTRWWAGL.mjs +50 -0
- package/dist/chunk-KTRWWAGL.mjs.map +1 -0
- package/dist/chunk-MZJHJ6BV.mjs +21 -0
- package/dist/chunk-MZJHJ6BV.mjs.map +1 -0
- package/dist/chunk-NXRIAL7T.mjs +3119 -0
- package/dist/chunk-NXRIAL7T.mjs.map +1 -0
- package/dist/components/index.d.mts +822 -0
- package/dist/components/index.d.ts +822 -0
- package/dist/components/index.js +3738 -0
- package/dist/components/index.js.map +1 -0
- package/dist/components/index.mjs +3627 -0
- package/dist/components/index.mjs.map +1 -0
- package/dist/index.css +297 -0
- package/dist/index.css.map +1 -0
- package/dist/index.d.mts +545 -0
- package/dist/index.d.ts +545 -0
- package/dist/index.js +4648 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +347 -0
- package/dist/index.mjs.map +1 -0
- package/dist/lib/index.d.mts +798 -0
- package/dist/lib/index.d.ts +798 -0
- package/dist/lib/index.js +1301 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/index.mjs +89 -0
- package/dist/lib/index.mjs.map +1 -0
- package/package.json +119 -0
- package/src/app/api/mdx-watch/route.ts +86 -0
- package/src/app/docs-page.tsx +212 -0
- package/src/app/layout.tsx +74 -0
- package/src/components/docs/accordion.tsx +53 -0
- package/src/components/docs/api/api-endpoint.tsx +59 -0
- package/src/components/docs/api/api-params.tsx +43 -0
- package/src/components/docs/api/api-playground.tsx +233 -0
- package/src/components/docs/api/api-reference.tsx +291 -0
- package/src/components/docs/api/api-response.tsx +48 -0
- package/src/components/docs/api/index.ts +5 -0
- package/src/components/docs/badge.tsx +22 -0
- package/src/components/docs/breadcrumb.tsx +51 -0
- package/src/components/docs/callout.tsx +109 -0
- package/src/components/docs/card.tsx +84 -0
- package/src/components/docs/category-index.tsx +112 -0
- package/src/components/docs/code-block.tsx +129 -0
- package/src/components/docs/columns.tsx +45 -0
- package/src/components/docs/componentTextProps.ts +85 -0
- package/src/components/docs/dev-mode-badge.tsx +35 -0
- package/src/components/docs/doc-layout-wrapper.tsx +54 -0
- package/src/components/docs/doc-layout.tsx +111 -0
- package/src/components/docs/doc-loading.tsx +15 -0
- package/src/components/docs/doc-metadata.tsx +55 -0
- package/src/components/docs/doc-navigation.tsx +62 -0
- package/src/components/docs/doc-tags.tsx +25 -0
- package/src/components/docs/draft-badge.tsx +10 -0
- package/src/components/docs/footer.tsx +47 -0
- package/src/components/docs/frame.tsx +22 -0
- package/src/components/docs/header.tsx +122 -0
- package/src/components/docs/hot-reload-indicator.tsx +77 -0
- package/src/components/docs/icon.tsx +70 -0
- package/src/components/docs/image-card.tsx +95 -0
- package/src/components/docs/image.tsx +73 -0
- package/src/components/docs/index.ts +48 -0
- package/src/components/docs/math.tsx +46 -0
- package/src/components/docs/mdx-components.tsx +166 -0
- package/src/components/docs/mdx-hot-reload.tsx +37 -0
- package/src/components/docs/mermaid.tsx +77 -0
- package/src/components/docs/mobile-doc-layout.tsx +115 -0
- package/src/components/docs/not-found-content.tsx +55 -0
- package/src/components/docs/search-highlight.tsx +127 -0
- package/src/components/docs/search-modal.tsx +223 -0
- package/src/components/docs/sidebar-skeleton.tsx +39 -0
- package/src/components/docs/sidebar.tsx +323 -0
- package/src/components/docs/site-banner.tsx +92 -0
- package/src/components/docs/steps.tsx +29 -0
- package/src/components/docs/tab-context.tsx +28 -0
- package/src/components/docs/tab-groups.tsx +50 -0
- package/src/components/docs/table-of-contents.tsx +104 -0
- package/src/components/docs/tabs.tsx +63 -0
- package/src/components/docs/theme-toggle.tsx +39 -0
- package/src/components/docs/tooltip.tsx +37 -0
- package/src/components/docs/version-switcher.tsx +52 -0
- package/src/components/docs/video.tsx +80 -0
- package/src/components/global/index.ts +3 -0
- package/src/components/global/version-not-found.tsx +26 -0
- package/src/components/index.ts +8 -0
- package/src/components/theme-provider.tsx +11 -0
- package/src/components/ui/badge.tsx +46 -0
- package/src/components/ui/button.tsx +60 -0
- package/src/components/ui/dialog.tsx +143 -0
- package/src/components/ui/index.ts +6 -0
- package/src/components/ui/input.tsx +21 -0
- package/src/components/ui/textarea.tsx +18 -0
- package/src/index.ts +41 -0
- package/src/lib/api-parser.types.ts +78 -0
- package/src/lib/api.types.ts +202 -0
- package/src/lib/category.ts +71 -0
- package/src/lib/config.server.ts +170 -0
- package/src/lib/config.ts +20 -0
- package/src/lib/config.types.ts +295 -0
- package/src/lib/dev-utils.ts +75 -0
- package/src/lib/index.ts +27 -0
- package/src/lib/mdx-cache.ts +200 -0
- package/src/lib/mdx.ts +402 -0
- package/src/lib/parsers/base-parser.ts +16 -0
- package/src/lib/parsers/index.ts +69 -0
- package/src/lib/parsers/openapi-parser.ts +251 -0
- package/src/lib/parsers/postman-parser.ts +301 -0
- package/src/lib/parsers/specra-parser.ts +24 -0
- package/src/lib/redirects.ts +40 -0
- package/src/lib/remark-code-meta.ts +23 -0
- package/src/lib/sidebar-utils.ts +188 -0
- package/src/lib/toc.ts +24 -0
- package/src/lib/utils.ts +36 -0
- package/src/specra.config.json +124 -0
- package/src/styles/globals.css +427 -0
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import specraConfigJson from "../specra.config.json"
|
|
2
|
+
import { SpecraConfig, defaultConfig } from "./config.types"
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Deep merge two objects
|
|
6
|
+
*/
|
|
7
|
+
function deepMerge<T extends Record<string, any>>(target: T, source: Partial<T>): T {
|
|
8
|
+
const result = { ...target }
|
|
9
|
+
|
|
10
|
+
for (const key in source) {
|
|
11
|
+
const sourceValue = source[key]
|
|
12
|
+
const targetValue = result[key]
|
|
13
|
+
|
|
14
|
+
if (sourceValue && typeof sourceValue === "object" && !Array.isArray(sourceValue)) {
|
|
15
|
+
result[key] = deepMerge(
|
|
16
|
+
targetValue && typeof targetValue === "object" ? targetValue : {},
|
|
17
|
+
sourceValue,
|
|
18
|
+
) as T[Extract<keyof T, string>]
|
|
19
|
+
} else if (sourceValue !== undefined) {
|
|
20
|
+
result[key] = sourceValue as T[Extract<keyof T, string>]
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return result
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Load and parse the Specra configuration file
|
|
29
|
+
* Falls back to default configuration if file doesn't exist or is invalid
|
|
30
|
+
*/
|
|
31
|
+
export function loadConfig(userConfig: Partial<SpecraConfig>): SpecraConfig {
|
|
32
|
+
try {
|
|
33
|
+
// const userConfig = specraConfigJson as unknown as Partial<SpecraConfig>
|
|
34
|
+
|
|
35
|
+
// Merge user config with defaults
|
|
36
|
+
const config = deepMerge(defaultConfig, userConfig)
|
|
37
|
+
|
|
38
|
+
return config
|
|
39
|
+
} catch (error) {
|
|
40
|
+
console.error(`ā Error loading configuration:`, error)
|
|
41
|
+
console.warn("Using default configuration.")
|
|
42
|
+
return defaultConfig
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Get a specific configuration value by path (SERVER ONLY)
|
|
48
|
+
* Example: getConfigValue('site.title') or getConfigValue('theme.defaultMode')
|
|
49
|
+
*/
|
|
50
|
+
export function getConfigValue<T = any>(path: string, config?: SpecraConfig): T | undefined {
|
|
51
|
+
const cfg = config || loadConfig({})
|
|
52
|
+
const keys = path.split(".")
|
|
53
|
+
let value: any = cfg
|
|
54
|
+
|
|
55
|
+
for (const key of keys) {
|
|
56
|
+
if (value && typeof value === "object" && key in value) {
|
|
57
|
+
value = value[key]
|
|
58
|
+
} else {
|
|
59
|
+
return undefined
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return value as T
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Replace environment variables in a string (SERVER ONLY)
|
|
68
|
+
* Supports ${ENV_VAR} and {{ENV_VAR}} syntax
|
|
69
|
+
*/
|
|
70
|
+
export function replaceEnvVariables(text: string, config?: SpecraConfig): string {
|
|
71
|
+
const cfg = config || loadConfig({})
|
|
72
|
+
const envVars = cfg.env || {}
|
|
73
|
+
|
|
74
|
+
let result = text
|
|
75
|
+
|
|
76
|
+
// Replace ${VAR} syntax
|
|
77
|
+
result = result.replace(/\$\{([^}]+)\}/g, (match, varName) => {
|
|
78
|
+
return envVars[varName] || match
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
// Replace {{VAR}} syntax
|
|
82
|
+
result = result.replace(/\{\{([^}]+)\}\}/g, (match, varName) => {
|
|
83
|
+
return envVars[varName] || match
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
return result
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Process content and replace all environment variables (SERVER ONLY)
|
|
91
|
+
*/
|
|
92
|
+
export function processContentWithEnv(content: string, config?: SpecraConfig): string {
|
|
93
|
+
return replaceEnvVariables(content, config)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Validate configuration (basic validation) (SERVER ONLY)
|
|
98
|
+
*/
|
|
99
|
+
export function validateConfig(config: SpecraConfig): { valid: boolean; errors: string[] } {
|
|
100
|
+
const errors: string[] = []
|
|
101
|
+
|
|
102
|
+
// Required fields
|
|
103
|
+
if (!config.site?.title) {
|
|
104
|
+
errors.push("site.title is required")
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// URL validation
|
|
108
|
+
if (config.site?.url) {
|
|
109
|
+
try {
|
|
110
|
+
new URL(config.site.url)
|
|
111
|
+
} catch {
|
|
112
|
+
errors.push("site.url must be a valid URL")
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Social links validation
|
|
117
|
+
if (config.social) {
|
|
118
|
+
const socialKeys = ["github", "twitter", "discord", "linkedin", "youtube"] as const
|
|
119
|
+
for (const key of socialKeys) {
|
|
120
|
+
const url = config.social[key]
|
|
121
|
+
if (url) {
|
|
122
|
+
try {
|
|
123
|
+
new URL(url)
|
|
124
|
+
} catch {
|
|
125
|
+
errors.push(`social.${key} must be a valid URL`)
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return {
|
|
132
|
+
valid: errors.length === 0,
|
|
133
|
+
errors,
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Singleton instance
|
|
138
|
+
let configInstance: SpecraConfig | null = null
|
|
139
|
+
|
|
140
|
+
export function initConfig(userConfig: Partial<SpecraConfig>): SpecraConfig {
|
|
141
|
+
if (configInstance) {
|
|
142
|
+
throw new Error("Specra config has already been initialized")
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
configInstance = loadConfig(userConfig)
|
|
146
|
+
return configInstance
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Get the configuration instance (cached) (SERVER ONLY)
|
|
151
|
+
*/
|
|
152
|
+
export function getConfig(): SpecraConfig {
|
|
153
|
+
if (!configInstance) {
|
|
154
|
+
throw new Error("Specra config has not been initialized")
|
|
155
|
+
}
|
|
156
|
+
return configInstance
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Reload the configuration (useful for development) (SERVER ONLY)
|
|
161
|
+
*/
|
|
162
|
+
export function reloadConfig(userConfig: Partial<SpecraConfig>): SpecraConfig {
|
|
163
|
+
configInstance = loadConfig(userConfig)
|
|
164
|
+
return configInstance
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Export the loaded config as default (SERVER ONLY)
|
|
169
|
+
*/
|
|
170
|
+
// export default getConfig()
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client-safe config access
|
|
3
|
+
* This file re-exports server functions but is safe to import in client components
|
|
4
|
+
* The actual config loading happens on the server and is passed as props
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export { defaultConfig } from "./config.types"
|
|
8
|
+
export type { SpecraConfig } from "./config.types"
|
|
9
|
+
|
|
10
|
+
// For client components, config should be passed as props from server components
|
|
11
|
+
// These are re-exported for convenience but will only work on the server
|
|
12
|
+
export {
|
|
13
|
+
getConfig,
|
|
14
|
+
getConfigValue,
|
|
15
|
+
loadConfig,
|
|
16
|
+
processContentWithEnv,
|
|
17
|
+
replaceEnvVariables,
|
|
18
|
+
validateConfig,
|
|
19
|
+
reloadConfig,
|
|
20
|
+
} from "./config.server"
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration schema for Specra documentation system
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Site metadata and branding
|
|
7
|
+
*/
|
|
8
|
+
export interface SiteConfig {
|
|
9
|
+
/** The title of the documentation site */
|
|
10
|
+
title: string
|
|
11
|
+
/** Short description of the documentation */
|
|
12
|
+
description?: string
|
|
13
|
+
/** URL where the documentation is hosted */
|
|
14
|
+
url?: string
|
|
15
|
+
/** Base URL path for the documentation (e.g., '/docs') */
|
|
16
|
+
baseUrl?: string
|
|
17
|
+
/** Path to the site logo */
|
|
18
|
+
logo?: string
|
|
19
|
+
/** Path to the favicon */
|
|
20
|
+
favicon?: string
|
|
21
|
+
/** Default language for the documentation */
|
|
22
|
+
language?: string
|
|
23
|
+
/** Organization or author name */
|
|
24
|
+
organizationName?: string
|
|
25
|
+
/** Project name */
|
|
26
|
+
projectName?: string
|
|
27
|
+
/** Active/default version for the documentation */
|
|
28
|
+
activeVersion?: string
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Theme and appearance settings
|
|
33
|
+
*/
|
|
34
|
+
export interface ThemeConfig {
|
|
35
|
+
/** Primary color for the theme */
|
|
36
|
+
primaryColor?: string
|
|
37
|
+
/** Default theme mode */
|
|
38
|
+
defaultMode?: "light" | "dark" | "system"
|
|
39
|
+
/** Whether to respect system preferences */
|
|
40
|
+
respectPrefersColorScheme?: boolean
|
|
41
|
+
/** Custom CSS file path */
|
|
42
|
+
customCss?: string
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Tab group for organizing documentation
|
|
47
|
+
*/
|
|
48
|
+
export interface TabGroup {
|
|
49
|
+
/** Unique identifier for the tab group */
|
|
50
|
+
id: string
|
|
51
|
+
/** Display label for the tab */
|
|
52
|
+
label: string
|
|
53
|
+
/** Optional icon name (lucide-react icon) */
|
|
54
|
+
icon?: string
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Navigation and sidebar configuration
|
|
59
|
+
*/
|
|
60
|
+
export interface NavigationConfig {
|
|
61
|
+
/** Whether to show the sidebar by default */
|
|
62
|
+
showSidebar?: boolean
|
|
63
|
+
/** Whether the sidebar is collapsible */
|
|
64
|
+
collapsibleSidebar?: boolean
|
|
65
|
+
/** Whether to show breadcrumbs */
|
|
66
|
+
showBreadcrumbs?: boolean
|
|
67
|
+
/** Whether to show table of contents */
|
|
68
|
+
showTableOfContents?: boolean
|
|
69
|
+
/** Position of table of contents */
|
|
70
|
+
tocPosition?: "left" | "right"
|
|
71
|
+
/** Maximum depth for table of contents */
|
|
72
|
+
tocMaxDepth?: number
|
|
73
|
+
/** Tab groups for organizing documentation sections */
|
|
74
|
+
tabGroups?: TabGroup[]
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Social and external links
|
|
79
|
+
*/
|
|
80
|
+
export interface SocialLinks {
|
|
81
|
+
/** GitHub repository URL */
|
|
82
|
+
github?: string
|
|
83
|
+
/** Twitter/X handle or URL */
|
|
84
|
+
twitter?: string
|
|
85
|
+
/** Discord invite URL */
|
|
86
|
+
discord?: string
|
|
87
|
+
/** LinkedIn profile or company page */
|
|
88
|
+
linkedin?: string
|
|
89
|
+
/** YouTube channel URL */
|
|
90
|
+
youtube?: string
|
|
91
|
+
/** Custom social links */
|
|
92
|
+
custom?: Array<{
|
|
93
|
+
label: string
|
|
94
|
+
url: string
|
|
95
|
+
icon?: string
|
|
96
|
+
}>
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Search configuration
|
|
101
|
+
*/
|
|
102
|
+
export interface SearchConfig {
|
|
103
|
+
/** Enable/disable search functionality */
|
|
104
|
+
enabled?: boolean
|
|
105
|
+
/** Placeholder text for search input */
|
|
106
|
+
placeholder?: string
|
|
107
|
+
/** Search provider type */
|
|
108
|
+
provider?: "meilisearch" | "algolia" | "local"
|
|
109
|
+
/** Meilisearch configuration */
|
|
110
|
+
meilisearch?: {
|
|
111
|
+
/** Meilisearch server URL */
|
|
112
|
+
host: string
|
|
113
|
+
/** API key for Meilisearch */
|
|
114
|
+
apiKey?: string
|
|
115
|
+
/** Index name */
|
|
116
|
+
indexName: string
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Analytics configuration
|
|
122
|
+
*/
|
|
123
|
+
export interface AnalyticsConfig {
|
|
124
|
+
/** Google Analytics tracking ID */
|
|
125
|
+
googleAnalytics?: string
|
|
126
|
+
/** Google Tag Manager ID */
|
|
127
|
+
googleTagManager?: string
|
|
128
|
+
/** Plausible Analytics domain */
|
|
129
|
+
plausible?: string
|
|
130
|
+
/** Custom analytics scripts */
|
|
131
|
+
custom?: Array<{
|
|
132
|
+
src: string
|
|
133
|
+
async?: boolean
|
|
134
|
+
defer?: boolean
|
|
135
|
+
}>
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Footer configuration
|
|
140
|
+
*/
|
|
141
|
+
export interface FooterConfig {
|
|
142
|
+
/** Copyright text */
|
|
143
|
+
copyright?: string
|
|
144
|
+
/** Footer links organized by columns */
|
|
145
|
+
links?: Array<{
|
|
146
|
+
title: string
|
|
147
|
+
items: Array<{
|
|
148
|
+
label: string
|
|
149
|
+
href: string
|
|
150
|
+
}>
|
|
151
|
+
}>
|
|
152
|
+
/** Custom footer content */
|
|
153
|
+
customContent?: string
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Documentation features
|
|
158
|
+
*/
|
|
159
|
+
export interface FeaturesConfig {
|
|
160
|
+
/** Enable/disable edit this page links */
|
|
161
|
+
editUrl?: string | false
|
|
162
|
+
/** Show last updated timestamp */
|
|
163
|
+
showLastUpdated?: boolean
|
|
164
|
+
/** Show reading time estimate */
|
|
165
|
+
showReadingTime?: boolean
|
|
166
|
+
/** Show author information */
|
|
167
|
+
showAuthors?: boolean
|
|
168
|
+
/** Show tags */
|
|
169
|
+
showTags?: boolean
|
|
170
|
+
/** Enable version dropdown */
|
|
171
|
+
versioning?: boolean
|
|
172
|
+
/** Enable i18n (internationalization) */
|
|
173
|
+
i18n?: boolean
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Site-wide banner configuration
|
|
178
|
+
*/
|
|
179
|
+
export interface BannerConfig {
|
|
180
|
+
/** Whether the banner is enabled */
|
|
181
|
+
enabled?: boolean
|
|
182
|
+
/** Banner message */
|
|
183
|
+
message?: string
|
|
184
|
+
/** Banner type */
|
|
185
|
+
type?: "info" | "warning" | "success" | "error"
|
|
186
|
+
/** Whether the banner can be dismissed */
|
|
187
|
+
dismissible?: boolean
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Environment variables that can be used in documentation
|
|
192
|
+
* These will be replaced at build time or runtime
|
|
193
|
+
*/
|
|
194
|
+
export interface EnvironmentVariables {
|
|
195
|
+
/** API base URL */
|
|
196
|
+
API_BASE_URL?: string
|
|
197
|
+
/** API version */
|
|
198
|
+
API_VERSION?: string
|
|
199
|
+
/** CDN URL */
|
|
200
|
+
CDN_URL?: string
|
|
201
|
+
/** Custom environment variables */
|
|
202
|
+
[key: string]: string | undefined
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Deployment configuration for different hosting scenarios
|
|
207
|
+
*/
|
|
208
|
+
export interface DeploymentConfig {
|
|
209
|
+
/**
|
|
210
|
+
* Deployment target
|
|
211
|
+
* - 'vercel': For Vercel or similar Node.js hosting (uses 'standalone' output)
|
|
212
|
+
* - 'github-pages': For GitHub Pages static hosting (uses 'export' output)
|
|
213
|
+
* - 'static': For any static hosting like Netlify, Cloudflare Pages, etc.
|
|
214
|
+
* - 'custom-domain-static': For static hosting with custom domain (no basePath needed)
|
|
215
|
+
*/
|
|
216
|
+
target?: "vercel" | "github-pages" | "static" | "custom-domain-static"
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Base path for assets when deploying to GitHub Pages without custom domain
|
|
220
|
+
* This should be your repository name (e.g., 'my-repo')
|
|
221
|
+
* Only used when target is 'github-pages' and no custom domain is configured
|
|
222
|
+
*/
|
|
223
|
+
basePath?: string
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Whether a custom domain is configured
|
|
227
|
+
* When true, basePath will be ignored even for GitHub Pages
|
|
228
|
+
*/
|
|
229
|
+
customDomain?: boolean
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Main configuration interface
|
|
234
|
+
*/
|
|
235
|
+
export interface SpecraConfig {
|
|
236
|
+
/** Site metadata and branding */
|
|
237
|
+
site: SiteConfig
|
|
238
|
+
/** Theme and appearance settings */
|
|
239
|
+
theme?: ThemeConfig
|
|
240
|
+
/** Navigation and sidebar configuration */
|
|
241
|
+
navigation?: NavigationConfig
|
|
242
|
+
/** Social and external links */
|
|
243
|
+
social?: SocialLinks
|
|
244
|
+
/** Search configuration */
|
|
245
|
+
search?: SearchConfig
|
|
246
|
+
/** Analytics configuration */
|
|
247
|
+
analytics?: AnalyticsConfig
|
|
248
|
+
/** Footer configuration */
|
|
249
|
+
footer?: FooterConfig
|
|
250
|
+
/** Site-wide banner */
|
|
251
|
+
banner?: BannerConfig
|
|
252
|
+
/** Documentation features */
|
|
253
|
+
features?: FeaturesConfig
|
|
254
|
+
/** Environment variables for use in docs */
|
|
255
|
+
env?: EnvironmentVariables
|
|
256
|
+
/** Deployment configuration */
|
|
257
|
+
deployment?: DeploymentConfig
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Default configuration values
|
|
262
|
+
*/
|
|
263
|
+
export const defaultConfig: SpecraConfig = {
|
|
264
|
+
site: {
|
|
265
|
+
title: "Documentation",
|
|
266
|
+
description: "Project documentation",
|
|
267
|
+
baseUrl: "/",
|
|
268
|
+
language: "en",
|
|
269
|
+
},
|
|
270
|
+
theme: {
|
|
271
|
+
defaultMode: "system",
|
|
272
|
+
respectPrefersColorScheme: true,
|
|
273
|
+
},
|
|
274
|
+
navigation: {
|
|
275
|
+
showSidebar: true,
|
|
276
|
+
collapsibleSidebar: true,
|
|
277
|
+
showBreadcrumbs: true,
|
|
278
|
+
showTableOfContents: true,
|
|
279
|
+
tocPosition: "right",
|
|
280
|
+
tocMaxDepth: 3,
|
|
281
|
+
},
|
|
282
|
+
search: {
|
|
283
|
+
enabled: true,
|
|
284
|
+
provider: "local",
|
|
285
|
+
placeholder: "Search documentation...",
|
|
286
|
+
},
|
|
287
|
+
features: {
|
|
288
|
+
showLastUpdated: true,
|
|
289
|
+
showReadingTime: true,
|
|
290
|
+
showAuthors: false,
|
|
291
|
+
showTags: true,
|
|
292
|
+
versioning: true,
|
|
293
|
+
i18n: false,
|
|
294
|
+
},
|
|
295
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Development utilities for debugging and performance monitoring
|
|
3
|
+
* Only active in development mode
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const isDevelopment = process.env.NODE_ENV === 'development'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Performance timer for measuring operation duration
|
|
10
|
+
*/
|
|
11
|
+
export class PerfTimer {
|
|
12
|
+
private startTime: number
|
|
13
|
+
private label: string
|
|
14
|
+
|
|
15
|
+
constructor(label: string) {
|
|
16
|
+
this.label = label
|
|
17
|
+
this.startTime = isDevelopment ? performance.now() : 0
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
end() {
|
|
21
|
+
if (!isDevelopment) return
|
|
22
|
+
|
|
23
|
+
const duration = performance.now() - this.startTime
|
|
24
|
+
const color = duration > 1000 ? '\x1b[31m' : duration > 500 ? '\x1b[33m' : '\x1b[32m'
|
|
25
|
+
const reset = '\x1b[0m'
|
|
26
|
+
|
|
27
|
+
console.log(`${color}ā±ļø ${this.label}: ${duration.toFixed(2)}ms${reset}`)
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Log file system operations
|
|
33
|
+
*/
|
|
34
|
+
export function logFsOperation(operation: string, path: string, details?: any) {
|
|
35
|
+
if (!isDevelopment) return
|
|
36
|
+
|
|
37
|
+
console.log(`š [FS] ${operation}: ${path}`, details || '')
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Log cache operations
|
|
42
|
+
*/
|
|
43
|
+
export function logCacheOperation(operation: 'hit' | 'miss' | 'invalidate', key: string) {
|
|
44
|
+
if (!isDevelopment) return
|
|
45
|
+
|
|
46
|
+
const emoji = operation === 'hit' ? 'ā
' : operation === 'miss' ? 'ā' : 'š'
|
|
47
|
+
console.log(`${emoji} [Cache] ${operation}: ${key}`)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Memory usage reporter
|
|
52
|
+
*/
|
|
53
|
+
export function logMemoryUsage(label?: string) {
|
|
54
|
+
if (!isDevelopment) return
|
|
55
|
+
|
|
56
|
+
const used = process.memoryUsage()
|
|
57
|
+
const prefix = label ? `[${label}] ` : ''
|
|
58
|
+
|
|
59
|
+
console.log(`š¾ ${prefix}Memory Usage:`, {
|
|
60
|
+
rss: `${Math.round(used.rss / 1024 / 1024)}MB`,
|
|
61
|
+
heapTotal: `${Math.round(used.heapTotal / 1024 / 1024)}MB`,
|
|
62
|
+
heapUsed: `${Math.round(used.heapUsed / 1024 / 1024)}MB`,
|
|
63
|
+
})
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Pretty print object for debugging
|
|
68
|
+
*/
|
|
69
|
+
export function debugLog(label: string, data: any) {
|
|
70
|
+
if (!isDevelopment) return
|
|
71
|
+
|
|
72
|
+
console.log(`\nš ${label}:`)
|
|
73
|
+
console.dir(data, { depth: null, colors: true })
|
|
74
|
+
console.log('')
|
|
75
|
+
}
|
package/src/lib/index.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// MDX Processing
|
|
2
|
+
export * from './mdx'
|
|
3
|
+
export * from './mdx-cache'
|
|
4
|
+
export * from './toc'
|
|
5
|
+
|
|
6
|
+
// Configuration
|
|
7
|
+
export * from './config.server'
|
|
8
|
+
export * from './config'
|
|
9
|
+
export type * from './config.types'
|
|
10
|
+
|
|
11
|
+
// API Parsers
|
|
12
|
+
export * from './parsers'
|
|
13
|
+
export type * from './api.types'
|
|
14
|
+
export type {
|
|
15
|
+
ApiParam,
|
|
16
|
+
ApiHeader,
|
|
17
|
+
ApiResponse as SpecraApiResponse,
|
|
18
|
+
ApiEndpointSpec,
|
|
19
|
+
SpecraApiSpec
|
|
20
|
+
} from './api-parser.types'
|
|
21
|
+
|
|
22
|
+
// Utilities
|
|
23
|
+
export * from './utils'
|
|
24
|
+
export * from './sidebar-utils'
|
|
25
|
+
export * from './category'
|
|
26
|
+
export * from './redirects'
|
|
27
|
+
export * from './dev-utils'
|