reallysimpledocs 1.0.0-beta.5 → 1.0.1

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.
@@ -28,10 +28,15 @@
28
28
  > p a,
29
29
  > li a,
30
30
  > dl a,
31
- > table td a,
32
- > table th a {
31
+ > .table-container a,
32
+ [role="listitem"] > p > a,
33
+ [role="listitem"] > li > a {
33
34
  @apply underline underline-offset-2 decoration-muted-foreground/50 hover:decoration-foreground/50 transition-all;
34
35
  }
36
+ b,
37
+ strong {
38
+ @apply font-semibold;
39
+ }
35
40
  code:not(pre > code) {
36
41
  @apply relative rounded-md bg-muted px-[0.3rem] py-[0.2rem] font-mono text-[13px];
37
42
  }
@@ -76,10 +81,6 @@
76
81
  @apply mt-4 border-b-0 pb-0 pl-8 my-0;
77
82
  }
78
83
  }
79
- b,
80
- strong {
81
- @apply font-semibold;
82
- }
83
84
  > p,
84
85
  > blockquote,
85
86
  > ul,
@@ -94,29 +95,10 @@
94
95
  > *:last-child {
95
96
  @apply !mb-0;
96
97
  }
97
- > table {
98
- @apply w-full caption-bottom text-sm;
99
- thead {
100
- @apply [&_tr]:border-b;
101
- }
102
- tbody {
103
- @apply [&_tr:last-child]:border-0;
104
- }
105
- tfoot {
106
- @apply bg-muted/50 border-t font-medium [&>tr]:last:border-b-0;
107
- }
108
- tr {
109
- @apply hover:bg-muted/50 border-b transition-colors;
110
- }
111
- th {
112
- @apply text-foreground h-10 px-2 text-left align-middle font-medium [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px];
113
- }
114
- td {
115
- @apply p-2 align-middle [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px];
116
- }
117
- caption {
118
- @apply text-muted-foreground mt-4 text-sm;
119
- }
98
+
99
+ > .table-container .table th,
100
+ > .table-container .table td {
101
+ @apply whitespace-normal;
120
102
  }
121
103
  }
122
104
 
@@ -184,20 +166,28 @@ html.dark .astro-code span {
184
166
  @apply text-amber-700 dark:text-amber-300;
185
167
  }
186
168
 
187
- .code-block {
188
- @apply relative my-6 w-full max-w-full overflow-hidden rounded-lg;
169
+ .code-frame,
170
+ .tabs-frame {
171
+ @apply relative my-6 w-full max-w-full rounded-lg;
172
+ }
173
+
174
+ .code-frame > header {
175
+ @apply flex h-10 items-center gap-2 overflow-x-auto rounded-t-[inherit] border-b bg-muted px-3 text-sm font-medium dark:bg-muted/50;
176
+ scrollbar-width: none;
177
+ }
178
+
179
+ .tabs-frame > header {
180
+ @apply flex items-center gap-2 overflow-x-auto rounded-t-[inherit] border-b bg-muted px-3 py-0.5 text-sm font-medium dark:bg-muted/50;
181
+ scrollbar-width: none;
189
182
  }
190
183
 
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;
184
+ .code-frame > header::-webkit-scrollbar,
185
+ .tabs-frame > header::-webkit-scrollbar {
186
+ display: none;
195
187
  }
196
188
 
197
- .code-block > header > :first-child,
198
- .code-group > header > :first-child,
199
- .preview > header > :first-child {
200
- @apply mr-auto;
189
+ .code-block {
190
+ @apply relative my-6 w-full max-w-full overflow-hidden rounded-lg;
201
191
  }
202
192
 
203
193
  .code-block > pre {
@@ -213,103 +203,28 @@ html.dark .astro-code span {
213
203
  }
214
204
 
215
205
  .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;
206
+ @apply absolute right-2.5 top-2.5 z-10 [&_svg]:size-4 flex size-6 shrink-0 items-center justify-center rounded-md text-muted-foreground outline-none bg-muted/50 dark:bg-muted/25 backdrop-blur-sm hover:text-foreground transition-colors;
237
207
  }
238
208
 
239
- .code-group > header > .tabs {
240
- @apply my-0 min-w-0 max-w-full gap-0;
209
+ .code-frame > .code-block,
210
+ .tabs-frame > [data-code-panel] .code-block {
211
+ @apply my-0 min-w-0 rounded-none rounded-b-[inherit];
241
212
  }
242
213
 
243
- .code-group > header > .tabs > nav {
244
- @apply h-full justify-start rounded-none bg-transparent p-0;
214
+ .tabs-frame {
215
+ @apply overflow-visible;
245
216
  }
246
217
 
247
- .code-group > [role="tabpanel"] {
248
- @apply border-t-0;
218
+ .code-frame {
219
+ @apply overflow-hidden;
249
220
  }
250
221
 
251
- .code-group .code-block {
252
- @apply my-0 min-w-0 rounded-none;
222
+ .tabs-frame > [role="tabpanel"] {
223
+ @apply rounded-b-[inherit];
253
224
  }
254
225
 
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;
226
+ .tabs-frame > [data-preview-panel] {
227
+ @apply flex min-h-64 items-center justify-center p-6 bg-muted/50 dark:bg-muted/25;
313
228
  }
314
229
 
315
230
  .steps {
@@ -353,11 +268,15 @@ html.dark .astro-code span {
353
268
  }
354
269
 
355
270
  .steps > section > * + * {
356
- @apply mt-6;
271
+ @apply mt-3;
357
272
  }
358
273
 
359
274
  .steps > section > h3 + * {
360
- @apply mt-4;
275
+ @apply mt-2;
276
+ }
277
+
278
+ .steps > section > :where(.code-frame, .code-block, .tabs-frame) {
279
+ @apply my-3;
361
280
  }
362
281
 
363
282
  .steps > section > * {
@@ -375,7 +294,8 @@ html.dark .astro-code span {
375
294
  .prose > .alert,
376
295
  .prose > .docs-card,
377
296
  .prose > .grid,
378
- .prose > .tabs {
297
+ .prose > .tabs,
298
+ .prose > .tabs-frame {
379
299
  @apply my-6;
380
300
  }
381
301
 
@@ -1,11 +1,9 @@
1
+ .code-frame,
1
2
  .code-block,
2
- .code-group,
3
- .preview {
3
+ .tabs-frame {
4
4
  @apply rounded-2xl;
5
5
  }
6
6
 
7
- .code-block > header,
8
- .code-group > header,
9
- .preview > header {
10
- @apply h-[38px];
7
+ .code-frame > header {
8
+ @apply h-[40px];
11
9
  }
@@ -1,11 +1,9 @@
1
+ .code-frame,
1
2
  .code-block,
2
- .code-group,
3
- .preview {
3
+ .tabs-frame {
4
4
  @apply rounded-none;
5
5
  }
6
6
 
7
- .code-block > header,
8
- .code-group > header,
9
- .preview > header {
10
- @apply h-[30px];
7
+ .code-frame > header {
8
+ @apply h-[32px];
11
9
  }
@@ -1,11 +1,9 @@
1
+ .code-frame,
1
2
  .code-block,
2
- .code-group,
3
- .preview {
3
+ .tabs-frame {
4
4
  @apply rounded-lg;
5
5
  }
6
6
 
7
- .code-block > header,
8
- .code-group > header,
9
- .preview > header {
10
- @apply h-[38px];
7
+ .code-frame > header {
8
+ @apply h-[40px];
11
9
  }
@@ -1,11 +1,9 @@
1
+ .code-frame,
1
2
  .code-block,
2
- .code-group,
3
- .preview {
3
+ .tabs-frame {
4
4
  @apply rounded-lg;
5
5
  }
6
6
 
7
- .code-block > header,
8
- .code-group > header,
9
- .preview > header {
10
- @apply h-[30px];
7
+ .code-frame > header {
8
+ @apply h-[32px];
11
9
  }
@@ -1,11 +1,9 @@
1
+ .code-frame,
1
2
  .code-block,
2
- .code-group,
3
- .preview {
3
+ .tabs-frame {
4
4
  @apply rounded-lg;
5
5
  }
6
6
 
7
- .code-block > header,
8
- .code-group > header,
9
- .preview > header {
10
- @apply h-[34px];
7
+ .code-frame > header {
8
+ @apply h-[36px];
11
9
  }
@@ -1,11 +1,9 @@
1
+ .code-frame,
1
2
  .code-block,
2
- .code-group,
3
- .preview {
3
+ .tabs-frame {
4
4
  @apply rounded-2xl;
5
5
  }
6
6
 
7
- .code-block > header,
8
- .code-group > header,
9
- .preview > header {
10
- @apply h-[34px];
7
+ .code-frame > header {
8
+ @apply h-[36px];
11
9
  }
@@ -1,11 +1,9 @@
1
+ .code-frame,
1
2
  .code-block,
2
- .code-group,
3
- .preview {
3
+ .tabs-frame {
4
4
  @apply rounded-none;
5
5
  }
6
6
 
7
- .code-block > header,
8
- .code-group > header,
9
- .preview > header {
10
- @apply h-[38px];
7
+ .code-frame > header {
8
+ @apply h-[40px];
11
9
  }
@@ -1,11 +1,9 @@
1
+ .code-frame,
1
2
  .code-block,
2
- .code-group,
3
- .preview {
3
+ .tabs-frame {
4
4
  @apply rounded-lg;
5
5
  }
6
6
 
7
- .code-block > header,
8
- .code-group > header,
9
- .preview > header {
10
- @apply h-[38px];
7
+ .code-frame > header {
8
+ @apply h-[40px];
11
9
  }
@@ -23,29 +23,12 @@ const absoluteAssetUrl = (value) => {
23
23
  const path = assetPath(value);
24
24
  return path.startsWith("http") ? path : `${siteUrl}${path}`;
25
25
  };
26
+ const bodyAttrs = config.bodyAttrs || {};
26
27
  ---
27
28
 
28
29
  <!doctype html>
29
30
  <html lang="en">
30
31
  <head>
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
- />
49
32
  <meta charset="utf-8" />
50
33
  <meta http-equiv="Content-Language" content="en" />
51
34
  <meta name="viewport" content="width=device-width, initial-scale=1" />
@@ -69,8 +52,26 @@ const absoluteAssetUrl = (value) => {
69
52
  <meta name="twitter:description" content={metaDescription} />
70
53
  {socialImage && <meta name="twitter:image" content={absoluteAssetUrl(socialImage)} />}
71
54
  {site.author?.x && <meta name="twitter:creator" content={site.author.x} />}
55
+ <DefaultHead
56
+ config={config}
57
+ site={site}
58
+ title={title}
59
+ description={metaDescription}
60
+ pagePath={pagePath}
61
+ metaTitle={metaTitle}
62
+ absoluteUrl={absoluteUrl}
63
+ />
64
+ <Head
65
+ config={config}
66
+ site={site}
67
+ title={title}
68
+ description={metaDescription}
69
+ pagePath={pagePath}
70
+ metaTitle={metaTitle}
71
+ absoluteUrl={absoluteUrl}
72
+ />
72
73
  </head>
73
- <body>
74
+ <body {...bodyAttrs}>
74
75
  <slot />
75
76
  </body>
76
77
  </html>
@@ -212,18 +212,33 @@ const { indexUrl = routeFilePath(config.routeBase, "search-index.json") } = Astr
212
212
  refreshCommand();
213
213
  }
214
214
 
215
+ function renderEmpty() {
216
+ if (!menu) return;
217
+ delete menu.dataset.loading;
218
+ menu.innerHTML = "";
219
+ refreshCommand();
220
+ }
221
+
215
222
  async function loadIndex() {
216
223
  if (state.index) return state;
217
224
  if (!indexUrl) throw new Error("Missing ReallySimpleDocs search index URL.");
218
225
  if (!state.loadPromise) {
219
226
  renderLoading();
220
227
  state.loadPromise = fetch(indexUrl)
221
- .then((response) => response.json())
228
+ .then((response) => {
229
+ if (!response.ok) throw new Error(`Failed to load search index: ${response.status}`);
230
+ return response.json();
231
+ })
222
232
  .then((data) => {
223
233
  state.documents = data.documents || [];
224
234
  state.bySlug = new Map(state.documents.map((doc) => [doc.slug, doc]));
225
235
  state.index = lunr.Index.load(data.index);
226
236
  return state;
237
+ })
238
+ .catch((error) => {
239
+ state.loadPromise = null;
240
+ renderEmpty();
241
+ throw error;
227
242
  });
228
243
  }
229
244
  return state.loadPromise;
@@ -253,10 +268,14 @@ const { indexUrl = routeFilePath(config.routeBase, "search-index.json") } = Astr
253
268
  }
254
269
 
255
270
  async function refreshResults() {
256
- await loadIndex();
257
- const query = input?.value || "";
258
- const results = search(query).slice(0, MAX_RESULTS);
259
- renderItems(results, query.trim() ? "Results" : "Docs", query);
271
+ try {
272
+ await loadIndex();
273
+ const query = input?.value || "";
274
+ const results = search(query).slice(0, MAX_RESULTS);
275
+ renderItems(results, query.trim() ? "Results" : "Docs", query);
276
+ } catch (error) {
277
+ console.error("[search] Failed to load index:", error);
278
+ }
260
279
  }
261
280
 
262
281
  window.rsdOpenCommandSearch = async () => {
@@ -8,7 +8,11 @@ import basecoatJsUrl from "basecoat-css/all.min?url";
8
8
  (() => {
9
9
  try {
10
10
  const stored = localStorage.getItem("themeMode");
11
- if (stored ? stored === "dark" : matchMedia("(prefers-color-scheme: dark)").matches) {
11
+ if (
12
+ stored
13
+ ? stored === "dark"
14
+ : matchMedia("(prefers-color-scheme: dark)").matches
15
+ ) {
12
16
  document.documentElement.classList.add("dark");
13
17
  }
14
18
  } catch (_) {}
@@ -34,37 +38,22 @@ import basecoatJsUrl from "basecoat-css/all.min?url";
34
38
  if (!ok) throw new Error("Copy failed");
35
39
  };
36
40
 
37
- const activePanelCode = (root) => root.querySelector(':scope > [role="tabpanel"]:not([hidden]) code');
38
-
39
41
  const initCopyCode = (codeBlock) => {
40
42
  if (codeBlock.dataset.copyCodeInitialized) return;
41
43
  const codeEl = codeBlock.querySelector(":scope > code");
42
44
  if (!codeEl) return;
43
45
 
44
- let target = null;
45
- let frame = codeBlock.closest(".code-group");
46
- let getCode = frame ? () => activePanelCode(frame) || codeEl : () => codeEl;
47
- if (frame) target = frame.querySelector(":scope > header");
48
-
49
- const preview = codeBlock.closest(".preview");
50
- const previewCodePanel = preview?.querySelector(":scope > [data-code-panel]");
51
- if (!frame && previewCodePanel?.contains(codeBlock)) {
52
- frame = preview;
53
- target = frame.querySelector(":scope > header");
54
- getCode = () => codeEl;
55
- }
56
-
46
+ let frame = codeBlock.parentElement?.classList.contains("code-block")
47
+ ? codeBlock.parentElement
48
+ : null;
57
49
  if (!frame) {
58
- frame = codeBlock.parentElement?.classList.contains("code-block") ? codeBlock.parentElement : null;
59
- if (!frame) {
60
- frame = document.createElement("div");
61
- frame.className = "code-block";
62
- codeBlock.parentNode.insertBefore(frame, codeBlock);
63
- frame.appendChild(codeBlock);
64
- }
50
+ frame = document.createElement("div");
51
+ frame.className = "code-block";
52
+ codeBlock.parentNode.insertBefore(frame, codeBlock);
53
+ frame.appendChild(codeBlock);
65
54
  }
66
55
 
67
- target ||= frame.querySelector(":scope > header") || frame;
56
+ const target = frame;
68
57
  if (target.querySelector(":scope > button[aria-label='Copy code']")) {
69
58
  codeBlock.dataset.copyCodeInitialized = "true";
70
59
  return;
@@ -72,14 +61,11 @@ import basecoatJsUrl from "basecoat-css/all.min?url";
72
61
 
73
62
  const button = document.createElement("button");
74
63
  button.type = "button";
75
- button.className = "btn";
76
- button.dataset.variant = "ghost";
77
- button.dataset.size = "icon-xs";
78
64
  button.setAttribute("aria-label", "Copy code");
79
65
  button.innerHTML = copyIcon;
80
66
 
81
67
  button.addEventListener("click", async () => {
82
- const text = (getCode()?.textContent || "").replace(/\n$/, "");
68
+ const text = (codeEl.textContent || "").replace(/\n$/, "");
83
69
  if (!text) return;
84
70
 
85
71
  try {
@@ -99,11 +85,15 @@ import basecoatJsUrl from "basecoat-css/all.min?url";
99
85
  };
100
86
 
101
87
  const initCopyButtons = (root = document) => {
102
- root.querySelectorAll("pre:has(> code):not([data-copy-code-initialized])").forEach(initCopyCode);
88
+ root
89
+ .querySelectorAll("pre:has(> code):not([data-copy-code-initialized])")
90
+ .forEach(initCopyCode);
103
91
  };
104
92
 
105
93
  if (document.readyState === "loading") {
106
- document.addEventListener("DOMContentLoaded", () => initCopyButtons(), { once: true });
94
+ document.addEventListener("DOMContentLoaded", () => initCopyButtons(), {
95
+ once: true,
96
+ });
107
97
  } else {
108
98
  initCopyButtons();
109
99
  }