@raystack/chronicle 0.1.0-canary.e11f924
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/bin/chronicle.js +2 -0
- package/dist/cli/index.js +9788 -0
- package/next.config.mjs +10 -0
- package/package.json +62 -0
- package/source.config.ts +50 -0
- package/src/app/[[...slug]]/layout.tsx +15 -0
- package/src/app/[[...slug]]/page.tsx +57 -0
- package/src/app/api/apis-proxy/route.ts +59 -0
- package/src/app/api/health/route.ts +3 -0
- package/src/app/api/search/route.ts +90 -0
- package/src/app/apis/[[...slug]]/layout.module.css +22 -0
- package/src/app/apis/[[...slug]]/layout.tsx +26 -0
- package/src/app/apis/[[...slug]]/page.tsx +57 -0
- package/src/app/layout.tsx +26 -0
- package/src/app/llms-full.txt/route.ts +18 -0
- package/src/app/llms.txt/route.ts +15 -0
- package/src/app/providers.tsx +8 -0
- package/src/cli/commands/build.ts +33 -0
- package/src/cli/commands/dev.ts +34 -0
- package/src/cli/commands/init.ts +58 -0
- package/src/cli/commands/serve.ts +54 -0
- package/src/cli/commands/start.ts +34 -0
- package/src/cli/index.ts +21 -0
- package/src/cli/utils/config.ts +43 -0
- package/src/cli/utils/index.ts +2 -0
- package/src/cli/utils/process.ts +7 -0
- package/src/components/api/code-snippets.module.css +7 -0
- package/src/components/api/code-snippets.tsx +76 -0
- package/src/components/api/endpoint-page.module.css +58 -0
- package/src/components/api/endpoint-page.tsx +283 -0
- package/src/components/api/field-row.module.css +126 -0
- package/src/components/api/field-row.tsx +204 -0
- package/src/components/api/field-section.module.css +24 -0
- package/src/components/api/field-section.tsx +100 -0
- package/src/components/api/index.ts +8 -0
- package/src/components/api/json-editor.module.css +9 -0
- package/src/components/api/json-editor.tsx +61 -0
- package/src/components/api/key-value-editor.module.css +13 -0
- package/src/components/api/key-value-editor.tsx +62 -0
- package/src/components/api/method-badge.module.css +4 -0
- package/src/components/api/method-badge.tsx +29 -0
- package/src/components/api/response-panel.module.css +8 -0
- package/src/components/api/response-panel.tsx +44 -0
- package/src/components/common/breadcrumb.tsx +3 -0
- package/src/components/common/button.tsx +3 -0
- package/src/components/common/callout.module.css +7 -0
- package/src/components/common/callout.tsx +27 -0
- package/src/components/common/code-block.tsx +3 -0
- package/src/components/common/dialog.tsx +3 -0
- package/src/components/common/index.ts +10 -0
- package/src/components/common/input-field.tsx +3 -0
- package/src/components/common/sidebar.tsx +3 -0
- package/src/components/common/switch.tsx +3 -0
- package/src/components/common/table.tsx +3 -0
- package/src/components/common/tabs.tsx +3 -0
- package/src/components/mdx/code.module.css +42 -0
- package/src/components/mdx/code.tsx +27 -0
- package/src/components/mdx/details.module.css +37 -0
- package/src/components/mdx/details.tsx +18 -0
- package/src/components/mdx/image.tsx +38 -0
- package/src/components/mdx/index.tsx +35 -0
- package/src/components/mdx/link.tsx +38 -0
- package/src/components/mdx/mermaid.module.css +9 -0
- package/src/components/mdx/mermaid.tsx +37 -0
- package/src/components/mdx/paragraph.module.css +8 -0
- package/src/components/mdx/paragraph.tsx +19 -0
- package/src/components/mdx/table.tsx +40 -0
- package/src/components/ui/breadcrumbs.tsx +72 -0
- package/src/components/ui/client-theme-switcher.tsx +18 -0
- package/src/components/ui/footer.module.css +27 -0
- package/src/components/ui/footer.tsx +30 -0
- package/src/components/ui/search.module.css +104 -0
- package/src/components/ui/search.tsx +202 -0
- package/src/lib/api-routes.ts +120 -0
- package/src/lib/config.ts +47 -0
- package/src/lib/get-llm-text.ts +10 -0
- package/src/lib/index.ts +2 -0
- package/src/lib/openapi.ts +188 -0
- package/src/lib/remark-unused-directives.ts +30 -0
- package/src/lib/schema.ts +99 -0
- package/src/lib/snippet-generators.ts +87 -0
- package/src/lib/source.ts +67 -0
- package/src/themes/default/Layout.module.css +81 -0
- package/src/themes/default/Layout.tsx +133 -0
- package/src/themes/default/Page.module.css +46 -0
- package/src/themes/default/Page.tsx +21 -0
- package/src/themes/default/Toc.module.css +48 -0
- package/src/themes/default/Toc.tsx +66 -0
- package/src/themes/default/font.ts +6 -0
- package/src/themes/default/index.ts +13 -0
- package/src/themes/paper/ChapterNav.module.css +71 -0
- package/src/themes/paper/ChapterNav.tsx +96 -0
- package/src/themes/paper/Layout.module.css +33 -0
- package/src/themes/paper/Layout.tsx +25 -0
- package/src/themes/paper/Page.module.css +174 -0
- package/src/themes/paper/Page.tsx +107 -0
- package/src/themes/paper/ReadingProgress.module.css +132 -0
- package/src/themes/paper/ReadingProgress.tsx +294 -0
- package/src/themes/paper/index.ts +8 -0
- package/src/themes/registry.ts +14 -0
- package/src/types/config.ts +69 -0
- package/src/types/content.ts +35 -0
- package/src/types/index.ts +3 -0
- package/src/types/theme.ts +22 -0
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import { cx } from 'class-variance-authority'
|
|
4
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
|
5
|
+
import type { TocItem } from '@/types'
|
|
6
|
+
import styles from './ReadingProgress.module.css'
|
|
7
|
+
|
|
8
|
+
interface Heading {
|
|
9
|
+
title: string
|
|
10
|
+
level: number
|
|
11
|
+
id: string
|
|
12
|
+
url: string
|
|
13
|
+
yPosition: number
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const ARTICLE_SELECTOR = '[data-article-content]'
|
|
17
|
+
const TICK_HEIGHT = 20
|
|
18
|
+
const NAV_HEIGHT = 60
|
|
19
|
+
|
|
20
|
+
function calculateTickBounds(containerHeight: number) {
|
|
21
|
+
const numTicks = Math.floor(containerHeight / TICK_HEIGHT) + 1
|
|
22
|
+
const maxPosition = (numTicks - 1) * TICK_HEIGHT
|
|
23
|
+
return { numTicks, maxPosition }
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function snapToTick(value: number, maxPosition: number): number {
|
|
27
|
+
const snapped = Math.round(value / TICK_HEIGHT) * TICK_HEIGHT
|
|
28
|
+
return Math.max(0, Math.min(snapped, maxPosition))
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function resolveOverlaps(headings: Heading[], maxPosition: number): Heading[] {
|
|
32
|
+
if (headings.length <= 1) return headings
|
|
33
|
+
|
|
34
|
+
const resolved: Heading[] = []
|
|
35
|
+
let lastUsedPos = -TICK_HEIGHT
|
|
36
|
+
|
|
37
|
+
for (const heading of headings) {
|
|
38
|
+
let newPos = heading.yPosition
|
|
39
|
+
if (newPos <= lastUsedPos) {
|
|
40
|
+
newPos = lastUsedPos + TICK_HEIGHT
|
|
41
|
+
}
|
|
42
|
+
resolved.push({ ...heading, yPosition: newPos })
|
|
43
|
+
lastUsedPos = newPos
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Backward pass: clamp-and-shift to prevent overlapping positions
|
|
47
|
+
for (let i = resolved.length - 1; i >= 0; i--) {
|
|
48
|
+
const maxAllowed =
|
|
49
|
+
i === resolved.length - 1
|
|
50
|
+
? maxPosition
|
|
51
|
+
: resolved[i + 1].yPosition - TICK_HEIGHT
|
|
52
|
+
|
|
53
|
+
const clampedPos = Math.max(0, maxAllowed)
|
|
54
|
+
if (resolved[i].yPosition > clampedPos) {
|
|
55
|
+
resolved[i] = { ...resolved[i], yPosition: clampedPos }
|
|
56
|
+
for (let j = i - 1; j >= 0; j--) {
|
|
57
|
+
const upperBound = resolved[j + 1].yPosition - TICK_HEIGHT
|
|
58
|
+
if (resolved[j].yPosition > upperBound) {
|
|
59
|
+
resolved[j] = { ...resolved[j], yPosition: Math.max(0, upperBound) }
|
|
60
|
+
} else {
|
|
61
|
+
break
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return resolved
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
interface ReadingProgressProps {
|
|
71
|
+
items: TocItem[]
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function ReadingProgress({ items }: ReadingProgressProps) {
|
|
75
|
+
const [headings, setHeadings] = useState<Heading[]>([])
|
|
76
|
+
const [containerHeight, setContainerHeight] = useState<number>(0)
|
|
77
|
+
const [ready, setReady] = useState<boolean>(false)
|
|
78
|
+
const [isScrollable, setIsScrollable] = useState<boolean>(true)
|
|
79
|
+
const containerRef = useRef<HTMLDivElement>(null)
|
|
80
|
+
const scrollMarkerRef = useRef<HTMLDivElement>(null)
|
|
81
|
+
const scrollPosRef = useRef<number>(0)
|
|
82
|
+
|
|
83
|
+
const { numTicks, maxPosition } = useMemo(
|
|
84
|
+
() => calculateTickBounds(containerHeight),
|
|
85
|
+
[containerHeight]
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
const recalcHeadings = useCallback(() => {
|
|
89
|
+
const article = document.querySelector(ARTICLE_SELECTOR)
|
|
90
|
+
const container = containerRef.current
|
|
91
|
+
if (!article || !container || !items.length) return
|
|
92
|
+
|
|
93
|
+
const articleBox = article.getBoundingClientRect()
|
|
94
|
+
const containerBox = container.getBoundingClientRect()
|
|
95
|
+
const articleTop = articleBox.top + window.scrollY
|
|
96
|
+
|
|
97
|
+
const hasScroll = articleBox.height > window.innerHeight
|
|
98
|
+
setIsScrollable(hasScroll)
|
|
99
|
+
setContainerHeight(containerBox.height)
|
|
100
|
+
|
|
101
|
+
const { maxPosition: maxPos } = calculateTickBounds(containerBox.height)
|
|
102
|
+
|
|
103
|
+
const mapped = items
|
|
104
|
+
.map((tocItem) => {
|
|
105
|
+
const id = tocItem.url.startsWith('#') ? tocItem.url.slice(1) : tocItem.url
|
|
106
|
+
const node = document.getElementById(id)
|
|
107
|
+
if (!node) return null
|
|
108
|
+
|
|
109
|
+
const { top } = node.getBoundingClientRect()
|
|
110
|
+
const headingPosInArticle = top + window.scrollY - articleTop
|
|
111
|
+
const progress = headingPosInArticle / articleBox.height
|
|
112
|
+
const rawY = progress * maxPos
|
|
113
|
+
const yPos = snapToTick(rawY, maxPos)
|
|
114
|
+
|
|
115
|
+
return {
|
|
116
|
+
title: tocItem.title,
|
|
117
|
+
level: tocItem.depth,
|
|
118
|
+
id,
|
|
119
|
+
url: tocItem.url,
|
|
120
|
+
yPosition: yPos,
|
|
121
|
+
}
|
|
122
|
+
})
|
|
123
|
+
.filter((item): item is Heading => item !== null)
|
|
124
|
+
|
|
125
|
+
const resolvedItems = resolveOverlaps(mapped, maxPos)
|
|
126
|
+
setHeadings(resolvedItems)
|
|
127
|
+
}, [items])
|
|
128
|
+
|
|
129
|
+
// Imperative DOM updates to avoid React re-render on every scroll event
|
|
130
|
+
const handleScroll = useCallback(() => {
|
|
131
|
+
const article = document.querySelector(ARTICLE_SELECTOR)
|
|
132
|
+
const container = containerRef.current
|
|
133
|
+
const scrollMarker = scrollMarkerRef.current
|
|
134
|
+
if (!article || !container || !scrollMarker) return
|
|
135
|
+
|
|
136
|
+
const { top, height } = article.getBoundingClientRect()
|
|
137
|
+
const { height: cHeight } = container.getBoundingClientRect()
|
|
138
|
+
const viewportHeight = window.innerHeight
|
|
139
|
+
const { maxPosition: maxPos } = calculateTickBounds(cHeight)
|
|
140
|
+
|
|
141
|
+
let newScrollPos: number
|
|
142
|
+
if (top > 0) {
|
|
143
|
+
newScrollPos = 0
|
|
144
|
+
} else {
|
|
145
|
+
const scrolled = Math.abs(top)
|
|
146
|
+
const scrollRange = height - viewportHeight
|
|
147
|
+
const progress = scrollRange > 0 ? Math.min(1, scrolled / scrollRange) : 0
|
|
148
|
+
const rawPos = progress * maxPos
|
|
149
|
+
newScrollPos = snapToTick(rawPos, maxPos)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const prevScrollPos = scrollPosRef.current
|
|
153
|
+
if (newScrollPos !== prevScrollPos) {
|
|
154
|
+
scrollPosRef.current = newScrollPos
|
|
155
|
+
scrollMarker.style.top = `${newScrollPos}px`
|
|
156
|
+
|
|
157
|
+
const textEl = scrollMarker.querySelector('[data-scroll-text]')
|
|
158
|
+
if (textEl) {
|
|
159
|
+
textEl.textContent = (maxPos > 0 ? newScrollPos / maxPos : 0).toFixed(2)
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const tickLines = container.querySelectorAll('[data-tick-line]')
|
|
163
|
+
tickLines.forEach((tick) => {
|
|
164
|
+
const tickPos = Number(tick.getAttribute('data-tick-pos'))
|
|
165
|
+
if (tickPos < newScrollPos) {
|
|
166
|
+
tick.classList.remove(styles.tickLineAfter)
|
|
167
|
+
tick.classList.add(styles.tickLineBefore)
|
|
168
|
+
} else {
|
|
169
|
+
tick.classList.remove(styles.tickLineBefore)
|
|
170
|
+
tick.classList.add(styles.tickLineAfter)
|
|
171
|
+
}
|
|
172
|
+
})
|
|
173
|
+
}
|
|
174
|
+
}, [])
|
|
175
|
+
|
|
176
|
+
useEffect(() => {
|
|
177
|
+
recalcHeadings()
|
|
178
|
+
handleScroll()
|
|
179
|
+
setReady(true)
|
|
180
|
+
|
|
181
|
+
const article = document.querySelector(ARTICLE_SELECTOR)
|
|
182
|
+
let ro: ResizeObserver | undefined
|
|
183
|
+
if (article) {
|
|
184
|
+
ro = new ResizeObserver(() => {
|
|
185
|
+
recalcHeadings()
|
|
186
|
+
handleScroll()
|
|
187
|
+
})
|
|
188
|
+
ro.observe(article)
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
window.addEventListener('resize', recalcHeadings)
|
|
192
|
+
window.addEventListener('scroll', handleScroll, { passive: true })
|
|
193
|
+
|
|
194
|
+
return () => {
|
|
195
|
+
ro?.disconnect()
|
|
196
|
+
window.removeEventListener('resize', recalcHeadings)
|
|
197
|
+
window.removeEventListener('scroll', handleScroll)
|
|
198
|
+
}
|
|
199
|
+
}, [recalcHeadings, handleScroll])
|
|
200
|
+
|
|
201
|
+
const scrollToTick = (y: number): void => {
|
|
202
|
+
const article = document.querySelector(ARTICLE_SELECTOR)
|
|
203
|
+
if (!article || maxPosition === 0) return
|
|
204
|
+
|
|
205
|
+
const articleBox = article.getBoundingClientRect()
|
|
206
|
+
const articleTop = articleBox.top + window.scrollY
|
|
207
|
+
const progress = y / maxPosition
|
|
208
|
+
const articlePos = progress * articleBox.height
|
|
209
|
+
const targetScroll = articleTop + articlePos - NAV_HEIGHT
|
|
210
|
+
|
|
211
|
+
window.scrollTo({ top: Math.max(0, targetScroll), behavior: 'smooth' })
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const scrollToHeading = (id: string): void => {
|
|
215
|
+
const element = document.getElementById(id)
|
|
216
|
+
if (!element) return
|
|
217
|
+
|
|
218
|
+
const elementTop = element.getBoundingClientRect().top + window.scrollY
|
|
219
|
+
window.scrollTo({ top: Math.max(0, elementTop - NAV_HEIGHT), behavior: 'smooth' })
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const ticks = useMemo(
|
|
223
|
+
() => Array.from({ length: numTicks }, (_, i) => i * TICK_HEIGHT),
|
|
224
|
+
[numTicks]
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
if (!isScrollable || ticks.length < 2) {
|
|
228
|
+
return <div ref={containerRef} className={styles.container} />
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
return (
|
|
232
|
+
<div ref={containerRef} className={styles.container}>
|
|
233
|
+
<div className={styles.inner}>
|
|
234
|
+
{ticks.map((y, i) => (
|
|
235
|
+
<div key={`tick-${i}`} style={{ top: `${y}px` }} className={styles.tickContainer}>
|
|
236
|
+
<div data-tick-line data-tick-pos={y} className={cx(styles.tickLine, styles.tickLineAfter)} />
|
|
237
|
+
<div className={styles.tickClickable} onClick={() => scrollToTick(y)} />
|
|
238
|
+
</div>
|
|
239
|
+
))}
|
|
240
|
+
|
|
241
|
+
{headings.map((h, i) => (
|
|
242
|
+
<div key={h.id || i} className={styles.headingContainer}>
|
|
243
|
+
<div
|
|
244
|
+
className={styles.headingLabel}
|
|
245
|
+
style={{
|
|
246
|
+
top: `${h.yPosition - 6}px`,
|
|
247
|
+
right: '24px',
|
|
248
|
+
zIndex: h.level < 4 ? 10 : 0,
|
|
249
|
+
transitionDelay: `${50 * i}ms`,
|
|
250
|
+
}}
|
|
251
|
+
>
|
|
252
|
+
<a
|
|
253
|
+
href={h.url}
|
|
254
|
+
className={styles.headingLink}
|
|
255
|
+
onClick={(e) => {
|
|
256
|
+
e.preventDefault()
|
|
257
|
+
e.stopPropagation()
|
|
258
|
+
scrollToHeading(h.id)
|
|
259
|
+
}}
|
|
260
|
+
>
|
|
261
|
+
{h.title}
|
|
262
|
+
</a>
|
|
263
|
+
</div>
|
|
264
|
+
</div>
|
|
265
|
+
))}
|
|
266
|
+
|
|
267
|
+
{headings.map((h, i) => (
|
|
268
|
+
<div
|
|
269
|
+
key={`line-${i}`}
|
|
270
|
+
className={styles.connectingLine}
|
|
271
|
+
style={{
|
|
272
|
+
top: `${h.yPosition}px`,
|
|
273
|
+
width: `${Math.max(4, (3 - h.level) * 4 + 12)}px`,
|
|
274
|
+
}}
|
|
275
|
+
/>
|
|
276
|
+
))}
|
|
277
|
+
|
|
278
|
+
<div
|
|
279
|
+
ref={scrollMarkerRef}
|
|
280
|
+
className={cx(
|
|
281
|
+
styles.scrollMarkerContainer,
|
|
282
|
+
ready ? styles.scrollMarkerContainerReady : styles.scrollMarkerContainerNotReady
|
|
283
|
+
)}
|
|
284
|
+
style={{ top: '0px' }}
|
|
285
|
+
>
|
|
286
|
+
<div className={styles.scrollMarkerLine} />
|
|
287
|
+
<span data-scroll-text className={styles.scrollMarkerText}>
|
|
288
|
+
0.00
|
|
289
|
+
</span>
|
|
290
|
+
</div>
|
|
291
|
+
</div>
|
|
292
|
+
</div>
|
|
293
|
+
)
|
|
294
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Theme } from '@/types'
|
|
2
|
+
import { defaultTheme } from './default'
|
|
3
|
+
import { paperTheme } from './paper'
|
|
4
|
+
|
|
5
|
+
const themes: Record<string, Theme> = {
|
|
6
|
+
default: defaultTheme,
|
|
7
|
+
paper: paperTheme,
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function getTheme(name?: string): Theme {
|
|
11
|
+
if (!name || !themes[name]) return defaultTheme
|
|
12
|
+
|
|
13
|
+
return themes[name]
|
|
14
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
export interface ChronicleConfig {
|
|
2
|
+
title: string
|
|
3
|
+
description?: string
|
|
4
|
+
logo?: LogoConfig
|
|
5
|
+
theme?: ThemeConfig
|
|
6
|
+
navigation?: NavigationConfig
|
|
7
|
+
search?: SearchConfig
|
|
8
|
+
footer?: FooterConfig
|
|
9
|
+
api?: ApiConfig[]
|
|
10
|
+
llms?: LlmsConfig
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface LlmsConfig {
|
|
14
|
+
enabled?: boolean
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface ApiConfig {
|
|
18
|
+
name: string
|
|
19
|
+
spec: string
|
|
20
|
+
basePath: string
|
|
21
|
+
server: ApiServerConfig
|
|
22
|
+
auth?: ApiAuthConfig
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface ApiServerConfig {
|
|
26
|
+
url: string
|
|
27
|
+
description?: string
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface ApiAuthConfig {
|
|
31
|
+
type: string
|
|
32
|
+
header: string
|
|
33
|
+
placeholder?: string
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface LogoConfig {
|
|
37
|
+
light?: string
|
|
38
|
+
dark?: string
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface ThemeConfig {
|
|
42
|
+
name: 'default' | 'paper'
|
|
43
|
+
colors?: Record<string, string>
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface NavigationConfig {
|
|
47
|
+
links?: NavLink[]
|
|
48
|
+
social?: SocialLink[]
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface NavLink {
|
|
52
|
+
label: string
|
|
53
|
+
href: string
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface SocialLink {
|
|
57
|
+
type: 'github' | 'twitter' | 'discord' | string
|
|
58
|
+
href: string
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface SearchConfig {
|
|
62
|
+
enabled?: boolean
|
|
63
|
+
placeholder?: string
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export interface FooterConfig {
|
|
67
|
+
copyright?: string
|
|
68
|
+
links?: NavLink[]
|
|
69
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { ReactNode } from 'react'
|
|
2
|
+
|
|
3
|
+
export interface Frontmatter {
|
|
4
|
+
title: string
|
|
5
|
+
description?: string
|
|
6
|
+
order?: number
|
|
7
|
+
icon?: string
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface Page {
|
|
11
|
+
slug: string[]
|
|
12
|
+
frontmatter: Frontmatter
|
|
13
|
+
content: ReactNode
|
|
14
|
+
toc: TocItem[]
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface TocItem {
|
|
18
|
+
title: string
|
|
19
|
+
url: string
|
|
20
|
+
depth: number
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface PageTreeItem {
|
|
24
|
+
type: 'page' | 'folder' | 'separator'
|
|
25
|
+
name: string
|
|
26
|
+
url?: string
|
|
27
|
+
order?: number
|
|
28
|
+
icon?: string
|
|
29
|
+
children?: PageTreeItem[]
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface PageTree {
|
|
33
|
+
name: string
|
|
34
|
+
children: PageTreeItem[]
|
|
35
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ReactNode } from 'react'
|
|
2
|
+
import type { ChronicleConfig } from './config'
|
|
3
|
+
import type { Page, PageTree } from './content'
|
|
4
|
+
|
|
5
|
+
export interface ThemeLayoutProps {
|
|
6
|
+
children: ReactNode
|
|
7
|
+
config: ChronicleConfig
|
|
8
|
+
tree: PageTree
|
|
9
|
+
classNames?: { layout?: string; body?: string; sidebar?: string; content?: string }
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface ThemePageProps {
|
|
13
|
+
page: Page
|
|
14
|
+
config: ChronicleConfig
|
|
15
|
+
tree: PageTree
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface Theme {
|
|
19
|
+
Layout: React.ComponentType<ThemeLayoutProps>
|
|
20
|
+
Page: React.ComponentType<ThemePageProps>
|
|
21
|
+
className?: string
|
|
22
|
+
}
|