@raystack/chronicle 0.7.3 → 0.7.4
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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@raystack/chronicle",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.4",
|
|
4
4
|
"description": "Config-driven documentation framework",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
"@opentelemetry/resources": "^2.6.1",
|
|
47
47
|
"@opentelemetry/sdk-metrics": "^2.6.1",
|
|
48
48
|
"@opentelemetry/semantic-conventions": "^1.40.0",
|
|
49
|
+
"@radix-ui/react-icons": "^1.3.2",
|
|
49
50
|
"@raystack/apsara": "1.0.0-rc.4",
|
|
50
51
|
"@shikijs/rehype": "^4.0.2",
|
|
51
52
|
"@vitejs/plugin-react": "^6.0.1",
|
package/src/lib/source.ts
CHANGED
|
@@ -97,6 +97,8 @@ function buildSyntheticMeta(): {
|
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
let cachedSource: ReturnType<typeof loader> | null = null;
|
|
100
|
+
let cachedTree: Root | null = null;
|
|
101
|
+
let cachedNavMap: Map<string, PageNav> | null = null;
|
|
100
102
|
|
|
101
103
|
async function getSource() {
|
|
102
104
|
if (cachedSource) return cachedSource;
|
|
@@ -112,6 +114,8 @@ export { getSource as source };
|
|
|
112
114
|
|
|
113
115
|
export function invalidate() {
|
|
114
116
|
cachedSource = null;
|
|
117
|
+
cachedTree = null;
|
|
118
|
+
cachedNavMap = null;
|
|
115
119
|
}
|
|
116
120
|
|
|
117
121
|
function getOrder(node: Node, orderMap: Map<string, number>): number | undefined {
|
|
@@ -146,8 +150,10 @@ function sortTreeByOrder(tree: Root, pages: { url: string; data: unknown }[]): R
|
|
|
146
150
|
}
|
|
147
151
|
|
|
148
152
|
export async function getPageTree(): Promise<Root> {
|
|
153
|
+
if (cachedTree) return cachedTree;
|
|
149
154
|
const s = await getSource();
|
|
150
|
-
|
|
155
|
+
cachedTree = sortTreeByOrder(s.pageTree as Root, s.getPages());
|
|
156
|
+
return cachedTree;
|
|
151
157
|
}
|
|
152
158
|
|
|
153
159
|
export async function getPages() {
|
|
@@ -186,12 +192,10 @@ function titleFromUrl(url: string): string {
|
|
|
186
192
|
.join(' ');
|
|
187
193
|
}
|
|
188
194
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
const
|
|
192
|
-
const
|
|
193
|
-
const i = pages.findIndex(p => p.url === url);
|
|
194
|
-
if (i < 0) return { prev: null, next: null };
|
|
195
|
+
async function getNavMap(): Promise<Map<string, PageNav>> {
|
|
196
|
+
if (cachedNavMap) return cachedNavMap;
|
|
197
|
+
const tree = await getPageTree();
|
|
198
|
+
const pages = flattenTree(tree.children);
|
|
195
199
|
const toLink = (p: (typeof pages)[number]): PageNavLink => ({
|
|
196
200
|
url: p.url,
|
|
197
201
|
title:
|
|
@@ -199,10 +203,21 @@ export async function getPageNav(slug: string[], tree?: Root): Promise<PageNav>
|
|
|
199
203
|
? p.name
|
|
200
204
|
: titleFromUrl(p.url)
|
|
201
205
|
});
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
+
const navMap = new Map<string, PageNav>();
|
|
207
|
+
for (let i = 0; i < pages.length; i++) {
|
|
208
|
+
navMap.set(pages[i].url, {
|
|
209
|
+
prev: i > 0 ? toLink(pages[i - 1]) : null,
|
|
210
|
+
next: i < pages.length - 1 ? toLink(pages[i + 1]) : null
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
cachedNavMap = navMap;
|
|
214
|
+
return cachedNavMap;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
export async function getPageNav(slug: string[]): Promise<PageNav> {
|
|
218
|
+
const navMap = await getNavMap();
|
|
219
|
+
const url = slug.length === 0 ? '/' : `/${slug.join('/')}`;
|
|
220
|
+
return navMap.get(url) ?? { prev: null, next: null };
|
|
206
221
|
}
|
|
207
222
|
|
|
208
223
|
export function extractFrontmatter(page: { data: unknown }, fallbackTitle?: string): Frontmatter {
|
|
@@ -45,7 +45,7 @@ export default {
|
|
|
45
45
|
getPageTree(),
|
|
46
46
|
route.type === RouteType.DocsPage ? getPage(route.slug) : Promise.resolve(null),
|
|
47
47
|
]);
|
|
48
|
-
const nav = page ? await getPageNav(pageSlug
|
|
48
|
+
const nav = page ? await getPageNav(pageSlug) : { prev: null, next: null };
|
|
49
49
|
|
|
50
50
|
const relativePath = page ? getRelativePath(page) : null;
|
|
51
51
|
const originalPath = page ? getOriginalPath(page) : null;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
.main {
|
|
2
2
|
flex: 1;
|
|
3
|
-
width:
|
|
3
|
+
width: 100%;
|
|
4
4
|
max-width: calc(1024px + var(--rs-space-17));
|
|
5
5
|
margin: 0 auto;
|
|
6
6
|
padding-top: var(--rs-space-12);
|
|
@@ -137,8 +137,8 @@
|
|
|
137
137
|
box-shadow:
|
|
138
138
|
0 1px 3px rgba(0, 0, 0, 0.08),
|
|
139
139
|
0 4px 12px rgba(0, 0, 0, 0.04);
|
|
140
|
-
margin-bottom: var(--rs-space-9);
|
|
141
140
|
min-height: calc(100vh - var(--rs-space-12));
|
|
141
|
+
margin: 0 var(--rs-space-7) var(--rs-space-9) var(--rs-space-7);
|
|
142
142
|
}
|
|
143
143
|
|
|
144
144
|
.content h1,
|
|
@@ -225,5 +225,10 @@
|
|
|
225
225
|
}
|
|
226
226
|
|
|
227
227
|
.loader {
|
|
228
|
+
flex: 1;
|
|
228
229
|
margin-bottom: var(--rs-space-3)
|
|
229
230
|
}
|
|
231
|
+
|
|
232
|
+
.navbarLoaderWrapper {
|
|
233
|
+
width: 30%;
|
|
234
|
+
}
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
|
-
ArrowLeftIcon,
|
|
3
|
-
ArrowRightIcon,
|
|
4
|
-
AdjustmentsHorizontalIcon,
|
|
5
2
|
EyeIcon,
|
|
6
3
|
SunIcon,
|
|
7
4
|
MoonIcon,
|
|
8
|
-
XMarkIcon,
|
|
9
5
|
} from '@heroicons/react/24/outline';
|
|
6
|
+
import {
|
|
7
|
+
ArrowLeftIcon,
|
|
8
|
+
ArrowRightIcon,
|
|
9
|
+
MixerHorizontalIcon,
|
|
10
|
+
Cross2Icon
|
|
11
|
+
} from '@radix-ui/react-icons'
|
|
10
12
|
import { IconButton, useTheme } from '@raystack/apsara';
|
|
11
13
|
import { useEffect, useMemo, useState } from 'react';
|
|
12
14
|
import { Link as RouterLink, useLocation } from 'react-router';
|
|
@@ -83,12 +85,12 @@ export function Page({ page, tree }: ThemePageProps) {
|
|
|
83
85
|
</IconButton>
|
|
84
86
|
)}
|
|
85
87
|
<IconButton size={2} onClick={() => setSettingsOpen(false)} aria-label='Close settings'>
|
|
86
|
-
<
|
|
88
|
+
<Cross2Icon width={14} height={14} />
|
|
87
89
|
</IconButton>
|
|
88
90
|
</>
|
|
89
91
|
) : (
|
|
90
92
|
<IconButton size={2} onClick={() => setSettingsOpen(true)} aria-label='Open settings'>
|
|
91
|
-
<
|
|
93
|
+
<MixerHorizontalIcon width={14} height={14} />
|
|
92
94
|
</IconButton>
|
|
93
95
|
)}
|
|
94
96
|
</div>
|
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
import { Skeleton } from '@raystack/apsara';
|
|
2
2
|
import styles from './Page.module.css';
|
|
3
|
+
import { cx } from 'class-variance-authority';
|
|
3
4
|
|
|
4
5
|
export function PageSkeleton() {
|
|
5
6
|
return (
|
|
6
7
|
<main className={styles.main}>
|
|
8
|
+
<div className={styles.navbar}>
|
|
9
|
+
<div className={cx(styles.navLeft, styles.navbarLoaderWrapper)}>
|
|
10
|
+
<Skeleton highlightColor="var(--rs-color-foreground-base-emphasis)" containerClassName={styles.loader}/>
|
|
11
|
+
</div>
|
|
12
|
+
<div className={cx(styles.navRight, styles.navbarLoaderWrapper)}>
|
|
13
|
+
<Skeleton highlightColor="var(--rs-color-foreground-base-emphasis)" containerClassName={styles.loader}/>
|
|
14
|
+
</div>
|
|
15
|
+
</div>
|
|
7
16
|
<div className={styles.content}>
|
|
8
17
|
<header className={styles.articleHeader}>
|
|
9
18
|
<Skeleton width="50%" height="16px" containerClassName={styles.headerLoader}/>
|