@openlaboratory/open-doc 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/README.md +91 -0
- package/app/.astro/collections/docs.schema.json +24 -0
- package/app/.astro/content-assets.mjs +1 -0
- package/app/.astro/content-modules.mjs +4 -0
- package/app/.astro/content.d.ts +218 -0
- package/app/.astro/data-store.json +1 -0
- package/app/.astro/settings.json +5 -0
- package/app/.astro/types.d.ts +2 -0
- package/app/astro.config.mjs +43 -0
- package/app/node_modules/.astro/data-store.json +1 -0
- package/app/node_modules/.vite/deps/@astrojs_react_client__js.js +163 -0
- package/app/node_modules/.vite/deps/@astrojs_react_client__js.js.map +7 -0
- package/app/node_modules/.vite/deps/_metadata.json +67 -0
- package/app/node_modules/.vite/deps/astro___aria-query.js +6776 -0
- package/app/node_modules/.vite/deps/astro___aria-query.js.map +7 -0
- package/app/node_modules/.vite/deps/astro___axobject-query.js +3754 -0
- package/app/node_modules/.vite/deps/astro___axobject-query.js.map +7 -0
- package/app/node_modules/.vite/deps/astro___cssesc.js +99 -0
- package/app/node_modules/.vite/deps/astro___cssesc.js.map +7 -0
- package/app/node_modules/.vite/deps/chunk-55ZOATU5.js +305 -0
- package/app/node_modules/.vite/deps/chunk-55ZOATU5.js.map +7 -0
- package/app/node_modules/.vite/deps/chunk-5WRI5ZAA.js +30 -0
- package/app/node_modules/.vite/deps/chunk-5WRI5ZAA.js.map +7 -0
- package/app/node_modules/.vite/deps/chunk-FEZZJEG2.js +6935 -0
- package/app/node_modules/.vite/deps/chunk-FEZZJEG2.js.map +7 -0
- package/app/node_modules/.vite/deps/package.json +3 -0
- package/app/node_modules/.vite/deps/react-dom.js +6 -0
- package/app/node_modules/.vite/deps/react-dom.js.map +7 -0
- package/app/node_modules/.vite/deps/react.js +5 -0
- package/app/node_modules/.vite/deps/react.js.map +7 -0
- package/app/node_modules/.vite/deps/react_jsx-dev-runtime.js +39 -0
- package/app/node_modules/.vite/deps/react_jsx-dev-runtime.js.map +7 -0
- package/app/node_modules/.vite/deps/react_jsx-runtime.js +57 -0
- package/app/node_modules/.vite/deps/react_jsx-runtime.js.map +7 -0
- package/app/src/components/DocsMobileNav.tsx +124 -0
- package/app/src/components/DocsSearch.tsx +315 -0
- package/app/src/components/DocsSidebar.astro +46 -0
- package/app/src/components/DocsTableOfContents.tsx +92 -0
- package/app/src/components/Navbar.astro +39 -0
- package/app/src/components/SocialIcon.astro +54 -0
- package/app/src/components/ThemeToggle.tsx +62 -0
- package/app/src/content.config.ts +17 -0
- package/app/src/env.d.ts +7 -0
- package/app/src/integrations/open-doc-config.mjs +65 -0
- package/app/src/layouts/DocsLayout.astro +369 -0
- package/app/src/lib/config.ts +36 -0
- package/app/src/lib/navigation.ts +68 -0
- package/app/src/lib/withBase.ts +11 -0
- package/app/src/pages/404.astro +24 -0
- package/app/src/pages/[...slug].astro +34 -0
- package/app/src/pages/index.astro +107 -0
- package/app/src/styles/global.css +324 -0
- package/app/tailwind.config.mjs +53 -0
- package/app/tsconfig.json +11 -0
- package/bin/open-doc.js +2 -0
- package/dist/chunk-BRUM67K7.js +30 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +268 -0
- package/dist/index.d.ts +116 -0
- package/dist/index.js +8 -0
- package/package.json +77 -0
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
@tailwind base;
|
|
2
|
+
@tailwind components;
|
|
3
|
+
@tailwind utilities;
|
|
4
|
+
|
|
5
|
+
/* ─── Design tokens ──────────────────────────────────────────────────────────
|
|
6
|
+
Every color is an HSL triplet so it can be tinted with Tailwind's alpha
|
|
7
|
+
syntax (e.g. text-foreground/55) and overridden per-theme from user config.
|
|
8
|
+
Light values live on :root; dark values on .dark (toggled on <html>). */
|
|
9
|
+
|
|
10
|
+
@layer base {
|
|
11
|
+
:root {
|
|
12
|
+
--background: 0 0% 100%;
|
|
13
|
+
--foreground: 0 0% 11%;
|
|
14
|
+
--muted: 0 0% 96%;
|
|
15
|
+
--muted-foreground: 0 0% 40%;
|
|
16
|
+
--primary: 0 0% 10%;
|
|
17
|
+
--primary-foreground: 0 0% 98%;
|
|
18
|
+
--border: 0 0% 90%;
|
|
19
|
+
--input: 0 0% 89%;
|
|
20
|
+
--ring: 0 0% 70%;
|
|
21
|
+
|
|
22
|
+
--surface: 0 0% 100%;
|
|
23
|
+
--surface-sidebar: 0 0% 97.5%;
|
|
24
|
+
--surface-content: 0 0% 100%;
|
|
25
|
+
--surface-raised: 0 0% 100%;
|
|
26
|
+
|
|
27
|
+
--link: 221 83% 48%;
|
|
28
|
+
--link-hover: 221 83% 40%;
|
|
29
|
+
--success: 142 71% 40%;
|
|
30
|
+
--warning: 38 92% 45%;
|
|
31
|
+
|
|
32
|
+
--code-bg: 0 0% 96.5%;
|
|
33
|
+
--code-border: 0 0% 90%;
|
|
34
|
+
|
|
35
|
+
--radius: 0.5rem;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.dark {
|
|
39
|
+
--background: 0 0% 4%;
|
|
40
|
+
--foreground: 0 0% 96%;
|
|
41
|
+
--muted: 0 0% 11%;
|
|
42
|
+
--muted-foreground: 0 0% 68%;
|
|
43
|
+
--primary: 0 0% 96%;
|
|
44
|
+
--primary-foreground: 0 0% 4%;
|
|
45
|
+
--border: 0 0% 16%;
|
|
46
|
+
--input: 0 0% 18%;
|
|
47
|
+
--ring: 0 0% 30%;
|
|
48
|
+
|
|
49
|
+
--surface: 0 0% 3.9%;
|
|
50
|
+
--surface-sidebar: 0 0% 5.5%;
|
|
51
|
+
--surface-content: 0 0% 6.7%;
|
|
52
|
+
--surface-raised: 0 0% 8%;
|
|
53
|
+
|
|
54
|
+
--link: 213 97% 68%;
|
|
55
|
+
--link-hover: 210 100% 76%;
|
|
56
|
+
--success: 142 71% 50%;
|
|
57
|
+
--warning: 38 92% 55%;
|
|
58
|
+
|
|
59
|
+
--code-bg: 0 0% 7%;
|
|
60
|
+
--code-border: 0 0% 14%;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
* {
|
|
64
|
+
@apply border-border;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
html {
|
|
68
|
+
scrollbar-gutter: stable;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
body {
|
|
72
|
+
@apply bg-surface text-foreground antialiased;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/* ─── Utilities ───────────────────────────────────────────────────────────── */
|
|
77
|
+
|
|
78
|
+
.hide-scrollbar::-webkit-scrollbar {
|
|
79
|
+
display: none;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.hide-scrollbar {
|
|
83
|
+
-ms-overflow-style: none;
|
|
84
|
+
scrollbar-width: none;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/* Keyboard focus ring */
|
|
88
|
+
:focus-visible {
|
|
89
|
+
outline: 2px solid hsl(var(--link));
|
|
90
|
+
outline-offset: 2px;
|
|
91
|
+
border-radius: 3px;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/* Respect users who prefer less motion */
|
|
95
|
+
@media (prefers-reduced-motion: reduce) {
|
|
96
|
+
*,
|
|
97
|
+
::before,
|
|
98
|
+
::after {
|
|
99
|
+
animation-duration: 0.01ms !important;
|
|
100
|
+
animation-iteration-count: 1 !important;
|
|
101
|
+
transition-duration: 0.01ms !important;
|
|
102
|
+
scroll-behavior: auto !important;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/* ─── Markdown prose ──────────────────────────────────────────────────────────
|
|
107
|
+
Drives @tailwindcss/typography from the theme tokens so the article body
|
|
108
|
+
adapts to light/dark automatically. */
|
|
109
|
+
|
|
110
|
+
.docs-prose {
|
|
111
|
+
--tw-prose-body: hsl(var(--foreground) / 0.78);
|
|
112
|
+
--tw-prose-headings: hsl(var(--foreground) / 0.96);
|
|
113
|
+
--tw-prose-lead: hsl(var(--foreground) / 0.7);
|
|
114
|
+
--tw-prose-links: hsl(var(--link));
|
|
115
|
+
--tw-prose-bold: hsl(var(--foreground) / 0.96);
|
|
116
|
+
--tw-prose-counters: hsl(var(--foreground) / 0.55);
|
|
117
|
+
--tw-prose-bullets: hsl(var(--foreground) / 0.3);
|
|
118
|
+
--tw-prose-hr: hsl(var(--border));
|
|
119
|
+
--tw-prose-quotes: hsl(var(--foreground) / 0.8);
|
|
120
|
+
--tw-prose-quote-borders: hsl(var(--border));
|
|
121
|
+
--tw-prose-captions: hsl(var(--foreground) / 0.55);
|
|
122
|
+
--tw-prose-code: hsl(var(--foreground) / 0.9);
|
|
123
|
+
--tw-prose-th-borders: hsl(var(--border));
|
|
124
|
+
--tw-prose-td-borders: hsl(var(--border));
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.docs-prose a {
|
|
128
|
+
color: hsl(var(--link));
|
|
129
|
+
text-decoration: underline;
|
|
130
|
+
text-underline-offset: 3px;
|
|
131
|
+
text-decoration-color: hsl(var(--link) / 0.4);
|
|
132
|
+
transition:
|
|
133
|
+
color 0.15s,
|
|
134
|
+
text-decoration-color 0.15s;
|
|
135
|
+
font-weight: 500;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
.docs-prose a:hover {
|
|
139
|
+
color: hsl(var(--link-hover));
|
|
140
|
+
text-decoration-color: hsl(var(--link-hover) / 0.7);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
.docs-prose :not(pre) > code {
|
|
144
|
+
background: hsl(var(--code-bg));
|
|
145
|
+
border: 1px solid hsl(var(--code-border));
|
|
146
|
+
border-radius: 4px;
|
|
147
|
+
padding: 0.15em 0.4em;
|
|
148
|
+
font-size: 0.875em;
|
|
149
|
+
color: hsl(var(--foreground) / 0.88);
|
|
150
|
+
font-weight: 400;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.docs-prose :not(pre) > code::before,
|
|
154
|
+
.docs-prose :not(pre) > code::after {
|
|
155
|
+
content: none;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.docs-prose pre {
|
|
159
|
+
border: 1px solid hsl(var(--code-border));
|
|
160
|
+
border-radius: 0.625rem;
|
|
161
|
+
position: relative;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
.docs-prose blockquote {
|
|
165
|
+
border-left: 2px solid hsl(var(--border));
|
|
166
|
+
background: hsl(var(--foreground) / 0.03);
|
|
167
|
+
border-radius: 0 0.5rem 0.5rem 0;
|
|
168
|
+
padding: 0.7rem 1rem;
|
|
169
|
+
color: hsl(var(--foreground) / 0.7);
|
|
170
|
+
font-style: normal;
|
|
171
|
+
quotes: none;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
.docs-prose blockquote::before,
|
|
175
|
+
.docs-prose blockquote::after {
|
|
176
|
+
content: none;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.docs-prose blockquote p {
|
|
180
|
+
margin: 0;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.docs-prose blockquote strong {
|
|
184
|
+
color: hsl(var(--foreground) / 0.9);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.docs-prose table {
|
|
188
|
+
font-size: 0.9em;
|
|
189
|
+
border-radius: 0.5rem;
|
|
190
|
+
overflow: hidden;
|
|
191
|
+
border: 1px solid hsl(var(--border));
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
.docs-prose thead {
|
|
195
|
+
background: hsl(var(--foreground) / 0.04);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
.docs-prose thead th {
|
|
199
|
+
color: hsl(var(--foreground) / 0.85);
|
|
200
|
+
font-weight: 600;
|
|
201
|
+
padding: 0.6rem 0.8rem;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
.docs-prose tbody td {
|
|
205
|
+
padding: 0.6rem 0.8rem;
|
|
206
|
+
color: hsl(var(--foreground) / 0.72);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
.docs-prose h1 {
|
|
210
|
+
font-size: 2rem;
|
|
211
|
+
letter-spacing: -0.025em;
|
|
212
|
+
margin-bottom: 1rem;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
.docs-prose h2 {
|
|
216
|
+
font-size: 1.35rem;
|
|
217
|
+
letter-spacing: -0.015em;
|
|
218
|
+
margin-top: 2.5rem;
|
|
219
|
+
margin-bottom: 0.75rem;
|
|
220
|
+
padding-bottom: 0.5rem;
|
|
221
|
+
border-bottom: 1px solid hsl(var(--border));
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
.docs-prose h3 {
|
|
225
|
+
font-size: 1.1rem;
|
|
226
|
+
margin-top: 1.75rem;
|
|
227
|
+
margin-bottom: 0.5rem;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
.docs-prose hr {
|
|
231
|
+
border-color: hsl(var(--border));
|
|
232
|
+
margin: 2rem 0;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/* Heading anchor links (injected client-side) */
|
|
236
|
+
.docs-prose h1,
|
|
237
|
+
.docs-prose h2,
|
|
238
|
+
.docs-prose h3,
|
|
239
|
+
.docs-prose h4 {
|
|
240
|
+
position: relative;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
.docs-prose .heading-anchor {
|
|
244
|
+
position: absolute;
|
|
245
|
+
right: 100%;
|
|
246
|
+
top: 50%;
|
|
247
|
+
transform: translateY(-50%);
|
|
248
|
+
padding-right: 0.4em;
|
|
249
|
+
color: hsl(var(--foreground) / 0.35);
|
|
250
|
+
text-decoration: none;
|
|
251
|
+
font-weight: 400;
|
|
252
|
+
opacity: 0;
|
|
253
|
+
transition:
|
|
254
|
+
opacity 0.15s,
|
|
255
|
+
color 0.15s;
|
|
256
|
+
user-select: none;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
.docs-prose h1:hover .heading-anchor,
|
|
260
|
+
.docs-prose h2:hover .heading-anchor,
|
|
261
|
+
.docs-prose h3:hover .heading-anchor,
|
|
262
|
+
.docs-prose h4:hover .heading-anchor {
|
|
263
|
+
opacity: 1;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
.docs-prose .heading-anchor:hover {
|
|
267
|
+
color: hsl(var(--foreground) / 0.65);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/* Code-block copy button (injected client-side) */
|
|
271
|
+
.code-copy-btn {
|
|
272
|
+
position: absolute;
|
|
273
|
+
top: 0.6rem;
|
|
274
|
+
right: 0.6rem;
|
|
275
|
+
display: flex;
|
|
276
|
+
align-items: center;
|
|
277
|
+
justify-content: center;
|
|
278
|
+
width: 1.75rem;
|
|
279
|
+
height: 1.75rem;
|
|
280
|
+
border-radius: 0.375rem;
|
|
281
|
+
border: 1px solid hsl(var(--foreground) / 0.18);
|
|
282
|
+
background: hsl(var(--foreground) / 0.08);
|
|
283
|
+
color: hsl(var(--foreground) / 0.5);
|
|
284
|
+
cursor: pointer;
|
|
285
|
+
opacity: 0;
|
|
286
|
+
transition:
|
|
287
|
+
opacity 0.15s,
|
|
288
|
+
color 0.15s,
|
|
289
|
+
background 0.15s;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
.docs-prose pre:hover .code-copy-btn {
|
|
293
|
+
opacity: 1;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
.code-copy-btn:hover {
|
|
297
|
+
color: hsl(var(--foreground) / 0.85);
|
|
298
|
+
background: hsl(var(--foreground) / 0.14);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
.code-copy-btn.copied {
|
|
302
|
+
color: hsl(var(--success));
|
|
303
|
+
border-color: hsl(var(--success) / 0.5);
|
|
304
|
+
opacity: 1;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
.code-copy-btn svg {
|
|
308
|
+
width: 0.875rem;
|
|
309
|
+
height: 0.875rem;
|
|
310
|
+
flex-shrink: 0;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/* ─── Shiki dual-theme switch ─────────────────────────────────────────────────
|
|
314
|
+
The light theme renders inline by default; under .dark we swap to the dark
|
|
315
|
+
theme's CSS variables that Astro emits per-token. */
|
|
316
|
+
|
|
317
|
+
html.dark .astro-code,
|
|
318
|
+
html.dark .astro-code span {
|
|
319
|
+
color: var(--shiki-dark) !important;
|
|
320
|
+
background-color: var(--shiki-dark-bg) !important;
|
|
321
|
+
font-style: var(--shiki-dark-font-style) !important;
|
|
322
|
+
font-weight: var(--shiki-dark-font-weight) !important;
|
|
323
|
+
text-decoration: var(--shiki-dark-text-decoration) !important;
|
|
324
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { dirname, join } from 'node:path'
|
|
2
|
+
import { fileURLToPath } from 'node:url'
|
|
3
|
+
import typography from '@tailwindcss/typography'
|
|
4
|
+
|
|
5
|
+
const appDir = dirname(fileURLToPath(import.meta.url))
|
|
6
|
+
const appContent = join(appDir, 'src/**/*.{astro,html,js,jsx,md,mdx,ts,tsx}')
|
|
7
|
+
|
|
8
|
+
// Also scan the consumer's content dir so utility classes used in their
|
|
9
|
+
// Markdown / MDX / components are not purged.
|
|
10
|
+
const contentDir = process.env.OPEN_DOC_CONTENT_DIR
|
|
11
|
+
const userContent = contentDir ? `${contentDir}/**/*.{astro,html,js,jsx,md,mdx,ts,tsx}` : null
|
|
12
|
+
|
|
13
|
+
/** @type {import('tailwindcss').Config} */
|
|
14
|
+
export default {
|
|
15
|
+
darkMode: 'class',
|
|
16
|
+
content: [appContent, userContent].filter(Boolean),
|
|
17
|
+
theme: {
|
|
18
|
+
extend: {
|
|
19
|
+
colors: {
|
|
20
|
+
border: 'hsl(var(--border) / <alpha-value>)',
|
|
21
|
+
input: 'hsl(var(--input) / <alpha-value>)',
|
|
22
|
+
ring: 'hsl(var(--ring) / <alpha-value>)',
|
|
23
|
+
background: 'hsl(var(--background) / <alpha-value>)',
|
|
24
|
+
foreground: 'hsl(var(--foreground) / <alpha-value>)',
|
|
25
|
+
muted: {
|
|
26
|
+
DEFAULT: 'hsl(var(--muted) / <alpha-value>)',
|
|
27
|
+
foreground: 'hsl(var(--muted-foreground) / <alpha-value>)',
|
|
28
|
+
},
|
|
29
|
+
primary: {
|
|
30
|
+
DEFAULT: 'hsl(var(--primary) / <alpha-value>)',
|
|
31
|
+
foreground: 'hsl(var(--primary-foreground) / <alpha-value>)',
|
|
32
|
+
},
|
|
33
|
+
link: {
|
|
34
|
+
DEFAULT: 'hsl(var(--link) / <alpha-value>)',
|
|
35
|
+
hover: 'hsl(var(--link-hover) / <alpha-value>)',
|
|
36
|
+
},
|
|
37
|
+
success: 'hsl(var(--success) / <alpha-value>)',
|
|
38
|
+
warning: 'hsl(var(--warning) / <alpha-value>)',
|
|
39
|
+
surface: {
|
|
40
|
+
DEFAULT: 'hsl(var(--surface) / <alpha-value>)',
|
|
41
|
+
sidebar: 'hsl(var(--surface-sidebar) / <alpha-value>)',
|
|
42
|
+
content: 'hsl(var(--surface-content) / <alpha-value>)',
|
|
43
|
+
raised: 'hsl(var(--surface-raised) / <alpha-value>)',
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
fontFamily: {
|
|
47
|
+
sans: ['Montserrat', 'ui-sans-serif', 'system-ui', 'sans-serif'],
|
|
48
|
+
mono: ['Red Hat Mono', 'ui-monospace', 'SFMono-Regular', 'monospace'],
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
plugins: [typography],
|
|
53
|
+
}
|
package/bin/open-doc.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// src/define-config.ts
|
|
2
|
+
function defineConfig(config) {
|
|
3
|
+
return config;
|
|
4
|
+
}
|
|
5
|
+
function normalizeConfig(config) {
|
|
6
|
+
return {
|
|
7
|
+
title: config.title,
|
|
8
|
+
description: config.description ?? "",
|
|
9
|
+
base: config.base ?? "/",
|
|
10
|
+
site: config.site,
|
|
11
|
+
lang: config.lang ?? "en",
|
|
12
|
+
favicon: config.favicon,
|
|
13
|
+
logo: {
|
|
14
|
+
text: config.logo?.text ?? config.title,
|
|
15
|
+
src: config.logo?.src,
|
|
16
|
+
href: config.logo?.href ?? "/"
|
|
17
|
+
},
|
|
18
|
+
social: config.social ?? [],
|
|
19
|
+
defaultTheme: config.defaultTheme ?? "dark",
|
|
20
|
+
themeToggle: config.themeToggle ?? true,
|
|
21
|
+
theme: config.theme ?? {},
|
|
22
|
+
editLinkBase: config.editLinkBase,
|
|
23
|
+
nav: config.nav ?? []
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export {
|
|
28
|
+
defineConfig,
|
|
29
|
+
normalizeConfig
|
|
30
|
+
};
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import {
|
|
2
|
+
normalizeConfig
|
|
3
|
+
} from "./chunk-BRUM67K7.js";
|
|
4
|
+
|
|
5
|
+
// src/cli.ts
|
|
6
|
+
import { spawn } from "child_process";
|
|
7
|
+
import { createRequire } from "module";
|
|
8
|
+
import { dirname as dirname2, join as join2 } from "path";
|
|
9
|
+
import { fileURLToPath } from "url";
|
|
10
|
+
import { cac } from "cac";
|
|
11
|
+
import pc from "picocolors";
|
|
12
|
+
|
|
13
|
+
// src/config-loader.ts
|
|
14
|
+
import { createJiti } from "jiti";
|
|
15
|
+
async function loadUserConfig(configPath) {
|
|
16
|
+
const jiti = createJiti(import.meta.url, { moduleCache: false, fsCache: false });
|
|
17
|
+
const config = await jiti.import(configPath, { default: true });
|
|
18
|
+
if (!config || typeof config !== "object") {
|
|
19
|
+
throw new Error(`${configPath} must "export default defineConfig({ ... })".`);
|
|
20
|
+
}
|
|
21
|
+
if (typeof config.title !== "string" || config.title.length === 0) {
|
|
22
|
+
throw new Error(`Your open-doc config is missing a "title" string.`);
|
|
23
|
+
}
|
|
24
|
+
if (!Array.isArray(config.nav)) {
|
|
25
|
+
throw new Error(`Your open-doc config is missing a "nav" array.`);
|
|
26
|
+
}
|
|
27
|
+
return config;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// src/resolve-paths.ts
|
|
31
|
+
import { existsSync, realpathSync } from "fs";
|
|
32
|
+
import { resolve } from "path";
|
|
33
|
+
var CONFIG_NAMES = [
|
|
34
|
+
"open-doc.config.ts",
|
|
35
|
+
"open-doc.config.mts",
|
|
36
|
+
"open-doc.config.js",
|
|
37
|
+
"open-doc.config.mjs"
|
|
38
|
+
];
|
|
39
|
+
function findConfig(cwd) {
|
|
40
|
+
const found = CONFIG_NAMES.map((name) => resolve(cwd, name)).find(existsSync);
|
|
41
|
+
if (!found) {
|
|
42
|
+
throw new Error(
|
|
43
|
+
`Could not find an open-doc config file in ${cwd}
|
|
44
|
+
Create one of: ${CONFIG_NAMES.join(", ")}`
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
return found;
|
|
48
|
+
}
|
|
49
|
+
function resolvePaths(cwd, config, configPath = findConfig(cwd)) {
|
|
50
|
+
const contentInput = resolve(cwd, config.contentDir ?? "./content");
|
|
51
|
+
if (!existsSync(contentInput)) {
|
|
52
|
+
throw new Error(
|
|
53
|
+
`Content directory not found: ${contentInput}
|
|
54
|
+
Create it, or set "contentDir" in your open-doc config.`
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
const contentDir = realpathSync(contentInput);
|
|
58
|
+
let publicDir;
|
|
59
|
+
if (config.publicDir) {
|
|
60
|
+
const p = resolve(cwd, config.publicDir);
|
|
61
|
+
if (existsSync(p)) publicDir = realpathSync(p);
|
|
62
|
+
} else {
|
|
63
|
+
const fallback = resolve(cwd, "public");
|
|
64
|
+
if (existsSync(fallback)) publicDir = realpathSync(fallback);
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
cwd,
|
|
68
|
+
configPath,
|
|
69
|
+
contentDir,
|
|
70
|
+
publicDir,
|
|
71
|
+
outDir: resolve(cwd, "dist")
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// src/init.ts
|
|
76
|
+
import { existsSync as existsSync2, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
77
|
+
import { dirname, join, resolve as resolve2 } from "path";
|
|
78
|
+
var CONFIG_TEMPLATE = `import { defineConfig } from '@openlaboratory/open-doc'
|
|
79
|
+
|
|
80
|
+
export default defineConfig({
|
|
81
|
+
title: 'My Docs',
|
|
82
|
+
description: 'Documentation for my project.',
|
|
83
|
+
// social: [{ icon: 'github', href: 'https://github.com/you/repo' }],
|
|
84
|
+
nav: [
|
|
85
|
+
{
|
|
86
|
+
label: 'Getting Started',
|
|
87
|
+
dir: 'getting-started',
|
|
88
|
+
pages: ['introduction'],
|
|
89
|
+
},
|
|
90
|
+
],
|
|
91
|
+
})
|
|
92
|
+
`;
|
|
93
|
+
var INTRO_TEMPLATE = `---
|
|
94
|
+
title: Introduction
|
|
95
|
+
description: Welcome to your new documentation site.
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
# Introduction
|
|
99
|
+
|
|
100
|
+
Welcome to **open-doc**! Edit this page at
|
|
101
|
+
\`content/getting-started/introduction.md\`, then add more pages and list them in
|
|
102
|
+
\`open-doc.config.ts\`.
|
|
103
|
+
|
|
104
|
+
## Next steps
|
|
105
|
+
|
|
106
|
+
- Add Markdown or MDX files under \`content/\`.
|
|
107
|
+
- Reference each page's slug in your config's \`nav\`.
|
|
108
|
+
- Run \`open-doc dev\` to preview and \`open-doc build\` to ship.
|
|
109
|
+
`;
|
|
110
|
+
var CONFIG_NAMES2 = ["open-doc.config.ts", "open-doc.config.js", "open-doc.config.mjs"];
|
|
111
|
+
function initProject(cwd) {
|
|
112
|
+
const existing = CONFIG_NAMES2.map((n) => resolve2(cwd, n)).find(existsSync2);
|
|
113
|
+
if (existing) {
|
|
114
|
+
throw new Error(`This project is already initialized (${existing}).`);
|
|
115
|
+
}
|
|
116
|
+
const created = [];
|
|
117
|
+
const writeFile = (relPath, contents) => {
|
|
118
|
+
const abs = resolve2(cwd, relPath);
|
|
119
|
+
mkdirSync(dirname(abs), { recursive: true });
|
|
120
|
+
writeFileSync(abs, contents);
|
|
121
|
+
created.push(relPath);
|
|
122
|
+
};
|
|
123
|
+
writeFile("open-doc.config.ts", CONFIG_TEMPLATE);
|
|
124
|
+
writeFile("content/getting-started/introduction.md", INTRO_TEMPLATE);
|
|
125
|
+
const pkgPath = join(cwd, "package.json");
|
|
126
|
+
const hasPackageJson = existsSync2(pkgPath);
|
|
127
|
+
let addedScripts = false;
|
|
128
|
+
if (hasPackageJson) {
|
|
129
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
|
|
130
|
+
pkg.scripts ??= {};
|
|
131
|
+
for (const [name, command] of [
|
|
132
|
+
["dev", "open-doc dev"],
|
|
133
|
+
["build", "open-doc build"],
|
|
134
|
+
["preview", "open-doc preview"]
|
|
135
|
+
]) {
|
|
136
|
+
if (!pkg.scripts[name]) {
|
|
137
|
+
pkg.scripts[name] = command;
|
|
138
|
+
addedScripts = true;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
if (addedScripts) writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}
|
|
142
|
+
`);
|
|
143
|
+
}
|
|
144
|
+
return { created, addedScripts, hasPackageJson };
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// src/cli.ts
|
|
148
|
+
var require2 = createRequire(import.meta.url);
|
|
149
|
+
var APP_ROOT = fileURLToPath(new URL("../app/", import.meta.url));
|
|
150
|
+
var { version } = require2("../package.json");
|
|
151
|
+
async function prepare(cwd) {
|
|
152
|
+
const configPath = findConfig(cwd);
|
|
153
|
+
const userConfig = await loadUserConfig(configPath);
|
|
154
|
+
const paths = resolvePaths(cwd, userConfig, configPath);
|
|
155
|
+
process.env.OPEN_DOC_CONTENT_DIR = paths.contentDir;
|
|
156
|
+
process.env.OPEN_DOC_OUT_DIR = paths.outDir;
|
|
157
|
+
process.env.OPEN_DOC_CONFIG_JSON = JSON.stringify(normalizeConfig(userConfig));
|
|
158
|
+
if (paths.publicDir) process.env.OPEN_DOC_PUBLIC_DIR = paths.publicDir;
|
|
159
|
+
return paths;
|
|
160
|
+
}
|
|
161
|
+
function fail(err) {
|
|
162
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
163
|
+
console.error(`
|
|
164
|
+
${pc.red("\u2716 open-doc")} ${message}
|
|
165
|
+
`);
|
|
166
|
+
process.exit(1);
|
|
167
|
+
}
|
|
168
|
+
function parsePort(value) {
|
|
169
|
+
const port = Number(value);
|
|
170
|
+
if (!Number.isInteger(port) || port < 0 || port > 65535) {
|
|
171
|
+
throw new Error(`Invalid --port "${value}". Expected a number between 0 and 65535.`);
|
|
172
|
+
}
|
|
173
|
+
return port;
|
|
174
|
+
}
|
|
175
|
+
var cli = cac("open-doc");
|
|
176
|
+
cli.command("dev", "Start the local development server").option("--port <port>", "Port to listen on", { default: 4321 }).option("--host", "Expose the server to the local network").action(async (options) => {
|
|
177
|
+
try {
|
|
178
|
+
const port = parsePort(options.port);
|
|
179
|
+
await prepare(process.cwd());
|
|
180
|
+
const { dev } = await import("astro");
|
|
181
|
+
await dev({
|
|
182
|
+
root: APP_ROOT,
|
|
183
|
+
server: { port, host: options.host ?? false }
|
|
184
|
+
});
|
|
185
|
+
} catch (err) {
|
|
186
|
+
fail(err);
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
cli.command("build", "Build the static site into ./dist").action(async () => {
|
|
190
|
+
try {
|
|
191
|
+
const paths = await prepare(process.cwd());
|
|
192
|
+
const { build } = await import("astro");
|
|
193
|
+
await build({ root: APP_ROOT });
|
|
194
|
+
console.log(`
|
|
195
|
+
${pc.green("\u2714 open-doc")} built your site to ${pc.cyan(paths.outDir)}
|
|
196
|
+
`);
|
|
197
|
+
} catch (err) {
|
|
198
|
+
fail(err);
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
cli.command("preview", "Preview the built site from ./dist").option("--port <port>", "Port to listen on", { default: 4321 }).option("--host", "Expose the server to the local network").action(async (options) => {
|
|
202
|
+
try {
|
|
203
|
+
const port = parsePort(options.port);
|
|
204
|
+
await prepare(process.cwd());
|
|
205
|
+
const { preview } = await import("astro");
|
|
206
|
+
await preview({
|
|
207
|
+
root: APP_ROOT,
|
|
208
|
+
server: { port, host: options.host ?? false }
|
|
209
|
+
});
|
|
210
|
+
} catch (err) {
|
|
211
|
+
fail(err);
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
cli.command("check", "Type-check your content, config, and components").action(async () => {
|
|
215
|
+
try {
|
|
216
|
+
for (const dep of ["@astrojs/check", "typescript"]) {
|
|
217
|
+
try {
|
|
218
|
+
require2.resolve(dep);
|
|
219
|
+
} catch {
|
|
220
|
+
throw new Error(
|
|
221
|
+
"Type-checking needs extra tooling. Install it with:\n npm i -D @astrojs/check typescript @types/react @types/react-dom"
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
await prepare(process.cwd());
|
|
226
|
+
const astroBin = join2(dirname2(require2.resolve("astro/package.json")), "astro.js");
|
|
227
|
+
const child = spawn(process.execPath, [astroBin, "check", "--root", APP_ROOT], {
|
|
228
|
+
stdio: "inherit",
|
|
229
|
+
env: process.env
|
|
230
|
+
});
|
|
231
|
+
child.on("exit", (code) => process.exit(code ?? 0));
|
|
232
|
+
} catch (err) {
|
|
233
|
+
fail(err);
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
cli.command("init", "Scaffold a starter config and first page").action(() => {
|
|
237
|
+
try {
|
|
238
|
+
const result = initProject(process.cwd());
|
|
239
|
+
console.log(`
|
|
240
|
+
${pc.green("\u2714 open-doc")} scaffolded your docs:
|
|
241
|
+
`);
|
|
242
|
+
for (const file of result.created) console.log(` ${pc.cyan(file)}`);
|
|
243
|
+
console.log("\nNext steps:");
|
|
244
|
+
let step = 1;
|
|
245
|
+
if (!result.hasPackageJson) {
|
|
246
|
+
console.log(` ${step++}. ${pc.bold("npm init -y")}`);
|
|
247
|
+
}
|
|
248
|
+
console.log(` ${step++}. ${pc.bold("npm install -D @openlaboratory/open-doc")}`);
|
|
249
|
+
if (!result.addedScripts) {
|
|
250
|
+
console.log(` add scripts: "dev": "open-doc dev", "build": "open-doc build"`);
|
|
251
|
+
}
|
|
252
|
+
console.log(` ${step++}. ${pc.bold("npm run dev")}
|
|
253
|
+
`);
|
|
254
|
+
} catch (err) {
|
|
255
|
+
fail(err);
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
cli.help();
|
|
259
|
+
cli.version(version);
|
|
260
|
+
var parsed = cli.parse(process.argv, { run: false });
|
|
261
|
+
if (parsed.options.help || parsed.options.version) {
|
|
262
|
+
} else if (cli.matchedCommand) {
|
|
263
|
+
cli.runMatchedCommand();
|
|
264
|
+
} else if (parsed.args.length > 0) {
|
|
265
|
+
fail(`Unknown command "${parsed.args[0]}". Run "open-doc --help" to see available commands.`);
|
|
266
|
+
} else {
|
|
267
|
+
cli.outputHelp();
|
|
268
|
+
}
|