@astrojs/starlight 0.9.1 → 0.10.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # @astrojs/starlight
2
2
 
3
+ ## 0.10.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [#726](https://github.com/withastro/starlight/pull/726) [`f3157c6`](https://github.com/withastro/starlight/commit/f3157c6065943af39995b6dbae5f63cf424bd9a3) Thanks [@delucis](https://github.com/delucis)! - Fix a rare bug in table of contents when handling headings that increase by more than one level on a page.
8
+
9
+ - [#729](https://github.com/withastro/starlight/pull/729) [`80c6ab1`](https://github.com/withastro/starlight/commit/80c6ab1c1ec48805e74c53b615a78d65127eeacb) Thanks [@delucis](https://github.com/delucis)! - Upgrade Pagefind to v1.0.3
10
+
11
+ - [#715](https://github.com/withastro/starlight/pull/715) [`e726155`](https://github.com/withastro/starlight/commit/e7261559f2539a0ceefd36a28e4fbbc17f5970b8) Thanks [@itsmatteomanf](https://github.com/itsmatteomanf)! - feat: prevent scroll on body when search is open
12
+
13
+ ## 0.10.0
14
+
15
+ ### Minor Changes
16
+
17
+ - [#692](https://github.com/withastro/starlight/pull/692) [`2a58e1a`](https://github.com/withastro/starlight/commit/2a58e1aa068d01833a0ab9e74e4b46cccaee1775) Thanks [@delucis](https://github.com/delucis)! - Upgrade Pagefind to v1 and display page headings in search results
18
+
19
+ ### Patch Changes
20
+
21
+ - [#708](https://github.com/withastro/starlight/pull/708) [`136cfb1`](https://github.com/withastro/starlight/commit/136cfb180f22db116cfdb62fd93d21daff596946) Thanks [@julien-deramond](https://github.com/julien-deramond)! - Fix main content column width for pages without a table of contents
22
+
23
+ - [#682](https://github.com/withastro/starlight/pull/682) [`660a5f5`](https://github.com/withastro/starlight/commit/660a5f57adf0340de21df3e364aada38255bb06c) Thanks [@vedmalex](https://github.com/vedmalex)! - Add Russian language support
24
+
3
25
  ## 0.9.1
4
26
 
5
27
  ### Patch Changes
@@ -58,31 +58,37 @@ const pagefindTranslations = {
58
58
  const dialog = this.querySelector('dialog')!;
59
59
  const dialogFrame = this.querySelector('.dialog-frame')!;
60
60
 
61
- /** Close the modal if a user clicks outside of the modal. */
62
- const onWindowClick = (event: MouseEvent) => {
61
+ /** Close the modal if a user clicks on a link or outside of the modal. */
62
+ const onClick = (event: MouseEvent) => {
63
+ const isLink = 'href' in (event.target || {});
63
64
  if (
64
- document.body.contains(event.target as Node) &&
65
- !dialogFrame.contains(event.target as Node)
66
- )
65
+ isLink ||
66
+ (document.body.contains(event.target as Node) &&
67
+ !dialogFrame.contains(event.target as Node))
68
+ ) {
67
69
  closeModal();
70
+ }
68
71
  };
69
72
 
70
73
  const openModal = (event?: MouseEvent) => {
71
74
  dialog.showModal();
75
+ document.body.toggleAttribute('data-search-modal-open', true);
72
76
  this.querySelector('input')?.focus();
73
77
  event?.stopPropagation();
74
- window.addEventListener('click', onWindowClick);
78
+ window.addEventListener('click', onClick);
75
79
  };
76
80
 
77
- const closeModal = () => {
78
- dialog.close();
79
- window.removeEventListener('click', onWindowClick);
80
- };
81
+ const closeModal = () => dialog.close();
81
82
 
82
83
  openBtn.addEventListener('click', openModal);
83
84
  openBtn.disabled = false;
84
85
  closeBtn.addEventListener('click', closeModal);
85
86
 
87
+ dialog.addEventListener('close', () => {
88
+ document.body.toggleAttribute('data-search-modal-open', false);
89
+ window.removeEventListener('click', onClick);
90
+ });
91
+
86
92
  // Listen for `/` and `cmd + k` keyboard shortcuts.
87
93
  window.addEventListener('keydown', (e) => {
88
94
  const isInput =
@@ -113,6 +119,7 @@ const pagefindTranslations = {
113
119
  bundlePath: import.meta.env.BASE_URL.replace(/\/$/, '') + '/pagefind/',
114
120
  showImages: false,
115
121
  translations,
122
+ showSubResults: true,
116
123
  });
117
124
  });
118
125
  });
@@ -179,7 +186,7 @@ const pagefindTranslations = {
179
186
  .dialog-frame {
180
187
  flex-direction: column;
181
188
  gap: 1rem;
182
- padding: 1.5rem;
189
+ padding: 1rem;
183
190
  }
184
191
 
185
192
  button[data-close-modal] {
@@ -218,10 +225,35 @@ const pagefindTranslations = {
218
225
  min-height: 15rem;
219
226
  max-height: calc(100% - 8rem);
220
227
  }
228
+
229
+ .dialog-frame {
230
+ padding: 1.5rem;
231
+ }
221
232
  }
222
233
  </style>
223
234
 
224
235
  <style is:global>
236
+ [data-search-modal-open] {
237
+ overflow: hidden;
238
+ }
239
+
240
+ #starlight__search {
241
+ --sl-search-result-spacing: calc(1.25rem * var(--pagefind-ui-scale));
242
+ --sl-search-result-pad-inline-start: calc(3.75rem * var(--pagefind-ui-scale));
243
+ --sl-search-result-pad-inline-end: calc(1.25rem * var(--pagefind-ui-scale));
244
+ --sl-search-result-pad-block: calc(0.9375rem * var(--pagefind-ui-scale));
245
+ --sl-search-result-nested-pad-block: calc(0.625rem * var(--pagefind-ui-scale));
246
+ --sl-search-corners: calc(0.3125rem * var(--pagefind-ui-scale));
247
+ --sl-search-page-icon-size: calc(1.875rem * var(--pagefind-ui-scale));
248
+ --sl-search-page-icon-inline-start: calc(
249
+ (var(--sl-search-result-pad-inline-start) - var(--sl-search-page-icon-size)) / 2
250
+ );
251
+ --sl-search-tree-diagram-size: calc(2.5rem * var(--pagefind-ui-scale));
252
+ --sl-search-tree-diagram-inline-start: calc(
253
+ (var(--sl-search-result-pad-inline-start) - var(--sl-search-tree-diagram-size)) / 2
254
+ );
255
+ }
256
+
225
257
  #starlight__search .pagefind-ui__form::before {
226
258
  --pagefind-ui-text: var(--sl-color-gray-1);
227
259
  opacity: 1;
@@ -260,22 +292,36 @@ const pagefindTranslations = {
260
292
  }
261
293
 
262
294
  #starlight__search .pagefind-ui__results > * + * {
263
- margin-top: 0.5rem;
295
+ margin-top: var(--sl-search-result-spacing);
264
296
  }
265
297
  #starlight__search .pagefind-ui__result {
266
- position: relative;
267
298
  border: 0;
268
- border-radius: 0.25rem;
269
- padding: 1rem;
299
+ padding: 0;
300
+ }
301
+
302
+ #starlight__search .pagefind-ui__result-nested {
303
+ position: relative;
304
+ padding: var(--sl-search-result-nested-pad-block) var(--sl-search-result-pad-inline-end);
305
+ padding-inline-start: var(--sl-search-result-pad-inline-start);
306
+ }
307
+
308
+ #starlight__search .pagefind-ui__result-title:not(:where(.pagefind-ui__result-nested *)),
309
+ #starlight__search .pagefind-ui__result-nested {
310
+ position: relative;
270
311
  background-color: var(--sl-color-black);
271
312
  }
272
313
 
273
- #starlight__search .pagefind-ui__result:hover,
274
- #starlight__search .pagefind-ui__result:focus-within {
314
+ #starlight__search .pagefind-ui__result-title:not(:where(.pagefind-ui__result-nested *)):hover,
315
+ #starlight__search
316
+ .pagefind-ui__result-title:not(:where(.pagefind-ui__result-nested *)):focus-within,
317
+ #starlight__search .pagefind-ui__result-nested:hover,
318
+ #starlight__search .pagefind-ui__result-nested:focus-within {
275
319
  outline: 1px solid var(--sl-color-accent-high);
276
320
  }
277
321
 
278
- #starlight__search .pagefind-ui__result:focus-within {
322
+ #starlight__search
323
+ .pagefind-ui__result-title:not(:where(.pagefind-ui__result-nested *)):focus-within,
324
+ #starlight__search .pagefind-ui__result-nested:focus-within {
279
325
  background-color: var(--sl-color-accent-low);
280
326
  }
281
327
 
@@ -284,7 +330,37 @@ const pagefindTranslations = {
284
330
  margin-top: 0;
285
331
  }
286
332
 
333
+ #starlight__search .pagefind-ui__result-inner > :first-child {
334
+ border-radius: var(--sl-search-corners) var(--sl-search-corners) 0 0;
335
+ }
336
+ #starlight__search .pagefind-ui__result-inner > :last-child {
337
+ border-radius: 0 0 var(--sl-search-corners) var(--sl-search-corners);
338
+ }
339
+
340
+ #starlight__search .pagefind-ui__result-inner > .pagefind-ui__result-title {
341
+ padding: var(--sl-search-result-pad-block) var(--sl-search-result-pad-inline-end);
342
+ padding-inline-start: var(--sl-search-result-pad-inline-start);
343
+ }
344
+ #starlight__search .pagefind-ui__result-inner > .pagefind-ui__result-title::before {
345
+ content: '';
346
+ position: absolute;
347
+ inset-block: 0;
348
+ inset-inline-start: var(--sl-search-page-icon-inline-start);
349
+ width: var(--sl-search-page-icon-size);
350
+ background: var(--sl-color-gray-3);
351
+ -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='currentColor' viewBox='0 0 24 24'%3E%3Cpath d='M9 10h1a1 1 0 1 0 0-2H9a1 1 0 0 0 0 2Zm0 2a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2H9Zm11-3V8l-6-6a1 1 0 0 0-1 0H7a3 3 0 0 0-3 3v14a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V9Zm-6-4 3 3h-2a1 1 0 0 1-1-1V5Zm4 14a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h5v3a3 3 0 0 0 3 3h3v9Zm-3-3H9a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2Z'/%3E%3C/svg%3E")
352
+ center no-repeat;
353
+ mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='currentColor' viewBox='0 0 24 24'%3E%3Cpath d='M9 10h1a1 1 0 1 0 0-2H9a1 1 0 0 0 0 2Zm0 2a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2H9Zm11-3V8l-6-6a1 1 0 0 0-1 0H7a3 3 0 0 0-3 3v14a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V9Zm-6-4 3 3h-2a1 1 0 0 1-1-1V5Zm4 14a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h5v3a3 3 0 0 0 3 3h3v9Zm-3-3H9a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2Z'/%3E%3C/svg%3E")
354
+ center no-repeat;
355
+ }
356
+
357
+ #starlight__search .pagefind-ui__result-inner {
358
+ align-items: stretch;
359
+ gap: 1px;
360
+ }
361
+
287
362
  #starlight__search .pagefind-ui__result-link {
363
+ position: unset;
288
364
  --pagefind-ui-text: var(--sl-color-white);
289
365
  font-weight: 600;
290
366
  }
@@ -293,6 +369,27 @@ const pagefindTranslations = {
293
369
  text-decoration: none;
294
370
  }
295
371
 
372
+ #starlight__search .pagefind-ui__result-nested .pagefind-ui__result-link::before {
373
+ content: unset;
374
+ }
375
+
376
+ #starlight__search .pagefind-ui__result-nested::before {
377
+ content: '';
378
+ position: absolute;
379
+ inset-block: 0;
380
+ inset-inline-start: var(--sl-search-tree-diagram-inline-start);
381
+ width: var(--sl-search-tree-diagram-size);
382
+ background: var(--sl-color-gray-4);
383
+ -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' viewBox='0 0 16 1000' preserveAspectRatio='xMinYMin slice'%3E%3Cpath d='M8 0v1000m6-988H8'/%3E%3C/svg%3E")
384
+ 0% 0% / 100% no-repeat;
385
+ mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' viewBox='0 0 16 1000' preserveAspectRatio='xMinYMin slice'%3E%3Cpath d='M8 0v1000m6-988H8'/%3E%3C/svg%3E")
386
+ 0% 0% / 100% no-repeat;
387
+ }
388
+ #starlight__search .pagefind-ui__result-nested:last-child::before {
389
+ -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' viewBox='0 0 16 16'%3E%3Cpath d='M8 0v12m6 0H8'/%3E%3C/svg%3E");
390
+ mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' viewBox='0 0 16 16'%3E%3Cpath d='M8 0v12m6 0H8'/%3E%3C/svg%3E");
391
+ }
392
+
296
393
  #starlight__search .pagefind-ui__result-link::after {
297
394
  content: '';
298
395
  position: absolute;
@@ -300,18 +397,13 @@ const pagefindTranslations = {
300
397
  }
301
398
 
302
399
  #starlight__search .pagefind-ui__result-excerpt {
303
- font-size: var(--sl-text-body-sm);
400
+ font-size: calc(1rem * var(--pagefind-ui-scale));
304
401
  word-break: break-word;
305
402
  }
306
403
 
307
404
  #starlight__search mark {
308
- color: var(--sl-color-white);
309
- background-color: var(--sl-color-accent-low);
310
- font-weight: 500;
311
- padding: 0.1em 0.2em;
312
- }
313
-
314
- #starlight__search .pagefind-ui__result:focus-within mark {
315
- text-decoration: underline;
405
+ color: var(--sl-color-gray-2);
406
+ background-color: transparent;
407
+ font-weight: 600;
316
408
  }
317
409
  </style>
@@ -4,52 +4,29 @@ export interface TocItem extends MarkdownHeading {
4
4
  children: TocItem[];
5
5
  }
6
6
 
7
- function diveChildren(item: TocItem, depth: number): TocItem[] {
8
- if (depth === 1) {
9
- return item.children;
10
- } else if (item.children.length > 0) {
11
- return diveChildren(item.children.at(-1)!, depth - 1);
12
- } else {
13
- return [];
14
- }
15
- }
16
-
17
7
  interface TocOpts {
18
8
  minHeadingLevel: number;
19
9
  maxHeadingLevel: number;
20
- title?: string;
10
+ title: string;
21
11
  }
22
12
 
13
+ /** Convert the flat headings array generated by Astro into a nested tree structure. */
23
14
  export function generateToC(
24
15
  headings: MarkdownHeading[],
25
- { minHeadingLevel, maxHeadingLevel, title = 'Overview' }: TocOpts
16
+ { minHeadingLevel, maxHeadingLevel, title }: TocOpts
26
17
  ) {
27
- const overview = { depth: 2, slug: '_top', text: title };
28
- headings = [
29
- overview,
30
- ...headings.filter(({ depth }) => depth >= minHeadingLevel && depth <= maxHeadingLevel),
31
- ];
32
- const toc: Array<TocItem> = [];
18
+ headings = headings.filter(({ depth }) => depth >= minHeadingLevel && depth <= maxHeadingLevel);
19
+ const toc: Array<TocItem> = [{ depth: 2, slug: '_top', text: title, children: [] }];
20
+ for (const heading of headings) injectChild(toc, { ...heading, children: [] });
21
+ return toc;
22
+ }
33
23
 
34
- for (const heading of headings) {
35
- if (toc.length === 0) {
36
- toc.push({ ...heading, children: [] });
37
- } else {
38
- const lastItemInToc = toc.at(-1)!;
39
- if (heading.depth < lastItemInToc.depth) {
40
- throw new Error(`Orphan heading found: ${heading.text}.`);
41
- }
42
- if (heading.depth === lastItemInToc.depth) {
43
- // same depth
44
- toc.push({ ...heading, children: [] });
45
- } else {
46
- // higher depth
47
- // push into children, or children's children alike
48
- const gap = heading.depth - lastItemInToc.depth;
49
- const target = diveChildren(lastItemInToc, gap);
50
- target.push({ ...heading, children: [] });
51
- }
52
- }
24
+ /** Inject a ToC entry as deep in the tree as its `depth` property requires. */
25
+ function injectChild(items: TocItem[], item: TocItem): void {
26
+ const lastItem = items.at(-1);
27
+ if (!lastItem || lastItem.depth >= item.depth) {
28
+ items.push(item);
29
+ } else {
30
+ return injectChild(lastItem.children, item);
53
31
  }
54
- return toc;
55
32
  }
@@ -46,7 +46,7 @@ interface Props {
46
46
  width: 100%;
47
47
  }
48
48
 
49
- :global([data-has-sidebar]) .main-pane {
49
+ :global([data-has-sidebar][data-has-toc]) .main-pane {
50
50
  --sl-content-margin-inline: auto 0;
51
51
 
52
52
  order: 1;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astrojs/starlight",
3
- "version": "0.9.1",
3
+ "version": "0.10.1",
4
4
  "description": "Build beautiful, high-performance documentation websites with Astro",
5
5
  "keywords": [
6
6
  "docs",
@@ -39,13 +39,13 @@
39
39
  "dependencies": {
40
40
  "@astrojs/mdx": "^1.0.0",
41
41
  "@astrojs/sitemap": "^3.0.0",
42
- "@pagefind/default-ui": "1.0.0-beta.2",
42
+ "@pagefind/default-ui": "^1.0.3",
43
43
  "@types/mdast": "^3.0.11",
44
44
  "bcp-47": "^2.1.0",
45
45
  "execa": "^7.1.1",
46
46
  "hast-util-select": "^5.0.5",
47
47
  "hastscript": "^7.2.0",
48
- "pagefind": "1.0.0-beta.2",
48
+ "pagefind": "^1.0.3",
49
49
  "rehype": "^12.0.1",
50
50
  "remark-directive": "^2.0.1",
51
51
  "unified": "^10.1.2",
@@ -16,11 +16,12 @@ import nb from './nb.json';
16
16
  import zh from './zh.json';
17
17
  import ko from './ko.json';
18
18
  import sv from './sv.json';
19
+ import ru from './ru.json';
19
20
 
20
21
  const { parse } = builtinI18nSchema();
21
22
 
22
23
  export default Object.fromEntries(
23
- Object.entries({ cs, en, es, de, ja, pt, fa, fr, it, nl, da, tr, ar, nb, zh, ko, sv }).map(
24
+ Object.entries({ cs, en, es, de, ja, pt, fa, fr, it, nl, da, tr, ar, nb, zh, ko, sv, ru }).map(
24
25
  ([key, dict]) => [key, parse(dict)]
25
26
  )
26
27
  );
@@ -0,0 +1,22 @@
1
+ {
2
+ "skipLink.label": "Пропустить до содержимого",
3
+ "search.label": "Поиск",
4
+ "search.shortcutLabel": "(Нажмите / для Поиска)",
5
+ "search.cancelLabel": "Отменить",
6
+ "search.devWarning": "Поиск доступен только в производственных сборках. \nПопробуйте выполнить сборку и просмотреть сайт, чтобы протестировать его локально.",
7
+ "themeSelect.accessibleLabel": "Выберите тему",
8
+ "themeSelect.dark": "Темная",
9
+ "themeSelect.light": "Светлая",
10
+ "themeSelect.auto": "Авто",
11
+ "languageSelect.accessibleLabel": "Выберите язык",
12
+ "menuButton.accessibleLabel": "Меню",
13
+ "sidebarNav.accessibleLabel": "Основное",
14
+ "tableOfContents.onThisPage": "На странице",
15
+ "tableOfContents.overview": "Обзор",
16
+ "i18n.untranslatedContent": "Этот содержимое пока не доступно на вашем языке.",
17
+ "page.editLink": "Редактировать странице",
18
+ "page.lastUpdated": "Последнее обновление:",
19
+ "page.previousLink": "Предыдущая",
20
+ "page.nextLink": "Следующая",
21
+ "404.text": "Страница не найдена. Проверьтье URL или используйте поиск по сайту"
22
+ }