reallysimpledocs 1.0.0-beta.3 → 1.0.0-beta.5

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.
Files changed (43) hide show
  1. package/README.md +33 -31
  2. package/package.json +10 -5
  3. package/src/astro/index.js +46 -43
  4. package/src/astro/preview-source.js +90 -0
  5. package/src/components/index.js +1 -0
  6. package/src/css/custom.css +259 -29
  7. package/src/css/styles/luma.css +11 -0
  8. package/src/css/styles/lyra.css +11 -0
  9. package/src/css/styles/maia.css +11 -0
  10. package/src/css/styles/mira.css +11 -0
  11. package/src/css/styles/nova.css +11 -0
  12. package/src/css/styles/rhea.css +11 -0
  13. package/src/css/styles/sera.css +11 -0
  14. package/src/css/styles/vega.css +11 -0
  15. package/src/runtime/components/BaseLayout.astro +20 -27
  16. package/src/runtime/components/CommandDialog.astro +29 -14
  17. package/src/runtime/components/DefaultContentHeader.astro +2 -0
  18. package/src/runtime/components/DefaultHead.astro +120 -0
  19. package/src/runtime/components/DefaultHeadContent.astro +2 -0
  20. package/src/runtime/components/DefaultSidebarFooter.astro +2 -0
  21. package/src/runtime/components/DefaultSidebarHeader.astro +1 -1
  22. package/src/runtime/components/DocsLayout.astro +90 -122
  23. package/src/runtime/components/DropdownMenu.astro +1 -1
  24. package/src/runtime/components/Sidebar.astro +4 -0
  25. package/src/runtime/components/ThemeToggle.astro +21 -0
  26. package/src/runtime/components/mdx/Callout.astro +2 -9
  27. package/src/runtime/components/mdx/Card.astro +3 -8
  28. package/src/runtime/components/mdx/CardGrid.astro +1 -1
  29. package/src/runtime/components/mdx/Code.astro +2 -16
  30. package/src/runtime/components/mdx/CodeGroup.astro +7 -11
  31. package/src/runtime/components/mdx/Preview.astro +7 -12
  32. package/src/runtime/components/mdx/Steps.astro +1 -5
  33. package/src/runtime/components/mdx/Tab.astro +6 -0
  34. package/src/runtime/components/mdx/Tabs.astro +7 -7
  35. package/src/runtime/lib/docs.js +122 -16
  36. package/src/runtime/lib/highlight.js +1 -14
  37. package/src/runtime/lib/macros.js +11 -2
  38. package/src/runtime/lib/markdown-export.js +163 -0
  39. package/src/runtime/lib/site.js +0 -1
  40. package/src/runtime/pages/search-index.ts +10 -1
  41. package/src/css/overrides.css +0 -1
  42. package/src/css/sources.css +0 -1
  43. package/src/runtime/scripts/copy-code.js +0 -109
@@ -1,3 +1,5 @@
1
+ @source "../runtime/**/*.{astro,js,ts}";
2
+
1
3
  @theme {
2
4
  --color-search-highlight: oklch(90.5% 0.182 98.111);
3
5
  }
@@ -23,12 +25,11 @@
23
25
  > h1:first-child {
24
26
  @apply hidden;
25
27
  }
26
- p > a,
27
- li > a,
28
- dt > a,
29
- dd > a,
30
- td > a,
31
- th > a {
28
+ > p a,
29
+ > li a,
30
+ > dl a,
31
+ > table td a,
32
+ > table th a {
32
33
  @apply underline underline-offset-2 decoration-muted-foreground/50 hover:decoration-foreground/50 transition-all;
33
34
  }
34
35
  code:not(pre > code) {
@@ -41,19 +42,19 @@
41
42
  @apply block min-w-full w-max px-4 py-3 text-[13px];
42
43
  }
43
44
  pre:has(> code) {
44
- @apply max-w-full overflow-x-auto;
45
+ @apply scrollbar max-w-full overflow-x-auto;
45
46
  }
46
- blockquote {
47
+ > blockquote {
47
48
  @apply border-l-4 border-border pl-4;
48
49
  }
49
- ol {
50
+ > ol {
50
51
  @apply list-decimal ml-6;
51
52
  }
52
- ul {
53
+ > ul {
53
54
  @apply list-disc ml-6;
54
55
  }
55
- ol,
56
- ul {
56
+ > ol,
57
+ > ul {
57
58
  li {
58
59
  @apply mt-2;
59
60
 
@@ -63,7 +64,7 @@
63
64
  }
64
65
  }
65
66
  }
66
- dl {
67
+ > dl {
67
68
  @apply border-b pb-3 my-6;
68
69
  dt {
69
70
  @apply border-t pt-3 mt-3 first:mt-0;
@@ -80,11 +81,11 @@
80
81
  @apply font-semibold;
81
82
  }
82
83
  > p,
83
- blockquote,
84
- ul,
85
- ol,
86
- dl,
87
- pre {
84
+ > blockquote,
85
+ > ul,
86
+ > ol,
87
+ > dl,
88
+ > pre {
88
89
  @apply my-6;
89
90
  }
90
91
  > *:first-child {
@@ -93,7 +94,7 @@
93
94
  > *:last-child {
94
95
  @apply !mb-0;
95
96
  }
96
- table {
97
+ > table {
97
98
  @apply w-full caption-bottom text-sm;
98
99
  thead {
99
100
  @apply [&_tr]:border-b;
@@ -122,7 +123,11 @@
122
123
  .shiki,
123
124
  .astro-code {
124
125
  @apply bg-muted/50;
125
- background-color: color-mix(in oklab, var(--color-muted) 50%, transparent) !important;
126
+ background-color: color-mix(
127
+ in oklab,
128
+ var(--color-muted) 50%,
129
+ transparent
130
+ ) !important;
126
131
  color: var(--shiki-light);
127
132
  }
128
133
 
@@ -141,22 +146,247 @@ html.dark .astro-code span {
141
146
  color: var(--shiki-dark);
142
147
  }
143
148
 
144
- #command-search > .command {
145
- @apply sm:max-w-2xl;
149
+ [data-search] .command a[role="menuitem"] {
150
+ @apply h-auto min-h-0 flex-col items-start gap-1 overflow-visible whitespace-normal py-2;
151
+ }
152
+
153
+ [data-search] .command a[role="menuitem"] > strong {
154
+ @apply w-full font-medium leading-5;
155
+ }
156
+
157
+ [data-search] .command a[role="menuitem"] > span {
158
+ @apply text-muted-foreground line-clamp-2 w-full text-sm font-normal leading-5;
159
+ }
160
+
161
+ .command mark {
162
+ @apply bg-search-highlight/50 text-foreground dark:bg-search-highlight/25;
146
163
  }
147
164
 
148
- [data-search] .command a[role='menuitem'] {
149
- @apply flex-col items-start gap-1;
165
+ .docs-card {
166
+ @apply block w-full rounded-lg border bg-card p-3 text-card-foreground no-underline;
150
167
  }
151
168
 
152
- [data-search] .command a[role='menuitem'] > strong {
169
+ .docs-card > h3 {
153
170
  @apply font-medium;
154
171
  }
155
172
 
156
- [data-search] .command a[role='menuitem'] > span {
157
- @apply text-muted-foreground line-clamp-2 text-xs font-normal leading-snug;
173
+ .docs-card > p {
174
+ @apply mt-1 text-sm text-muted-foreground;
158
175
  }
159
176
 
160
- .command mark {
161
- @apply bg-search-highlight/50 text-foreground rounded-sm px-0.5 dark:bg-search-highlight/25;
177
+ .docs-card-link {
178
+ @apply transition-colors hover:bg-accent focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50;
179
+ }
180
+
181
+ .alert[data-variant="warning"] > svg,
182
+ .alert[data-variant="warning"] > h3,
183
+ .alert[data-variant="warning"] > section {
184
+ @apply text-amber-700 dark:text-amber-300;
185
+ }
186
+
187
+ .code-block {
188
+ @apply relative my-6 w-full max-w-full overflow-hidden rounded-lg;
189
+ }
190
+
191
+ .code-block > header,
192
+ .code-group > header,
193
+ .preview > header {
194
+ @apply flex h-10 items-center gap-2 border-b border-border bg-muted/50 px-3 text-sm font-medium;
195
+ }
196
+
197
+ .code-block > header > :first-child,
198
+ .code-group > header > :first-child,
199
+ .preview > header > :first-child {
200
+ @apply mr-auto;
201
+ }
202
+
203
+ .code-block > pre {
204
+ @apply scrollbar my-0 max-w-full overflow-x-auto rounded-none border-0;
205
+ }
206
+
207
+ .code-block > pre > code {
208
+ @apply block min-w-full w-max px-4 py-3 text-[13px];
209
+ }
210
+
211
+ .code-block > .shiki {
212
+ @apply my-0 rounded-none border-0;
213
+ }
214
+
215
+ .code-block > button {
216
+ @apply absolute right-2.5 top-2.5 z-10;
217
+ }
218
+
219
+ .code-block button,
220
+ .code-group button[aria-label="Copy code"],
221
+ .preview button[aria-label="Copy code"] {
222
+ @apply flex size-6 shrink-0 items-center justify-center rounded-md text-muted-foreground outline-none hover:text-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 [&_svg]:size-4;
223
+ }
224
+
225
+ .code-block > button {
226
+ @apply bg-background/80 shadow-xs backdrop-blur-sm hover:bg-accent/80 dark:bg-background/60 dark:hover:bg-accent/70;
227
+ }
228
+
229
+ .code-block > header > button,
230
+ .code-group > header > button,
231
+ .preview > header > button {
232
+ @apply ml-auto;
233
+ }
234
+
235
+ .code-group {
236
+ @apply relative my-6 w-full max-w-full overflow-hidden rounded-lg;
237
+ }
238
+
239
+ .code-group > header > .tabs {
240
+ @apply my-0 min-w-0 max-w-full gap-0;
241
+ }
242
+
243
+ .code-group > header > .tabs > nav {
244
+ @apply h-full justify-start rounded-none bg-transparent p-0;
245
+ }
246
+
247
+ .code-group > [role="tabpanel"] {
248
+ @apply border-t-0;
249
+ }
250
+
251
+ .code-group .code-block {
252
+ @apply my-0 min-w-0 rounded-none;
253
+ }
254
+
255
+ .code-group .code-block > header {
256
+ @apply hidden;
257
+ }
258
+
259
+ .preview {
260
+ @apply relative my-6 max-w-full overflow-visible rounded-lg;
261
+ }
262
+
263
+ .preview::before {
264
+ @apply pointer-events-none absolute inset-0 z-10 border border-border;
265
+ border-radius: inherit;
266
+ content: "";
267
+ }
268
+
269
+ .preview > header > .tabs {
270
+ @apply my-0 min-w-0 max-w-full gap-0;
271
+ }
272
+
273
+ .preview > header {
274
+ @apply relative z-0 rounded-t-[inherit];
275
+ }
276
+
277
+ .preview > header > .tabs > nav {
278
+ @apply h-full justify-start rounded-none bg-transparent p-0;
279
+ }
280
+
281
+ .preview > [role="tabpanel"] {
282
+ @apply border-t-0;
283
+ }
284
+
285
+ .preview > [data-code-panel] {
286
+ @apply overflow-hidden rounded-b-[inherit];
287
+ }
288
+
289
+ .preview > [data-code-panel] .code-block {
290
+ @apply my-0 min-w-0 rounded-none;
291
+ }
292
+
293
+ .preview > header > button[aria-label="Copy code"] {
294
+ display: none;
295
+ }
296
+
297
+ .preview:has(> [data-code-panel]:not([hidden]))
298
+ > header
299
+ > button[aria-label="Copy code"] {
300
+ display: flex;
301
+ }
302
+
303
+ .preview > [data-preview-panel] {
304
+ @apply flex min-h-64 items-center justify-center p-6;
305
+ }
306
+
307
+ .preview > [data-preview-panel] :where(ul, ol) {
308
+ @apply m-0;
309
+ }
310
+
311
+ .preview > [data-preview-panel] :where(li) {
312
+ @apply mt-0;
313
+ }
314
+
315
+ .steps {
316
+ @apply mb-12 mt-6 md:ml-4 md:border-l md:pl-8;
317
+ counter-reset: step;
318
+ }
319
+
320
+ .steps > section {
321
+ counter-increment: step;
322
+ }
323
+
324
+ .steps > section + section {
325
+ @apply mt-6;
326
+ }
327
+
328
+ .steps > section > h3 {
329
+ @apply relative mt-12 scroll-m-28 text-lg font-medium tracking-tight;
330
+ }
331
+
332
+ .steps > section + section > h3 {
333
+ @apply mt-0;
334
+ }
335
+
336
+ .steps > section:first-child > h3 {
337
+ @apply mt-0;
338
+ }
339
+
340
+ .steps > section > h3::before {
341
+ @apply mr-4 inline-flex size-7 items-center justify-center rounded-full bg-muted text-sm font-medium text-muted-foreground;
342
+ content: counter(step);
343
+ }
344
+
345
+ @media (width >= 48rem) {
346
+ .steps > section > h3::before {
347
+ position: absolute;
348
+ left: 0;
349
+ top: 0;
350
+ margin-right: 0;
351
+ transform: translateX(-2.875rem);
352
+ }
353
+ }
354
+
355
+ .steps > section > * + * {
356
+ @apply mt-6;
357
+ }
358
+
359
+ .steps > section > h3 + * {
360
+ @apply mt-4;
361
+ }
362
+
363
+ .steps > section > * {
364
+ @apply leading-relaxed;
365
+ }
366
+
367
+ .steps > section > *:first-child {
368
+ @apply mt-0;
369
+ }
370
+
371
+ .steps > section > *:last-child {
372
+ @apply mb-0;
373
+ }
374
+
375
+ .prose > .alert,
376
+ .prose > .docs-card,
377
+ .prose > .grid,
378
+ .prose > .tabs {
379
+ @apply my-6;
380
+ }
381
+
382
+ .command [role="menu"][data-loading]::before {
383
+ content: none;
384
+ }
385
+
386
+ .command [role="menu"] > [data-rsd-command-loading] {
387
+ @apply flex min-h-16 items-center justify-center gap-2 py-6 text-center text-sm text-muted-foreground;
388
+
389
+ svg {
390
+ @apply size-4 animate-spin;
391
+ }
162
392
  }
@@ -0,0 +1,11 @@
1
+ .code-block,
2
+ .code-group,
3
+ .preview {
4
+ @apply rounded-2xl;
5
+ }
6
+
7
+ .code-block > header,
8
+ .code-group > header,
9
+ .preview > header {
10
+ @apply h-[38px];
11
+ }
@@ -0,0 +1,11 @@
1
+ .code-block,
2
+ .code-group,
3
+ .preview {
4
+ @apply rounded-none;
5
+ }
6
+
7
+ .code-block > header,
8
+ .code-group > header,
9
+ .preview > header {
10
+ @apply h-[30px];
11
+ }
@@ -0,0 +1,11 @@
1
+ .code-block,
2
+ .code-group,
3
+ .preview {
4
+ @apply rounded-lg;
5
+ }
6
+
7
+ .code-block > header,
8
+ .code-group > header,
9
+ .preview > header {
10
+ @apply h-[38px];
11
+ }
@@ -0,0 +1,11 @@
1
+ .code-block,
2
+ .code-group,
3
+ .preview {
4
+ @apply rounded-lg;
5
+ }
6
+
7
+ .code-block > header,
8
+ .code-group > header,
9
+ .preview > header {
10
+ @apply h-[30px];
11
+ }
@@ -0,0 +1,11 @@
1
+ .code-block,
2
+ .code-group,
3
+ .preview {
4
+ @apply rounded-lg;
5
+ }
6
+
7
+ .code-block > header,
8
+ .code-group > header,
9
+ .preview > header {
10
+ @apply h-[34px];
11
+ }
@@ -0,0 +1,11 @@
1
+ .code-block,
2
+ .code-group,
3
+ .preview {
4
+ @apply rounded-2xl;
5
+ }
6
+
7
+ .code-block > header,
8
+ .code-group > header,
9
+ .preview > header {
10
+ @apply h-[34px];
11
+ }
@@ -0,0 +1,11 @@
1
+ .code-block,
2
+ .code-group,
3
+ .preview {
4
+ @apply rounded-none;
5
+ }
6
+
7
+ .code-block > header,
8
+ .code-group > header,
9
+ .preview > header {
10
+ @apply h-[38px];
11
+ }
@@ -0,0 +1,11 @@
1
+ .code-block,
2
+ .code-group,
3
+ .preview {
4
+ @apply rounded-lg;
5
+ }
6
+
7
+ .code-block > header,
8
+ .code-group > header,
9
+ .preview > header {
10
+ @apply h-[38px];
11
+ }
@@ -1,6 +1,7 @@
1
1
  ---
2
- import "virtual:reallysimpledocs/styles.css";
3
2
  import config from "virtual:reallysimpledocs/config";
3
+ import Head from "virtual:reallysimpledocs/components/Head";
4
+ import DefaultHead from "./DefaultHead.astro";
4
5
  import { getSite } from "../lib/site.js";
5
6
 
6
7
  const { title, description, pagePath = "/" } = Astro.props;
@@ -27,28 +28,24 @@ const absoluteAssetUrl = (value) => {
27
28
  <!doctype html>
28
29
  <html lang="en">
29
30
  <head>
30
- <script is:inline>
31
- (() => {
32
- try {
33
- const stored = localStorage.getItem("themeMode");
34
- if (stored ? stored === "dark" : matchMedia("(prefers-color-scheme: dark)").matches) {
35
- document.documentElement.classList.add("dark");
36
- }
37
- } catch (_) {}
38
-
39
- const apply = (dark) => {
40
- document.documentElement.classList.toggle("dark", dark);
41
- try {
42
- localStorage.setItem("themeMode", dark ? "dark" : "light");
43
- } catch (_) {}
44
- };
45
-
46
- document.addEventListener("basecoat:theme", (event) => {
47
- const mode = event.detail?.mode;
48
- apply(mode === "dark" ? true : mode === "light" ? false : !document.documentElement.classList.contains("dark"));
49
- });
50
- })();
51
- </script>
31
+ <DefaultHead
32
+ config={config}
33
+ site={site}
34
+ title={title}
35
+ description={metaDescription}
36
+ pagePath={pagePath}
37
+ metaTitle={metaTitle}
38
+ absoluteUrl={absoluteUrl}
39
+ />
40
+ <Head
41
+ config={config}
42
+ site={site}
43
+ title={title}
44
+ description={metaDescription}
45
+ pagePath={pagePath}
46
+ metaTitle={metaTitle}
47
+ absoluteUrl={absoluteUrl}
48
+ />
52
49
  <meta charset="utf-8" />
53
50
  <meta http-equiv="Content-Language" content="en" />
54
51
  <meta name="viewport" content="width=device-width, initial-scale=1" />
@@ -72,10 +69,6 @@ const absoluteAssetUrl = (value) => {
72
69
  <meta name="twitter:description" content={metaDescription} />
73
70
  {socialImage && <meta name="twitter:image" content={absoluteAssetUrl(socialImage)} />}
74
71
  {site.author?.x && <meta name="twitter:creator" content={site.author.x} />}
75
- <script>
76
- import "basecoat-css/all.min";
77
- import "../scripts/copy-code.js";
78
- </script>
79
72
  </head>
80
73
  <body>
81
74
  <slot />
@@ -1,7 +1,11 @@
1
1
  ---
2
+ import config from "virtual:reallysimpledocs/config";
2
3
  import { renderCommandDialog } from "../lib/macros.js";
4
+ import { routeFilePath } from "../lib/paths.js";
5
+ import LoaderCircle from "lucide-static/icons/loader-circle.svg?raw";
6
+ import lunrUrl from "lunr/lunr.min.js?url";
3
7
 
4
- const { indexUrl } = Astro.props;
8
+ const { indexUrl = routeFilePath(config.routeBase, "search-index.json") } = Astro.props;
5
9
  ---
6
10
 
7
11
  <div data-search data-index-url={indexUrl}>
@@ -15,9 +19,8 @@ const { indexUrl } = Astro.props;
15
19
  />
16
20
  </div>
17
21
 
18
- <script>
19
- import lunr from "lunr";
20
-
22
+ <script src={lunrUrl}></script>
23
+ <script is:inline define:vars={{ loadingIcon: LoaderCircle }}>
21
24
  const root = document.querySelector("[data-search]");
22
25
  const indexUrl = root?.getAttribute("data-index-url");
23
26
  const dialog = document.getElementById("command-search");
@@ -130,8 +133,8 @@ const { indexUrl } = Astro.props;
130
133
  return space > -1 ? space : end;
131
134
  }
132
135
 
133
- function snippetFromBody(body, ranges) {
134
- const text = String(body || "");
136
+ function snippetFromText(value, ranges) {
137
+ const text = String(value || "");
135
138
  if (!text || !ranges.length) return "";
136
139
 
137
140
  const first = ranges[0];
@@ -148,25 +151,36 @@ const { indexUrl } = Astro.props;
148
151
 
149
152
  function resultView(result, query) {
150
153
  const doc = result.doc || result;
154
+ const displayTitle = doc.breadcrumb || doc.title;
151
155
  if (!query.trim()) {
152
156
  return {
153
157
  path: doc.path,
154
- title: escapeHtml(doc.title),
158
+ title: escapeHtml(displayTitle),
155
159
  snippet: "",
156
160
  };
157
161
  }
158
162
 
159
- const titleRanges = refineRanges(doc.title, rangesFromMatch(result.match, "title"), query);
163
+ let titleRanges = rangesFromMatch(result.match, "breadcrumb");
164
+ if (!titleRanges.length) {
165
+ const titleOffset = String(displayTitle).lastIndexOf(doc.title);
166
+ titleRanges = rangesFromMatch(result.match, "title").map(([start, end]) => [
167
+ titleOffset > -1 ? titleOffset + start : start,
168
+ titleOffset > -1 ? titleOffset + end : end,
169
+ ]);
170
+ }
171
+ titleRanges = refineRanges(displayTitle, titleRanges, query);
160
172
  const bodyRanges = refineRanges(doc.body, rangesFromMatch(result.match, "body"), query);
173
+ const codeRanges = refineRanges(doc.code, rangesFromMatch(result.match, "code"), query);
161
174
  return {
162
175
  path: doc.path,
163
- title: highlightRanges(doc.title, titleRanges),
164
- snippet: snippetFromBody(doc.body, bodyRanges),
176
+ title: highlightRanges(displayTitle, titleRanges),
177
+ snippet: snippetFromText(doc.body, bodyRanges) || snippetFromText(doc.code, codeRanges),
165
178
  };
166
179
  }
167
180
 
168
181
  function renderItems(items, label, query = "") {
169
182
  if (!menu) return;
183
+ delete menu.dataset.loading;
170
184
  if (!items.length) {
171
185
  menu.innerHTML = "";
172
186
  refreshCommand();
@@ -190,16 +204,17 @@ const { indexUrl } = Astro.props;
190
204
 
191
205
  function renderLoading() {
192
206
  if (!menu) return;
193
- menu.innerHTML = `<div role="group" aria-labelledby="command-search-loading-heading">
194
- <span role="heading" id="command-search-loading-heading">Search</span>
195
- <div role="menuitem" aria-disabled="true" data-force><span>Loading...</span></div>
207
+ menu.dataset.loading = "true";
208
+ menu.innerHTML = `<div role="status" aria-live="polite" data-rsd-command-loading>
209
+ <span aria-hidden="true">${loadingIcon}</span>
210
+ <span>Loading...</span>
196
211
  </div>`;
197
212
  refreshCommand();
198
213
  }
199
214
 
200
215
  async function loadIndex() {
201
216
  if (state.index) return state;
202
- if (!indexUrl) throw new Error("Missing reallysimpledocs search index URL.");
217
+ if (!indexUrl) throw new Error("Missing ReallySimpleDocs search index URL.");
203
218
  if (!state.loadPromise) {
204
219
  renderLoading();
205
220
  state.loadPromise = fetch(indexUrl)