Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
252 changes: 252 additions & 0 deletions bun.lock

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions packages/chronicle/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,15 @@
"fumadocs-core": "^16.4.9",
"fumadocs-mdx": "^14.2.6",
"lodash": "^4.17.23",
"mermaid": "^11.13.0",
"next": "16.1.6",
"react": "^19.0.0",
"react-device-detect": "^2.2.3",
"react-dom": "^19.0.0",
"remark-attr": "^0.11.1",
"remark-directive": "^4.0.0",
"slugify": "^1.6.6",
"unist-util-visit": "^5.1.0",
"yaml": "^2.8.2",
"zod": "^4.3.6"
}
Expand Down
5 changes: 4 additions & 1 deletion packages/chronicle/source.config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { defineDocs, defineConfig } from 'fumadocs-mdx/config'
import remarkDirective from 'remark-directive'
import { remarkDirectiveAdmonition } from 'fumadocs-core/mdx-plugins'
import { remarkDirectiveAdmonition, remarkMdxMermaid } from 'fumadocs-core/mdx-plugins'
import remarkUnusedDirectives from './src/lib/remark-unused-directives'

const contentDir = process.env.CHRONICLE_CONTENT_DIR || './content'

Expand Down Expand Up @@ -35,6 +36,8 @@ export default defineConfig({
},
},
],
remarkUnusedDirectives,
remarkMdxMermaid,
],
},
})
15 changes: 15 additions & 0 deletions packages/chronicle/src/app/[[...slug]]/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { loadConfig } from '@/lib/config'
import { buildPageTree } from '@/lib/source'
import { getTheme } from '@/themes/registry'

export default function DocsLayout({ children }: { children: React.ReactNode }) {
const config = loadConfig()
const tree = buildPageTree()
const { Layout, className } = getTheme(config.theme?.name)

return (
<Layout config={config} tree={tree} classNames={{ layout: className }}>
{children}
</Layout>
)
}
30 changes: 14 additions & 16 deletions packages/chronicle/src/app/[[...slug]]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,29 +26,27 @@ export default async function DocsPage({ params }: PageProps) {
notFound()
}

const { Layout, Page, className } = getTheme(config.theme?.name)
const { Page } = getTheme(config.theme?.name)

const data = page.data as PageData
const MDXBody = data.body

const tree = buildPageTree()

return (
<Layout config={config} tree={tree} classNames={{ layout: className }}>
<Page
page={{
slug: slug ?? [],
frontmatter: {
title: data.title,
description: data.description,
},
content: <MDXBody components={mdxComponents} />,
toc: data.toc ?? [],
}}
config={config}
tree={tree}
/>
</Layout>
<Page
page={{
slug: slug ?? [],
frontmatter: {
title: data.title,
description: data.description,
},
content: <MDXBody components={mdxComponents} />,
toc: data.toc ?? [],
}}
config={config}
tree={tree}
/>
)
}

Expand Down
4 changes: 4 additions & 0 deletions packages/chronicle/src/components/common/callout.module.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
.callout {
margin: var(--rs-space-5) 0;
}

.callout p:last-child {
margin-bottom: 0;
}
19 changes: 17 additions & 2 deletions packages/chronicle/src/components/mdx/code.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
border-radius: var(--rs-radius-2);
overflow: hidden;
margin: var(--rs-space-5) 0;
border: 1px solid var(--rs-color-border-base);
border: 1px solid var(--rs-color-border-base-primary);
}

.codeHeader {
padding: var(--rs-space-3) var(--rs-space-4);
background: var(--rs-color-background-base-secondary);
border-bottom: 1px solid var(--rs-color-border-base);
border-bottom: 1px solid var(--rs-color-border-base-primary);
font-size: var(--rs-font-size-mini);
color: var(--rs-color-text-base-secondary);
}
Expand All @@ -25,3 +25,18 @@
font-size: var(--rs-font-size-small);
line-height: 1.6;
}

.pre code span {
color: var(--shiki-light);
}

:global([data-theme=dark]) .pre code span {
color: var(--shiki-dark);
}

.inlineCode {
background: var(--rs-color-background-neutral-secondary);
padding: var(--rs-space-1) var(--rs-space-2);
border-radius: var(--rs-radius-1);
font-size: inherit;
}
7 changes: 7 additions & 0 deletions packages/chronicle/src/components/mdx/code.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ type PreProps = ComponentProps<'pre'> & {
title?: string
}

export function MdxCode({ children, className, ...props }: ComponentProps<'code'>) {
if (className || (typeof children === 'object')) {
return <code className={className} {...props}>{children}</code>
}
return <code className={styles.inlineCode} {...props}>{children}</code>
}

export function MdxPre({ children, title, className, ...props }: PreProps) {
return (
<div className={styles.codeBlock}>
Expand Down
37 changes: 37 additions & 0 deletions packages/chronicle/src/components/mdx/details.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
.details {
border: 1px solid var(--rs-color-border-base-primary);
border-radius: var(--rs-radius-2);
margin: var(--rs-space-5) 0;
}

.summary {
padding: var(--rs-space-4) var(--rs-space-5);
cursor: pointer;
font-weight: 500;
font-size: var(--rs-font-size-small);
color: var(--rs-color-text-base-primary);
background: var(--rs-color-background-base-secondary);
list-style: none;
display: flex;
align-items: center;
gap: var(--rs-space-3);
}

.summary::-webkit-details-marker {
display: none;
}

.summary::before {
content: '▶';
font-size: 10px;
transition: transform 0.2s ease;
color: var(--rs-color-text-base-secondary);
}

.details[open] > .summary::before {
transform: rotate(90deg);
}

.content {
padding: var(--rs-space-4) var(--rs-space-5);
}
18 changes: 18 additions & 0 deletions packages/chronicle/src/components/mdx/details.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import type { ComponentProps } from 'react'
import styles from './details.module.css'

export function MdxDetails({ children, className, ...props }: ComponentProps<'details'>) {
return (
<details className={`${styles.details} ${className ?? ''}`} {...props}>
{children}
</details>
)
}

export function MdxSummary({ children, className, ...props }: ComponentProps<'summary'>) {
return (
<summary className={`${styles.summary} ${className ?? ''}`} {...props}>
{children}
</summary>
)
}
10 changes: 9 additions & 1 deletion packages/chronicle/src/components/mdx/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@ import type { MDXComponents } from 'mdx/types'
import { Image } from './image'
import { Link } from './link'
import { MdxTable, MdxThead, MdxTbody, MdxTr, MdxTh, MdxTd } from './table'
import { MdxPre } from './code'
import { MdxPre, MdxCode } from './code'
import { MdxDetails, MdxSummary } from './details'
import { Mermaid } from './mermaid'
import { MdxParagraph } from './paragraph'
import { CalloutContainer, CalloutTitle, CalloutDescription, MdxBlockquote } from '@/components/common/callout'
import { Tabs } from '@raystack/apsara'

export const mdxComponents: MDXComponents = {
p: MdxParagraph,
img: Image,
a: Link,
table: MdxTable,
Expand All @@ -15,12 +19,16 @@ export const mdxComponents: MDXComponents = {
tr: MdxTr,
th: MdxTh,
td: MdxTd,
code: MdxCode,
pre: MdxPre,
details: MdxDetails,
summary: MdxSummary,
blockquote: MdxBlockquote,
Callout: CalloutContainer,
CalloutTitle,
CalloutDescription,
Tabs,
Mermaid,
}

export { Image } from './image'
Expand Down
9 changes: 9 additions & 0 deletions packages/chronicle/src/components/mdx/mermaid.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.mermaid {
margin: var(--rs-space-5) 0;
overflow-x: auto;
}

.mermaid svg {
max-width: 100%;
height: auto;
}
37 changes: 37 additions & 0 deletions packages/chronicle/src/components/mdx/mermaid.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
'use client'

import { useEffect, useId, useState } from 'react'
import styles from './mermaid.module.css'

interface MermaidProps {
chart: string
}

export function Mermaid({ chart }: MermaidProps) {
const mermaidId = useId().replace(/:/g, '-')
const [svg, setSvg] = useState<string>('')

useEffect(() => {
let cancelled = false

async function render() {
const { default: mermaid } = await import('mermaid')
mermaid.initialize({ startOnLoad: false, theme: 'default' })
const { svg: rendered } = await mermaid.render(
mermaidId,
chart
)
if (!cancelled) setSvg(rendered)
}

render()
return () => { cancelled = true }
}, [chart])

return (
<div
className={styles.mermaid}
dangerouslySetInnerHTML={{ __html: svg }}
/>
)
}
8 changes: 8 additions & 0 deletions packages/chronicle/src/components/mdx/paragraph.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.paragraph {
font-size: var(--rs-font-size-regular);
margin-bottom: var(--rs-space-5);
}

.paragraph :global(a) {
font-size: inherit;
}
19 changes: 19 additions & 0 deletions packages/chronicle/src/components/mdx/paragraph.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Children, isValidElement, type ComponentProps } from 'react'
import styles from './paragraph.module.css'

const BLOCK_ELEMENTS = new Set(['summary', 'details', 'div', 'table', 'ul', 'ol'])

function hasBlockChild(children: React.ReactNode): boolean {
return Children.toArray(children).some(
(child) => isValidElement(child) && typeof child.type === 'string' && BLOCK_ELEMENTS.has(child.type)
)
}

export function MdxParagraph({ children, className, ...props }: ComponentProps<'p'>) {
const Tag = hasBlockChild(children) ? 'div' : 'p'
return (
<Tag className={`${styles.paragraph} ${className ?? ''}`} {...props}>
{children}
</Tag>
)
}
7 changes: 0 additions & 7 deletions packages/chronicle/src/components/ui/search.module.css
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
.trigger {
display: flex;
align-items: center;
gap: 8px;
padding: 6px 12px;
border-radius: 6px;
border: 1px solid var(--rs-color-border-base-primary);
background: transparent;
color: var(--rs-color-foreground-base-secondary);
font-size: 14px;
cursor: pointer;
}

Expand Down
3 changes: 2 additions & 1 deletion packages/chronicle/src/components/ui/search.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,12 @@ export function Search({ className }: SearchProps) {
<Button
variant="outline"
color="neutral"
size="small"
onClick={() => setOpen(true)}
className={cx(styles.trigger, className)}
trailingIcon={<SearchShortcutKey className={styles.kbd} />}
>
<Text>Search...</Text>
Search...
</Button>

<Dialog open={open} onOpenChange={setOpen}>
Expand Down
31 changes: 31 additions & 0 deletions packages/chronicle/src/lib/remark-unused-directives.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { visit } from 'unist-util-visit'
import type { Plugin } from 'unified'
import type { Node } from 'unist'

interface DirectiveNode extends Node {
name?: string
attributes?: Record<string, string>
children?: Node[]
data?: unknown
[key: string]: unknown
}

const remarkUnusedDirectives: Plugin = () => {
return (tree) => {
visit(tree, ['textDirective'], (node: DirectiveNode) => {
if (!node.data) {
const hasAttributes = node.attributes && Object.keys(node.attributes).length > 0
const hasChildren = node.children && node.children.length > 0
if (!hasAttributes && !hasChildren) {
const name = node.name
if (!name) return
Object.keys(node).forEach((key) => delete node[key])
node.type = 'text'
node.value = `:${name}`
}
}
})
}
}

export default remarkUnusedDirectives
Loading