diff --git a/.changeset/breezy-cats-taste.md b/.changeset/breezy-cats-taste.md new file mode 100644 index 00000000000..3f2add688df --- /dev/null +++ b/.changeset/breezy-cats-taste.md @@ -0,0 +1,5 @@ +--- +'@astrojs/starlight': patch +--- + +Adds extra information to the errors thrown by the `` component to help locate misformatted code diff --git a/docs/src/content/docs/zh-cn/guides/components.mdx b/docs/src/content/docs/zh-cn/guides/components.mdx index 5b4913843b0..4565c32836c 100644 --- a/docs/src/content/docs/zh-cn/guides/components.mdx +++ b/docs/src/content/docs/zh-cn/guides/components.mdx @@ -86,6 +86,50 @@ import { Tabs, TabItem } from '@astrojs/starlight/components'; +#### 同步选项卡 + +通过添加 `syncKey` 属性来保持多个选项卡组同步。 + +页面上拥有相同的 `syncKey` 值的所有 `` 都将展示相同的活动标签。这使得你的读者只需选择一次(例如他们的操作系统或包管理器),就可以看到他们的选择反映在整个页面中。 + +若要同步相关的选项卡,请为每个 `` 组件添加相同的 `syncKey` 属性,并确保它们都使用相同的 `` 标签: + +```mdx 'syncKey="constellations"' +# src/content/docs/example.mdx + +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +_一些星座:_ + + + Bellatrix, Rigel, Betelgeuse + Pollux, Castor A, Castor B + + +_一些系外行星:_ + + + HD 34445 b, Gliese 179 b, Wasp-82 b + Pollux b, HAT-P-24b, HD 50554 b + +``` + +以上代码在页面上生成了以下内容: + +_一些星座:_ + + + Bellatrix, Rigel, Betelgeuse + Pollux, Castor A, Castor B + + +_一些系外行星:_ + + + HD 34445 b, Gliese 179 b, Wasp-82 b + Pollux b, HAT-P-24b, HD 50554 b + + ### 卡片 import { Card, CardGrid } from '@astrojs/starlight/components'; diff --git a/docs/src/content/docs/zh-cn/guides/i18n.mdx b/docs/src/content/docs/zh-cn/guides/i18n.mdx index 79d4cd3d95b..0e83217b4c0 100644 --- a/docs/src/content/docs/zh-cn/guides/i18n.mdx +++ b/docs/src/content/docs/zh-cn/guides/i18n.mdx @@ -143,6 +143,34 @@ Starlight 期望你在所有语言中创建等效的页面。例如,如果你 如果某种语言尚未提供翻译,Starlight 将为读者显示该页面的默认语言(通过 `defaultLocale` 设置)的内容。例如,如果你尚未创建关于你的法语版本,并且你的默认语言是英语,那么访问 `/fr/about` 的访问者将看到来自 `/en/about` 的英语内容,并显示该页面尚未翻译的通知。这有助于你在默认语言中添加内容,然后在翻译人员有时间时逐步翻译它。 +## 翻译网站标题 + +默认情况下,Starlight 会为所有语言使用相同的站点标题。 +如果你需要为每种语言自定义标题,你可以在 Starlight 的选项中将一个对象传递给 [`title`](/zh-cn/reference/configuration/#title-必填): + +```diff lang="js" +// astro.config.mjs +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +export default defineConfig({ + integrations: [ + starlight({ +- title: 'My Docs', ++ title: { ++ en: 'My Docs', ++ 'zh-CN': '我的文档', ++ }, + defaultLocale: 'en', + locales: { + en: { label: 'English' }, + 'zh-cn': { label: '简体中文', lang: 'zh-CN' }, + }, + }), + ], +}); +``` + ## 翻译 Starlight 的 UI import LanguagesList from '~/components/languages-list.astro'; diff --git a/docs/src/content/docs/zh-cn/guides/pages.mdx b/docs/src/content/docs/zh-cn/guides/pages.mdx index 0298dc6119b..2d15d5f1ca2 100644 --- a/docs/src/content/docs/zh-cn/guides/pages.mdx +++ b/docs/src/content/docs/zh-cn/guides/pages.mdx @@ -107,6 +107,7 @@ import CustomComponent from './CustomComponent.astro'; - [`slug`](/zh-cn/reference/frontmatter/#slug) 属性不受支持,并且会根据自定义页面的 URL 自动设置。 - [`editUrl`](/zh-cn/reference/frontmatter/#editurl) 选项需要一个 URL 来显示编辑链接。 - 用于自定义页面如何在 [自动生成的链接组](/zh-cn/reference/configuration/#sidebar) 中显示的 [`sidebar`](/zh-cn/reference/frontmatter/#sidebar) frontmatter 属性不可用。使用 `` 组件的页面不是集合的一部分,不能添加到自动生成的侧边栏组中。 +- [`draft`](/zh-cn/reference/frontmatter/#draft) 选项仅会显示页面为草稿的 [通知](/zh-cn/reference/overrides/#draftcontentnotice),但不会自动将其从生产版本中排除。 ##### `sidebar` diff --git a/docs/src/content/docs/zh-cn/reference/configuration.mdx b/docs/src/content/docs/zh-cn/reference/configuration.mdx index 8e3b3ce6bd1..6bb76418438 100644 --- a/docs/src/content/docs/zh-cn/reference/configuration.mdx +++ b/docs/src/content/docs/zh-cn/reference/configuration.mdx @@ -25,10 +25,22 @@ export default defineConfig({ ### `title` (必填) -**类型:** `string` +**类型:** `string | Record` 设置你的网站标题。将用于元数据和浏览器标签标题。 +这个值可以是一个字符串,或者对于多语言网站,可以是一个包含每种不同语言值的对象。 +当使用对象形式时,键必须是 BCP-47 标签(例如 `en`,`ar` 或 `zh-CN`): + +```ts +starlight({ + title: { + en: 'My delightful docs site', + de: 'Meine bezaubernde Dokumentationsseite', + }, +}); +``` + ### `description` **类型:** `string` diff --git a/docs/src/content/docs/zh-cn/reference/frontmatter.md b/docs/src/content/docs/zh-cn/reference/frontmatter.md index c7d37556b36..408cc689cc2 100644 --- a/docs/src/content/docs/zh-cn/reference/frontmatter.md +++ b/docs/src/content/docs/zh-cn/reference/frontmatter.md @@ -267,6 +267,21 @@ pagefind: false --- ``` +### `draft` + +**类型:** `boolean` +**默认值:** `false` + +设置此页面是否应被视为草稿,并且不包含在 [生产版本](https://docs.astro.build/zh-cn/reference/cli-reference/#astro-build) 和 [自动生成的链接组](/zh-cn/guides/sidebar/#自动生成的分组) 中。设置为 `true` 可将页面标记为草稿,并使其仅在开发过程中可见。 + +```md +--- +# src/content/docs/example.md +# 从生产版本中排除此页面 +draft: true +--- +``` + ### `sidebar` **类型:** [`SidebarConfig`](#sidebarconfig) diff --git a/docs/src/content/docs/zh-cn/reference/overrides.md b/docs/src/content/docs/zh-cn/reference/overrides.md index 4769f656a71..aebbc401db3 100644 --- a/docs/src/content/docs/zh-cn/reference/overrides.md +++ b/docs/src/content/docs/zh-cn/reference/overrides.md @@ -50,6 +50,12 @@ Starlight 会将以下参数传递给你的自定义组件。 当前语言的根路径。对于默认语言来说是 `undefined`。 +#### `siteTitle` + +**类型:** `string` + +根据页面语言设置的网站标题。 + #### `slug` **类型:** `string` @@ -218,7 +224,7 @@ entry: { **默认组件:** [`Header.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/Header.astro) 在每个页面顶部显示的导航栏组件。 -默认实现显示了 [``](#sitetitle)、[``](#search)、[``](#socialicons)、[``](#themeselect) 和 [``](#languageselect)。 +默认实现显示了 [``](#sitetitle-1)、[``](#search)、[``](#socialicons)、[``](#themeselect) 和 [``](#languageselect)。 #### `SiteTitle` @@ -332,6 +338,12 @@ Starlight 的页面侧边栏负责显示当前页面的子标题的目录。 自定义实现应确保在 `

` 元素上设置 `id="_top"`,就像默认实现中一样。 +#### `DraftContentNotice` + +**默认组件:** [`DraftContentNotice.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/DraftContentNotice.astro) + +在开发过程中,当当前页面被标记为草稿时,向用户显示的通知。 + #### `FallbackContentNotice` **默认组件:** [`FallbackContentNotice.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/components/FallbackContentNotice.astro) diff --git a/docs/src/content/docs/zh-cn/resources/community-content.mdx b/docs/src/content/docs/zh-cn/resources/community-content.mdx index 78b4365af23..37fbbe3915c 100644 --- a/docs/src/content/docs/zh-cn/resources/community-content.mdx +++ b/docs/src/content/docs/zh-cn/resources/community-content.mdx @@ -124,5 +124,10 @@ import YouTubeGrid from '~/components/youtube-grid.astro'; title: 'Astro Starlight 文档模板(构建自定义 app 文档!)', description: '在大约 5 分钟内启动并运行新的 Starlight 网站', }, + { + href: 'https://www.youtube.com/watch?v=12o7WxjAxjM', + title: '使用代理将 Starlight 文档包含在 Next.js 项目中', + description: '将 Starlight 设置为 Next.js 网站内的子目录项目', + }, ]} /> diff --git a/packages/starlight/__tests__/remark-rehype/rehype-steps.test.ts b/packages/starlight/__tests__/remark-rehype/rehype-steps.test.ts index d97f7db8e18..36f4082c5bf 100644 --- a/packages/starlight/__tests__/remark-rehype/rehype-steps.test.ts +++ b/packages/starlight/__tests__/remark-rehype/rehype-steps.test.ts @@ -29,16 +29,36 @@ test('component with non-`
    ` content throws an error', () => { "[AstroUserError]: The \`\` component expects its content to be a single ordered list (\`
      \`) but found the following element: \`

      \`. Hint: - To learn more about the \`\` component, see https://starlight.astro.build/guides/components/#steps" + To learn more about the \`\` component, see https://starlight.astro.build/guides/components/#steps + + Full HTML passed to \`\`: + +

      A paragraph is not an ordered list

      + " `); }); test('component with multiple children throws an error', () => { - expect(() => processSteps('
          ')).toThrowErrorMatchingInlineSnapshot(` + expect(() => + processSteps( + '
          1. List item

          I intended this to be part of the same list item

          1. Other list item
          ' + ) + ).toThrowErrorMatchingInlineSnapshot(` "[AstroUserError]: - The \`\` component expects its content to be a single ordered list (\`
            \`) but found multiple child elements: \`
              \`, \`
                \`. + The \`\` component expects its content to be a single ordered list (\`
                  \`) but found multiple child elements: \`
                    \`, \`

                    \`, \`

                      \`. Hint: - To learn more about the \`\` component, see https://starlight.astro.build/guides/components/#steps" + To learn more about the \`\` component, see https://starlight.astro.build/guides/components/#steps + + Full HTML passed to \`\`: + +
                        +
                      1. List item
                      2. +
                      +

                      I intended this to be part of the same list item

                      +
                        +
                      1. Other list item
                      2. +
                      + " `); }); diff --git a/packages/starlight/package.json b/packages/starlight/package.json index 70ff9ed4211..2e503cf8d0c 100644 --- a/packages/starlight/package.json +++ b/packages/starlight/package.json @@ -206,6 +206,7 @@ "mdast-util-to-markdown": "^2.1.0", "pagefind": "^1.0.3", "rehype": "^13.0.1", + "rehype-format": "^5.0.0", "remark-directive": "^3.0.0", "unified": "^11.0.4", "unist-util-visit": "^5.0.0", diff --git a/packages/starlight/user-components/rehype-steps.ts b/packages/starlight/user-components/rehype-steps.ts index dd912ced7b9..ff9c9593f85 100644 --- a/packages/starlight/user-components/rehype-steps.ts +++ b/packages/starlight/user-components/rehype-steps.ts @@ -1,11 +1,17 @@ import { AstroError } from 'astro/errors'; import type { Element, Root } from 'hast'; import { rehype } from 'rehype'; +import rehypeFormat from 'rehype-format'; +import type { VFile } from 'vfile'; + +const prettyPrintProcessor = rehype().data('settings', { fragment: true }).use(rehypeFormat); +const prettyPrintHtml = (html: string) => + prettyPrintProcessor.processSync({ value: html }).toString(); const stepsProcessor = rehype() .data('settings', { fragment: true }) .use(function steps() { - return (tree: Root) => { + return (tree: Root, vfile: VFile) => { const rootElements = tree.children.filter((item): item is Element => item.type === 'element'); const [rootElement] = rootElements; @@ -17,12 +23,14 @@ const stepsProcessor = rehype() throw new StepsError( 'The `` component expects its content to be a single ordered list (`
                        `) but found multiple child elements: ' + rootElements.map((element: Element) => `\`<${element.tagName}>\``).join(', ') + - '.' + '.', + vfile.value.toString() ); } else if (rootElement.tagName !== 'ol') { throw new StepsError( 'The `` component expects its content to be a single ordered list (`
                          `) but found the following element: ' + - `\`<${rootElement.tagName}>\`.` + `\`<${rootElement.tagName}>\`.`, + vfile.value.toString() ); } @@ -49,10 +57,12 @@ export const processSteps = (html: string | undefined) => { }; class StepsError extends AstroError { - constructor(message: string) { - super( - message, - 'To learn more about the `` component, see https://starlight.astro.build/guides/components/#steps' - ); + constructor(message: string, html?: string) { + let hint = + 'To learn more about the `` component, see https://starlight.astro.build/guides/components/#steps'; + if (html) { + hint += '\n\nFull HTML passed to ``:\n' + prettyPrintHtml(html); + } + super(message, hint); } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b2c15cfcd0a..97c6b646fd8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -175,6 +175,9 @@ importers: rehype: specifier: ^13.0.1 version: 13.0.1 + rehype-format: + specifier: ^5.0.0 + version: 5.0.0 remark-directive: specifier: ^3.0.0 version: 3.0.0 @@ -3461,6 +3464,13 @@ packages: dependencies: function-bind: 1.1.2 + /hast-util-embedded@3.0.0: + resolution: {integrity: sha512-naH8sld4Pe2ep03qqULEtvYr7EjrLK2QHY8KJR6RJkTUjPGObe1vnx585uzem2hGra+s1q08DZZpfgDVYRbaXA==} + dependencies: + '@types/hast': 3.0.3 + hast-util-is-element: 3.0.0 + dev: false + /hast-util-from-html@2.0.1: resolution: {integrity: sha512-RXQBLMl9kjKVNkJTIO6bZyb2n+cUH8LFaSSzo82jiLT6Tfc+Pt7VQCS+/h3YwG4jaNE2TA2sdJisGWR+aJrp0g==} dependencies: @@ -3488,6 +3498,12 @@ packages: dependencies: '@types/hast': 3.0.3 + /hast-util-is-body-ok-link@3.0.0: + resolution: {integrity: sha512-VFHY5bo2nY8HiV6nir2ynmEB1XkxzuUffhEGeVx7orbu/B1KaGyeGgMZldvMVx5xWrDlLLG/kQ6YkJAMkBEx0w==} + dependencies: + '@types/hast': 3.0.3 + dev: false + /hast-util-is-element@3.0.0: resolution: {integrity: sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==} dependencies: @@ -3499,6 +3515,16 @@ packages: dependencies: '@types/hast': 3.0.3 + /hast-util-phrasing@3.0.1: + resolution: {integrity: sha512-6h60VfI3uBQUxHqTyMymMZnEbNl1XmEGtOxxKYL7stY2o601COo62AWAYBQR9lZbYXYSBoxag8UpPRXK+9fqSQ==} + dependencies: + '@types/hast': 3.0.3 + hast-util-embedded: 3.0.0 + hast-util-has-property: 3.0.0 + hast-util-is-body-ok-link: 3.0.0 + hast-util-is-element: 3.0.0 + dev: false + /hast-util-raw@9.0.1: resolution: {integrity: sha512-5m1gmba658Q+lO5uqL5YNGQWeh1MYWZbZmWrM5lncdcuiXuo5E2HT/CIOp0rLF8ksfSwiCVJ3twlgVRyTGThGA==} dependencies: @@ -3692,6 +3718,10 @@ packages: /html-void-elements@3.0.0: resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} + /html-whitespace-sensitive-tag-names@3.0.0: + resolution: {integrity: sha512-KlClZ3/Qy5UgvpvVvDomGhnQhNWH5INE8GwvSIQ9CWt1K0zbbXrl7eN5bWaafOZgtmO3jMPwUqmrmEwinhPq1w==} + dev: false + /html_codesniffer@2.5.1: resolution: {integrity: sha512-vcz0yAaX/OaV6sdNHuT9alBOKkSxYb8h5Yq26dUqgi7XmCgGUSa7U9PiY1PBXQFMjKv1wVPs5/QzHlGuxPDUGg==} engines: {node: '>=6'} @@ -5711,6 +5741,29 @@ packages: expressive-code: 0.35.2 dev: false + /rehype-format@5.0.0: + resolution: {integrity: sha512-kM4II8krCHmUhxrlvzFSptvaWh280Fr7UGNJU5DCMuvmAwGCNmGfi9CvFAQK6JDjsNoRMWQStglK3zKJH685Wg==} + dependencies: + '@types/hast': 3.0.3 + hast-util-embedded: 3.0.0 + hast-util-is-element: 3.0.0 + hast-util-phrasing: 3.0.1 + hast-util-whitespace: 3.0.0 + html-whitespace-sensitive-tag-names: 3.0.0 + rehype-minify-whitespace: 6.0.0 + unist-util-visit-parents: 6.0.1 + dev: false + + /rehype-minify-whitespace@6.0.0: + resolution: {integrity: sha512-i9It4YHR0Sf3GsnlR5jFUKXRr9oayvEk9GKQUkwZv6hs70OH9q3OCZrq9PpLvIGKt3W+JxBOxCidNVpH/6rWdA==} + dependencies: + '@types/hast': 3.0.3 + hast-util-embedded: 3.0.0 + hast-util-is-element: 3.0.0 + hast-util-whitespace: 3.0.0 + unist-util-is: 6.0.0 + dev: false + /rehype-parse@9.0.0: resolution: {integrity: sha512-WG7nfvmWWkCR++KEkZevZb/uw41E8TsH4DsY9UxsTbIXCVGbAs4S+r8FrQ+OtH5EEQAs+5UxKC42VinkmpA1Yw==} dependencies: