@astrojs/starlight 0.15.2 → 0.15.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/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # @astrojs/starlight
2
2
 
3
+ ## 0.15.4
4
+
5
+ ### Patch Changes
6
+
7
+ - [#1378](https://github.com/withastro/starlight/pull/1378) [`0f4a31d`](https://github.com/withastro/starlight/commit/0f4a31da4b6d384c569e8556dcc559dc8bfbfebd) Thanks [@delucis](https://github.com/delucis)! - Updates dependencies: `@astrojs/mdx`, `@astrojs/sitemap`, and `astro-expressive-code`
8
+
9
+ ## 0.15.3
10
+
11
+ ### Patch Changes
12
+
13
+ - [#1303](https://github.com/withastro/starlight/pull/1303) [`3eefd21`](https://github.com/withastro/starlight/commit/3eefd21f2267648b17bc2d6874350fd5dd8bbcb2) Thanks [@lilnasy](https://github.com/lilnasy)! - chore: fix type errors in Starlight internals
14
+
15
+ - [#1351](https://github.com/withastro/starlight/pull/1351) [`932c022`](https://github.com/withastro/starlight/commit/932c0229d7d8d55f30161ccc36c908140c1f252a) Thanks [@roberto-butti](https://github.com/roberto-butti)! - Adds Italian translation for `search.devWarning` UI
16
+
17
+ - [#1298](https://github.com/withastro/starlight/pull/1298) [`c7e995c`](https://github.com/withastro/starlight/commit/c7e995cb018179789b5ee45bae5fdd9c20309945) Thanks [@kevinzunigacuellar](https://github.com/kevinzunigacuellar)! - Fixes incorrect sorting behavior for some autogenerated sidebars
18
+
19
+ - [#1347](https://github.com/withastro/starlight/pull/1347) [`8994d00`](https://github.com/withastro/starlight/commit/8994d007266e0bd8e6116b306ccd9e24c9710411) Thanks [@kevinzunigacuellar](https://github.com/kevinzunigacuellar)! - Refactor `getLastUpdated` to use `node:child_process` instead of `execa`.
20
+
21
+ - [#1353](https://github.com/withastro/starlight/pull/1353) [`90fe8da`](https://github.com/withastro/starlight/commit/90fe8da15c8eb227817c2232345ac359aef6bab5) Thanks [@delucis](https://github.com/delucis)! - Fixes sidebar scrollbar hiding behind navbar
22
+
3
23
  ## 0.15.2
4
24
 
5
25
  ### Patch Changes
@@ -49,9 +49,8 @@ const { hasSidebar, labels } = Astro.props;
49
49
  visibility: var(--sl-sidebar-visibility, hidden);
50
50
  position: fixed;
51
51
  z-index: var(--sl-z-index-menu);
52
- inset-block: 0;
52
+ inset-block: var(--sl-nav-height) 0;
53
53
  inset-inline-start: 0;
54
- padding-top: var(--sl-nav-height);
55
54
  width: 100%;
56
55
  background-color: var(--sl-color-black);
57
56
  overflow-y: auto;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astrojs/starlight",
3
- "version": "0.15.2",
3
+ "version": "0.15.4",
4
4
  "description": "Build beautiful, high-performance documentation websites with Astro",
5
5
  "keywords": [
6
6
  "docs",
@@ -162,21 +162,20 @@
162
162
  "astro": "^4.0.0"
163
163
  },
164
164
  "devDependencies": {
165
- "@astrojs/markdown-remark": "^4.0.0",
165
+ "@astrojs/markdown-remark": "^4.0.1",
166
166
  "@types/node": "^18.16.19",
167
167
  "@vitest/coverage-v8": "^0.33.0",
168
168
  "astro": "^4.0.1",
169
169
  "vitest": "^0.33.0"
170
170
  },
171
171
  "dependencies": {
172
- "@astrojs/mdx": "^2.0.0",
173
- "@astrojs/sitemap": "^3.0.3",
172
+ "@astrojs/mdx": "^2.0.4",
173
+ "@astrojs/sitemap": "^3.0.4",
174
174
  "@pagefind/default-ui": "^1.0.3",
175
175
  "@types/hast": "^3.0.3",
176
176
  "@types/mdast": "^4.0.3",
177
- "astro-expressive-code": "^0.30.1",
177
+ "astro-expressive-code": "^0.31.0",
178
178
  "bcp-47": "^2.1.0",
179
- "execa": "^8.0.1",
180
179
  "hast-util-select": "^6.0.2",
181
180
  "hastscript": "^8.0.0",
182
181
  "mdast-util-directive": "^3.0.0",
@@ -3,7 +3,7 @@
3
3
  "search.label": "Cerca",
4
4
  "search.shortcutLabel": "(Usa / per cercare)",
5
5
  "search.cancelLabel": "Cancella",
6
- "search.devWarning": "Search is only available in production builds. \nTry building and previewing the site to test it out locally.",
6
+ "search.devWarning": "La ricerca è disponibile solo nelle build di produzione. \nProvare ad eseguire il processo di build e visualizzare la preview del sito per testarlo localmente.",
7
7
  "themeSelect.accessibleLabel": "Seleziona tema",
8
8
  "themeSelect.dark": "Scuro",
9
9
  "themeSelect.light": "Chiaro",
@@ -76,8 +76,8 @@ function buildDictionary(
76
76
  // Iterate over alternate dictionaries to avoid overwriting preceding values with `undefined`.
77
77
  for (const dict of dictionaries) {
78
78
  for (const key in dict) {
79
- const value = dict[key as keyof typeof dict];
80
- if (value) dictionary[key as keyof typeof dict] = value;
79
+ const value = dict[key];
80
+ if (value) dictionary[key as keyof typeof dictionary] = value;
81
81
  }
82
82
  }
83
83
  return dictionary;
package/utils/git.ts CHANGED
@@ -1,74 +1,24 @@
1
- /**
2
- * Heavily inspired by
3
- * https://github.com/facebook/docusaurus/blob/46d2aa231ddb18ed67311b6195260af46d7e8bdc/packages/docusaurus-utils/src/gitUtils.ts
4
- *
5
- * Copyright (c) Facebook, Inc. and its affiliates.
6
- *
7
- * This source code is licensed under the MIT license found in the
8
- * LICENSE file in the root directory of this source tree.
9
- */
10
-
11
1
  import { basename, dirname } from 'node:path';
12
- import { execaSync } from 'execa';
2
+ import { spawnSync } from 'node:child_process';
13
3
 
14
- /** Custom error thrown when the current file is not tracked by git. */
15
- class FileNotTrackedError extends Error {}
4
+ export function getNewestCommitDate(file: string) {
5
+ const result = spawnSync('git', ['log', '--format=%ct', '--max-count=1', basename(file)], {
6
+ cwd: dirname(file),
7
+ encoding: 'utf-8',
8
+ });
16
9
 
17
- /**
18
- * Fetches the git history of a file and returns a relevant commit date.
19
- * It gets the commit date instead of author date so that amended commits
20
- * can have their dates updated.
21
- *
22
- * @throws {FileNotTrackedError} If the current file is not tracked by git.
23
- * @throws Also throws when `git log` exited with non-zero, or when it outputs
24
- * unexpected text.
25
- */
26
- export function getFileCommitDate(
27
- file: string,
28
- age: 'oldest' | 'newest' = 'oldest'
29
- ): {
30
- date: Date;
31
- timestamp: number;
32
- } {
33
- const result = execaSync(
34
- 'git',
35
- [
36
- 'log',
37
- `--format=%ct`,
38
- '--max-count=1',
39
- ...(age === 'oldest' ? ['--follow', '--diff-filter=A'] : []),
40
- '--',
41
- basename(file),
42
- ],
43
- {
44
- cwd: dirname(file),
45
- }
46
- );
47
- if (result.exitCode !== 0) {
48
- throw new Error(
49
- `Failed to retrieve the git history for file "${file}" with exit code ${result.exitCode}: ${result.stderr}`
50
- );
10
+ if (result.error) {
11
+ throw new Error(`Failed to retrieve the git history for file "${file}"`);
51
12
  }
52
-
53
13
  const output = result.stdout.trim();
54
-
55
- if (!output) {
56
- throw new FileNotTrackedError(
57
- `Failed to retrieve the git history for file "${file}" because the file is not tracked by git.`
58
- );
59
- }
60
-
61
14
  const regex = /^(?<timestamp>\d+)$/;
62
15
  const match = output.match(regex);
63
16
 
64
- if (!match) {
65
- throw new Error(
66
- `Failed to retrieve the git history for file "${file}" with unexpected output: ${output}`
67
- );
17
+ if (!match?.groups?.timestamp) {
18
+ throw new Error(`Failed to validate the timestamp for file "${file}"`);
68
19
  }
69
20
 
70
- const timestamp = Number(match.groups!.timestamp);
21
+ const timestamp = Number(match.groups.timestamp);
71
22
  const date = new Date(timestamp * 1000);
72
-
73
- return { date, timestamp };
23
+ return date;
74
24
  }
@@ -212,19 +212,24 @@ function getOrder(routeOrDir: Route | Dir): number {
212
212
  : // If no order value is found, set it to the largest number possible.
213
213
  routeOrDir.entry.data.sidebar.order ?? Number.MAX_VALUE;
214
214
  }
215
+ /** Get the comparison ID for a given route to sort them alphabetically. */
216
+ function getComparisonId(id: string) {
217
+ const filename = stripExtension(basename(id));
218
+ return filename === 'index' ? '' : filename;
219
+ }
215
220
 
216
221
  /** Sort a directory’s entries by user-specified order or alphabetically if no order specified. */
217
- function sortDirEntries(
218
- dir: [string, Dir | Route][],
219
- locale: string | undefined
220
- ): [string, Dir | Route][] {
221
- const collator = new Intl.Collator(localeToLang(locale));
222
+ function sortDirEntries(dir: [string, Dir | Route][]): [string, Dir | Route][] {
223
+ const collator = new Intl.Collator(localeToLang(undefined));
222
224
  return dir.sort(([keyA, a], [keyB, b]) => {
223
225
  const [aOrder, bOrder] = [getOrder(a), getOrder(b)];
224
226
  // Pages are sorted by order in ascending order.
225
227
  if (aOrder !== bOrder) return aOrder < bOrder ? -1 : 1;
226
228
  // If two pages have the same order value they will be sorted by their slug.
227
- return collator.compare(isDir(a) ? keyA : a.slug, isDir(b) ? keyB : b.slug);
229
+ return collator.compare(
230
+ isDir(a) ? keyA : getComparisonId(a.id),
231
+ isDir(b) ? keyB : getComparisonId(b.id)
232
+ );
228
233
  });
229
234
  }
230
235
 
@@ -237,7 +242,7 @@ function groupFromDir(
237
242
  locale: string | undefined,
238
243
  collapsed: boolean
239
244
  ): Group {
240
- const entries = sortDirEntries(Object.entries(dir), locale).map(([key, dirOrRoute]) =>
245
+ const entries = sortDirEntries(Object.entries(dir)).map(([key, dirOrRoute]) =>
241
246
  dirToItem(dirOrRoute, `${fullPath}/${key}`, key, currentPathname, locale, collapsed)
242
247
  );
243
248
  return {
@@ -270,7 +275,7 @@ function sidebarFromDir(
270
275
  locale: string | undefined,
271
276
  collapsed: boolean
272
277
  ) {
273
- return sortDirEntries(Object.entries(tree), locale).map(([key, dirOrRoute]) =>
278
+ return sortDirEntries(Object.entries(tree)).map(([key, dirOrRoute]) =>
274
279
  dirToItem(dirOrRoute, key, key, currentPathname, locale, collapsed)
275
280
  );
276
281
  }
@@ -3,7 +3,7 @@ import { fileURLToPath } from 'node:url';
3
3
  import project from 'virtual:starlight/project-context';
4
4
  import config from 'virtual:starlight/user-config';
5
5
  import { generateToC, type TocItem } from './generateToC';
6
- import { getFileCommitDate } from './git';
6
+ import { getNewestCommitDate } from './git';
7
7
  import { getPrevNextLinks, getSidebar, type SidebarEntry } from './navigation';
8
8
  import { ensureTrailingSlash } from './path';
9
9
  import type { Route } from './routing';
@@ -70,17 +70,22 @@ function getToC({ entry, locale, headings }: PageProps) {
70
70
  }
71
71
 
72
72
  function getLastUpdated({ entry }: PageProps): Date | undefined {
73
- if (entry.data.lastUpdated ?? config.lastUpdated) {
73
+ const { lastUpdated: frontmatterLastUpdated } = entry.data;
74
+ const { lastUpdated: configLastUpdated } = config;
75
+
76
+ if (frontmatterLastUpdated ?? configLastUpdated) {
74
77
  const currentFilePath = fileURLToPath(new URL('src/content/docs/' + entry.id, project.root));
75
- let date = typeof entry.data.lastUpdated !== 'boolean' ? entry.data.lastUpdated : undefined;
76
- if (!date) {
77
- try {
78
- ({ date } = getFileCommitDate(currentFilePath, 'newest'));
79
- } catch {}
78
+ try {
79
+ return frontmatterLastUpdated instanceof Date
80
+ ? frontmatterLastUpdated
81
+ : getNewestCommitDate(currentFilePath);
82
+ } catch {
83
+ // If the git command fails, ignore the error.
84
+ return undefined;
80
85
  }
81
- return date;
82
86
  }
83
- return;
87
+
88
+ return undefined;
84
89
  }
85
90
 
86
91
  function getEditUrl({ entry, id, isFallback }: PageProps): URL | undefined {
@@ -8,6 +8,8 @@ let userTranslations: Record<string, i18nSchemaOutput> = {};
8
8
  try {
9
9
  // Load the user’s i18n collection and ignore the error if it doesn’t exist.
10
10
  userTranslations = Object.fromEntries(
11
+ // @ts-ignore — may be an error in projects without an i18n collection
12
+
11
13
  (await getCollection('i18n')).map(({ id, data }) => [id, data] as const)
12
14
  );
13
15
  } catch {}